dos.pp 25 KB

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