mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 06:57:59 +02:00
575 lines
14 KiB
ObjectPascal
575 lines
14 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2000 by Michael Van Canneyt and Peter Vreman,
|
|
members of the Free Pascal development team
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
{$IFNDEF FPC_DOTTEDUNITS}
|
|
Unit Dos;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
Interface
|
|
|
|
Const
|
|
FileNameLen = 255;
|
|
|
|
Type
|
|
SearchRec =
|
|
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
|
|
packed
|
|
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
|
|
Record
|
|
{Fill : array[1..21] of byte; Fill replaced with below}
|
|
SearchPos : UInt64; {directory position}
|
|
SearchNum : LongInt; {to track which search this is}
|
|
DirFD : LongInt; {directory fd handle for reading directory}
|
|
SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
|
|
SearchAttr : Byte; {attribute we are searching for}
|
|
Mode : Word;
|
|
Fill : Array[1..1] of Byte; {future use}
|
|
{End of fill}
|
|
Attr : Byte; {attribute of found file}
|
|
Time : LongInt; {last modify date of found file}
|
|
Size : LongInt; {file size of found file}
|
|
Reserved : Word; {future use}
|
|
Name : String[FileNameLen]; {name of found file}
|
|
SearchSpec : String[FileNameLen]; {search pattern}
|
|
NamePos : Word; {end of path, start of name position}
|
|
End;
|
|
|
|
{$DEFINE HAS_FILENAMELEN}
|
|
{$i dosh.inc}
|
|
|
|
{Extra Utils}
|
|
function weekday(y,m,d : longint) : longint; platform;
|
|
Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime); platform;
|
|
Function DTToWasiDate(DT: DateTime): UInt64; platform;
|
|
|
|
{Disk}
|
|
//Function AddDisk(const path:string) : byte; platform;
|
|
|
|
Implementation
|
|
|
|
{$IFDEF FPC_DOTTEDUNITS}
|
|
Uses
|
|
WASIApi.WASIApi, WASIApi.WASIUtil;
|
|
{$ELSE FPC_DOTTEDUNITS}
|
|
Uses
|
|
WasiAPI, WasiUtil;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
{$DEFINE HAS_GETMSCOUNT}
|
|
|
|
{$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
|
|
{$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PAnsiChar }
|
|
|
|
{$I dos.inc}
|
|
|
|
|
|
{******************************************************************************
|
|
--- Link C Lib if set ---
|
|
******************************************************************************}
|
|
|
|
|
|
{******************************************************************************
|
|
--- Info / Date / Time ---
|
|
******************************************************************************}
|
|
|
|
Function DosVersion:Word;
|
|
Begin
|
|
End;
|
|
|
|
function WeekDay (y,m,d:longint):longint;
|
|
{
|
|
Calculates th day of the week. returns -1 on error
|
|
}
|
|
var
|
|
u,v : longint;
|
|
begin
|
|
if (m<1) or (m>12) or (y<1600) or (y>4000) or
|
|
(d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
|
|
((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
|
|
WeekDay:=-1
|
|
else
|
|
begin
|
|
u:=m;
|
|
v:=y;
|
|
if m<3 then
|
|
begin
|
|
inc(u,12);
|
|
dec(v);
|
|
end;
|
|
WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
|
|
end;
|
|
end;
|
|
|
|
|
|
Procedure GetDate(Var Year, Month, MDay, WDay: Word);
|
|
var
|
|
NanoSecsPast: __wasi_timestamp_t;
|
|
DT: DateTime;
|
|
begin
|
|
if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
|
|
begin
|
|
WasiDateToDT(NanoSecsPast,DT);
|
|
Year:=DT.Year;
|
|
Month:=DT.Month;
|
|
MDay:=DT.Day;
|
|
WDay:=weekday(DT.Year,DT.Month,DT.Day);
|
|
end
|
|
else
|
|
begin
|
|
Year:=0;
|
|
Month:=0;
|
|
MDay:=0;
|
|
WDay:=0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure SetTime(Hour,Minute,Second,sec100:word);
|
|
begin
|
|
end;
|
|
|
|
procedure SetDate(Year,Month,Day:Word);
|
|
begin
|
|
end;
|
|
|
|
|
|
Function SetDateTime(Year,Month,Day,hour,minute,second:Word) : Boolean;
|
|
begin
|
|
end;
|
|
|
|
|
|
Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
|
|
var
|
|
NanoSecsPast: __wasi_timestamp_t;
|
|
begin
|
|
if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
|
|
begin
|
|
{ todo: convert UTC to local time, as soon as we can get the local timezone
|
|
from WASI: https://github.com/WebAssembly/WASI/issues/239 }
|
|
NanoSecsPast:=NanoSecsPast div 10000000;
|
|
Sec100:=NanoSecsPast mod 100;
|
|
NanoSecsPast:=NanoSecsPast div 100;
|
|
Second:=NanoSecsPast mod 60;
|
|
NanoSecsPast:=NanoSecsPast div 60;
|
|
Minute:=NanoSecsPast mod 60;
|
|
NanoSecsPast:=NanoSecsPast div 60;
|
|
Hour:=NanoSecsPast mod 24;
|
|
end
|
|
else
|
|
begin
|
|
Hour:=0;
|
|
Minute:=0;
|
|
Second:=0;
|
|
Sec100:=0;
|
|
end;
|
|
end;
|
|
|
|
|
|
Function DTToWasiDate(DT: DateTime): UInt64;
|
|
var
|
|
res: Int64;
|
|
begin
|
|
res:={$IFDEF FPC_DOTTEDUNITS}WASIApi.{$ENDIF}WasiUtil.LocalToEpoch(DT.year,DT.month,DT.day,DT.hour,DT.min,DT.sec);
|
|
if res<0 then
|
|
DTToWasiDate:=0
|
|
else
|
|
DTToWasiDate:=res*1000000000;
|
|
end;
|
|
|
|
|
|
Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime);
|
|
Begin
|
|
{$IFDEF FPC_DOTTEDUNITS}WASIApi.{$ENDIF}WasiUtil.EpochToLocal(NanoSecsPast div 1000000000,Dt.Year,Dt.Month,Dt.Day,Dt.Hour,Dt.Min,Dt.Sec);
|
|
End;
|
|
|
|
|
|
function GetMsCount: int64;
|
|
var
|
|
NanoSecsPast: __wasi_timestamp_t;
|
|
begin
|
|
if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,1000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
|
|
GetMsCount:=NanoSecsPast div 1000000
|
|
else
|
|
GetMsCount:=0;
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Exec ---
|
|
******************************************************************************}
|
|
|
|
Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
|
|
Begin
|
|
End;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Disk ---
|
|
******************************************************************************}
|
|
|
|
{
|
|
The Diskfree and Disksize functions need a file on the specified drive, since this
|
|
is required for the fpstatfs system call.
|
|
These filenames are set in drivestr[0..26], and have been preset to :
|
|
0 - '.' (default drive - hence current dir is ok.)
|
|
1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
|
|
2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
|
|
3 - '/' (C: equivalent of dos is the root partition)
|
|
4..26 (can be set by you're own applications)
|
|
! Use AddDisk() to Add new drives !
|
|
They both return -1 when a failure occurs.
|
|
}
|
|
Const
|
|
FixDriveStr : array[0..3] of PAnsiChar=(
|
|
'.',
|
|
'/fd0/.',
|
|
'/fd1/.',
|
|
'/.'
|
|
);
|
|
const
|
|
Drives : byte = 4;
|
|
var
|
|
DriveStr : array[4..26] of PAnsiChar;
|
|
|
|
Function AddDisk(const path:string) : byte;
|
|
begin
|
|
{ if not (DriveStr[Drives]=nil) then
|
|
FreeMem(DriveStr[Drives]);
|
|
GetMem(DriveStr[Drives],length(Path)+1);
|
|
StrPCopy(DriveStr[Drives],path);
|
|
AddDisk:=Drives;
|
|
inc(Drives);
|
|
if Drives>26 then
|
|
Drives:=4;}
|
|
end;
|
|
|
|
|
|
|
|
Function DiskFree(Drive: Byte): int64;
|
|
{var
|
|
fs : tstatfs;}
|
|
Begin
|
|
{ if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
|
|
((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
|
|
Diskfree:=int64(fs.bavail)*int64(fs.bsize)
|
|
else
|
|
Diskfree:=-1;}
|
|
End;
|
|
|
|
|
|
|
|
Function DiskSize(Drive: Byte): int64;
|
|
{var
|
|
fs : tstatfs;}
|
|
Begin
|
|
{ if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
|
|
((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
|
|
DiskSize:=int64(fs.blocks)*int64(fs.bsize)
|
|
else
|
|
DiskSize:=-1;}
|
|
End;
|
|
|
|
|
|
|
|
Procedure FreeDriveStr;
|
|
{var
|
|
i: longint;}
|
|
begin
|
|
{ for i:=low(drivestr) to high(drivestr) do
|
|
if assigned(drivestr[i]) then
|
|
begin
|
|
freemem(drivestr[i]);
|
|
drivestr[i]:=nil;
|
|
end;}
|
|
end;
|
|
|
|
{******************************************************************************
|
|
--- Findfirst FindNext ---
|
|
******************************************************************************}
|
|
|
|
|
|
procedure SearchRec2WasiSearchRec(const i: SearchRec; var o: TWasiSearchRec);
|
|
var
|
|
DT: DateTime;
|
|
begin
|
|
FillChar(o,SizeOf(o),0);
|
|
o.SearchPos:=i.SearchPos;
|
|
o.SearchNum:=i.SearchNum;
|
|
o.DirFD:=i.DirFD;
|
|
o.SearchType:=i.SearchType;
|
|
o.SearchAttr:=i.SearchAttr;
|
|
o.Attr:=i.Attr;
|
|
UnpackTime(i.Time,DT);
|
|
o.Time:=DTToWasiDate(DT);
|
|
o.Size:=i.Size;
|
|
o.Name:=i.Name;
|
|
o.SearchSpec:=i.SearchSpec;
|
|
o.NamePos:=i.NamePos;
|
|
end;
|
|
|
|
|
|
procedure WasiSearchRec2SearchRec(const i: TWasiSearchRec; var o: SearchRec);
|
|
var
|
|
DT: DateTime;
|
|
begin
|
|
FillChar(o,SizeOf(o),0);
|
|
o.SearchPos:=i.SearchPos;
|
|
o.SearchNum:=i.SearchNum;
|
|
o.DirFD:=i.DirFD;
|
|
o.SearchType:=i.SearchType;
|
|
o.SearchAttr:=i.SearchAttr;
|
|
o.Attr:=i.Attr;
|
|
WasiDateToDt(i.Time,DT);
|
|
PackTime(DT,o.Time);
|
|
o.Size:=i.Size;
|
|
o.Name:=i.Name;
|
|
o.SearchSpec:=i.SearchSpec;
|
|
o.NamePos:=i.NamePos;
|
|
end;
|
|
|
|
|
|
Procedure FindClose(Var f: SearchRec);
|
|
var
|
|
wf: TWasiSearchRec;
|
|
Begin
|
|
SearchRec2WasiSearchRec(f,wf);
|
|
WasiFindClose(wf);
|
|
WasiSearchRec2SearchRec(wf,f);
|
|
End;
|
|
|
|
|
|
Procedure FindNext(Var f: SearchRec);
|
|
var
|
|
wf: TWasiSearchRec;
|
|
Begin
|
|
SearchRec2WasiSearchRec(f,wf);
|
|
doserror:=WasiFindNext(wf);
|
|
WasiSearchRec2SearchRec(wf,f);
|
|
End;
|
|
|
|
|
|
Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
|
|
var
|
|
wf: TWasiSearchRec;
|
|
Begin
|
|
SearchRec2WasiSearchRec(f,wf);
|
|
doserror:=WasiFindFirst(Path,Attr,wf);
|
|
WasiSearchRec2SearchRec(wf,f);
|
|
End;
|
|
|
|
|
|
{******************************************************************************
|
|
--- File ---
|
|
******************************************************************************}
|
|
|
|
Function FSearch(path: pathstr; dirlist: shortstring): pathstr;
|
|
var
|
|
p1 : longint;
|
|
s : searchrec;
|
|
newdir : pathstr;
|
|
begin
|
|
{ No wildcards allowed in these things }
|
|
if (pos('?',path)<>0) or (pos('*',path)<>0) then
|
|
begin
|
|
fsearch:='';
|
|
exit;
|
|
end;
|
|
{ check if the file specified exists }
|
|
findfirst(path,anyfile and not(directory),s);
|
|
if doserror=0 then
|
|
begin
|
|
findclose(s);
|
|
fsearch:=path;
|
|
exit;
|
|
end;
|
|
findclose(s);
|
|
//{ allow slash as backslash }
|
|
//DoDirSeparators(dirlist);
|
|
repeat
|
|
p1:=pos(';',dirlist);
|
|
if p1<>0 then
|
|
begin
|
|
newdir:=copy(dirlist,1,p1-1);
|
|
delete(dirlist,1,p1);
|
|
end
|
|
else
|
|
begin
|
|
newdir:=dirlist;
|
|
dirlist:='';
|
|
end;
|
|
if (newdir<>'') and (not (newdir[length(newdir)] in (AllowDirectorySeparators+[':']))) then
|
|
newdir:=newdir+DirectorySeparator;
|
|
findfirst(newdir+path,anyfile and not(directory),s);
|
|
if doserror=0 then
|
|
newdir:=newdir+path
|
|
else
|
|
newdir:='';
|
|
findclose(s);
|
|
until (dirlist='') or (newdir<>'');
|
|
fsearch:=newdir;
|
|
end;
|
|
|
|
Procedure GetFAttr(var f; var attr : word);
|
|
Var
|
|
pr: RawByteString;
|
|
fd: __wasi_fd_t;
|
|
Info: __wasi_filestat_t;
|
|
Begin
|
|
DosError:=0;
|
|
Attr:=0;
|
|
if ConvertToFdRelativePath(textrec(f).name,fd,pr)<>0 then
|
|
begin
|
|
DosError:=3;
|
|
exit;
|
|
end;
|
|
if __wasi_path_filestat_get(fd,__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW,PAnsiChar(pr),length(pr),@Info)<>__WASI_ERRNO_SUCCESS then
|
|
begin
|
|
DosError:=3;
|
|
exit;
|
|
end;
|
|
if Info.filetype=__WASI_FILETYPE_DIRECTORY then
|
|
Attr:=$10;
|
|
if filerec(f).name[0]='.' then
|
|
Attr:=Attr or $2;
|
|
end;
|
|
|
|
Procedure getftime (var f; var time : longint);
|
|
Var
|
|
res: __wasi_errno_t;
|
|
Info: __wasi_filestat_t;
|
|
DT: DateTime;
|
|
Begin
|
|
doserror:=0;
|
|
res:=__wasi_fd_filestat_get(filerec(f).handle,@Info);
|
|
if res<>__WASI_ERRNO_SUCCESS then
|
|
begin
|
|
Time:=0;
|
|
case res of
|
|
__WASI_ERRNO_ACCES,
|
|
__WASI_ERRNO_NOTCAPABLE:
|
|
doserror:=5;
|
|
else
|
|
doserror:=6;
|
|
end;
|
|
exit
|
|
end
|
|
else
|
|
WasiDateToDt(Info.mtim,DT);
|
|
PackTime(DT,Time);
|
|
End;
|
|
|
|
Procedure setftime(var f; time : longint);
|
|
Var
|
|
DT: DateTime;
|
|
modtime: UInt64;
|
|
pr: RawByteString;
|
|
fd: __wasi_fd_t;
|
|
Begin
|
|
doserror:=0;
|
|
UnPackTime(Time,DT);
|
|
modtime:=DTToWasiDate(DT);
|
|
if ConvertToFdRelativePath(textrec(f).name,fd,pr)<>0 then
|
|
begin
|
|
doserror:=3;
|
|
exit;
|
|
end;
|
|
if __wasi_path_filestat_set_times(fd,0,PAnsiChar(pr),length(pr),0,modtime,
|
|
__WASI_FSTFLAGS_MTIM or __WASI_FSTFLAGS_ATIM_NOW)<>__WASI_ERRNO_SUCCESS then
|
|
doserror:=3;
|
|
End;
|
|
|
|
{******************************************************************************
|
|
--- Environment ---
|
|
******************************************************************************}
|
|
|
|
Function EnvCount: Longint;
|
|
var
|
|
envcnt : longint;
|
|
p : PPAnsiChar;
|
|
Begin
|
|
envcnt:=0;
|
|
p:=envp; {defined in system}
|
|
if p<>nil then
|
|
while p^<>nil do
|
|
begin
|
|
inc(envcnt);
|
|
inc(p);
|
|
end;
|
|
EnvCount := envcnt
|
|
End;
|
|
|
|
|
|
Function EnvStr (Index: longint): ShortString;
|
|
Var
|
|
i : longint;
|
|
p : PPAnsiChar;
|
|
Begin
|
|
if (Index <= 0) or (envp=nil) then
|
|
envstr:=''
|
|
else
|
|
begin
|
|
p:=envp; {defined in system}
|
|
i:=1;
|
|
while (i<Index) and (p^<>nil) do
|
|
begin
|
|
inc(i);
|
|
inc(p);
|
|
end;
|
|
if p^=nil then
|
|
envstr:=''
|
|
else
|
|
envstr:=strpas(p^)
|
|
end;
|
|
end;
|
|
|
|
|
|
Function GetEnv(EnvVar: ShortString): ShortString;
|
|
var
|
|
hp : PPAnsiChar;
|
|
hs : string;
|
|
eqpos : longint;
|
|
Begin
|
|
getenv:='';
|
|
hp:=envp;
|
|
if hp<>nil then
|
|
while assigned(hp^) do
|
|
begin
|
|
hs:=strpas(hp^);
|
|
eqpos:=pos('=',hs);
|
|
if copy(hs,1,eqpos-1)=envvar then
|
|
begin
|
|
getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
|
|
break;
|
|
end;
|
|
inc(hp);
|
|
end;
|
|
End;
|
|
|
|
|
|
Procedure setfattr (var f;attr : word);
|
|
Begin
|
|
{! No WASI equivalent !}
|
|
{ Fail for setting VolumeId }
|
|
if (attr and VolumeID)<>0 then
|
|
doserror:=5;
|
|
End;
|
|
|
|
|
|
|
|
{******************************************************************************
|
|
--- Initialization ---
|
|
******************************************************************************}
|
|
|
|
//Finalization
|
|
// FreeDriveStr;
|
|
End.
|