dos.pp 26 KB

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