dos.pp 14 KB

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