dos.pp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2004 by Karoly Balogh for Genesi S.a.r.l.
  5. Heavily based on the Commodore Amiga/m68k RTL by Nils Sjoholm and
  6. Carl Eric Codere
  7. MorphOS port was done on a free Pegasos II/G4 machine
  8. provided by Genesi S.a.r.l. <www.genesi.lu>
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. {$INLINE ON}
  16. unit Dos;
  17. {--------------------------------------------------------------------}
  18. { LEFT TO DO: }
  19. {--------------------------------------------------------------------}
  20. { o DiskFree / Disksize don't work as expected }
  21. { o Implement EnvCount,EnvStr }
  22. { o FindFirst should only work with correct attributes }
  23. {--------------------------------------------------------------------}
  24. interface
  25. type
  26. SearchRec = Packed Record
  27. { watch out this is correctly aligned for all processors }
  28. { don't modify. }
  29. { Replacement for Fill }
  30. {0} AnchorPtr : Pointer; { Pointer to the Anchorpath structure }
  31. {4} Fill: Array[1..15] of Byte; {future use}
  32. {End of replacement for fill}
  33. Attr : BYTE; {attribute of found file}
  34. Time : LongInt; {last modify date of found file}
  35. Size : LongInt; {file size of found file}
  36. Name : String[255]; {name of found file}
  37. End;
  38. {$I dosh.inc}
  39. implementation
  40. {$DEFINE HAS_GETMSCOUNT}
  41. {$DEFINE HAS_GETCBREAK}
  42. {$DEFINE HAS_SETCBREAK}
  43. {$DEFINE FPC_FEXPAND_VOLUMES} (* Full paths begin with drive specification *)
  44. {$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT}
  45. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  46. {$I dos.inc}
  47. { * include MorphOS specific functions & definitions * }
  48. {$include execd.inc}
  49. {$include execf.inc}
  50. {$include timerd.inc}
  51. {$include doslibd.inc}
  52. {$include doslibf.inc}
  53. {$include utilf.inc}
  54. const
  55. DaysPerMonth : Array[1..12] of ShortInt =
  56. (031,028,031,030,031,030,031,031,030,031,030,031);
  57. DaysPerYear : Array[1..12] of Integer =
  58. (031,059,090,120,151,181,212,243,273,304,334,365);
  59. DaysPerLeapYear : Array[1..12] of Integer =
  60. (031,060,091,121,152,182,213,244,274,305,335,366);
  61. SecsPerYear : LongInt = 31536000;
  62. SecsPerLeapYear : LongInt = 31622400;
  63. SecsPerDay : LongInt = 86400;
  64. SecsPerHour : Integer = 3600;
  65. SecsPerMinute : ShortInt = 60;
  66. TICKSPERSECOND = 50;
  67. {******************************************************************************
  68. --- Internal routines ---
  69. ******************************************************************************}
  70. { * PathConv is implemented in the system unit! * }
  71. function PathConv(path: string): string; external name 'PATHCONV';
  72. function dosLock(const name: String;
  73. accessmode: Longint) : LongInt;
  74. var
  75. buffer: array[0..255] of Char;
  76. begin
  77. move(name[1],buffer,length(name));
  78. buffer[length(name)]:=#0;
  79. dosLock:=Lock(buffer,accessmode);
  80. end;
  81. function BADDR(bval: LongInt): Pointer; Inline;
  82. begin
  83. BADDR:=Pointer(bval Shl 2);
  84. end;
  85. function BSTR2STRING(s : LongInt): PChar; Inline;
  86. begin
  87. BSTR2STRING:=Pointer(Longint(BADDR(s))+1);
  88. end;
  89. function IsLeapYear(Source : Word) : Boolean;
  90. begin
  91. if (source Mod 400 = 0) or ((source Mod 4 = 0) and (source Mod 100 <> 0)) then
  92. IsLeapYear:=True
  93. else
  94. IsLeapYear:=False;
  95. end;
  96. Procedure Amiga2DateStamp(Date : LongInt; Var TotalDays,Minutes,Ticks: longint);
  97. { Converts a value in seconds past 1978 to a value in AMIGA DateStamp format }
  98. { Taken from SWAG and modified to work with the Amiga format - CEC }
  99. Var
  100. LocalDate : LongInt; Done : Boolean; TotDays : Integer;
  101. Y: Word;
  102. H: Word;
  103. Min: Word;
  104. S : Word;
  105. Begin
  106. Y := 1978; H := 0; Min := 0; S := 0;
  107. TotalDays := 0;
  108. Minutes := 0;
  109. Ticks := 0;
  110. LocalDate := Date;
  111. Done := False;
  112. While Not Done Do
  113. Begin
  114. If LocalDate >= SecsPerYear Then
  115. Begin
  116. Inc(Y,1);
  117. Dec(LocalDate,SecsPerYear);
  118. Inc(TotalDays,DaysPerYear[12]);
  119. End
  120. Else
  121. Done := True;
  122. If (IsLeapYear(Y+1)) And (LocalDate >= SecsPerLeapYear) And
  123. (Not Done) Then
  124. Begin
  125. Inc(Y,1);
  126. Dec(LocalDate,SecsPerLeapYear);
  127. Inc(TotalDays,DaysPerLeapYear[12]);
  128. End;
  129. End; { END WHILE }
  130. Done := False;
  131. TotDays := LocalDate Div SecsPerDay;
  132. { Total number of days }
  133. TotalDays := TotalDays + TotDays;
  134. Dec(LocalDate,TotDays*SecsPerDay);
  135. { Absolute hours since start of day }
  136. H := LocalDate Div SecsPerHour;
  137. { Convert to minutes }
  138. Minutes := H*60;
  139. Dec(LocalDate,(H * SecsPerHour));
  140. { Find the remaining minutes to add }
  141. Min := LocalDate Div SecsPerMinute;
  142. Dec(LocalDate,(Min * SecsPerMinute));
  143. Minutes:=Minutes+Min;
  144. { Find the number of seconds and convert to ticks }
  145. S := LocalDate;
  146. Ticks:=TICKSPERSECOND*S;
  147. End;
  148. function dosSetProtection(const name: string; mask:longint): Boolean;
  149. var
  150. buffer : array[0..255] of Char;
  151. begin
  152. move(name[1],buffer,length(name));
  153. buffer[length(name)]:=#0;
  154. dosSetProtection:=SetProtection(buffer,mask);
  155. end;
  156. function dosSetFileDate(name: string; p : PDateStamp): Boolean;
  157. var buffer : array[0..255] of Char;
  158. begin
  159. move(name[1],buffer,length(name));
  160. buffer[length(name)]:=#0;
  161. dosSetFileDate:=SetFileDate(buffer,p);
  162. end;
  163. {******************************************************************************
  164. --- Info / Date / Time ---
  165. ******************************************************************************}
  166. function DosVersion: Word;
  167. var p: PLibrary;
  168. begin
  169. p:=PLibrary(MOS_DOSBase);
  170. DosVersion:= p^.lib_Version or (p^.lib_Revision shl 8);
  171. end;
  172. { Here are a lot of stuff just for setdate and settime }
  173. var
  174. TimerBase : Pointer;
  175. procedure NewList (list: pList);
  176. begin
  177. with list^ do
  178. begin
  179. lh_Head := pNode(@lh_Tail);
  180. lh_Tail := NIL;
  181. lh_TailPred := pNode(@lh_Head)
  182. end
  183. end;
  184. function CreateExtIO (port: pMsgPort; size: Longint): pIORequest;
  185. var
  186. IOReq: pIORequest;
  187. begin
  188. IOReq := NIL;
  189. if port <> NIL then
  190. begin
  191. IOReq := execAllocMem(size, MEMF_CLEAR or MEMF_PUBLIC);
  192. if IOReq <> NIL then
  193. begin
  194. IOReq^.io_Message.mn_Node.ln_Type := 7;
  195. IOReq^.io_Message.mn_Length := size;
  196. IOReq^.io_Message.mn_ReplyPort := port;
  197. end;
  198. end;
  199. CreateExtIO := IOReq;
  200. end;
  201. procedure DeleteExtIO (ioReq: pIORequest);
  202. begin
  203. if ioReq <> NIL then
  204. begin
  205. ioReq^.io_Message.mn_Node.ln_Type := $FF;
  206. ioReq^.io_Message.mn_ReplyPort := pMsgPort(-1);
  207. ioReq^.io_Device := pDevice(-1);
  208. execFreeMem(ioReq, ioReq^.io_Message.mn_Length);
  209. end
  210. end;
  211. function Createport(name : PChar; pri : longint): pMsgPort;
  212. var
  213. sigbit : ShortInt;
  214. port : pMsgPort;
  215. begin
  216. sigbit := AllocSignal(-1);
  217. if sigbit = -1 then CreatePort := nil;
  218. port := execAllocMem(sizeof(tMsgPort),MEMF_CLEAR or MEMF_PUBLIC);
  219. if port = nil then begin
  220. FreeSignal(sigbit);
  221. CreatePort := nil;
  222. end;
  223. with port^ do begin
  224. if assigned(name) then
  225. mp_Node.ln_Name := name
  226. else mp_Node.ln_Name := nil;
  227. mp_Node.ln_Pri := pri;
  228. mp_Node.ln_Type := 4;
  229. mp_Flags := 0;
  230. mp_SigBit := sigbit;
  231. mp_SigTask := FindTask(nil);
  232. end;
  233. if assigned(name) then AddPort(port)
  234. else NewList(addr(port^.mp_MsgList));
  235. CreatePort := port;
  236. end;
  237. procedure DeletePort (port: pMsgPort);
  238. begin
  239. if port <> NIL then
  240. begin
  241. if port^.mp_Node.ln_Name <> NIL then
  242. RemPort(port);
  243. port^.mp_Node.ln_Type := $FF;
  244. port^.mp_MsgList.lh_Head := pNode(-1);
  245. FreeSignal(port^.mp_SigBit);
  246. execFreeMem(port, sizeof(tMsgPort));
  247. end;
  248. end;
  249. Function Create_Timer(theUnit : longint) : pTimeRequest;
  250. var
  251. Error : longint;
  252. TimerPort : pMsgPort;
  253. TimeReq : pTimeRequest;
  254. begin
  255. TimerPort := CreatePort(Nil, 0);
  256. if TimerPort = Nil then
  257. Create_Timer := Nil;
  258. TimeReq := pTimeRequest(CreateExtIO(TimerPort,sizeof(tTimeRequest)));
  259. if TimeReq = Nil then begin
  260. DeletePort(TimerPort);
  261. Create_Timer := Nil;
  262. end;
  263. Error := OpenDevice(TIMERNAME, theUnit, pIORequest(TimeReq), 0);
  264. if Error <> 0 then begin
  265. DeleteExtIO(pIORequest(TimeReq));
  266. DeletePort(TimerPort);
  267. Create_Timer := Nil;
  268. end;
  269. TimerBase := pointer(TimeReq^.tr_Node.io_Device);
  270. Create_Timer := pTimeRequest(TimeReq);
  271. end;
  272. Procedure Delete_Timer(WhichTimer : pTimeRequest);
  273. var
  274. WhichPort : pMsgPort;
  275. begin
  276. WhichPort := WhichTimer^.tr_Node.io_Message.mn_ReplyPort;
  277. if assigned(WhichTimer) then begin
  278. CloseDevice(pIORequest(WhichTimer));
  279. DeleteExtIO(pIORequest(WhichTimer));
  280. end;
  281. if assigned(WhichPort) then
  282. DeletePort(WhichPort);
  283. end;
  284. function set_new_time(secs, micro : longint): longint;
  285. var
  286. tr : ptimerequest;
  287. begin
  288. tr := create_timer(UNIT_MICROHZ);
  289. { non zero return says error }
  290. if tr = nil then set_new_time := -1;
  291. tr^.tr_time.tv_secs := secs;
  292. tr^.tr_time.tv_micro := micro;
  293. tr^.tr_node.io_Command := TR_SETSYSTIME;
  294. DoIO(pIORequest(tr));
  295. delete_timer(tr);
  296. set_new_time := 0;
  297. end;
  298. function get_sys_time(tv : ptimeval): longint;
  299. var
  300. tr : ptimerequest;
  301. begin
  302. tr := create_timer( UNIT_MICROHZ );
  303. { non zero return says error }
  304. if tr = nil then get_sys_time := -1;
  305. tr^.tr_node.io_Command := TR_GETSYSTIME;
  306. DoIO(pIORequest(tr));
  307. { structure assignment }
  308. tv^ := tr^.tr_time;
  309. delete_timer(tr);
  310. get_sys_time := 0;
  311. end;
  312. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  313. Var
  314. cd : pClockData;
  315. oldtime : ttimeval;
  316. begin
  317. New(cd);
  318. get_sys_time(@oldtime);
  319. Amiga2Date(oldtime.tv_secs,cd);
  320. Year := cd^.year;
  321. Month := cd^.month;
  322. MDay := cd^.mday;
  323. WDay := cd^.wday;
  324. Dispose(cd);
  325. end;
  326. Procedure SetDate(Year, Month, Day: Word);
  327. var
  328. cd : pClockData;
  329. oldtime : ttimeval;
  330. Begin
  331. new(cd);
  332. get_sys_time(@oldtime);
  333. Amiga2Date(oldtime.tv_secs,cd);
  334. cd^.year := Year;
  335. cd^.month := Month;
  336. cd^.mday := Day;
  337. set_new_time(Date2Amiga(cd),0);
  338. dispose(cd);
  339. End;
  340. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  341. Var
  342. cd : pClockData;
  343. oldtime : ttimeval;
  344. begin
  345. New(cd);
  346. get_sys_time(@oldtime);
  347. Amiga2Date(oldtime.tv_secs,cd);
  348. Hour := cd^.hour;
  349. Minute := cd^.min;
  350. Second := cd^.sec;
  351. Sec100 := oldtime.tv_micro div 10000;
  352. Dispose(cd);
  353. END;
  354. Procedure SetTime(Hour, Minute, Second, Sec100: Word);
  355. var
  356. cd : pClockData;
  357. oldtime : ttimeval;
  358. Begin
  359. new(cd);
  360. get_sys_time(@oldtime);
  361. Amiga2Date(oldtime.tv_secs,cd);
  362. cd^.hour := Hour;
  363. cd^.min := Minute;
  364. cd^.sec := Second;
  365. set_new_time(Date2Amiga(cd), Sec100 * 10000);
  366. dispose(cd);
  367. End;
  368. function GetMsCount: int64;
  369. var
  370. TV: TTimeVal;
  371. begin
  372. Get_Sys_Time (@TV);
  373. GetMsCount := TV.TV_Secs * 1000 + TV.TV_Micro div 1000;
  374. end;
  375. {******************************************************************************
  376. --- Exec ---
  377. ******************************************************************************}
  378. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  379. var
  380. p : string;
  381. buf: array[0..255] of char;
  382. result : longint;
  383. MyLock : longint;
  384. i : Integer;
  385. Begin
  386. DosError := 0;
  387. LastdosExitCode := 0;
  388. p:=Path+' '+ComLine;
  389. { allow backslash as slash }
  390. for i:=1 to length(p) do
  391. if p[i]='\' then p[i]:='/';
  392. Move(p[1],buf,length(p));
  393. buf[Length(p)]:=#0;
  394. { Here we must first check if the command we wish to execute }
  395. { actually exists, because this is NOT handled by the }
  396. { _SystemTagList call (program will abort!!) }
  397. { Try to open with shared lock }
  398. MyLock:=dosLock(Path,SHARED_LOCK);
  399. if MyLock <> 0 then
  400. Begin
  401. { File exists - therefore unlock it }
  402. Unlock(MyLock);
  403. result:=SystemTagList(buf,nil);
  404. { on return of -1 the shell could not be executed }
  405. { probably because there was not enough memory }
  406. if result = -1 then
  407. DosError:=8
  408. else
  409. LastDosExitCode:=word(result);
  410. end
  411. else
  412. DosError:=3;
  413. End;
  414. Procedure GetCBreak(Var BreakValue: Boolean);
  415. Begin
  416. breakvalue := system.BreakOn;
  417. End;
  418. Procedure SetCBreak(BreakValue: Boolean);
  419. Begin
  420. system.Breakon := BreakValue;
  421. End;
  422. {******************************************************************************
  423. --- Disk ---
  424. ******************************************************************************}
  425. { How to solve the problem with this: }
  426. { We could walk through the device list }
  427. { at startup to determine possible devices }
  428. const
  429. not_to_use_devs : array[0..12] of string =(
  430. 'DF0:',
  431. 'DF1:',
  432. 'DF2:',
  433. 'DF3:',
  434. 'PED:',
  435. 'PRJ:',
  436. 'PIPE:',
  437. 'RAM:',
  438. 'CON:',
  439. 'RAW:',
  440. 'SER:',
  441. 'PAR:',
  442. 'PRT:');
  443. var
  444. deviceids : array[1..20] of byte;
  445. devicenames : array[1..20] of string[20];
  446. numberofdevices : Byte;
  447. Function DiskFree(Drive: Byte): int64;
  448. Var
  449. MyLock : LongInt;
  450. Inf : pInfoData;
  451. Free : Longint;
  452. myproc : pProcess;
  453. OldWinPtr : Pointer;
  454. Begin
  455. Free := -1;
  456. { Here we stop systemrequesters to appear }
  457. myproc := pProcess(FindTask(nil));
  458. OldWinPtr := myproc^.pr_WindowPtr;
  459. myproc^.pr_WindowPtr := Pointer(-1);
  460. { End of systemrequesterstop }
  461. New(Inf);
  462. MyLock := dosLock(devicenames[deviceids[Drive]],SHARED_LOCK);
  463. If MyLock <> 0 then begin
  464. if Info(MyLock,Inf) then begin
  465. Free := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock) -
  466. (Inf^.id_NumBlocksUsed * Inf^.id_BytesPerBlock);
  467. end;
  468. Unlock(MyLock);
  469. end;
  470. Dispose(Inf);
  471. { Restore systemrequesters }
  472. myproc^.pr_WindowPtr := OldWinPtr;
  473. diskfree := Free;
  474. end;
  475. Function DiskSize(Drive: Byte): int64;
  476. Var
  477. MyLock : LongInt;
  478. Inf : pInfoData;
  479. Size : Longint;
  480. myproc : pProcess;
  481. OldWinPtr : Pointer;
  482. Begin
  483. Size := -1;
  484. { Here we stop systemrequesters to appear }
  485. myproc := pProcess(FindTask(nil));
  486. OldWinPtr := myproc^.pr_WindowPtr;
  487. myproc^.pr_WindowPtr := Pointer(-1);
  488. { End of systemrequesterstop }
  489. New(Inf);
  490. MyLock := dosLock(devicenames[deviceids[Drive]],SHARED_LOCK);
  491. If MyLock <> 0 then begin
  492. if Info(MyLock,Inf) then begin
  493. Size := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock);
  494. end;
  495. Unlock(MyLock);
  496. end;
  497. Dispose(Inf);
  498. { Restore systemrequesters }
  499. myproc^.pr_WindowPtr := OldWinPtr;
  500. disksize := Size;
  501. end;
  502. procedure FindFirst(const Path: PathStr; Attr: Word; Var f: SearchRec);
  503. var
  504. tmpStr: array[0..255] of Char;
  505. Anchor: PAnchorPath;
  506. Result: LongInt;
  507. begin
  508. tmpStr:=PathConv(path)+#0;
  509. DosError:=0;
  510. new(Anchor);
  511. FillChar(Anchor^,sizeof(TAnchorPath),#0);
  512. Result:=MatchFirst(@tmpStr,Anchor);
  513. f.AnchorPtr:=Anchor;
  514. if Result = ERROR_NO_MORE_ENTRIES then
  515. DosError:=18
  516. else
  517. if Result<>0 then DosError:=3;
  518. if DosError=0 then begin
  519. {-------------------------------------------------------------------}
  520. { Here we fill up the SearchRec attribute, but we also do check }
  521. { something else, if the it does not match the mask we are looking }
  522. { for we should go to the next file or directory. }
  523. {-------------------------------------------------------------------}
  524. with Anchor^.ap_Info do begin
  525. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  526. fib_Date.ds_Minute * 60 +
  527. fib_Date.ds_Tick div 50;
  528. f.attr := 0;
  529. {*------------------------------------*}
  530. {* Determine if is a file or a folder *}
  531. {*------------------------------------*}
  532. if fib_DirEntryType>0 then f.attr:=f.attr OR DIRECTORY;
  533. {*------------------------------------*}
  534. {* Determine if Read only *}
  535. {* Readonly if R flag on and W flag *}
  536. {* off. *}
  537. {* Should we check also that EXEC *}
  538. {* is zero? for read only? *}
  539. {*------------------------------------*}
  540. if ((fib_Protection and FIBF_READ) <> 0) and
  541. ((fib_Protection and FIBF_WRITE) = 0) then f.attr:=f.attr or READONLY;
  542. f.Name := strpas(fib_FileName);
  543. f.Size := fib_Size;
  544. end; { end with }
  545. end;
  546. end;
  547. procedure FindNext(Var f: SearchRec);
  548. var
  549. Result: longint;
  550. Anchor: PAnchorPath;
  551. begin
  552. DosError:=0;
  553. Result:=MatchNext(f.AnchorPtr);
  554. if Result = ERROR_NO_MORE_ENTRIES then
  555. DosError:=18
  556. else
  557. if Result <> 0 then DosError:=3;
  558. if DosError=0 then begin
  559. { Fill up the Searchrec information }
  560. { and also check if the files are with }
  561. { the correct attributes }
  562. Anchor:=pAnchorPath(f.AnchorPtr);
  563. with Anchor^.ap_Info do begin
  564. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  565. fib_Date.ds_Minute * 60 +
  566. fib_Date.ds_Tick div 50;
  567. f.attr := 0;
  568. {*------------------------------------*}
  569. {* Determine if is a file or a folder *}
  570. {*------------------------------------*}
  571. if fib_DirEntryType > 0 then f.attr:=f.attr OR DIRECTORY;
  572. {*------------------------------------*}
  573. {* Determine if Read only *}
  574. {* Readonly if R flag on and W flag *}
  575. {* off. *}
  576. {* Should we check also that EXEC *}
  577. {* is zero? for read only? *}
  578. {*------------------------------------*}
  579. if ((fib_Protection and FIBF_READ) <> 0) and
  580. ((fib_Protection and FIBF_WRITE) = 0) then f.attr:=f.attr or READONLY;
  581. f.Name := strpas(fib_FileName);
  582. f.Size := fib_Size;
  583. end; { end with }
  584. end;
  585. end;
  586. procedure FindClose(Var f: SearchRec);
  587. begin
  588. MatchEnd(f.AnchorPtr);
  589. if assigned(f.AnchorPtr) then
  590. Dispose(PAnchorPath(f.AnchorPtr));
  591. end;
  592. {******************************************************************************
  593. --- File ---
  594. ******************************************************************************}
  595. function FSearch(path: PathStr; dirlist: String) : PathStr;
  596. var
  597. counter: LongInt;
  598. p1 : LongInt;
  599. tmpSR : SearchRec;
  600. newdir : PathStr;
  601. begin
  602. { No wildcards allowed in these things }
  603. if (pos('?',path)<>0) or (pos('*',path)<>0) or (path='') then
  604. FSearch:=''
  605. else begin
  606. repeat
  607. p1:=pos(';',dirlist);
  608. if p1<>0 then begin
  609. newdir:=Copy(dirlist,1,p1-1);
  610. Delete(dirlist,1,p1);
  611. end else begin
  612. newdir:=dirlist;
  613. dirlist:='';
  614. end;
  615. if (newdir<>'') and (not (newdir[length(newdir)] in ['/',':'])) then
  616. newdir:=newdir+'/';
  617. FindFirst(newdir+path,anyfile,tmpSR);
  618. if doserror=0 then
  619. newdir:=newdir+path
  620. else
  621. newdir:='';
  622. until (dirlist='') or (newdir<>'');
  623. FSearch:=newdir;
  624. end;
  625. end;
  626. Procedure getftime (var f; var time : longint);
  627. {
  628. This function returns a file's date and time as the number of
  629. seconds after January 1, 1978 that the file was created.
  630. }
  631. var
  632. FInfo : pFileInfoBlock;
  633. FTime : Longint;
  634. FLock : Longint;
  635. Str : String;
  636. i : integer;
  637. begin
  638. DosError:=0;
  639. FTime := 0;
  640. Str := StrPas(filerec(f).name);
  641. for i:=1 to length(Str) do
  642. if str[i]='\' then str[i]:='/';
  643. FLock := dosLock(Str, SHARED_LOCK);
  644. IF FLock <> 0 then begin
  645. New(FInfo);
  646. if Examine(FLock, FInfo) then begin
  647. with FInfo^.fib_Date do
  648. FTime := ds_Days * (24 * 60 * 60) +
  649. ds_Minute * 60 +
  650. ds_Tick div 50;
  651. end else begin
  652. FTime := 0;
  653. end;
  654. Unlock(FLock);
  655. Dispose(FInfo);
  656. end
  657. else
  658. DosError:=6;
  659. time := FTime;
  660. end;
  661. Procedure setftime(var f; time : longint);
  662. var
  663. DateStamp: pDateStamp;
  664. Str: String;
  665. i: Integer;
  666. Days, Minutes,Ticks: longint;
  667. FLock: longint;
  668. Begin
  669. new(DateStamp);
  670. Str := StrPas(filerec(f).name);
  671. for i:=1 to length(Str) do
  672. if str[i]='\' then str[i]:='/';
  673. { Check first of all, if file exists }
  674. FLock := dosLock(Str, SHARED_LOCK);
  675. IF FLock <> 0 then
  676. begin
  677. Unlock(FLock);
  678. Amiga2DateStamp(time,Days,Minutes,ticks);
  679. DateStamp^.ds_Days:=Days;
  680. DateStamp^.ds_Minute:=Minutes;
  681. DateStamp^.ds_Tick:=Ticks;
  682. if dosSetFileDate(Str,DateStamp) then
  683. DosError:=0
  684. else
  685. DosError:=6;
  686. end
  687. else
  688. DosError:=2;
  689. if assigned(DateStamp) then Dispose(DateStamp);
  690. End;
  691. Procedure getfattr(var f; var attr : word);
  692. var
  693. info : pFileInfoBlock;
  694. MyLock : Longint;
  695. flags: word;
  696. Str: String;
  697. i: integer;
  698. Begin
  699. DosError:=0;
  700. flags:=0;
  701. New(info);
  702. Str := StrPas(filerec(f).name);
  703. for i:=1 to length(Str) do
  704. if str[i]='\' then str[i]:='/';
  705. { open with shared lock to check if file exists }
  706. MyLock:=dosLock(Str,SHARED_LOCK);
  707. if MyLock <> 0 then
  708. Begin
  709. Examine(MyLock,info);
  710. {*------------------------------------*}
  711. {* Determine if is a file or a folder *}
  712. {*------------------------------------*}
  713. if info^.fib_DirEntryType > 0 then
  714. flags:=flags OR DIRECTORY;
  715. {*------------------------------------*}
  716. {* Determine if Read only *}
  717. {* Readonly if R flag on and W flag *}
  718. {* off. *}
  719. {* Should we check also that EXEC *}
  720. {* is zero? for read only? *}
  721. {*------------------------------------*}
  722. if ((info^.fib_Protection and FIBF_READ) <> 0)
  723. AND ((info^.fib_Protection and FIBF_WRITE) = 0)
  724. then
  725. flags:=flags OR ReadOnly;
  726. Unlock(mylock);
  727. end
  728. else
  729. DosError:=3;
  730. attr:=flags;
  731. Dispose(info);
  732. End;
  733. Procedure setfattr (var f;attr : word);
  734. var
  735. flags: longint;
  736. MyLock : longint;
  737. str: string;
  738. i: integer;
  739. Begin
  740. DosError:=0;
  741. flags:=FIBF_WRITE;
  742. { open with shared lock }
  743. Str := StrPas(filerec(f).name);
  744. for i:=1 to length(Str) do
  745. if str[i]='\' then str[i]:='/';
  746. MyLock:=dosLock(Str,SHARED_LOCK);
  747. { By default files are read-write }
  748. if attr AND ReadOnly <> 0 then
  749. { Clear the Fibf_write flags }
  750. flags:=FIBF_READ;
  751. if MyLock <> 0 then
  752. Begin
  753. Unlock(MyLock);
  754. if Not dosSetProtection(Str,flags) then
  755. DosError:=5;
  756. end
  757. else
  758. DosError:=3;
  759. End;
  760. {******************************************************************************
  761. --- Environment ---
  762. ******************************************************************************}
  763. var
  764. StrofPaths : string[255];
  765. function getpathstring: string;
  766. var
  767. f : text;
  768. s : string;
  769. found : boolean;
  770. temp : string[255];
  771. begin
  772. found := true;
  773. temp := '';
  774. assign(f,'ram:makepathstr');
  775. rewrite(f);
  776. writeln(f,'path >ram:temp.lst');
  777. close(f);
  778. exec('c:protect','ram:makepathstr sarwed quiet');
  779. exec('C:execute','ram:makepathstr');
  780. exec('c:delete','ram:makepathstr quiet');
  781. assign(f,'ram:temp.lst');
  782. reset(f);
  783. { skip the first line, garbage }
  784. if not eof(f) then readln(f,s);
  785. while not eof(f) do begin
  786. readln(f,s);
  787. if found then begin
  788. temp := s;
  789. found := false;
  790. end else begin;
  791. if (length(s) + length(temp)) < 255 then
  792. temp := temp + ';' + s;
  793. end;
  794. end;
  795. close(f);
  796. exec('C:delete','ram:temp.lst quiet');
  797. getpathstring := temp;
  798. end;
  799. Function EnvCount: Longint;
  800. { HOW TO GET THIS VALUE: }
  801. { Each time this function is called, we look at the }
  802. { local variables in the Process structure (2.0+) }
  803. { And we also read all files in the ENV: directory }
  804. Begin
  805. EnvCount := 0;
  806. End;
  807. Function EnvStr(Index: LongInt): String;
  808. Begin
  809. EnvStr:='';
  810. End;
  811. function GetEnv(envvar : String): String;
  812. var
  813. bufarr : array[0..255] of char;
  814. strbuffer : array[0..255] of char;
  815. temp : Longint;
  816. begin
  817. if UpCase(envvar) = 'PATH' then begin
  818. if StrOfpaths = '' then StrOfPaths := GetPathString;
  819. GetEnv := StrofPaths;
  820. end else begin
  821. move(envvar[1],strbuffer,length(envvar));
  822. strbuffer[length(envvar)] := #0;
  823. temp := GetVar(strbuffer,bufarr,255,$100);
  824. if temp = -1 then
  825. GetEnv := ''
  826. else GetEnv := StrPas(bufarr);
  827. end;
  828. end;
  829. procedure AddDevice(str : String);
  830. begin
  831. inc(numberofdevices);
  832. deviceids[numberofdevices] := numberofdevices;
  833. devicenames[numberofdevices] := str;
  834. end;
  835. function MakeDeviceName(str : pchar): string;
  836. var
  837. temp : string[20];
  838. begin
  839. temp := strpas(str);
  840. temp := temp + ':';
  841. MakeDeviceName := temp;
  842. end;
  843. function IsInDeviceList(str : string): boolean;
  844. var
  845. i : byte;
  846. theresult : boolean;
  847. begin
  848. theresult := false;
  849. for i := low(not_to_use_devs) to high(not_to_use_devs) do
  850. begin
  851. if str = not_to_use_devs[i] then begin
  852. theresult := true;
  853. break;
  854. end;
  855. end;
  856. IsInDeviceList := theresult;
  857. end;
  858. procedure ReadInDevices;
  859. var
  860. dl : pDosList;
  861. temp : pchar;
  862. str : string[20];
  863. begin
  864. dl := LockDosList(LDF_DEVICES or LDF_READ );
  865. repeat
  866. dl := NextDosEntry(dl,LDF_DEVICES );
  867. if dl <> nil then begin
  868. temp := BSTR2STRING(dl^.dol_Name);
  869. str := MakeDeviceName(temp);
  870. if not IsInDeviceList(str) then
  871. AddDevice(str);
  872. end;
  873. until dl = nil;
  874. UnLockDosList(LDF_DEVICES or LDF_READ );
  875. end;
  876. Begin
  877. DosError:=0;
  878. numberofdevices := 0;
  879. StrOfPaths := '';
  880. ReadInDevices;
  881. End.
  882. {
  883. $Log$
  884. Revision 1.15 2005-04-07 03:57:58 karoly
  885. * fixed attribute handling in findfirst/findnext
  886. Revision 1.14 2005/02/14 17:13:30 peter
  887. * truncate log
  888. }