sysutils.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2021 by the Free Pascal development team.
  4. Sysutils unit for The WebAssembly System Interface (WASI).
  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. {$inline on}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH out}
  16. { force ansistrings }
  17. {$H+}
  18. {$modeswitch typehelpers}
  19. {$modeswitch advancedrecords}
  20. uses
  21. wasiapi, wasiutil;
  22. {$DEFINE OS_FILESETDATEBYNAME}
  23. {$DEFINE HAS_SLEEP}
  24. {$DEFINE HAS_GETTICKCOUNT64}
  25. { used OS file system APIs use ansistring }
  26. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  27. { OS has an ansistring/single byte environment variable API }
  28. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  29. type
  30. TWasiFindData = TWasiSearchRec;
  31. { Include platform independent interface part }
  32. {$i sysutilh.inc}
  33. implementation
  34. uses
  35. sysconst;
  36. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  37. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  38. {$DEFINE HAS_LOCALTIMEZONEOFFSET}
  39. {$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *)
  40. Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64;
  41. const
  42. days_in_month: array [boolean, 1..12] of Byte =
  43. ((31,28,31,30,31,30,31,31,30,31,30,31),
  44. (31,29,31,30,31,30,31,31,30,31,30,31));
  45. days_before_month: array [boolean, 1..12] of Word =
  46. ((0,
  47. 0+31,
  48. 0+31+28,
  49. 0+31+28+31,
  50. 0+31+28+31+30,
  51. 0+31+28+31+30+31,
  52. 0+31+28+31+30+31+30,
  53. 0+31+28+31+30+31+30+31,
  54. 0+31+28+31+30+31+30+31+31,
  55. 0+31+28+31+30+31+30+31+31+30,
  56. 0+31+28+31+30+31+30+31+31+30+31,
  57. 0+31+28+31+30+31+30+31+31+30+31+30),
  58. (0,
  59. 0+31,
  60. 0+31+29,
  61. 0+31+29+31,
  62. 0+31+29+31+30,
  63. 0+31+29+31+30+31,
  64. 0+31+29+31+30+31+30,
  65. 0+31+29+31+30+31+30+31,
  66. 0+31+29+31+30+31+30+31+31,
  67. 0+31+29+31+30+31+30+31+31+30,
  68. 0+31+29+31+30+31+30+31+31+30+31,
  69. 0+31+29+31+30+31+30+31+31+30+31+30));
  70. var
  71. leap: Boolean;
  72. days_in_year: LongInt;
  73. y,m: LongInt;
  74. begin
  75. if (year<1970) or (month<1) or (month>12) or (day<1) or (day>31) or
  76. (hour>=24) or (minute>=60) or (second>=60) then
  77. begin
  78. result:=-1;
  79. exit;
  80. end;
  81. leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
  82. if day>days_in_month[leap,month] then
  83. begin
  84. result:=-1;
  85. exit;
  86. end;
  87. result:=0;
  88. for y:=1970 to year-1 do
  89. if ((y mod 4)=0) and (((y mod 100)<>0) or ((y mod 400)=0)) then
  90. Inc(result,366)
  91. else
  92. Inc(result,365);
  93. Inc(result,days_before_month[leap,month]);
  94. Inc(result,day-1);
  95. result:=(((result*24+hour)*60+minute)*60)+second;
  96. end;
  97. Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64;
  98. begin
  99. { todo: convert UTC to local time, as soon as we can get the local timezone
  100. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  101. result:=UniversalToEpoch(year,month,day,hour,minute,second);
  102. end;
  103. Procedure EpochToUniversal(epoch:int64;var year,month,day,hour,minute,second:Word);
  104. const
  105. days_in_month: array [boolean, 1..12] of Byte =
  106. ((31,28,31,30,31,30,31,31,30,31,30,31),
  107. (31,29,31,30,31,30,31,31,30,31,30,31));
  108. var
  109. leap: Boolean;
  110. days_in_year: LongInt;
  111. begin
  112. if epoch<0 then
  113. begin
  114. year:=0;
  115. month:=0;
  116. day:=0;
  117. hour:=0;
  118. minute:=0;
  119. second:=0;
  120. exit;
  121. end;
  122. second:=epoch mod 60;
  123. epoch:=epoch div 60;
  124. minute:=epoch mod 60;
  125. epoch:=epoch div 60;
  126. hour:=epoch mod 24;
  127. epoch:=epoch div 24;
  128. year:=1970;
  129. leap:=false;
  130. days_in_year:=365;
  131. while epoch>=days_in_year do
  132. begin
  133. Dec(epoch,days_in_year);
  134. Inc(year);
  135. leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
  136. if leap then
  137. days_in_year:=366
  138. else
  139. days_in_year:=365;
  140. end;
  141. month:=1;
  142. Inc(epoch);
  143. while epoch>days_in_month[leap,month] do
  144. begin
  145. Dec(epoch,days_in_month[leap,month]);
  146. Inc(month);
  147. end;
  148. day:=Word(epoch);
  149. end;
  150. Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word);
  151. begin
  152. { todo: convert UTC to local time, as soon as we can get the local timezone
  153. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  154. EpochToUniversal(epoch,year,month,day,hour,minute,second);
  155. end;
  156. { Include platform independent implementation part }
  157. {$i sysutils.inc}
  158. function GetTickCount64: QWord;
  159. var
  160. NanoSecsPast: __wasi_timestamp_t;
  161. begin
  162. if __wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  163. Result:=NanoSecsPast div 1000000
  164. else
  165. Result:=0;
  166. end;
  167. {****************************************************************************
  168. File Functions
  169. ****************************************************************************}
  170. Function WasiToWinAttr (const FN : RawByteString; fd: __wasi_fd_t; pr: PChar; pr_len: size_t; Const Info : __wasi_filestat_t) : Longint;
  171. Var
  172. LinkInfo : __wasi_filestat_t;
  173. nm : RawByteString;
  174. begin
  175. Result:=faArchive;
  176. if Info.filetype=__WASI_FILETYPE_DIRECTORY then
  177. Result:=Result or faDirectory;
  178. nm:=ExtractFileName(FN);
  179. If (Length(nm)>=2) and
  180. (nm[1]='.') and
  181. (nm[2]<>'.') then
  182. Result:=Result or faHidden;
  183. If (Info.filetype=__WASI_FILETYPE_BLOCK_DEVICE) or
  184. (Info.filetype=__WASI_FILETYPE_CHARACTER_DEVICE) or
  185. (Info.filetype=__WASI_FILETYPE_SOCKET_DGRAM) or
  186. (Info.filetype=__WASI_FILETYPE_SOCKET_STREAM) then
  187. Result:=Result or faSysFile;
  188. if Info.filetype=__WASI_FILETYPE_SYMBOLIC_LINK then
  189. begin
  190. Result:=Result or faSymLink;
  191. // Windows reports if the link points to a directory.
  192. if (__wasi_path_filestat_get(fd,__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW,pr,pr_len,@LinkInfo)=__WASI_ERRNO_SUCCESS) and
  193. (LinkInfo.filetype=__WASI_FILETYPE_DIRECTORY) then
  194. Result := Result or faDirectory;
  195. end;
  196. end;
  197. Function FileOpen (Const FileName : RawByteString; Mode : Integer) : THandle;
  198. Var
  199. fs_rights_base: __wasi_rights_t = 0;
  200. ourfd: __wasi_fd_t;
  201. res: __wasi_errno_t;
  202. pr: RawByteString;
  203. fd: __wasi_fd_t;
  204. Begin
  205. case (Mode and (fmOpenRead or fmOpenWrite or fmOpenReadWrite)) of
  206. fmOpenRead:
  207. fs_rights_base :=__WASI_RIGHTS_FD_READ or
  208. __WASI_RIGHTS_FD_FILESTAT_GET or
  209. __WASI_RIGHTS_FD_SEEK or
  210. __WASI_RIGHTS_FD_TELL or
  211. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  212. __WASI_RIGHTS_FD_ADVISE or
  213. __WASI_RIGHTS_POLL_FD_READWRITE;
  214. fmOpenWrite:
  215. fs_rights_base :=__WASI_RIGHTS_FD_WRITE or
  216. __WASI_RIGHTS_FD_FILESTAT_GET or
  217. __WASI_RIGHTS_FD_SEEK or
  218. __WASI_RIGHTS_FD_TELL or
  219. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  220. __WASI_RIGHTS_FD_ADVISE or
  221. __WASI_RIGHTS_POLL_FD_READWRITE or
  222. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  223. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  224. __WASI_RIGHTS_FD_ALLOCATE or
  225. __WASI_RIGHTS_FD_DATASYNC or
  226. __WASI_RIGHTS_FD_SYNC;
  227. fmOpenReadWrite:
  228. fs_rights_base :=__WASI_RIGHTS_FD_READ or
  229. __WASI_RIGHTS_FD_WRITE or
  230. __WASI_RIGHTS_FD_FILESTAT_GET or
  231. __WASI_RIGHTS_FD_SEEK or
  232. __WASI_RIGHTS_FD_TELL or
  233. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  234. __WASI_RIGHTS_FD_ADVISE or
  235. __WASI_RIGHTS_POLL_FD_READWRITE or
  236. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  237. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  238. __WASI_RIGHTS_FD_ALLOCATE or
  239. __WASI_RIGHTS_FD_DATASYNC or
  240. __WASI_RIGHTS_FD_SYNC;
  241. end;
  242. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  243. begin
  244. result:=-1;
  245. exit;
  246. end;
  247. repeat
  248. res:=__wasi_path_open(fd,
  249. 0,
  250. PChar(pr),
  251. length(pr),
  252. 0,
  253. fs_rights_base,
  254. fs_rights_base,
  255. 0,
  256. @ourfd);
  257. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  258. If res=__WASI_ERRNO_SUCCESS Then
  259. Result:=ourfd
  260. else
  261. Result:=-1;
  262. end;
  263. Function FileCreate (Const FileName : RawByteString) : THandle;
  264. Const
  265. fs_rights_base: __wasi_rights_t =
  266. __WASI_RIGHTS_FD_READ or
  267. __WASI_RIGHTS_FD_WRITE or
  268. __WASI_RIGHTS_FD_FILESTAT_GET or
  269. __WASI_RIGHTS_FD_SEEK or
  270. __WASI_RIGHTS_FD_TELL or
  271. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  272. __WASI_RIGHTS_FD_ADVISE or
  273. __WASI_RIGHTS_POLL_FD_READWRITE or
  274. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  275. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  276. __WASI_RIGHTS_FD_ALLOCATE or
  277. __WASI_RIGHTS_FD_DATASYNC or
  278. __WASI_RIGHTS_FD_SYNC;
  279. Var
  280. ourfd: __wasi_fd_t;
  281. res: __wasi_errno_t;
  282. pr: RawByteString;
  283. fd: __wasi_fd_t;
  284. Begin
  285. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  286. begin
  287. result:=-1;
  288. exit;
  289. end;
  290. repeat
  291. res:=__wasi_path_open(fd,
  292. 0,
  293. PChar(pr),
  294. length(pr),
  295. __WASI_OFLAGS_CREAT or __WASI_OFLAGS_TRUNC,
  296. fs_rights_base,
  297. fs_rights_base,
  298. 0,
  299. @ourfd);
  300. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  301. If res=__WASI_ERRNO_SUCCESS Then
  302. Result:=ourfd
  303. else
  304. Result:=-1;
  305. end;
  306. Function FileCreate (Const FileName : RawByteString; ShareMode:integer; Rights : integer) : THandle;
  307. begin
  308. FileCreate:=FileCreate(FileName);
  309. end;
  310. Function FileCreate (Const FileName : RawByteString; Rights:integer) : THandle;
  311. begin
  312. FileCreate:=FileCreate(FileName);
  313. end;
  314. Function FileRead (Handle : THandle; Out Buffer; Count : longint) : Longint;
  315. var
  316. our_iov: __wasi_iovec_t;
  317. our_nread: __wasi_size_t;
  318. res: __wasi_errno_t;
  319. begin
  320. repeat
  321. our_iov.buf:=@Buffer;
  322. our_iov.buf_len:=Count;
  323. res:=__wasi_fd_read(Handle,@our_iov,1,@our_nread);
  324. until (res=__WASI_ERRNO_SUCCESS) or ((res<>__WASI_ERRNO_INTR) and (res<>__WASI_ERRNO_AGAIN));
  325. if res=__WASI_ERRNO_SUCCESS then
  326. Result:=our_nread
  327. else
  328. Result:=-1;
  329. end;
  330. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
  331. var
  332. our_iov: __wasi_ciovec_t;
  333. our_nwritten: longint;
  334. res: __wasi_errno_t;
  335. begin
  336. repeat
  337. our_iov.buf:=@Buffer;
  338. our_iov.buf_len:=Count;
  339. res:=__wasi_fd_write(Handle,@our_iov,1,@our_nwritten);
  340. until (res=__WASI_ERRNO_SUCCESS) or ((res<>__WASI_ERRNO_INTR) and (res<>__WASI_ERRNO_AGAIN));
  341. if res=__WASI_ERRNO_SUCCESS then
  342. Result:=our_nwritten
  343. else
  344. Result:=-1;
  345. end;
  346. Function FileSeek (Handle : THandle; FOffset, Origin : Longint) : Longint;
  347. begin
  348. result:=longint(FileSeek(Handle,int64(FOffset),Origin));
  349. end;
  350. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  351. var
  352. res: __wasi_errno_t;
  353. newoffset: __wasi_filesize_t;
  354. whence: __wasi_whence_t;
  355. begin
  356. case Origin of
  357. fsFromBeginning:
  358. whence:=__WASI_WHENCE_SET;
  359. fsFromCurrent:
  360. whence:=__WASI_WHENCE_CUR;
  361. fsFromEnd:
  362. whence:=__WASI_WHENCE_END;
  363. else
  364. begin
  365. Result:=-1;
  366. exit;
  367. end;
  368. end;
  369. res:=__wasi_fd_seek(Handle,FOffset,whence,@newoffset);
  370. if res=__WASI_ERRNO_SUCCESS then
  371. Result:=newoffset
  372. else
  373. Result:=-1;
  374. end;
  375. Procedure FileClose (Handle : THandle);
  376. var
  377. res: __wasi_errno_t;
  378. begin
  379. repeat
  380. res:=__wasi_fd_close(Handle);
  381. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  382. end;
  383. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  384. var
  385. res: __wasi_errno_t;
  386. begin
  387. Result:=__wasi_fd_filestat_set_size(handle,Size)=__WASI_ERRNO_SUCCESS;
  388. end;
  389. Function FileAge (Const FileName : RawByteString): Int64;
  390. var
  391. res: __wasi_errno_t;
  392. pr: RawByteString;
  393. fd: __wasi_fd_t;
  394. Info: __wasi_filestat_t;
  395. begin
  396. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  397. begin
  398. result:=-1;
  399. exit;
  400. end;
  401. res:=__wasi_path_filestat_get(fd,0,PChar(pr),length(pr),@Info);
  402. if res=__WASI_ERRNO_SUCCESS then
  403. result:=Info.mtim div 1000000000
  404. else
  405. result:=-1;
  406. end;
  407. function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
  408. var
  409. pr: RawByteString;
  410. fd: __wasi_fd_t;
  411. Info: __wasi_filestat_t;
  412. symlink: RawByteString;
  413. res: __wasi_errno_t;
  414. begin
  415. FillChar(SymLinkRec, SizeOf(SymLinkRec), 0);
  416. result:=false;
  417. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  418. exit;
  419. if __wasi_path_filestat_get(fd,0,PChar(pr),length(pr),@Info)<>__WASI_ERRNO_SUCCESS then
  420. exit;
  421. if Info.filetype<>__WASI_FILETYPE_SYMBOLIC_LINK then
  422. exit;
  423. if fpc_wasi_path_readlink_ansistring(fd,PChar(pr),Length(pr),symlink)<>__WASI_ERRNO_SUCCESS then
  424. exit;
  425. SymLinkRec.TargetName:=symlink;
  426. res:=__wasi_path_filestat_get(fd,__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW,PChar(pr),length(pr),@Info);
  427. if res<>__WASI_ERRNO_SUCCESS then
  428. raise EDirectoryNotFoundException.Create('Error ' + IntToStr(res){todo: SysErrorMessage SysErrorMessage(GetLastOSError)});
  429. SymLinkRec.Attr := WasiToWinAttr(FileName,fd,PChar(pr),length(pr),Info);
  430. SymLinkRec.Size := Info.size;
  431. result:=true;
  432. end;
  433. function FileExists (const FileName: RawByteString; FollowLink : Boolean): boolean;
  434. var
  435. pr: RawByteString;
  436. fd: __wasi_fd_t;
  437. Info: __wasi_filestat_t;
  438. flags: __wasi_lookupflags_t;
  439. begin
  440. if FileName='' then
  441. exit(false);
  442. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  443. exit(false);
  444. if FollowLink then
  445. flags:=__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW
  446. else
  447. flags:=0;
  448. if __wasi_path_filestat_get(fd,flags,PChar(pr),length(pr),@Info)=__WASI_ERRNO_SUCCESS then
  449. result:=Info.filetype<>__WASI_FILETYPE_DIRECTORY
  450. else
  451. result:=false;
  452. end;
  453. Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean;
  454. var
  455. pr: RawByteString;
  456. fd: __wasi_fd_t;
  457. Info: __wasi_filestat_t;
  458. flags: __wasi_lookupflags_t;
  459. begin
  460. if Directory='' then
  461. exit(false);
  462. if ConvertToFdRelativePath(Directory,fd,pr)<>0 then
  463. exit(false);
  464. if FollowLink then
  465. flags:=__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW
  466. else
  467. flags:=0;
  468. if __wasi_path_filestat_get(fd,flags,PChar(pr),length(pr),@Info)=__WASI_ERRNO_SUCCESS then
  469. result:=Info.filetype=__WASI_FILETYPE_DIRECTORY
  470. else
  471. result:=false;
  472. end;
  473. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  474. var
  475. derror: longint;
  476. begin
  477. Result:=-1;
  478. { this is safe even though Rslt actually contains a refcounted field, because
  479. it is declared as "out" and hence has already been initialised }
  480. fillchar(Rslt,sizeof(Rslt),0);
  481. if Path='' then
  482. exit;
  483. derror:=WasiFindFirst(Path, Attr, Rslt.FindData);
  484. if derror=0 then
  485. result:=0
  486. else
  487. result:=-1;
  488. Name:=Rslt.FindData.Name;
  489. Rslt.Attr:=Rslt.FindData.Attr;
  490. Rslt.Size:=Rslt.FindData.Size;
  491. Rslt.Time:=Rslt.FindData.Time div 1000000000;
  492. end;
  493. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  494. var
  495. derror: longint;
  496. begin
  497. derror:=WasiFindNext(Rslt.FindData);
  498. if derror=0 then
  499. result:=0
  500. else
  501. result:=-1;
  502. Name:=Rslt.FindData.Name;
  503. Rslt.Attr:=Rslt.FindData.Attr;
  504. Rslt.Size:=Rslt.FindData.Size;
  505. Rslt.Time:=Rslt.FindData.Time div 1000000000;
  506. end;
  507. Procedure InternalFindClose(var Handle: THandle; var FindData: TFindData);
  508. begin
  509. WasiFindClose(FindData);
  510. end;
  511. Function FileGetDate (Handle : THandle) : Int64;
  512. var
  513. res: __wasi_errno_t;
  514. Info: __wasi_filestat_t;
  515. begin
  516. res:=__wasi_fd_filestat_get(Handle,@Info);
  517. if res=__WASI_ERRNO_SUCCESS then
  518. result:=Info.mtim div 1000000000
  519. else
  520. result:=-1;
  521. end;
  522. Function FileSetDate (Handle : THandle; Age : Int64) : Longint;
  523. begin
  524. if __wasi_fd_filestat_set_times(Handle,Age*1000000000,Age*1000000000,
  525. __WASI_FSTFLAGS_MTIM or __WASI_FSTFLAGS_ATIM)=__WASI_ERRNO_SUCCESS then
  526. result:=0
  527. else
  528. result:=-1;
  529. end;
  530. Function FileSetDate (Const FileName : RawByteString; Age : Int64) : Longint;
  531. var
  532. pr: RawByteString;
  533. fd: __wasi_fd_t;
  534. begin
  535. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  536. begin
  537. result:=-1;
  538. exit;
  539. end;
  540. if __wasi_path_filestat_set_times(fd,0,PChar(pr),length(pr),Age*1000000000,Age*1000000000,
  541. __WASI_FSTFLAGS_MTIM or __WASI_FSTFLAGS_ATIM)=__WASI_ERRNO_SUCCESS then
  542. result:=0
  543. else
  544. result:=-1;
  545. end;
  546. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  547. var
  548. pr: RawByteString;
  549. fd: __wasi_fd_t;
  550. Info: __wasi_filestat_t;
  551. begin
  552. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  553. begin
  554. result:=-1;
  555. exit;
  556. end;
  557. if __wasi_path_filestat_get(fd,0,PChar(pr),length(pr),@Info)=__WASI_ERRNO_SUCCESS then
  558. result:=WasiToWinAttr(FileName,fd,PChar(pr),length(pr),Info)
  559. else
  560. result:=-1;
  561. end;
  562. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  563. begin
  564. Result:=-1;
  565. end;
  566. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  567. var
  568. fd: __wasi_fd_t;
  569. pr: RawByteString;
  570. res: __wasi_errno_t;
  571. begin
  572. if ConvertToFdRelativePath(FileName,fd,pr)<>0 then
  573. begin
  574. result:=false;
  575. exit;
  576. end;
  577. result:=__wasi_path_unlink_file(fd,PChar(pr),Length(pr))=__WASI_ERRNO_SUCCESS;
  578. end;
  579. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  580. var
  581. fd1,fd2: __wasi_fd_t;
  582. pr1,pr2: RawByteString;
  583. res: __wasi_errno_t;
  584. begin
  585. result:=false;
  586. if ConvertToFdRelativePath(OldName,fd1,pr1)<>0 then
  587. exit;
  588. if ConvertToFdRelativePath(NewName,fd2,pr2)<>0 then
  589. exit;
  590. result:=__wasi_path_rename(fd1,PChar(pr1),Length(pr1),fd2,PChar(pr2),Length(pr2))=__WASI_ERRNO_SUCCESS;
  591. end;
  592. {****************************************************************************
  593. Disk Functions
  594. ****************************************************************************}
  595. function diskfree(drive : byte) : int64;
  596. begin
  597. end;
  598. function disksize(drive : byte) : int64;
  599. begin
  600. end;
  601. {****************************************************************************
  602. Time Functions
  603. ****************************************************************************}
  604. {$I tzenv.inc}
  605. Procedure GetLocalTime(var SystemTime: TSystemTime);
  606. var
  607. NanoSecsPast: __wasi_timestamp_t;
  608. begin
  609. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  610. begin
  611. EpochToLocal(NanoSecsPast div 1000000000,
  612. SystemTime.Year,SystemTime.Month,SystemTime.Day,
  613. SystemTime.Hour,SystemTime.Minute,SystemTime.Second);
  614. SystemTime.MilliSecond := (NanoSecsPast div 1000000) mod 1000;
  615. SystemTime.DayOfWeek := DayOfWeek(EncodeDate(SystemTime.Year,SystemTime.Month,SystemTime.Day))-1;
  616. end
  617. else
  618. FillChar(SystemTime,SizeOf(SystemTime),0);
  619. end;
  620. {****************************************************************************
  621. Misc Functions
  622. ****************************************************************************}
  623. procedure sysBeep;
  624. begin
  625. end;
  626. {****************************************************************************
  627. Locale Functions
  628. ****************************************************************************}
  629. procedure InitAnsi;
  630. Var
  631. i : longint;
  632. begin
  633. { Fill table entries 0 to 127 }
  634. for i := 0 to 96 do
  635. UpperCaseTable[i] := chr(i);
  636. for i := 97 to 122 do
  637. UpperCaseTable[i] := chr(i - 32);
  638. for i := 123 to 191 do
  639. UpperCaseTable[i] := chr(i);
  640. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  641. for i := 0 to 64 do
  642. LowerCaseTable[i] := chr(i);
  643. for i := 65 to 90 do
  644. LowerCaseTable[i] := chr(i + 32);
  645. for i := 91 to 191 do
  646. LowerCaseTable[i] := chr(i);
  647. Move (CPISO88591LCT,LowerCaseTable[192],SizeOf(CPISO88591UCT));
  648. end;
  649. Procedure InitInternational;
  650. begin
  651. InitInternationalGeneric;
  652. InitAnsi;
  653. end;
  654. function SysErrorMessage(ErrorCode: Integer): String;
  655. begin
  656. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  657. end;
  658. {****************************************************************************
  659. Os utils
  660. ****************************************************************************}
  661. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  662. var
  663. hp : ppchar;
  664. hs : string;
  665. eqpos : longint;
  666. begin
  667. result:='';
  668. hp:=envp;
  669. if hp<>nil then
  670. while assigned(hp^) do
  671. begin
  672. hs:=strpas(hp^);
  673. eqpos:=pos('=',hs);
  674. if copy(hs,1,eqpos-1)=envvar then
  675. begin
  676. result:=copy(hs,eqpos+1,length(hs)-eqpos);
  677. break;
  678. end;
  679. inc(hp);
  680. end;
  681. end;
  682. Function GetEnvironmentVariableCount : Integer;
  683. var
  684. p: ppchar;
  685. begin
  686. result:=0;
  687. p:=envp; {defined in system}
  688. if p<>nil then
  689. while p^<>nil do
  690. begin
  691. inc(result);
  692. inc(p);
  693. end;
  694. end;
  695. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  696. Var
  697. i : longint;
  698. p : ppchar;
  699. begin
  700. if (Index <= 0) or (envp=nil) then
  701. result:=''
  702. else
  703. begin
  704. p:=envp; {defined in system}
  705. i:=1;
  706. while (i<Index) and (p^<>nil) do
  707. begin
  708. inc(i);
  709. inc(p);
  710. end;
  711. if p^=nil then
  712. result:=''
  713. else
  714. result:=strpas(p^)
  715. end;
  716. end;
  717. function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
  718. begin
  719. end;
  720. function ExecuteProcess (const Path: RawByteString;
  721. const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;
  722. begin
  723. end;
  724. {*************************************************************************
  725. Sleep
  726. *************************************************************************}
  727. procedure Sleep (MilliSeconds: Cardinal);
  728. var
  729. subscription: __wasi_subscription_t;
  730. event: __wasi_event_t;
  731. nevents: __wasi_size_t;
  732. begin
  733. FillChar(subscription,SizeOf(subscription),0);
  734. subscription.u.tag:=__WASI_EVENTTYPE_CLOCK;
  735. subscription.u.u.clock.id:=__WASI_CLOCKID_MONOTONIC;
  736. subscription.u.u.clock.timeout:=MilliSeconds*1000000;
  737. subscription.u.u.clock.precision:=1000000;
  738. subscription.u.u.clock.flags:=0; { timeout value is relative }
  739. __wasi_poll_oneoff(@subscription,@event,1,@nevents);
  740. end;
  741. {****************************************************************************
  742. Initialization code
  743. ****************************************************************************}
  744. Initialization
  745. InitExceptions; { Initialize exceptions. OS independent }
  746. InitInternational; { Initialize internationalization settings }
  747. OnBeep:=@SysBeep;
  748. InitTZ;
  749. Finalization
  750. FreeTerminateProcs;
  751. DoneExceptions;
  752. end.