dos.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  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. [rocedure 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 := 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..255] of char;
  380. result : longint;
  381. MyLock : longint;
  382. begin
  383. DosError := 0;
  384. LastDosExitCode := 0;
  385. tmpPath:=PathConv(Path+' '+ComLine);
  386. Move(p[1],buf,length(p));
  387. buf[Length(p)]:=#0;
  388. { Here we must first check if the command we wish to execute }
  389. { actually exists, because this is NOT handled by the }
  390. { _SystemTagList call (program will abort!!) }
  391. { Try to open with shared lock }
  392. MyLock:=dosLock(Path,SHARED_LOCK);
  393. if MyLock <> 0 then
  394. begin
  395. { File exists - therefore unlock it }
  396. Unlock(MyLock);
  397. result:=SystemTagList(buf,nil);
  398. { on return of -1 the shell could not be executed }
  399. { probably because there was not enough memory }
  400. if result = -1 then
  401. DosError:=8
  402. else
  403. LastDosExitCode:=word(result);
  404. end
  405. else
  406. DosError:=3;
  407. end;
  408. procedure GetCBreak(Var BreakValue: Boolean);
  409. begin
  410. breakvalue := system.BreakOn;
  411. end;
  412. procedure SetCBreak(BreakValue: Boolean);
  413. begin
  414. system.Breakon := BreakValue;
  415. end;
  416. {******************************************************************************
  417. --- Disk ---
  418. ******************************************************************************}
  419. { How to solve the problem with this: }
  420. { We could walk through the device list }
  421. { at startup to determine possible devices }
  422. const
  423. not_to_use_devs : array[0..12] of string =(
  424. 'DF0:',
  425. 'DF1:',
  426. 'DF2:',
  427. 'DF3:',
  428. 'PED:',
  429. 'PRJ:',
  430. 'PIPE:',
  431. 'RAM:',
  432. 'CON:',
  433. 'RAW:',
  434. 'SER:',
  435. 'PAR:',
  436. 'PRT:');
  437. var
  438. deviceids : array[1..20] of byte;
  439. devicenames : array[1..20] of string[20];
  440. numberofdevices : Byte;
  441. Function DiskFree(Drive: Byte): int64;
  442. Var
  443. MyLock : LongInt;
  444. Inf : pInfoData;
  445. Free : Longint;
  446. myproc : pProcess;
  447. OldWinPtr : Pointer;
  448. Begin
  449. Free := -1;
  450. { Here we stop systemrequesters to appear }
  451. myproc := pProcess(FindTask(nil));
  452. OldWinPtr := myproc^.pr_WindowPtr;
  453. myproc^.pr_WindowPtr := Pointer(-1);
  454. { End of systemrequesterstop }
  455. New(Inf);
  456. MyLock := dosLock(devicenames[deviceids[Drive]],SHARED_LOCK);
  457. If MyLock <> 0 then begin
  458. if Info(MyLock,Inf) then begin
  459. Free := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock) -
  460. (Inf^.id_NumBlocksUsed * Inf^.id_BytesPerBlock);
  461. end;
  462. Unlock(MyLock);
  463. end;
  464. Dispose(Inf);
  465. { Restore systemrequesters }
  466. myproc^.pr_WindowPtr := OldWinPtr;
  467. diskfree := Free;
  468. end;
  469. Function DiskSize(Drive: Byte): int64;
  470. Var
  471. MyLock : LongInt;
  472. Inf : pInfoData;
  473. Size : Longint;
  474. myproc : pProcess;
  475. OldWinPtr : Pointer;
  476. Begin
  477. Size := -1;
  478. { Here we stop systemrequesters to appear }
  479. myproc := pProcess(FindTask(nil));
  480. OldWinPtr := myproc^.pr_WindowPtr;
  481. myproc^.pr_WindowPtr := Pointer(-1);
  482. { End of systemrequesterstop }
  483. New(Inf);
  484. MyLock := dosLock(devicenames[deviceids[Drive]],SHARED_LOCK);
  485. If MyLock <> 0 then begin
  486. if Info(MyLock,Inf) then begin
  487. Size := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock);
  488. end;
  489. Unlock(MyLock);
  490. end;
  491. Dispose(Inf);
  492. { Restore systemrequesters }
  493. myproc^.pr_WindowPtr := OldWinPtr;
  494. disksize := Size;
  495. end;
  496. procedure FindFirst(const Path: PathStr; Attr: Word; Var f: SearchRec);
  497. var
  498. tmpStr: array[0..255] of Char;
  499. Anchor: PAnchorPath;
  500. Result: LongInt;
  501. begin
  502. tmpStr:=PathConv(path)+#0;
  503. DosError:=0;
  504. new(Anchor);
  505. FillChar(Anchor^,sizeof(TAnchorPath),#0);
  506. Result:=MatchFirst(@tmpStr,Anchor);
  507. f.AnchorPtr:=Anchor;
  508. if Result = ERROR_NO_MORE_ENTRIES then
  509. DosError:=18
  510. else
  511. if Result<>0 then DosError:=3;
  512. if DosError=0 then begin
  513. {-------------------------------------------------------------------}
  514. { Here we fill up the SearchRec attribute, but we also do check }
  515. { something else, if the it does not match the mask we are looking }
  516. { for we should go to the next file or directory. }
  517. {-------------------------------------------------------------------}
  518. with Anchor^.ap_Info do begin
  519. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  520. fib_Date.ds_Minute * 60 +
  521. fib_Date.ds_Tick div 50;
  522. f.attr := 0;
  523. {*------------------------------------*}
  524. {* Determine if is a file or a folder *}
  525. {*------------------------------------*}
  526. if fib_DirEntryType>0 then f.attr:=f.attr OR DIRECTORY;
  527. {*------------------------------------*}
  528. {* Determine if Read only *}
  529. {* Readonly if R flag on and W flag *}
  530. {* off. *}
  531. {* Should we check also that EXEC *}
  532. {* is zero? for read only? *}
  533. {*------------------------------------*}
  534. if ((fib_Protection and FIBF_READ) <> 0) and
  535. ((fib_Protection and FIBF_WRITE) = 0) then f.attr:=f.attr or READONLY;
  536. f.Name := strpas(fib_FileName);
  537. f.Size := fib_Size;
  538. end; { end with }
  539. end;
  540. end;
  541. procedure FindNext(Var f: SearchRec);
  542. var
  543. Result: longint;
  544. Anchor: PAnchorPath;
  545. begin
  546. DosError:=0;
  547. Result:=MatchNext(f.AnchorPtr);
  548. if Result = ERROR_NO_MORE_ENTRIES then
  549. DosError:=18
  550. else
  551. if Result <> 0 then DosError:=3;
  552. if DosError=0 then begin
  553. { Fill up the Searchrec information }
  554. { and also check if the files are with }
  555. { the correct attributes }
  556. Anchor:=pAnchorPath(f.AnchorPtr);
  557. with Anchor^.ap_Info do begin
  558. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  559. fib_Date.ds_Minute * 60 +
  560. fib_Date.ds_Tick div 50;
  561. f.attr := 0;
  562. {*------------------------------------*}
  563. {* Determine if is a file or a folder *}
  564. {*------------------------------------*}
  565. if fib_DirEntryType > 0 then f.attr:=f.attr OR DIRECTORY;
  566. {*------------------------------------*}
  567. {* Determine if Read only *}
  568. {* Readonly if R flag on and W flag *}
  569. {* off. *}
  570. {* Should we check also that EXEC *}
  571. {* is zero? for read only? *}
  572. {*------------------------------------*}
  573. if ((fib_Protection and FIBF_READ) <> 0) and
  574. ((fib_Protection and FIBF_WRITE) = 0) then f.attr:=f.attr or READONLY;
  575. f.Name := strpas(fib_FileName);
  576. f.Size := fib_Size;
  577. end; { end with }
  578. end;
  579. end;
  580. procedure FindClose(Var f: SearchRec);
  581. begin
  582. MatchEnd(f.AnchorPtr);
  583. if assigned(f.AnchorPtr) then
  584. Dispose(PAnchorPath(f.AnchorPtr));
  585. end;
  586. {******************************************************************************
  587. --- File ---
  588. ******************************************************************************}
  589. function FSearch(path: PathStr; dirlist: String) : PathStr;
  590. var
  591. counter: LongInt;
  592. p1 : LongInt;
  593. tmpSR : SearchRec;
  594. newdir : PathStr;
  595. begin
  596. { No wildcards allowed in these things }
  597. if (pos('?',path)<>0) or (pos('*',path)<>0) or (path='') then
  598. FSearch:=''
  599. else begin
  600. repeat
  601. p1:=pos(';',dirlist);
  602. if p1<>0 then begin
  603. newdir:=Copy(dirlist,1,p1-1);
  604. Delete(dirlist,1,p1);
  605. end else begin
  606. newdir:=dirlist;
  607. dirlist:='';
  608. end;
  609. if (newdir<>'') and (not (newdir[length(newdir)] in ['/',':'])) then
  610. newdir:=newdir+'/';
  611. FindFirst(newdir+path,anyfile,tmpSR);
  612. if doserror=0 then
  613. newdir:=newdir+path
  614. else
  615. newdir:='';
  616. until (dirlist='') or (newdir<>'');
  617. FSearch:=newdir;
  618. end;
  619. end;
  620. Procedure getftime (var f; var time : longint);
  621. {
  622. This function returns a file's date and time as the number of
  623. seconds after January 1, 1978 that the file was created.
  624. }
  625. var
  626. FInfo : pFileInfoBlock;
  627. FTime : Longint;
  628. FLock : Longint;
  629. Str : String;
  630. i : integer;
  631. begin
  632. DosError:=0;
  633. FTime := 0;
  634. Str := StrPas(filerec(f).name);
  635. for i:=1 to length(Str) do
  636. if str[i]='\' then str[i]:='/';
  637. FLock := dosLock(Str, SHARED_LOCK);
  638. IF FLock <> 0 then begin
  639. New(FInfo);
  640. if Examine(FLock, FInfo) then begin
  641. with FInfo^.fib_Date do
  642. FTime := ds_Days * (24 * 60 * 60) +
  643. ds_Minute * 60 +
  644. ds_Tick div 50;
  645. end else begin
  646. FTime := 0;
  647. end;
  648. Unlock(FLock);
  649. Dispose(FInfo);
  650. end
  651. else
  652. DosError:=6;
  653. time := FTime;
  654. end;
  655. Procedure setftime(var f; time : longint);
  656. var
  657. DateStamp: pDateStamp;
  658. Str: String;
  659. i: Integer;
  660. Days, Minutes,Ticks: longint;
  661. FLock: longint;
  662. Begin
  663. new(DateStamp);
  664. Str := StrPas(filerec(f).name);
  665. for i:=1 to length(Str) do
  666. if str[i]='\' then str[i]:='/';
  667. { Check first of all, if file exists }
  668. FLock := dosLock(Str, SHARED_LOCK);
  669. IF FLock <> 0 then
  670. begin
  671. Unlock(FLock);
  672. Amiga2DateStamp(time,Days,Minutes,ticks);
  673. DateStamp^.ds_Days:=Days;
  674. DateStamp^.ds_Minute:=Minutes;
  675. DateStamp^.ds_Tick:=Ticks;
  676. if dosSetFileDate(Str,DateStamp) then
  677. DosError:=0
  678. else
  679. DosError:=6;
  680. end
  681. else
  682. DosError:=2;
  683. if assigned(DateStamp) then Dispose(DateStamp);
  684. End;
  685. procedure getfattr(var f; var attr : word);
  686. var
  687. info : pFileInfoBlock;
  688. MyLock : Longint;
  689. flags: word;
  690. Str: String;
  691. i: integer;
  692. begin
  693. DosError:=0;
  694. flags:=0;
  695. New(info);
  696. Str := StrPas(filerec(f).name);
  697. for i:=1 to length(Str) do
  698. if str[i]='\' then str[i]:='/';
  699. { open with shared lock to check if file exists }
  700. MyLock:=dosLock(Str,SHARED_LOCK);
  701. if MyLock <> 0 then
  702. Begin
  703. Examine(MyLock,info);
  704. {*------------------------------------*}
  705. {* Determine if is a file or a folder *}
  706. {*------------------------------------*}
  707. if info^.fib_DirEntryType > 0 then
  708. flags:=flags OR DIRECTORY;
  709. {*------------------------------------*}
  710. {* Determine if Read only *}
  711. {* Readonly if R flag on and W flag *}
  712. {* off. *}
  713. {* Should we check also that EXEC *}
  714. {* is zero? for read only? *}
  715. {*------------------------------------*}
  716. if ((info^.fib_Protection and FIBF_READ) <> 0)
  717. AND ((info^.fib_Protection and FIBF_WRITE) = 0)
  718. then
  719. flags:=flags OR ReadOnly;
  720. Unlock(mylock);
  721. end
  722. else
  723. DosError:=3;
  724. attr:=flags;
  725. Dispose(info);
  726. End;
  727. procedure setfattr(var f; attr : word);
  728. var
  729. flags: longint;
  730. tmpLock : longint;
  731. begin
  732. DosError:=0;
  733. flags:=FIBF_WRITE;
  734. { no need for path conversion here, because file opening already }
  735. { converts the path (KB) }
  736. { create a shared lock on the file }
  737. tmpLock:=Lock(filerec(f).name,SHARED_LOCK);
  738. { By default files are read-write }
  739. if attr and ReadOnly <> 0 then flags:=FIBF_READ; { Clear the Fibf_write flags }
  740. if MyLock <> 0 then begin
  741. Unlock(MyLock);
  742. if not SetProtection(filerec(f).name,flags) then DosError:=5;
  743. end else
  744. DosError:=3;
  745. end;
  746. {******************************************************************************
  747. --- Environment ---
  748. ******************************************************************************}
  749. var
  750. strofpaths : string[255];
  751. function getpathstring: string;
  752. var
  753. f : text;
  754. s : string;
  755. found : boolean;
  756. temp : string[255];
  757. begin
  758. found := true;
  759. temp := '';
  760. assign(f,'ram:makepathstr');
  761. rewrite(f);
  762. writeln(f,'path >ram:temp.lst');
  763. close(f);
  764. exec('c:protect','ram:makepathstr sarwed quiet');
  765. exec('C:execute','ram:makepathstr');
  766. exec('c:delete','ram:makepathstr quiet');
  767. assign(f,'ram:temp.lst');
  768. reset(f);
  769. { skip the first line, garbage }
  770. if not eof(f) then readln(f,s);
  771. while not eof(f) do begin
  772. readln(f,s);
  773. if found then begin
  774. temp := s;
  775. found := false;
  776. end else begin;
  777. if (length(s) + length(temp)) < 255 then
  778. temp := temp + ';' + s;
  779. end;
  780. end;
  781. close(f);
  782. exec('C:delete','ram:temp.lst quiet');
  783. getpathstring := temp;
  784. end;
  785. Function EnvCount: Longint;
  786. { HOW TO GET THIS VALUE: }
  787. { Each time this function is called, we look at the }
  788. { local variables in the Process structure (2.0+) }
  789. { And we also read all files in the ENV: directory }
  790. Begin
  791. EnvCount := 0;
  792. End;
  793. Function EnvStr(Index: LongInt): String;
  794. Begin
  795. EnvStr:='';
  796. End;
  797. function GetEnv(envvar : String): String;
  798. var
  799. bufarr : array[0..255] of char;
  800. strbuffer : array[0..255] of char;
  801. temp : Longint;
  802. begin
  803. if UpCase(envvar) = 'PATH' then begin
  804. if StrOfpaths = '' then StrOfPaths := GetPathString;
  805. GetEnv := StrofPaths;
  806. end else begin
  807. move(envvar[1],strbuffer,length(envvar));
  808. strbuffer[length(envvar)] := #0;
  809. temp := GetVar(strbuffer,bufarr,255,$100);
  810. if temp = -1 then
  811. GetEnv := ''
  812. else GetEnv := StrPas(bufarr);
  813. end;
  814. end;
  815. procedure AddDevice(str : String);
  816. begin
  817. inc(numberofdevices);
  818. deviceids[numberofdevices] := numberofdevices;
  819. devicenames[numberofdevices] := str;
  820. end;
  821. function MakeDeviceName(str : pchar): string;
  822. var
  823. temp : string[20];
  824. begin
  825. temp := strpas(str);
  826. temp := temp + ':';
  827. MakeDeviceName := temp;
  828. end;
  829. function IsInDeviceList(str : string): boolean;
  830. var
  831. i : byte;
  832. theresult : boolean;
  833. begin
  834. theresult := false;
  835. for i := low(not_to_use_devs) to high(not_to_use_devs) do
  836. begin
  837. if str = not_to_use_devs[i] then begin
  838. theresult := true;
  839. break;
  840. end;
  841. end;
  842. IsInDeviceList := theresult;
  843. end;
  844. procedure ReadInDevices;
  845. var
  846. dl : pDosList;
  847. temp : pchar;
  848. str : string[20];
  849. begin
  850. dl := LockDosList(LDF_DEVICES or LDF_READ );
  851. repeat
  852. dl := NextDosEntry(dl,LDF_DEVICES );
  853. if dl <> nil then begin
  854. temp := BSTR2STRING(dl^.dol_Name);
  855. str := MakeDeviceName(temp);
  856. if not IsInDeviceList(str) then
  857. AddDevice(str);
  858. end;
  859. until dl = nil;
  860. UnLockDosList(LDF_DEVICES or LDF_READ );
  861. end;
  862. begin
  863. DosError:=0;
  864. numberofdevices := 0;
  865. StrOfPaths := '';
  866. ReadInDevices;
  867. end.