dos.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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 DTToWasiDate(DT: DateTime): UInt64; platform;
  44. {Disk}
  45. //Function AddDisk(const path:string) : byte; platform;
  46. Implementation
  47. Uses
  48. WasiAPI, WasiUtil;
  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. {******************************************************************************
  57. --- Info / Date / Time ---
  58. ******************************************************************************}
  59. Function DosVersion:Word;
  60. Begin
  61. End;
  62. function WeekDay (y,m,d:longint):longint;
  63. {
  64. Calculates th day of the week. returns -1 on error
  65. }
  66. var
  67. u,v : longint;
  68. begin
  69. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  70. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  71. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  72. WeekDay:=-1
  73. else
  74. begin
  75. u:=m;
  76. v:=y;
  77. if m<3 then
  78. begin
  79. inc(u,12);
  80. dec(v);
  81. end;
  82. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  83. end;
  84. end;
  85. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  86. var
  87. NanoSecsPast: __wasi_timestamp_t;
  88. DT: DateTime;
  89. begin
  90. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  91. begin
  92. WasiDateToDT(NanoSecsPast,DT);
  93. Year:=DT.Year;
  94. Month:=DT.Month;
  95. MDay:=DT.Day;
  96. WDay:=weekday(DT.Year,DT.Month,DT.Day);
  97. end
  98. else
  99. begin
  100. Year:=0;
  101. Month:=0;
  102. MDay:=0;
  103. WDay:=0;
  104. end;
  105. end;
  106. procedure SetTime(Hour,Minute,Second,sec100:word);
  107. begin
  108. end;
  109. procedure SetDate(Year,Month,Day:Word);
  110. begin
  111. end;
  112. Function SetDateTime(Year,Month,Day,hour,minute,second:Word) : Boolean;
  113. begin
  114. end;
  115. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  116. var
  117. NanoSecsPast: __wasi_timestamp_t;
  118. begin
  119. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  120. begin
  121. { todo: convert UTC to local time, as soon as we can get the local timezone
  122. from WASI: https://github.com/WebAssembly/WASI/issues/239 }
  123. NanoSecsPast:=NanoSecsPast div 10000000;
  124. Sec100:=NanoSecsPast mod 100;
  125. NanoSecsPast:=NanoSecsPast div 100;
  126. Second:=NanoSecsPast mod 60;
  127. NanoSecsPast:=NanoSecsPast div 60;
  128. Minute:=NanoSecsPast mod 60;
  129. NanoSecsPast:=NanoSecsPast div 60;
  130. Hour:=NanoSecsPast mod 24;
  131. end
  132. else
  133. begin
  134. Hour:=0;
  135. Minute:=0;
  136. Second:=0;
  137. Sec100:=0;
  138. end;
  139. end;
  140. Function DTToWasiDate(DT: DateTime): UInt64;
  141. var
  142. res: Int64;
  143. begin
  144. res:=WasiUtil.LocalToEpoch(DT.year,DT.month,DT.day,DT.hour,DT.min,DT.sec);
  145. if res<0 then
  146. DTToWasiDate:=0
  147. else
  148. DTToWasiDate:=res*1000000000;
  149. end;
  150. Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime);
  151. Begin
  152. WasiUtil.EpochToLocal(NanoSecsPast div 1000000000,Dt.Year,Dt.Month,Dt.Day,Dt.Hour,Dt.Min,Dt.Sec);
  153. End;
  154. function GetMsCount: int64;
  155. var
  156. NanoSecsPast: __wasi_timestamp_t;
  157. begin
  158. if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
  159. GetMsCount:=NanoSecsPast div 1000000
  160. else
  161. GetMsCount:=0;
  162. end;
  163. {******************************************************************************
  164. --- Exec ---
  165. ******************************************************************************}
  166. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  167. Begin
  168. End;
  169. {******************************************************************************
  170. --- Disk ---
  171. ******************************************************************************}
  172. {
  173. The Diskfree and Disksize functions need a file on the specified drive, since this
  174. is required for the fpstatfs system call.
  175. These filenames are set in drivestr[0..26], and have been preset to :
  176. 0 - '.' (default drive - hence current dir is ok.)
  177. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  178. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  179. 3 - '/' (C: equivalent of dos is the root partition)
  180. 4..26 (can be set by you're own applications)
  181. ! Use AddDisk() to Add new drives !
  182. They both return -1 when a failure occurs.
  183. }
  184. Const
  185. FixDriveStr : array[0..3] of pchar=(
  186. '.',
  187. '/fd0/.',
  188. '/fd1/.',
  189. '/.'
  190. );
  191. const
  192. Drives : byte = 4;
  193. var
  194. DriveStr : array[4..26] of pchar;
  195. Function AddDisk(const path:string) : byte;
  196. begin
  197. { if not (DriveStr[Drives]=nil) then
  198. FreeMem(DriveStr[Drives]);
  199. GetMem(DriveStr[Drives],length(Path)+1);
  200. StrPCopy(DriveStr[Drives],path);
  201. AddDisk:=Drives;
  202. inc(Drives);
  203. if Drives>26 then
  204. Drives:=4;}
  205. end;
  206. Function DiskFree(Drive: Byte): int64;
  207. {var
  208. fs : tstatfs;}
  209. Begin
  210. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  211. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  212. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  213. else
  214. Diskfree:=-1;}
  215. End;
  216. Function DiskSize(Drive: Byte): int64;
  217. {var
  218. fs : tstatfs;}
  219. Begin
  220. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  221. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  222. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  223. else
  224. DiskSize:=-1;}
  225. End;
  226. Procedure FreeDriveStr;
  227. {var
  228. i: longint;}
  229. begin
  230. { for i:=low(drivestr) to high(drivestr) do
  231. if assigned(drivestr[i]) then
  232. begin
  233. freemem(drivestr[i]);
  234. drivestr[i]:=nil;
  235. end;}
  236. end;
  237. {******************************************************************************
  238. --- Findfirst FindNext ---
  239. ******************************************************************************}
  240. procedure SearchRec2WasiSearchRec(const i: SearchRec; var o: TWasiSearchRec);
  241. var
  242. DT: DateTime;
  243. begin
  244. FillChar(o,SizeOf(o),0);
  245. o.SearchPos:=i.SearchPos;
  246. o.SearchNum:=i.SearchNum;
  247. o.DirFD:=i.DirFD;
  248. o.SearchType:=i.SearchType;
  249. o.SearchAttr:=i.SearchAttr;
  250. o.Attr:=i.Attr;
  251. UnpackTime(i.Time,DT);
  252. o.Time:=DTToWasiDate(DT);
  253. o.Size:=i.Size;
  254. o.Name:=i.Name;
  255. o.SearchSpec:=i.SearchSpec;
  256. o.NamePos:=i.NamePos;
  257. end;
  258. procedure WasiSearchRec2SearchRec(const i: TWasiSearchRec; var o: SearchRec);
  259. var
  260. DT: DateTime;
  261. begin
  262. FillChar(o,SizeOf(o),0);
  263. o.SearchPos:=i.SearchPos;
  264. o.SearchNum:=i.SearchNum;
  265. o.DirFD:=i.DirFD;
  266. o.SearchType:=i.SearchType;
  267. o.SearchAttr:=i.SearchAttr;
  268. o.Attr:=i.Attr;
  269. WasiDateToDt(i.Time,DT);
  270. PackTime(DT,o.Time);
  271. o.Size:=i.Size;
  272. o.Name:=i.Name;
  273. o.SearchSpec:=i.SearchSpec;
  274. o.NamePos:=i.NamePos;
  275. end;
  276. Procedure FindClose(Var f: SearchRec);
  277. var
  278. wf: TWasiSearchRec;
  279. Begin
  280. SearchRec2WasiSearchRec(f,wf);
  281. WasiFindClose(wf);
  282. WasiSearchRec2SearchRec(wf,f);
  283. End;
  284. Procedure FindNext(Var f: SearchRec);
  285. var
  286. wf: TWasiSearchRec;
  287. Begin
  288. SearchRec2WasiSearchRec(f,wf);
  289. doserror:=WasiFindNext(wf);
  290. WasiSearchRec2SearchRec(wf,f);
  291. End;
  292. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  293. var
  294. wf: TWasiSearchRec;
  295. Begin
  296. SearchRec2WasiSearchRec(f,wf);
  297. doserror:=WasiFindFirst(Path,Attr,wf);
  298. WasiSearchRec2SearchRec(wf,f);
  299. End;
  300. {******************************************************************************
  301. --- File ---
  302. ******************************************************************************}
  303. Function FSearch(path: pathstr; dirlist: string): pathstr;
  304. var
  305. p1 : longint;
  306. s : searchrec;
  307. newdir : pathstr;
  308. begin
  309. { No wildcards allowed in these things }
  310. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  311. begin
  312. fsearch:='';
  313. exit;
  314. end;
  315. { check if the file specified exists }
  316. findfirst(path,anyfile and not(directory),s);
  317. if doserror=0 then
  318. begin
  319. findclose(s);
  320. fsearch:=path;
  321. exit;
  322. end;
  323. findclose(s);
  324. //{ allow slash as backslash }
  325. //DoDirSeparators(dirlist);
  326. repeat
  327. p1:=pos(';',dirlist);
  328. if p1<>0 then
  329. begin
  330. newdir:=copy(dirlist,1,p1-1);
  331. delete(dirlist,1,p1);
  332. end
  333. else
  334. begin
  335. newdir:=dirlist;
  336. dirlist:='';
  337. end;
  338. if (newdir<>'') and (not (newdir[length(newdir)] in (AllowDirectorySeparators+[':']))) then
  339. newdir:=newdir+DirectorySeparator;
  340. findfirst(newdir+path,anyfile and not(directory),s);
  341. if doserror=0 then
  342. newdir:=newdir+path
  343. else
  344. newdir:='';
  345. findclose(s);
  346. until (dirlist='') or (newdir<>'');
  347. fsearch:=newdir;
  348. end;
  349. Procedure GetFAttr(var f; var attr : word);
  350. Var
  351. pr: RawByteString;
  352. fd: __wasi_fd_t;
  353. Info: __wasi_filestat_t;
  354. Begin
  355. DosError:=0;
  356. Attr:=0;
  357. if ConvertToFdRelativePath(textrec(f).name,fd,pr)<>0 then
  358. begin
  359. DosError:=3;
  360. exit;
  361. end;
  362. if __wasi_path_filestat_get(fd,__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW,PChar(pr),length(pr),@Info)<>__WASI_ERRNO_SUCCESS then
  363. begin
  364. DosError:=3;
  365. exit;
  366. end;
  367. if Info.filetype=__WASI_FILETYPE_DIRECTORY then
  368. Attr:=$10;
  369. if filerec(f).name[0]='.' then
  370. Attr:=Attr or $2;
  371. end;
  372. Procedure getftime (var f; var time : longint);
  373. Var
  374. res: __wasi_errno_t;
  375. Info: __wasi_filestat_t;
  376. DT: DateTime;
  377. Begin
  378. doserror:=0;
  379. res:=__wasi_fd_filestat_get(filerec(f).handle,@Info);
  380. if res<>__WASI_ERRNO_SUCCESS then
  381. begin
  382. Time:=0;
  383. case res of
  384. __WASI_ERRNO_ACCES,
  385. __WASI_ERRNO_NOTCAPABLE:
  386. doserror:=5;
  387. else
  388. doserror:=6;
  389. end;
  390. exit
  391. end
  392. else
  393. WasiDateToDt(Info.mtim,DT);
  394. PackTime(DT,Time);
  395. End;
  396. Procedure setftime(var f; time : longint);
  397. Var
  398. DT: DateTime;
  399. modtime: UInt64;
  400. pr: RawByteString;
  401. fd: __wasi_fd_t;
  402. Begin
  403. doserror:=0;
  404. UnPackTime(Time,DT);
  405. modtime:=DTToWasiDate(DT);
  406. if ConvertToFdRelativePath(textrec(f).name,fd,pr)<>0 then
  407. begin
  408. doserror:=3;
  409. exit;
  410. end;
  411. if __wasi_path_filestat_set_times(fd,0,PChar(pr),length(pr),0,modtime,
  412. __WASI_FSTFLAGS_MTIM or __WASI_FSTFLAGS_ATIM_NOW)<>__WASI_ERRNO_SUCCESS then
  413. doserror:=3;
  414. End;
  415. {******************************************************************************
  416. --- Environment ---
  417. ******************************************************************************}
  418. Function EnvCount: Longint;
  419. var
  420. envcnt : longint;
  421. p : ppchar;
  422. Begin
  423. envcnt:=0;
  424. p:=envp; {defined in system}
  425. if p<>nil then
  426. while p^<>nil do
  427. begin
  428. inc(envcnt);
  429. inc(p);
  430. end;
  431. EnvCount := envcnt
  432. End;
  433. Function EnvStr (Index: longint): String;
  434. Var
  435. i : longint;
  436. p : ppchar;
  437. Begin
  438. if (Index <= 0) or (envp=nil) then
  439. envstr:=''
  440. else
  441. begin
  442. p:=envp; {defined in system}
  443. i:=1;
  444. while (i<Index) and (p^<>nil) do
  445. begin
  446. inc(i);
  447. inc(p);
  448. end;
  449. if p^=nil then
  450. envstr:=''
  451. else
  452. envstr:=strpas(p^)
  453. end;
  454. end;
  455. Function GetEnv(EnvVar: String): String;
  456. var
  457. hp : ppchar;
  458. hs : string;
  459. eqpos : longint;
  460. Begin
  461. getenv:='';
  462. hp:=envp;
  463. if hp<>nil then
  464. while assigned(hp^) do
  465. begin
  466. hs:=strpas(hp^);
  467. eqpos:=pos('=',hs);
  468. if copy(hs,1,eqpos-1)=envvar then
  469. begin
  470. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  471. break;
  472. end;
  473. inc(hp);
  474. end;
  475. End;
  476. Procedure setfattr (var f;attr : word);
  477. Begin
  478. {! No WASI equivalent !}
  479. { Fail for setting VolumeId }
  480. if (attr and VolumeID)<>0 then
  481. doserror:=5;
  482. End;
  483. {******************************************************************************
  484. --- Initialization ---
  485. ******************************************************************************}
  486. //Finalization
  487. // FreeDriveStr;
  488. End.