dos.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt and Peter Vreman,
  4. members of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. Unit Dos;
  12. Interface
  13. Const
  14. FileNameLen = 255;
  15. Type
  16. SearchRec =
  17. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  18. packed
  19. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  20. Record
  21. {Fill : array[1..21] of byte; Fill replaced with below}
  22. SearchPos : UInt64; {directory position}
  23. SearchNum : LongInt; {to track which search this is}
  24. DirFD : LongInt; {directory fd handle for reading directory}
  25. SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
  26. SearchAttr : Byte; {attribute we are searching for}
  27. Mode : Word;
  28. Fill : Array[1..1] of Byte; {future use}
  29. {End of fill}
  30. Attr : Byte; {attribute of found file}
  31. Time : LongInt; {last modify date of found file}
  32. Size : LongInt; {file size of found file}
  33. Reserved : Word; {future use}
  34. Name : String[FileNameLen]; {name of found file}
  35. SearchSpec : String[FileNameLen]; {search pattern}
  36. NamePos : Word; {end of path, start of name position}
  37. End;
  38. {$DEFINE HAS_FILENAMELEN}
  39. {$i dosh.inc}
  40. {Extra Utils}
  41. function weekday(y,m,d : longint) : longint; platform;
  42. Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime); platform;
  43. //Function DTToUnixDate(DT: DateTime): LongInt; platform;
  44. {Disk}
  45. //Function AddDisk(const path:string) : byte; platform;
  46. Implementation
  47. Uses
  48. WasiAPI;
  49. {$DEFINE HAS_GETMSCOUNT}
  50. {$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
  51. {$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PChar }
  52. {$I dos.inc}
  53. {******************************************************************************
  54. --- Link C Lib if set ---
  55. ******************************************************************************}
  56. type
  57. RtlInfoType = Record
  58. FMode: LongInt;
  59. {FInode,
  60. FUid,
  61. FGid,}
  62. FSize: __wasi_filesize_t;
  63. FMTime: __wasi_timestamp_t;
  64. End;
  65. {******************************************************************************
  66. --- Info / Date / Time ---
  67. ******************************************************************************}
  68. Function DosVersion:Word;
  69. Begin
  70. End;
  71. function WeekDay (y,m,d:longint):longint;
  72. {
  73. Calculates th day of the week. returns -1 on error
  74. }
  75. var
  76. u,v : longint;
  77. begin
  78. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  79. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  80. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  81. WeekDay:=-1
  82. else
  83. begin
  84. u:=m;
  85. v:=y;
  86. if m<3 then
  87. begin
  88. inc(u,12);
  89. dec(v);
  90. end;
  91. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  92. end;
  93. end;
  94. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  95. var
  96. NanoSecsPast: __wasi_timestamp_t;
  97. DT: DateTime;
  98. begin
  99. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  100. begin
  101. { todo: convert UTC to local time, as soon as we can get the local timezone
  102. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  103. WasiDateToDT(NanoSecsPast,DT);
  104. Year:=DT.Year;
  105. Month:=DT.Month;
  106. MDay:=DT.Day;
  107. WDay:=weekday(DT.Year,DT.Month,DT.Day);
  108. end
  109. else
  110. begin
  111. Year:=0;
  112. Month:=0;
  113. MDay:=0;
  114. WDay:=0;
  115. end;
  116. end;
  117. procedure SetTime(Hour,Minute,Second,sec100:word);
  118. begin
  119. end;
  120. procedure SetDate(Year,Month,Day:Word);
  121. begin
  122. end;
  123. Function SetDateTime(Year,Month,Day,hour,minute,second:Word) : Boolean;
  124. begin
  125. end;
  126. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  127. var
  128. NanoSecsPast: __wasi_timestamp_t;
  129. begin
  130. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  131. begin
  132. { todo: convert UTC to local time, as soon as we can get the local timezone
  133. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  134. NanoSecsPast:=NanoSecsPast div 10000000;
  135. Sec100:=NanoSecsPast mod 100;
  136. NanoSecsPast:=NanoSecsPast div 100;
  137. Second:=NanoSecsPast mod 60;
  138. NanoSecsPast:=NanoSecsPast div 60;
  139. Minute:=NanoSecsPast mod 60;
  140. NanoSecsPast:=NanoSecsPast div 60;
  141. Hour:=NanoSecsPast mod 24;
  142. end
  143. else
  144. begin
  145. Hour:=0;
  146. Minute:=0;
  147. Second:=0;
  148. Sec100:=0;
  149. end;
  150. end;
  151. Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime);
  152. const
  153. days_in_month: array [boolean, 1..12] of Byte =
  154. ((31,28,31,30,31,30,31,31,30,31,30,31),
  155. (31,29,31,30,31,30,31,31,30,31,30,31));
  156. var
  157. leap: Boolean;
  158. days_in_year: LongInt;
  159. Begin
  160. { todo: convert UTC to local time, as soon as we can get the local timezone
  161. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  162. NanoSecsPast:=NanoSecsPast div 1000000000;
  163. Dt.Sec:=NanoSecsPast mod 60;
  164. NanoSecsPast:=NanoSecsPast div 60;
  165. Dt.Min:=NanoSecsPast mod 60;
  166. NanoSecsPast:=NanoSecsPast div 60;
  167. Dt.Hour:=NanoSecsPast mod 24;
  168. NanoSecsPast:=NanoSecsPast div 24;
  169. Dt.Year:=1970;
  170. leap:=false;
  171. days_in_year:=365;
  172. while NanoSecsPast>=days_in_year do
  173. begin
  174. Dec(NanoSecsPast,days_in_year);
  175. Inc(Dt.Year);
  176. leap:=((Dt.Year mod 4)=0) and (((Dt.Year mod 100)<>0) or ((Dt.Year mod 400)=0));
  177. if leap then
  178. days_in_year:=366
  179. else
  180. days_in_year:=365;
  181. end;
  182. Dt.Month:=1;
  183. Inc(NanoSecsPast);
  184. while NanoSecsPast>days_in_month[leap,Dt.Month] do
  185. begin
  186. Dec(NanoSecsPast,days_in_month[leap,Dt.Month]);
  187. Inc(Dt.Month);
  188. end;
  189. Dt.Day:=Word(NanoSecsPast);
  190. End;
  191. Function DTToUnixDate(DT: DateTime): LongInt;
  192. Begin
  193. End;
  194. function GetMsCount: int64;
  195. begin
  196. end;
  197. {******************************************************************************
  198. --- Exec ---
  199. ******************************************************************************}
  200. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  201. Begin
  202. End;
  203. {******************************************************************************
  204. --- Disk ---
  205. ******************************************************************************}
  206. {
  207. The Diskfree and Disksize functions need a file on the specified drive, since this
  208. is required for the fpstatfs system call.
  209. These filenames are set in drivestr[0..26], and have been preset to :
  210. 0 - '.' (default drive - hence current dir is ok.)
  211. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  212. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  213. 3 - '/' (C: equivalent of dos is the root partition)
  214. 4..26 (can be set by you're own applications)
  215. ! Use AddDisk() to Add new drives !
  216. They both return -1 when a failure occurs.
  217. }
  218. Const
  219. FixDriveStr : array[0..3] of pchar=(
  220. '.',
  221. '/fd0/.',
  222. '/fd1/.',
  223. '/.'
  224. );
  225. const
  226. Drives : byte = 4;
  227. var
  228. DriveStr : array[4..26] of pchar;
  229. Function AddDisk(const path:string) : byte;
  230. begin
  231. { if not (DriveStr[Drives]=nil) then
  232. FreeMem(DriveStr[Drives]);
  233. GetMem(DriveStr[Drives],length(Path)+1);
  234. StrPCopy(DriveStr[Drives],path);
  235. AddDisk:=Drives;
  236. inc(Drives);
  237. if Drives>26 then
  238. Drives:=4;}
  239. end;
  240. Function DiskFree(Drive: Byte): int64;
  241. {var
  242. fs : tstatfs;}
  243. Begin
  244. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  245. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  246. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  247. else
  248. Diskfree:=-1;}
  249. End;
  250. Function DiskSize(Drive: Byte): int64;
  251. {var
  252. fs : tstatfs;}
  253. Begin
  254. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  255. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  256. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  257. else
  258. DiskSize:=-1;}
  259. End;
  260. Procedure FreeDriveStr;
  261. {var
  262. i: longint;}
  263. begin
  264. { for i:=low(drivestr) to high(drivestr) do
  265. if assigned(drivestr[i]) then
  266. begin
  267. freemem(drivestr[i]);
  268. drivestr[i]:=nil;
  269. end;}
  270. end;
  271. {******************************************************************************
  272. --- Findfirst FindNext ---
  273. ******************************************************************************}
  274. Function FNMatch(const Pattern,Name:string):Boolean;
  275. Var
  276. LenPat,LenName : longint;
  277. Function DoFNMatch(i,j:longint):Boolean;
  278. Var
  279. Found : boolean;
  280. Begin
  281. Found:=true;
  282. While Found and (i<=LenPat) Do
  283. Begin
  284. Case Pattern[i] of
  285. '?' : Found:=(j<=LenName);
  286. '*' : Begin
  287. {find the next character in pattern, different of ? and *}
  288. while Found do
  289. begin
  290. inc(i);
  291. if i>LenPat then Break;
  292. case Pattern[i] of
  293. '*' : ;
  294. '?' : begin
  295. if j>LenName then begin DoFNMatch:=false; Exit; end;
  296. inc(j);
  297. end;
  298. else
  299. Found:=false;
  300. end;
  301. end;
  302. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  303. {Now, find in name the character which i points to, if the * or ?
  304. wasn't the last character in the pattern, else, use up all the
  305. chars in name}
  306. Found:=false;
  307. if (i<=LenPat) then
  308. begin
  309. repeat
  310. {find a letter (not only first !) which maches pattern[i]}
  311. while (j<=LenName) and (name[j]<>pattern[i]) do
  312. inc (j);
  313. if (j<LenName) then
  314. begin
  315. if DoFnMatch(i+1,j+1) then
  316. begin
  317. i:=LenPat;
  318. j:=LenName;{we can stop}
  319. Found:=true;
  320. Break;
  321. end else
  322. inc(j);{We didn't find one, need to look further}
  323. end else
  324. if j=LenName then
  325. begin
  326. Found:=true;
  327. Break;
  328. end;
  329. { This 'until' condition must be j>LenName, not j>=LenName.
  330. That's because when we 'need to look further' and
  331. j = LenName then loop must not terminate. }
  332. until (j>LenName);
  333. end else
  334. begin
  335. j:=LenName;{we can stop}
  336. Found:=true;
  337. end;
  338. end;
  339. else {not a wildcard character in pattern}
  340. Found:=(j<=LenName) and (pattern[i]=name[j]);
  341. end;
  342. inc(i);
  343. inc(j);
  344. end;
  345. DoFnMatch:=Found and (j>LenName);
  346. end;
  347. Begin {start FNMatch}
  348. LenPat:=Length(Pattern);
  349. LenName:=Length(Name);
  350. FNMatch:=DoFNMatch(1,1);
  351. End;
  352. Const
  353. RtlFindSize = 15;
  354. Type
  355. RtlFindRecType = Record
  356. DirFD : LongInt;
  357. SearchNum,
  358. LastUsed : LongInt;
  359. End;
  360. Var
  361. RtlFindRecs : Array[1..RtlFindSize] of RtlFindRecType;
  362. CurrSearchNum : LongInt;
  363. Procedure FindClose(Var f: SearchRec);
  364. {
  365. Closes dirfd if it is open
  366. }
  367. Var
  368. res: __wasi_errno_t;
  369. i : longint;
  370. Begin
  371. if f.SearchType=0 then
  372. begin
  373. i:=1;
  374. repeat
  375. if (RtlFindRecs[i].SearchNum=f.SearchNum) then
  376. break;
  377. inc(i);
  378. until (i>RtlFindSize);
  379. If i<=RtlFindSize Then
  380. Begin
  381. RtlFindRecs[i].SearchNum:=0;
  382. if f.dirfd<>-1 then
  383. repeat
  384. res:=__wasi_fd_close(f.dirfd);
  385. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  386. End;
  387. end;
  388. f.dirfd:=-1;
  389. End;
  390. Function FindGetFileInfo(const s:string;var f:SearchRec):boolean;
  391. var
  392. s_ansi: ansistring;
  393. DT : DateTime;
  394. Info : RtlInfoType;
  395. st : __wasi_filestat_t;
  396. fd : __wasi_fd_t;
  397. pr : PChar;
  398. begin
  399. FindGetFileInfo:=false;
  400. s_ansi:=s;
  401. if not ConvertToFdRelativePath(PChar(s_ansi),fd,pr) then
  402. exit;
  403. { todo: __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW??? }
  404. if __wasi_path_filestat_get(fd,0,pr,StrLen(pr),@st)<>__WASI_ERRNO_SUCCESS then
  405. begin
  406. FreeMem(pr);
  407. exit;
  408. end;
  409. info.FSize:=st.size;
  410. info.FMTime:=st.mtim;
  411. if st.filetype=__WASI_FILETYPE_DIRECTORY then
  412. info.fmode:=$10
  413. else
  414. info.fmode:=$0;
  415. {if (st.st_mode and STAT_IWUSR)=0 then
  416. info.fmode:=info.fmode or 1;}
  417. if s[f.NamePos+1]='.' then
  418. info.fmode:=info.fmode or $2;
  419. If ((Info.FMode and Not(f.searchattr))=0) Then
  420. Begin
  421. f.Name:=Copy(s,f.NamePos+1,255);
  422. f.Attr:=Info.FMode;
  423. f.Size:=Info.FSize;
  424. {f.mode:=st.st_mode;}
  425. WasiDateToDT(Info.FMTime, DT);
  426. PackTime(DT,f.Time);
  427. FindGetFileInfo:=true;
  428. End;
  429. FreeMem(pr);
  430. end;
  431. Function FindLastUsed: Longint;
  432. {
  433. Find unused or least recently used dirpointer slot in findrecs array
  434. }
  435. Var
  436. BestMatch,i : Longint;
  437. Found : Boolean;
  438. Begin
  439. BestMatch:=1;
  440. i:=1;
  441. Found:=False;
  442. While (i <= RtlFindSize) And (Not Found) Do
  443. Begin
  444. If (RtlFindRecs[i].SearchNum = 0) Then
  445. Begin
  446. BestMatch := i;
  447. Found := True;
  448. End
  449. Else
  450. Begin
  451. If RtlFindRecs[i].LastUsed > RtlFindRecs[BestMatch].LastUsed Then
  452. BestMatch := i;
  453. End;
  454. Inc(i);
  455. End;
  456. FindLastUsed := BestMatch;
  457. End;
  458. Procedure FindNext(Var f: SearchRec);
  459. {
  460. re-opens dir if not already in array and calls FindWorkProc
  461. }
  462. Var
  463. fd,ourfd: __wasi_fd_t;
  464. pr: PChar;
  465. res: __wasi_errno_t;
  466. DirName : Array[0..256] of Char;
  467. i,
  468. ArrayPos : Longint;
  469. FName,
  470. SName : string;
  471. Found,
  472. Finished : boolean;
  473. Buf: array [0..SizeOf(__wasi_dirent_t)+256-1] of Byte;
  474. BufUsed: __wasi_size_t;
  475. Begin
  476. If f.SearchType=0 Then
  477. Begin
  478. ArrayPos:=0;
  479. For i:=1 to RtlFindSize Do
  480. Begin
  481. If RtlFindRecs[i].SearchNum = f.SearchNum Then
  482. ArrayPos:=i;
  483. Inc(RtlFindRecs[i].LastUsed);
  484. End;
  485. If ArrayPos=0 Then
  486. Begin
  487. If f.NamePos = 0 Then
  488. Begin
  489. DirName[0] := '.';
  490. DirName[1] := '/';
  491. DirName[2] := #0;
  492. End
  493. Else
  494. Begin
  495. Move(f.SearchSpec[1], DirName[0], f.NamePos);
  496. DirName[f.NamePos] := #0;
  497. End;
  498. if ConvertToFdRelativePath(@DirName[0],fd,pr) then
  499. begin
  500. repeat
  501. res:=__wasi_path_open(fd,
  502. 0,
  503. pr,
  504. strlen(pr),
  505. __WASI_OFLAGS_DIRECTORY,
  506. __WASI_RIGHTS_FD_READDIR,
  507. __WASI_RIGHTS_FD_READDIR,
  508. 0,
  509. @ourfd);
  510. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  511. If res=__WASI_ERRNO_SUCCESS Then
  512. begin
  513. f.DirFD := ourfd;
  514. ArrayPos:=FindLastUsed;
  515. If RtlFindRecs[ArrayPos].SearchNum > 0 Then
  516. repeat
  517. res:=__wasi_fd_close(RtlFindRecs[arraypos].DirFD);
  518. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  519. RtlFindRecs[ArrayPos].SearchNum := f.SearchNum;
  520. RtlFindRecs[ArrayPos].DirFD := f.DirFD;
  521. end
  522. else
  523. f.DirFD:=-1;
  524. FreeMem(pr);
  525. end
  526. else
  527. f.DirFD:=-1;
  528. End;
  529. if ArrayPos>0 then
  530. RtlFindRecs[ArrayPos].LastUsed:=0;
  531. end;
  532. {Main loop}
  533. SName:=Copy(f.SearchSpec,f.NamePos+1,255);
  534. Found:=False;
  535. Finished:=(f.DirFD=-1);
  536. While Not Finished Do
  537. Begin
  538. res:=__wasi_fd_readdir(f.DirFD,
  539. @buf,
  540. SizeOf(buf),
  541. f.searchpos,
  542. @bufused);
  543. if (res<>__WASI_ERRNO_SUCCESS) or (bufused<=SizeOf(__wasi_dirent_t)) then
  544. FName:=''
  545. else
  546. begin
  547. if P__wasi_dirent_t(@buf)^.d_namlen<=255 then
  548. SetLength(FName,P__wasi_dirent_t(@buf)^.d_namlen)
  549. else
  550. SetLength(FName,255);
  551. Move(buf[SizeOf(__wasi_dirent_t)],FName[1],Length(FName));
  552. f.searchpos:=P__wasi_dirent_t(@buf)^.d_next;
  553. end;
  554. If FName='' Then
  555. Finished:=True
  556. Else
  557. Begin
  558. If FNMatch(SName,FName) Then
  559. Begin
  560. Found:=FindGetFileInfo(Copy(f.SearchSpec,1,f.NamePos)+FName,f);
  561. if Found then
  562. Finished:=true;
  563. End;
  564. End;
  565. End;
  566. {Shutdown}
  567. If Found Then
  568. DosError:=0
  569. Else
  570. Begin
  571. FindClose(f);
  572. DosError:=18;
  573. End;
  574. End;
  575. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  576. {
  577. opens dir and calls FindWorkProc
  578. }
  579. Begin
  580. fillchar(f,sizeof(f),0);
  581. if Path='' then
  582. begin
  583. DosError:=3;
  584. exit;
  585. end;
  586. {Create Info}
  587. f.SearchSpec := Path;
  588. {We always also search for readonly and archive, regardless of Attr:}
  589. f.SearchAttr := Attr or archive or readonly;
  590. f.SearchPos := 0;
  591. f.NamePos := Length(f.SearchSpec);
  592. while (f.NamePos>0) and not (f.SearchSpec[f.NamePos] in ['/','\']) do
  593. dec(f.NamePos);
  594. {Wildcards?}
  595. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  596. begin
  597. if FindGetFileInfo(Path,f) then
  598. DosError:=0
  599. else
  600. begin
  601. { According to tdos2 test it should return 18
  602. if ErrNo=Sys_ENOENT then
  603. DosError:=3
  604. else }
  605. DosError:=18;
  606. end;
  607. f.DirFD:=-1;
  608. f.SearchType:=1;
  609. f.searchnum:=-1;
  610. end
  611. else
  612. {Find Entry}
  613. begin
  614. Inc(CurrSearchNum);
  615. f.SearchNum:=CurrSearchNum;
  616. f.SearchType:=0;
  617. FindNext(f);
  618. end;
  619. End;
  620. {******************************************************************************
  621. --- File ---
  622. ******************************************************************************}
  623. Function FSearch(path : pathstr;dirlist : string) : pathstr;
  624. {Var
  625. info : BaseUnix.stat;}
  626. Begin
  627. { if (length(Path)>0) and (path[1]='/') and (fpStat(path,info)>=0) and (not fpS_ISDIR(Info.st_Mode)) then
  628. FSearch:=path
  629. else
  630. FSearch:=Unix.FSearch(path,dirlist);}
  631. End;
  632. Procedure GetFAttr(var f; var attr : word);
  633. (*Var
  634. info : baseunix.stat;
  635. LinAttr : longint;
  636. p : pchar;
  637. {$ifndef FPC_ANSI_TEXTFILEREC}
  638. r : RawByteString;
  639. {$endif not FPC_ANSI_TEXTFILEREC}*)
  640. Begin
  641. (* DosError:=0;
  642. {$ifdef FPC_ANSI_TEXTFILEREC}
  643. { encoding is already correct }
  644. p:=@textrec(f).name;
  645. {$else}
  646. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  647. p:=pchar(r);
  648. {$endif}
  649. { use the pchar rather than the rawbytestring version so that we don't check
  650. a second time whether the string needs to be converted to the right code
  651. page
  652. }
  653. if FPStat(p,info)<0 then
  654. begin
  655. Attr:=0;
  656. DosError:=3;
  657. exit;
  658. end
  659. else
  660. LinAttr:=Info.st_Mode;
  661. if fpS_ISDIR(LinAttr) then
  662. Attr:=$10
  663. else
  664. Attr:=$0;
  665. if fpAccess(p,W_OK)<0 then
  666. Attr:=Attr or $1;
  667. if filerec(f).name[0]='.' then
  668. Attr:=Attr or $2;*)
  669. end;
  670. Procedure getftime (var f; var time : longint);
  671. Var
  672. res: __wasi_errno_t;
  673. Info: __wasi_filestat_t;
  674. DT: DateTime;
  675. Begin
  676. doserror:=0;
  677. res:=__wasi_fd_filestat_get(filerec(f).handle,@Info);
  678. if res<>__WASI_ERRNO_SUCCESS then
  679. begin
  680. Time:=0;
  681. case res of
  682. __WASI_ERRNO_ACCES,
  683. __WASI_ERRNO_NOTCAPABLE:
  684. doserror:=5;
  685. else
  686. doserror:=6;
  687. end;
  688. exit
  689. end
  690. else
  691. WasiDateToDt(Info.mtim,DT);
  692. PackTime(DT,Time);
  693. End;
  694. Procedure setftime(var f; time : longint);
  695. (*
  696. Var
  697. utim: utimbuf;
  698. DT: DateTime;
  699. p : pchar;
  700. {$ifndef FPC_ANSI_TEXTFILEREC}
  701. r : Rawbytestring;
  702. {$endif not FPC_ANSI_TEXTFILEREC}*)
  703. Begin
  704. (* doserror:=0;
  705. with utim do
  706. begin
  707. actime:=fptime;
  708. UnPackTime(Time,DT);
  709. modtime:=DTToUnixDate(DT);
  710. end;
  711. {$ifdef FPC_ANSI_TEXTFILEREC}
  712. { encoding is already correct }
  713. p:=@textrec(f).name;
  714. {$else}
  715. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  716. p:=pchar(r);
  717. {$endif}
  718. { use the pchar rather than the rawbytestring version so that we don't check
  719. a second time whether the string needs to be converted to the right code
  720. page
  721. }
  722. if fputime(p,@utim)<0 then
  723. begin
  724. Time:=0;
  725. doserror:=3;
  726. end;*)
  727. End;
  728. {******************************************************************************
  729. --- Environment ---
  730. ******************************************************************************}
  731. Function EnvCount: Longint;
  732. var
  733. envcnt : longint;
  734. p : ppchar;
  735. Begin
  736. envcnt:=0;
  737. p:=envp; {defined in system}
  738. if p<>nil then
  739. while p^<>nil do
  740. begin
  741. inc(envcnt);
  742. inc(p);
  743. end;
  744. EnvCount := envcnt
  745. End;
  746. Function EnvStr (Index: longint): String;
  747. Var
  748. i : longint;
  749. p : ppchar;
  750. Begin
  751. if (Index <= 0) or (envp=nil) then
  752. envstr:=''
  753. else
  754. begin
  755. p:=envp; {defined in system}
  756. i:=1;
  757. while (i<Index) and (p^<>nil) do
  758. begin
  759. inc(i);
  760. inc(p);
  761. end;
  762. if p^=nil then
  763. envstr:=''
  764. else
  765. envstr:=strpas(p^)
  766. end;
  767. end;
  768. Function GetEnv(EnvVar: String): String;
  769. var
  770. hp : ppchar;
  771. hs : string;
  772. eqpos : longint;
  773. Begin
  774. getenv:='';
  775. hp:=envp;
  776. if hp<>nil then
  777. while assigned(hp^) do
  778. begin
  779. hs:=strpas(hp^);
  780. eqpos:=pos('=',hs);
  781. if copy(hs,1,eqpos-1)=envvar then
  782. begin
  783. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  784. break;
  785. end;
  786. inc(hp);
  787. end;
  788. End;
  789. Procedure setfattr (var f;attr : word);
  790. Begin
  791. (* {! No Unix equivalent !}
  792. { Fail for setting VolumeId }
  793. if (attr and VolumeID)<>0 then
  794. doserror:=5;*)
  795. End;
  796. {******************************************************************************
  797. --- Initialization ---
  798. ******************************************************************************}
  799. //Finalization
  800. // FreeDriveStr;
  801. End.