sysutils.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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;
  22. {$DEFINE HAS_SLEEP}
  23. {$DEFINE HAS_GETTICKCOUNT64}
  24. { used OS file system APIs use ansistring }
  25. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  26. { OS has an ansistring/single byte environment variable API }
  27. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  28. { Include platform independent interface part }
  29. {$i sysutilh.inc}
  30. implementation
  31. uses
  32. sysconst;
  33. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  34. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  35. {$DEFINE HAS_LOCALTIMEZONEOFFSET}
  36. {$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *)
  37. Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64;
  38. const
  39. days_in_month: array [boolean, 1..12] of Byte =
  40. ((31,28,31,30,31,30,31,31,30,31,30,31),
  41. (31,29,31,30,31,30,31,31,30,31,30,31));
  42. days_before_month: array [boolean, 1..12] of Byte =
  43. ((0,
  44. 0+31,
  45. 0+31+28,
  46. 0+31+28+31,
  47. 0+31+28+31+30,
  48. 0+31+28+31+30+31,
  49. 0+31+28+31+30+31+30,
  50. 0+31+28+31+30+31+30+31,
  51. 0+31+28+31+30+31+30+31+31,
  52. 0+31+28+31+30+31+30+31+31+30,
  53. 0+31+28+31+30+31+30+31+31+30+31,
  54. 0+31+28+31+30+31+30+31+31+30+31+30),
  55. (0,
  56. 0+31,
  57. 0+31+29,
  58. 0+31+29+31,
  59. 0+31+29+31+30,
  60. 0+31+29+31+30+31,
  61. 0+31+29+31+30+31+30,
  62. 0+31+29+31+30+31+30+31,
  63. 0+31+29+31+30+31+30+31+31,
  64. 0+31+29+31+30+31+30+31+31+30,
  65. 0+31+29+31+30+31+30+31+31+30+31,
  66. 0+31+29+31+30+31+30+31+31+30+31+30));
  67. var
  68. leap: Boolean;
  69. days_in_year: LongInt;
  70. y,m: LongInt;
  71. begin
  72. if (year<1970) or (month<1) or (month>12) or (day<1) or (day>31) or
  73. (hour>=24) or (minute>=60) or (second>=60) then
  74. begin
  75. result:=-1;
  76. exit;
  77. end;
  78. leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
  79. if day>days_in_month[leap,month] then
  80. begin
  81. result:=-1;
  82. exit;
  83. end;
  84. result:=0;
  85. for y:=1970 to year-1 do
  86. if ((y mod 4)=0) and (((y mod 100)<>0) or ((y mod 400)=0)) then
  87. Inc(result,366)
  88. else
  89. Inc(result,365);
  90. Inc(result,days_before_month[leap,month]);
  91. Inc(result,day-1);
  92. result:=(((result*24+hour)*60+minute)*60)+second;
  93. end;
  94. Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64;
  95. begin
  96. { todo: convert UTC to local time, as soon as we can get the local timezone
  97. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  98. result:=UniversalToEpoch(year,month,day,hour,minute,second);
  99. end;
  100. Procedure EpochToUniversal(epoch:int64;var year,month,day,hour,minute,second:Word);
  101. const
  102. days_in_month: array [boolean, 1..12] of Byte =
  103. ((31,28,31,30,31,30,31,31,30,31,30,31),
  104. (31,29,31,30,31,30,31,31,30,31,30,31));
  105. var
  106. leap: Boolean;
  107. days_in_year: LongInt;
  108. begin
  109. if epoch<0 then
  110. begin
  111. year:=0;
  112. month:=0;
  113. day:=0;
  114. hour:=0;
  115. minute:=0;
  116. second:=0;
  117. exit;
  118. end;
  119. second:=epoch mod 60;
  120. epoch:=epoch div 60;
  121. minute:=epoch mod 60;
  122. epoch:=epoch div 60;
  123. hour:=epoch mod 24;
  124. epoch:=epoch div 24;
  125. year:=1970;
  126. leap:=false;
  127. days_in_year:=365;
  128. while epoch>=days_in_year do
  129. begin
  130. Dec(epoch,days_in_year);
  131. Inc(year);
  132. leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
  133. if leap then
  134. days_in_year:=366
  135. else
  136. days_in_year:=365;
  137. end;
  138. month:=1;
  139. Inc(epoch);
  140. while epoch>days_in_month[leap,month] do
  141. begin
  142. Dec(epoch,days_in_month[leap,month]);
  143. Inc(month);
  144. end;
  145. day:=Word(epoch);
  146. end;
  147. Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word);
  148. begin
  149. { todo: convert UTC to local time, as soon as we can get the local timezone
  150. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  151. EpochToUniversal(epoch,year,month,day,hour,minute,second);
  152. end;
  153. { Include platform independent implementation part }
  154. {$i sysutils.inc}
  155. function GetTickCount64: QWord;
  156. var
  157. NanoSecsPast: __wasi_timestamp_t;
  158. begin
  159. if __wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  160. Result:=NanoSecsPast div 1000000
  161. else
  162. Result:=0;
  163. end;
  164. {****************************************************************************
  165. File Functions
  166. ****************************************************************************}
  167. Function FileOpen (Const FileName : RawByteString; Mode : Integer) : THandle;
  168. Var
  169. fs_rights_base: __wasi_rights_t = 0;
  170. ourfd: __wasi_fd_t;
  171. res: __wasi_errno_t;
  172. pr: RawByteString;
  173. fd: __wasi_fd_t;
  174. Begin
  175. case (Mode and (fmOpenRead or fmOpenWrite or fmOpenReadWrite)) of
  176. fmOpenRead:
  177. fs_rights_base :=__WASI_RIGHTS_FD_READ or
  178. __WASI_RIGHTS_FD_FILESTAT_GET or
  179. __WASI_RIGHTS_FD_SEEK or
  180. __WASI_RIGHTS_FD_TELL or
  181. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  182. __WASI_RIGHTS_FD_ADVISE or
  183. __WASI_RIGHTS_POLL_FD_READWRITE;
  184. fmOpenWrite:
  185. fs_rights_base :=__WASI_RIGHTS_FD_WRITE or
  186. __WASI_RIGHTS_FD_FILESTAT_GET or
  187. __WASI_RIGHTS_FD_SEEK or
  188. __WASI_RIGHTS_FD_TELL or
  189. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  190. __WASI_RIGHTS_FD_ADVISE or
  191. __WASI_RIGHTS_POLL_FD_READWRITE or
  192. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  193. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  194. __WASI_RIGHTS_FD_ALLOCATE or
  195. __WASI_RIGHTS_FD_DATASYNC or
  196. __WASI_RIGHTS_FD_SYNC;
  197. fmOpenReadWrite:
  198. fs_rights_base :=__WASI_RIGHTS_FD_READ or
  199. __WASI_RIGHTS_FD_WRITE or
  200. __WASI_RIGHTS_FD_FILESTAT_GET or
  201. __WASI_RIGHTS_FD_SEEK or
  202. __WASI_RIGHTS_FD_TELL or
  203. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  204. __WASI_RIGHTS_FD_ADVISE or
  205. __WASI_RIGHTS_POLL_FD_READWRITE or
  206. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  207. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  208. __WASI_RIGHTS_FD_ALLOCATE or
  209. __WASI_RIGHTS_FD_DATASYNC or
  210. __WASI_RIGHTS_FD_SYNC;
  211. end;
  212. if not ConvertToFdRelativePath(FileName,fd,pr) then
  213. begin
  214. result:=-1;
  215. exit;
  216. end;
  217. repeat
  218. res:=__wasi_path_open(fd,
  219. 0,
  220. PChar(pr),
  221. length(pr),
  222. 0,
  223. fs_rights_base,
  224. fs_rights_base,
  225. 0,
  226. @ourfd);
  227. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  228. If res=__WASI_ERRNO_SUCCESS Then
  229. Result:=ourfd
  230. else
  231. Result:=-1;
  232. end;
  233. Function FileCreate (Const FileName : RawByteString) : THandle;
  234. Const
  235. fs_rights_base: __wasi_rights_t =
  236. __WASI_RIGHTS_FD_READ or
  237. __WASI_RIGHTS_FD_WRITE or
  238. __WASI_RIGHTS_FD_FILESTAT_GET or
  239. __WASI_RIGHTS_FD_SEEK or
  240. __WASI_RIGHTS_FD_TELL or
  241. __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS or
  242. __WASI_RIGHTS_FD_ADVISE or
  243. __WASI_RIGHTS_POLL_FD_READWRITE or
  244. __WASI_RIGHTS_FD_FILESTAT_SET_SIZE or
  245. __WASI_RIGHTS_FD_FILESTAT_SET_TIMES or
  246. __WASI_RIGHTS_FD_ALLOCATE or
  247. __WASI_RIGHTS_FD_DATASYNC or
  248. __WASI_RIGHTS_FD_SYNC;
  249. Var
  250. ourfd: __wasi_fd_t;
  251. res: __wasi_errno_t;
  252. pr: RawByteString;
  253. fd: __wasi_fd_t;
  254. Begin
  255. if not ConvertToFdRelativePath(FileName,fd,pr) then
  256. begin
  257. result:=-1;
  258. exit;
  259. end;
  260. repeat
  261. res:=__wasi_path_open(fd,
  262. 0,
  263. PChar(pr),
  264. length(pr),
  265. __WASI_OFLAGS_CREAT or __WASI_OFLAGS_TRUNC,
  266. fs_rights_base,
  267. fs_rights_base,
  268. 0,
  269. @ourfd);
  270. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  271. If res=__WASI_ERRNO_SUCCESS Then
  272. Result:=ourfd
  273. else
  274. Result:=-1;
  275. end;
  276. Function FileCreate (Const FileName : RawByteString; ShareMode:integer; Rights : integer) : THandle;
  277. begin
  278. FileCreate:=FileCreate(FileName);
  279. end;
  280. Function FileCreate (Const FileName : RawByteString; Rights:integer) : THandle;
  281. begin
  282. FileCreate:=FileCreate(FileName);
  283. end;
  284. Function FileRead (Handle : THandle; Out Buffer; Count : longint) : Longint;
  285. var
  286. our_iov: __wasi_iovec_t;
  287. our_nread: __wasi_size_t;
  288. res: __wasi_errno_t;
  289. begin
  290. repeat
  291. our_iov.buf:=@Buffer;
  292. our_iov.buf_len:=Count;
  293. res:=__wasi_fd_read(Handle,@our_iov,1,@our_nread);
  294. until (res=__WASI_ERRNO_SUCCESS) or ((res<>__WASI_ERRNO_INTR) and (res<>__WASI_ERRNO_AGAIN));
  295. if res=__WASI_ERRNO_SUCCESS then
  296. Result:=our_nread
  297. else
  298. Result:=-1;
  299. end;
  300. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
  301. var
  302. our_iov: __wasi_ciovec_t;
  303. our_nwritten: longint;
  304. res: __wasi_errno_t;
  305. begin
  306. repeat
  307. our_iov.buf:=@Buffer;
  308. our_iov.buf_len:=Count;
  309. res:=__wasi_fd_write(Handle,@our_iov,1,@our_nwritten);
  310. until (res=__WASI_ERRNO_SUCCESS) or ((res<>__WASI_ERRNO_INTR) and (res<>__WASI_ERRNO_AGAIN));
  311. if res=__WASI_ERRNO_SUCCESS then
  312. Result:=our_nwritten
  313. else
  314. Result:=-1;
  315. end;
  316. Function FileSeek (Handle : THandle; FOffset, Origin : Longint) : Longint;
  317. begin
  318. result:=longint(FileSeek(Handle,int64(FOffset),Origin));
  319. end;
  320. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  321. var
  322. res: __wasi_errno_t;
  323. newoffset: __wasi_filesize_t;
  324. whence: __wasi_whence_t;
  325. begin
  326. case Origin of
  327. fsFromBeginning:
  328. whence:=__WASI_WHENCE_SET;
  329. fsFromCurrent:
  330. whence:=__WASI_WHENCE_CUR;
  331. fsFromEnd:
  332. whence:=__WASI_WHENCE_END;
  333. else
  334. begin
  335. Result:=-1;
  336. exit;
  337. end;
  338. end;
  339. res:=__wasi_fd_seek(Handle,FOffset,whence,@newoffset);
  340. if res=__WASI_ERRNO_SUCCESS then
  341. Result:=newoffset
  342. else
  343. Result:=-1;
  344. end;
  345. Procedure FileClose (Handle : THandle);
  346. var
  347. res: __wasi_errno_t;
  348. begin
  349. repeat
  350. res:=__wasi_fd_close(Handle);
  351. until (res=__WASI_ERRNO_SUCCESS) or (res<>__WASI_ERRNO_INTR);
  352. end;
  353. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  354. var
  355. res: __wasi_errno_t;
  356. begin
  357. Result:=__wasi_fd_filestat_set_size(handle,Size)=__WASI_ERRNO_SUCCESS;
  358. end;
  359. Function FileAge (Const FileName : RawByteString): Int64;
  360. begin
  361. end;
  362. function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
  363. begin
  364. Result := False;
  365. end;
  366. function FileExists (const FileName: RawByteString; FollowLink : Boolean): boolean;
  367. begin
  368. end;
  369. Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean;
  370. begin
  371. end;
  372. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  373. begin
  374. { not yet implemented }
  375. Result := -1;
  376. end;
  377. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  378. begin
  379. { not yet implemented }
  380. Result := -1;
  381. end;
  382. Procedure InternalFindClose(var Handle: THandle);
  383. begin
  384. end;
  385. Function FileGetDate (Handle : THandle) : Int64;
  386. var
  387. res: __wasi_errno_t;
  388. Info: __wasi_filestat_t;
  389. begin
  390. res:=__wasi_fd_filestat_get(Handle,@Info);
  391. if res=__WASI_ERRNO_SUCCESS then
  392. result:=Info.mtim div 1000000000
  393. else
  394. result:=-1;
  395. end;
  396. Function FileSetDate (Handle : THandle; Age : Int64) : Longint;
  397. begin
  398. end;
  399. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  400. begin
  401. end;
  402. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  403. begin
  404. end;
  405. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  406. var
  407. fd: __wasi_fd_t;
  408. pr: RawByteString;
  409. res: __wasi_errno_t;
  410. begin
  411. if not ConvertToFdRelativePath(FileName,fd,pr) then
  412. begin
  413. result:=false;
  414. exit;
  415. end;
  416. result:=__wasi_path_unlink_file(fd,PChar(pr),Length(pr))=__WASI_ERRNO_SUCCESS;
  417. end;
  418. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  419. var
  420. fd1,fd2: __wasi_fd_t;
  421. pr1,pr2: RawByteString;
  422. res: __wasi_errno_t;
  423. begin
  424. result:=false;
  425. if not ConvertToFdRelativePath(OldName,fd1,pr1) then
  426. exit;
  427. if not ConvertToFdRelativePath(NewName,fd2,pr2) then
  428. exit;
  429. result:=__wasi_path_rename(fd1,PChar(pr1),Length(pr1),fd2,PChar(pr2),Length(pr2))=__WASI_ERRNO_SUCCESS;
  430. end;
  431. {****************************************************************************
  432. Disk Functions
  433. ****************************************************************************}
  434. function diskfree(drive : byte) : int64;
  435. begin
  436. end;
  437. function disksize(drive : byte) : int64;
  438. begin
  439. end;
  440. {****************************************************************************
  441. Time Functions
  442. ****************************************************************************}
  443. {$I tzenv.inc}
  444. Procedure GetLocalTime(var SystemTime: TSystemTime);
  445. begin
  446. end ;
  447. {****************************************************************************
  448. Misc Functions
  449. ****************************************************************************}
  450. procedure sysBeep;
  451. begin
  452. end;
  453. {****************************************************************************
  454. Locale Functions
  455. ****************************************************************************}
  456. procedure InitAnsi;
  457. begin
  458. end;
  459. Procedure InitInternational;
  460. begin
  461. InitInternationalGeneric;
  462. InitAnsi;
  463. end;
  464. function SysErrorMessage(ErrorCode: Integer): String;
  465. begin
  466. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  467. end;
  468. {****************************************************************************
  469. Os utils
  470. ****************************************************************************}
  471. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  472. var
  473. hp : ppchar;
  474. hs : string;
  475. eqpos : longint;
  476. begin
  477. result:='';
  478. hp:=envp;
  479. if hp<>nil then
  480. while assigned(hp^) do
  481. begin
  482. hs:=strpas(hp^);
  483. eqpos:=pos('=',hs);
  484. if copy(hs,1,eqpos-1)=envvar then
  485. begin
  486. result:=copy(hs,eqpos+1,length(hs)-eqpos);
  487. break;
  488. end;
  489. inc(hp);
  490. end;
  491. end;
  492. Function GetEnvironmentVariableCount : Integer;
  493. var
  494. p: ppchar;
  495. begin
  496. result:=0;
  497. p:=envp; {defined in system}
  498. if p<>nil then
  499. while p^<>nil do
  500. begin
  501. inc(result);
  502. inc(p);
  503. end;
  504. end;
  505. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  506. Var
  507. i : longint;
  508. p : ppchar;
  509. begin
  510. if (Index <= 0) or (envp=nil) then
  511. result:=''
  512. else
  513. begin
  514. p:=envp; {defined in system}
  515. i:=1;
  516. while (i<Index) and (p^<>nil) do
  517. begin
  518. inc(i);
  519. inc(p);
  520. end;
  521. if p^=nil then
  522. result:=''
  523. else
  524. result:=strpas(p^)
  525. end;
  526. end;
  527. function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
  528. begin
  529. end;
  530. function ExecuteProcess (const Path: RawByteString;
  531. const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;
  532. begin
  533. end;
  534. {*************************************************************************
  535. Sleep
  536. *************************************************************************}
  537. procedure Sleep (MilliSeconds: Cardinal);
  538. var
  539. subscription: __wasi_subscription_t;
  540. event: __wasi_event_t;
  541. nevents: __wasi_size_t;
  542. begin
  543. FillChar(subscription,SizeOf(subscription),0);
  544. subscription.u.tag:=__WASI_EVENTTYPE_CLOCK;
  545. subscription.u.u.clock.id:=__WASI_CLOCKID_MONOTONIC;
  546. subscription.u.u.clock.timeout:=MilliSeconds*1000000;
  547. subscription.u.u.clock.precision:=1000000;
  548. subscription.u.u.clock.flags:=0; { timeout value is relative }
  549. __wasi_poll_oneoff(@subscription,@event,1,@nevents);
  550. end;
  551. {****************************************************************************
  552. Initialization code
  553. ****************************************************************************}
  554. Initialization
  555. InitExceptions; { Initialize exceptions. OS independent }
  556. InitInternational; { Initialize internationalization settings }
  557. OnBeep:=@SysBeep;
  558. InitTZ;
  559. Finalization
  560. FreeTerminateProcs;
  561. DoneExceptions;
  562. end.