dos.pp 21 KB

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