dos.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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. var
  196. NanoSecsPast: __wasi_timestamp_t;
  197. begin
  198. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  199. GetMsCount:=NanoSecsPast div 1000000
  200. else
  201. GetMsCount:=0;
  202. end;
  203. {******************************************************************************
  204. --- Exec ---
  205. ******************************************************************************}
  206. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  207. Begin
  208. End;
  209. {******************************************************************************
  210. --- Disk ---
  211. ******************************************************************************}
  212. {
  213. The Diskfree and Disksize functions need a file on the specified drive, since this
  214. is required for the fpstatfs system call.
  215. These filenames are set in drivestr[0..26], and have been preset to :
  216. 0 - '.' (default drive - hence current dir is ok.)
  217. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  218. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  219. 3 - '/' (C: equivalent of dos is the root partition)
  220. 4..26 (can be set by you're own applications)
  221. ! Use AddDisk() to Add new drives !
  222. They both return -1 when a failure occurs.
  223. }
  224. Const
  225. FixDriveStr : array[0..3] of pchar=(
  226. '.',
  227. '/fd0/.',
  228. '/fd1/.',
  229. '/.'
  230. );
  231. const
  232. Drives : byte = 4;
  233. var
  234. DriveStr : array[4..26] of pchar;
  235. Function AddDisk(const path:string) : byte;
  236. begin
  237. { if not (DriveStr[Drives]=nil) then
  238. FreeMem(DriveStr[Drives]);
  239. GetMem(DriveStr[Drives],length(Path)+1);
  240. StrPCopy(DriveStr[Drives],path);
  241. AddDisk:=Drives;
  242. inc(Drives);
  243. if Drives>26 then
  244. Drives:=4;}
  245. end;
  246. Function DiskFree(Drive: Byte): int64;
  247. {var
  248. fs : tstatfs;}
  249. Begin
  250. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  251. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  252. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  253. else
  254. Diskfree:=-1;}
  255. End;
  256. Function DiskSize(Drive: Byte): int64;
  257. {var
  258. fs : tstatfs;}
  259. Begin
  260. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  261. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  262. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  263. else
  264. DiskSize:=-1;}
  265. End;
  266. Procedure FreeDriveStr;
  267. {var
  268. i: longint;}
  269. begin
  270. { for i:=low(drivestr) to high(drivestr) do
  271. if assigned(drivestr[i]) then
  272. begin
  273. freemem(drivestr[i]);
  274. drivestr[i]:=nil;
  275. end;}
  276. end;
  277. {******************************************************************************
  278. --- Findfirst FindNext ---
  279. ******************************************************************************}
  280. Function FNMatch(const Pattern,Name:string):Boolean;
  281. Var
  282. LenPat,LenName : longint;
  283. Function DoFNMatch(i,j:longint):Boolean;
  284. Var
  285. Found : boolean;
  286. Begin
  287. Found:=true;
  288. While Found and (i<=LenPat) Do
  289. Begin
  290. Case Pattern[i] of
  291. '?' : Found:=(j<=LenName);
  292. '*' : Begin
  293. {find the next character in pattern, different of ? and *}
  294. while Found do
  295. begin
  296. inc(i);
  297. if i>LenPat then Break;
  298. case Pattern[i] of
  299. '*' : ;
  300. '?' : begin
  301. if j>LenName then begin DoFNMatch:=false; Exit; end;
  302. inc(j);
  303. end;
  304. else
  305. Found:=false;
  306. end;
  307. end;
  308. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  309. {Now, find in name the character which i points to, if the * or ?
  310. wasn't the last character in the pattern, else, use up all the
  311. chars in name}
  312. Found:=false;
  313. if (i<=LenPat) then
  314. begin
  315. repeat
  316. {find a letter (not only first !) which maches pattern[i]}
  317. while (j<=LenName) and (name[j]<>pattern[i]) do
  318. inc (j);
  319. if (j<LenName) then
  320. begin
  321. if DoFnMatch(i+1,j+1) then
  322. begin
  323. i:=LenPat;
  324. j:=LenName;{we can stop}
  325. Found:=true;
  326. Break;
  327. end else
  328. inc(j);{We didn't find one, need to look further}
  329. end else
  330. if j=LenName then
  331. begin
  332. Found:=true;
  333. Break;
  334. end;
  335. { This 'until' condition must be j>LenName, not j>=LenName.
  336. That's because when we 'need to look further' and
  337. j = LenName then loop must not terminate. }
  338. until (j>LenName);
  339. end else
  340. begin
  341. j:=LenName;{we can stop}
  342. Found:=true;
  343. end;
  344. end;
  345. else {not a wildcard character in pattern}
  346. Found:=(j<=LenName) and (pattern[i]=name[j]);
  347. end;
  348. inc(i);
  349. inc(j);
  350. end;
  351. DoFnMatch:=Found and (j>LenName);
  352. end;
  353. Begin {start FNMatch}
  354. LenPat:=Length(Pattern);
  355. LenName:=Length(Name);
  356. FNMatch:=DoFNMatch(1,1);
  357. End;
  358. Const
  359. RtlFindSize = 15;
  360. Type
  361. RtlFindRecType = Record
  362. DirFD : LongInt;
  363. SearchNum,
  364. LastUsed : LongInt;
  365. End;
  366. Var
  367. RtlFindRecs : Array[1..RtlFindSize] of RtlFindRecType;
  368. CurrSearchNum : LongInt;
  369. Procedure FindClose(Var f: SearchRec);
  370. {
  371. Closes dirfd if it is open
  372. }
  373. Var
  374. res: __wasi_errno_t;
  375. i : longint;
  376. Begin
  377. if f.SearchType=0 then
  378. begin
  379. i:=1;
  380. repeat
  381. if (RtlFindRecs[i].SearchNum=f.SearchNum) then
  382. break;
  383. inc(i);
  384. until (i>RtlFindSize);
  385. If i<=RtlFindSize Then
  386. Begin
  387. RtlFindRecs[i].SearchNum:=0;
  388. if f.dirfd<>-1 then
  389. repeat
  390. res:=__wasi_fd_close(f.dirfd);
  391. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  392. End;
  393. end;
  394. f.dirfd:=-1;
  395. End;
  396. Function FindGetFileInfo(const s:string;var f:SearchRec):boolean;
  397. var
  398. DT : DateTime;
  399. Info : RtlInfoType;
  400. st : __wasi_filestat_t;
  401. fd : __wasi_fd_t;
  402. pr : ansistring;
  403. begin
  404. FindGetFileInfo:=false;
  405. if not ConvertToFdRelativePath(s,fd,pr) then
  406. exit;
  407. { todo: __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW??? }
  408. if __wasi_path_filestat_get(fd,0,PChar(pr),Length(pr),@st)<>__WASI_ERRNO_SUCCESS then
  409. exit;
  410. info.FSize:=st.size;
  411. info.FMTime:=st.mtim;
  412. if st.filetype=__WASI_FILETYPE_DIRECTORY then
  413. info.fmode:=$10
  414. else
  415. info.fmode:=$0;
  416. {if (st.st_mode and STAT_IWUSR)=0 then
  417. info.fmode:=info.fmode or 1;}
  418. if s[f.NamePos+1]='.' then
  419. info.fmode:=info.fmode or $2;
  420. If ((Info.FMode and Not(f.searchattr))=0) Then
  421. Begin
  422. f.Name:=Copy(s,f.NamePos+1,255);
  423. f.Attr:=Info.FMode;
  424. f.Size:=Info.FSize;
  425. {f.mode:=st.st_mode;}
  426. WasiDateToDT(Info.FMTime, DT);
  427. PackTime(DT,f.Time);
  428. FindGetFileInfo:=true;
  429. End;
  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: ansistring;
  465. res: __wasi_errno_t;
  466. DirName : ansistring;
  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. DirName:='./'
  489. Else
  490. DirName:=Copy(f.SearchSpec,1,f.NamePos);
  491. if ConvertToFdRelativePath(DirName,fd,pr) then
  492. begin
  493. repeat
  494. res:=__wasi_path_open(fd,
  495. 0,
  496. PChar(pr),
  497. length(pr),
  498. __WASI_OFLAGS_DIRECTORY,
  499. __WASI_RIGHTS_FD_READDIR,
  500. __WASI_RIGHTS_FD_READDIR,
  501. 0,
  502. @ourfd);
  503. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  504. If res=__WASI_ERRNO_SUCCESS Then
  505. begin
  506. f.DirFD := ourfd;
  507. ArrayPos:=FindLastUsed;
  508. If RtlFindRecs[ArrayPos].SearchNum > 0 Then
  509. repeat
  510. res:=__wasi_fd_close(RtlFindRecs[arraypos].DirFD);
  511. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  512. RtlFindRecs[ArrayPos].SearchNum := f.SearchNum;
  513. RtlFindRecs[ArrayPos].DirFD := f.DirFD;
  514. end
  515. else
  516. f.DirFD:=-1;
  517. end
  518. else
  519. f.DirFD:=-1;
  520. End;
  521. if ArrayPos>0 then
  522. RtlFindRecs[ArrayPos].LastUsed:=0;
  523. end;
  524. {Main loop}
  525. SName:=Copy(f.SearchSpec,f.NamePos+1,255);
  526. Found:=False;
  527. Finished:=(f.DirFD=-1);
  528. While Not Finished Do
  529. Begin
  530. res:=__wasi_fd_readdir(f.DirFD,
  531. @buf,
  532. SizeOf(buf),
  533. f.searchpos,
  534. @bufused);
  535. if (res<>__WASI_ERRNO_SUCCESS) or (bufused<=SizeOf(__wasi_dirent_t)) then
  536. FName:=''
  537. else
  538. begin
  539. if P__wasi_dirent_t(@buf)^.d_namlen<=255 then
  540. SetLength(FName,P__wasi_dirent_t(@buf)^.d_namlen)
  541. else
  542. SetLength(FName,255);
  543. Move(buf[SizeOf(__wasi_dirent_t)],FName[1],Length(FName));
  544. f.searchpos:=P__wasi_dirent_t(@buf)^.d_next;
  545. end;
  546. If FName='' Then
  547. Finished:=True
  548. Else
  549. Begin
  550. If FNMatch(SName,FName) Then
  551. Begin
  552. Found:=FindGetFileInfo(Copy(f.SearchSpec,1,f.NamePos)+FName,f);
  553. if Found then
  554. Finished:=true;
  555. End;
  556. End;
  557. End;
  558. {Shutdown}
  559. If Found Then
  560. DosError:=0
  561. Else
  562. Begin
  563. FindClose(f);
  564. DosError:=18;
  565. End;
  566. End;
  567. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  568. {
  569. opens dir and calls FindWorkProc
  570. }
  571. Begin
  572. fillchar(f,sizeof(f),0);
  573. if Path='' then
  574. begin
  575. DosError:=3;
  576. exit;
  577. end;
  578. {Create Info}
  579. f.SearchSpec := Path;
  580. {We always also search for readonly and archive, regardless of Attr:}
  581. f.SearchAttr := Attr or archive or readonly;
  582. f.SearchPos := 0;
  583. f.NamePos := Length(f.SearchSpec);
  584. while (f.NamePos>0) and not (f.SearchSpec[f.NamePos] in ['/','\']) do
  585. dec(f.NamePos);
  586. {Wildcards?}
  587. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  588. begin
  589. if FindGetFileInfo(Path,f) then
  590. DosError:=0
  591. else
  592. begin
  593. { According to tdos2 test it should return 18
  594. if ErrNo=Sys_ENOENT then
  595. DosError:=3
  596. else }
  597. DosError:=18;
  598. end;
  599. f.DirFD:=-1;
  600. f.SearchType:=1;
  601. f.searchnum:=-1;
  602. end
  603. else
  604. {Find Entry}
  605. begin
  606. Inc(CurrSearchNum);
  607. f.SearchNum:=CurrSearchNum;
  608. f.SearchType:=0;
  609. FindNext(f);
  610. end;
  611. End;
  612. {******************************************************************************
  613. --- File ---
  614. ******************************************************************************}
  615. Function FSearch(path : pathstr;dirlist : string) : pathstr;
  616. {Var
  617. info : BaseUnix.stat;}
  618. Begin
  619. { if (length(Path)>0) and (path[1]='/') and (fpStat(path,info)>=0) and (not fpS_ISDIR(Info.st_Mode)) then
  620. FSearch:=path
  621. else
  622. FSearch:=Unix.FSearch(path,dirlist);}
  623. End;
  624. Procedure GetFAttr(var f; var attr : word);
  625. (*Var
  626. info : baseunix.stat;
  627. LinAttr : longint;
  628. p : pchar;
  629. {$ifndef FPC_ANSI_TEXTFILEREC}
  630. r : RawByteString;
  631. {$endif not FPC_ANSI_TEXTFILEREC}*)
  632. Begin
  633. (* DosError:=0;
  634. {$ifdef FPC_ANSI_TEXTFILEREC}
  635. { encoding is already correct }
  636. p:=@textrec(f).name;
  637. {$else}
  638. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  639. p:=pchar(r);
  640. {$endif}
  641. { use the pchar rather than the rawbytestring version so that we don't check
  642. a second time whether the string needs to be converted to the right code
  643. page
  644. }
  645. if FPStat(p,info)<0 then
  646. begin
  647. Attr:=0;
  648. DosError:=3;
  649. exit;
  650. end
  651. else
  652. LinAttr:=Info.st_Mode;
  653. if fpS_ISDIR(LinAttr) then
  654. Attr:=$10
  655. else
  656. Attr:=$0;
  657. if fpAccess(p,W_OK)<0 then
  658. Attr:=Attr or $1;
  659. if filerec(f).name[0]='.' then
  660. Attr:=Attr or $2;*)
  661. end;
  662. Procedure getftime (var f; var time : longint);
  663. Var
  664. res: __wasi_errno_t;
  665. Info: __wasi_filestat_t;
  666. DT: DateTime;
  667. Begin
  668. doserror:=0;
  669. res:=__wasi_fd_filestat_get(filerec(f).handle,@Info);
  670. if res<>__WASI_ERRNO_SUCCESS then
  671. begin
  672. Time:=0;
  673. case res of
  674. __WASI_ERRNO_ACCES,
  675. __WASI_ERRNO_NOTCAPABLE:
  676. doserror:=5;
  677. else
  678. doserror:=6;
  679. end;
  680. exit
  681. end
  682. else
  683. WasiDateToDt(Info.mtim,DT);
  684. PackTime(DT,Time);
  685. End;
  686. Procedure setftime(var f; time : longint);
  687. (*
  688. Var
  689. utim: utimbuf;
  690. DT: DateTime;
  691. p : pchar;
  692. {$ifndef FPC_ANSI_TEXTFILEREC}
  693. r : Rawbytestring;
  694. {$endif not FPC_ANSI_TEXTFILEREC}*)
  695. Begin
  696. (* doserror:=0;
  697. with utim do
  698. begin
  699. actime:=fptime;
  700. UnPackTime(Time,DT);
  701. modtime:=DTToUnixDate(DT);
  702. end;
  703. {$ifdef FPC_ANSI_TEXTFILEREC}
  704. { encoding is already correct }
  705. p:=@textrec(f).name;
  706. {$else}
  707. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  708. p:=pchar(r);
  709. {$endif}
  710. { use the pchar rather than the rawbytestring version so that we don't check
  711. a second time whether the string needs to be converted to the right code
  712. page
  713. }
  714. if fputime(p,@utim)<0 then
  715. begin
  716. Time:=0;
  717. doserror:=3;
  718. end;*)
  719. End;
  720. {******************************************************************************
  721. --- Environment ---
  722. ******************************************************************************}
  723. Function EnvCount: Longint;
  724. var
  725. envcnt : longint;
  726. p : ppchar;
  727. Begin
  728. envcnt:=0;
  729. p:=envp; {defined in system}
  730. if p<>nil then
  731. while p^<>nil do
  732. begin
  733. inc(envcnt);
  734. inc(p);
  735. end;
  736. EnvCount := envcnt
  737. End;
  738. Function EnvStr (Index: longint): String;
  739. Var
  740. i : longint;
  741. p : ppchar;
  742. Begin
  743. if (Index <= 0) or (envp=nil) then
  744. envstr:=''
  745. else
  746. begin
  747. p:=envp; {defined in system}
  748. i:=1;
  749. while (i<Index) and (p^<>nil) do
  750. begin
  751. inc(i);
  752. inc(p);
  753. end;
  754. if p^=nil then
  755. envstr:=''
  756. else
  757. envstr:=strpas(p^)
  758. end;
  759. end;
  760. Function GetEnv(EnvVar: String): String;
  761. var
  762. hp : ppchar;
  763. hs : string;
  764. eqpos : longint;
  765. Begin
  766. getenv:='';
  767. hp:=envp;
  768. if hp<>nil then
  769. while assigned(hp^) do
  770. begin
  771. hs:=strpas(hp^);
  772. eqpos:=pos('=',hs);
  773. if copy(hs,1,eqpos-1)=envvar then
  774. begin
  775. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  776. break;
  777. end;
  778. inc(hp);
  779. end;
  780. End;
  781. Procedure setfattr (var f;attr : word);
  782. Begin
  783. (* {! No Unix equivalent !}
  784. { Fail for setting VolumeId }
  785. if (attr and VolumeID)<>0 then
  786. doserror:=5;*)
  787. End;
  788. {******************************************************************************
  789. --- Initialization ---
  790. ******************************************************************************}
  791. //Finalization
  792. // FreeDriveStr;
  793. End.