{ $Id$ This file is part of the Free Pascal run time library. Copyright (c) 1999-2000 by the Free Pascal development team. Dos unit for BP7 compatible RTL 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. **********************************************************************} unit dos; interface uses beos; const FileNameLen=255; type ComStr = String[FileNameLen]; PathStr = String[FileNameLen]; DirStr = String[FileNameLen]; NameStr = String[FileNameLen]; ExtStr = String[FileNameLen]; Const {Bitmasks for CPU Flags} fcarry = $0001; fparity = $0004; fauxiliary = $0010; fzero = $0040; fsign = $0080; foverflow = $0800; {Bitmasks for file attribute} readonly = $01; hidden = $02; sysfile = $04; volumeid = $08; directory = $10; archive = $20; anyfile = $3F; {File Status} fmclosed = $D7B0; fminput = $D7B1; fmoutput = $D7B2; fminout = $D7B3; S_IFMT = $F000; { type of file } S_IFLNK = $A000; { symbolic link } S_IFREG = $8000; { regular } S_IFBLK = $6000; { block special } S_IFDIR = $4000; { directory } S_IFCHR = $2000; { character special } S_IFIFO = $1000; { fifo } { filerec.inc contains the definition of the filerec. textrec.inc contains the definition of the textrec. It is in a separate file to make it available in other units without having to use the DOS unit for it. } {$i filerec.inc} {$i textrec.inc} DateTime = packed record Year, Month, Day, Hour, Min, Sec : word; End; searchrec = record fd : longint; path : string; fname : string; attr : byte; time : longint; size : longint; name : string[255]; end; Var DosError : integer; {Info/Date/Time} Procedure GetDate(var year, month, mday, wday: word); procedure GetTime(var hour,min,sec,msec,usec:word); procedure GetTime(var hour,min,sec,sec100:word); procedure GetTime(Var Hour,Min,Sec:Word); Procedure UnpackTime(p: longint; var t: datetime); Procedure PackTime(var t: datetime; var p: longint); {Exec} Procedure Exec(const path: pathstr; const comline: comstr); Function DosExitCode: word; {Disk} Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec); Procedure FindNext(var f: searchRec); Procedure FindClose(var f: searchRec); {File} {Procedure GetFAttr(var f:File; var attr: word);} procedure GetFTime(var f:File; var time: longint); procedure GetFTime(f:string; var time: longint); Procedure SetFTime(var f:File; time : longint); Function FSearch(path: pathstr; dirlist: string): pathstr; Function FExpand(const path: pathstr): pathstr; Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr); {Environment} {Function EnvCount: longint; Function EnvStr(index: integer): string;} {Misc} {Procedure SetFAttr(var f; attr: word); Procedure SetFTime(var f; time: longint); Procedure GetVerify(var verify: boolean); Procedure SetVerify(verify: boolean);} {Do Nothing Functions} Procedure SwapVectors; {Procedure GetIntVec(intno: byte; var vector: pointer); Procedure SetIntVec(intno: byte; vector: pointer); Procedure Keep(exitcode: word);} function GetEnv(EnvVar: String): String; Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word); implementation uses strings; procedure GetFTime(var f:file; var time: longint); var info:stat; t:longint; dt:DateTime; begin if not FStat(F,Info) then begin t:=0; doserror:=3; exit; end else t:=info.ctime; EpochToLocal(t,dt.year,dt.month,dt.day,dt.hour,dt.min,dt.sec); packtime(dt,time); end; procedure GetFTime(f:string; var time: longint); var info:stat; t:longint; dt:DateTime; begin if not FStat(F,Info) then begin t:=0; doserror:=3; exit; end else t:=info.ctime; EpochToLocal(t,dt.year,dt.month,dt.day,dt.hour,dt.min,dt.sec); packtime(dt,time); end; type utimbuf=record actime,modtime:longint; end; {function _utime (path:pchar;var buf:utimbuf):longint; cdecl; external name 'utime';} Procedure setftime(var f:file; time : longint); {var buf:utimbuf;} begin { buf.actime:=time; buf.modtime:=time;} { writeln ('SetFTime ',PChar(@FileRec(f).Name),' := ',time);} { if _utime(PChar(@FileRec(f).Name),buf)<>0 then doserror:=3;} end; {****************************************************************************** --- Info / Date / Time --- ******************************************************************************} procedure getdate(var year,month,mday,wday : word); begin end; function sys_time:longint; cdecl; external name 'sys_time'; procedure GetTime(var hour,min,sec,msec,usec:word); { Gets the current time, adjusted to local time } var year,day,month:Word; t : longint; begin t:=sys_time; EpochToLocal(t,year,month,day,hour,min,sec); msec:=0; usec:=0; end; procedure GetTime(var hour,min,sec,sec100:word); { Gets the current time, adjusted to local time } var usec : word; begin gettime(hour,min,sec,sec100,usec); sec100:=sec100 div 10; end; procedure GetTime(Var Hour,Min,Sec:Word); { Gets the current time, adjusted to local time } var msec,usec : Word; Begin gettime(hour,min,sec,msec,usec); end; Procedure packtime(var t : datetime;var p : longint); Begin p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25); End; Procedure unpacktime(p : longint;var t : datetime); Begin with t do begin sec:=(p and 31) shl 1; min:=(p shr 5) and 63; hour:=(p shr 11) and 31; day:=(p shr 16) and 31; month:=(p shr 21) and 15; year:=(p shr 25)+1980; end; End; {****************************************************************************** --- Exec --- ******************************************************************************} Procedure Exec(const path: pathstr; const comline: comstr); var p:string; begin p:=path+' '+comline; doserror:=beos.shell(p); end; Function DosExitCode: word; begin dosexitcode:=doserror; end; {****************************************************************************** --- File --- ******************************************************************************} Procedure FSplit(Path: PathStr; Var Dir: DirStr; Var Name: NameStr;Var Ext: ExtStr); Begin beos.FSplit(Path,Dir,Name,Ext); End; Function FExpand(Const Path: PathStr): PathStr; Begin FExpand:=beos.FExpand(Path); End; Function FSearch(path : pathstr;dirlist : string) : pathstr; Var info:stat; Begin if (length(Path)>0) and (path[1]='/') and FStat(path,info) then FSearch:=path else FSearch:=beos.FSearch(path,dirlist); End; {****************************************************************************** --- Findfirst FindNext --- ******************************************************************************} {procedure dossearchrec2searchrec(var f : searchrec); var len : longint; begin len:=StrLen(@f.Name); Move(f.Name[0],f.Name[1],Len); f.Name[0]:=chr(len); end;} type dirent = packed record d_dev:longint; d_pdev:longint; d_ino:int64; d_pino:int64; d_reclen:word; d_name:array[0..255] of char; end; function sys_opendir (a:dword;path:pchar;b:longint):longint; cdecl; external name 'sys_opendir'; function sys_readdir (fd:longint;var de:dirent;a:longint;b:byte):longint; cdecl; external name 'sys_readdir'; procedure findnext(var f : searchRec); var len:longint; ent:dirent; info:stat; dt:DateTime; begin if sys_readdir(f.fd,ent,$11C,1)=0 then begin doserror:=3; exit; end; { writeln ('NAME: ',pchar(@ent.d_name[0]));} len:=StrLen(@ent.d_name); Move(ent.d_name,f.name[1],len); f.name[0]:=chr(len); { writeln ('NAME: "',f.path+f.name,'"');} if not FStat(f.path+f.name,info) then begin writeln ('NOT FOUND'); doserror:=3; exit; end; writeln ('OK'); f.size:=info.size; f.attr:=0; if (info.mode and S_IFMT)=S_IFDIR then f.attr:=directory; EpochToLocal(info.mtime,dt.year,dt.month,dt.day,dt.hour,dt.min,dt.sec); packtime(dt,f.time); doserror:=0; end; procedure findfirst(const path : pathstr;attr : word;var f : searchRec); var tmp:string; info:stat; ext:string; begin tmp:=path; if tmp='' then tmp:='.'; if FStat(tmp,info) then begin if ((info.mode and S_IFMT)=S_IFDIR) and (tmp[length(tmp)]<>'/') then tmp:=tmp+'/'; end; FSplit (tmp,f.path,f.fname,ext); { f.path:=FExpand(f.path);} f.fname:=f.fname+ext; if length(f.fname)=0 then f.fname:='*'; tmp:=tmp+#0; f.fd:=sys_opendir ($FF000000,@tmp[1],0); writeln ('F.PATH=',f.path,' ; ',f.fname); findnext(f); end; Procedure FindClose(Var f: SearchRec); begin DosError:=0; end; procedure swapvectors; begin { no beos equivalent } DosError:=0; end; {****************************************************************************** --- Environment --- ******************************************************************************} function envcount : longint; var hp : ppchar; begin hp:=envp; envcount:=0; while assigned(hp^) do begin inc(envcount); hp:=hp+4; end; end; function envstr(index : integer) : string; begin if (index<=0) or (index>envcount) then begin envstr:=''; exit; end; envstr:=strpas(ppchar(envp+4*(index-1))^); end; {****************************************************************************** --- Not Supported --- ******************************************************************************} Procedure keep(exitcode : word); Begin End; Procedure getintvec(intno : byte;var vector : pointer); Begin End; Procedure setintvec(intno : byte;vector : pointer); Begin End; {****************************************************************************** Date and Time related calls ******************************************************************************} Const {Date Translation} C1970=2440588; D0 = 1461; D1 = 146097; D2 =1721119; Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word); Var YYear,XYear,Temp,TempMonth : LongInt; Begin Temp:=((JulianDN-D2) shl 2)-1; JulianDN:=Temp Div D1; XYear:=(Temp Mod D1) or 3; YYear:=(XYear Div D0); Temp:=((((XYear mod D0)+4) shr 2)*5)-3; Day:=((Temp Mod 153)+5) Div 5; TempMonth:=Temp Div 153; If TempMonth>=10 Then Begin inc(YYear); dec(TempMonth,12); End; inc(TempMonth,3); Month := TempMonth; Year:=YYear+(JulianDN*100); end; Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word); { Transforms Epoch time into local time (hour, minute,seconds) } Var DateNum: LongInt; Begin Datenum:=(Epoch Div 86400) + c1970; JulianToGregorian(DateNum,Year,Month,day); Epoch:=Epoch Mod 86400; Hour:=Epoch Div 3600; Epoch:=Epoch Mod 3600; Minute:=Epoch Div 60; Second:=Epoch Mod 60; End; { $Log$ Revision 1.2 2001-06-19 20:46:07 hajny * platform specific constants moved after systemh.inc, BeOS omission corrected Revision 1.1 2001/06/02 19:26:03 peter * BeOS target! Revision 1.5 2000/01/07 16:41:29 daniel * copyright 2000 Revision 1.4 2000/01/07 16:32:23 daniel * copyright 2000 added Revision 1.3 1999/01/22 16:22:09 pierre * Daniel removal of findclose reverted Revision 1.2 1999/01/22 10:07:02 daniel - Findclose removed: This is TP incompatible!! Revision 1.1 1998/12/21 13:07:02 peter * use -FE Revision 1.19 1998/11/23 13:53:59 peter * more fexpand fixes from marco van de voort Revision 1.18 1998/11/23 12:48:02 peter * fexpand('o:') fixed to return o:\ (from the mailinglist) Revision 1.17 1998/11/22 09:33:21 florian * fexpand bug (temp. strings were too shoort) fixed, was reported by Marco van de Voort Revision 1.16 1998/11/17 09:37:41 pierre * explicit conversion from word dosreg.ax to integer doserror Revision 1.15 1998/11/01 20:27:18 peter * fixed some doserror settings Revision 1.14 1998/10/22 15:05:28 pierre * fsplit adapted to long filenames Revision 1.13 1998/09/16 16:47:24 peter * merged fixes Revision 1.11.2.2 1998/09/16 16:16:04 peter * go32v1 compiles again Revision 1.12 1998/09/11 12:46:44 pierre * range check problem with LFN attr removed Revision 1.11.2.1 1998/09/11 12:38:41 pierre * conversion from LFN attr to Dos attr did not respect range checking Revision 1.11 1998/08/28 10:45:58 peter * fixed path buffer in findfirst Revision 1.10 1998/08/27 10:30:48 pierre * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !) I renamed tb_selector to tb_segment because it is a real mode segment as opposed to a protected mode selector Fixed it for go32v1 (remove the $E0000000 offset !) Revision 1.9 1998/08/26 10:04:01 peter * new lfn check from mailinglist * renamed win95 -> LFNSupport + tb_selector, tb_offset for easier access to transferbuffer Revision 1.8 1998/08/16 20:39:49 peter + LFN Support Revision 1.7 1998/08/16 09:12:13 michael Corrected fexpand behaviour. Revision 1.6 1998/08/05 21:01:50 michael applied bugfix from maillist to fsearch Revision 1.5 1998/05/31 14:18:13 peter * force att or direct assembling * cleanup of some files Revision 1.4 1998/05/22 00:39:22 peter * go32v1, go32v2 recompiles with the new objects * remake3 works again with go32v2 - removed some "optimizes" from daniel which were wrong Revision 1.3 1998/05/21 19:30:47 peter * objects compiles for linux + assign(pchar), assign(char), rename(pchar), rename(char) * fixed read_text_as_array + read_text_as_pchar which was not yet in the rtl } Function StringToPPChar(Var S:STring):ppchar; { Create a PPChar to structure of pchars which are the arguments specified in the string S. Especially usefull for creating an ArgV for Exec-calls } var nr : longint; Buf : ^char; p : ppchar; begin s:=s+#0; buf:=@s[1]; nr:=0; while(buf^<>#0) do begin while (buf^ in [' ',#8,#10]) do inc(buf); inc(nr); while not (buf^ in [' ',#0,#8,#10]) do inc(buf); end; getmem(p,nr*4); StringToPPChar:=p; if p=nil then begin { LinuxError:=sys_enomem;} exit; end; buf:=@s[1]; while (buf^<>#0) do begin while (buf^ in [' ',#8,#10]) do begin buf^:=#0; inc(buf); end; p^:=buf; inc(p); p^:=nil; while not (buf^ in [' ',#0,#8,#10]) do inc(buf); end; end; Function Dirname(Const path:pathstr):pathstr; { This function returns the directory part of a complete path. Unless the directory is root '/', The last character is not a slash. } var Dir : PathStr; Name : NameStr; Ext : ExtStr; begin FSplit(Path,Dir,Name,Ext); if length(Dir)>1 then Delete(Dir,length(Dir),1); DirName:=Dir; end; Function Basename(Const path:pathstr;Const suf:pathstr):pathstr; { This function returns the filename part of a complete path. If suf is supplied, it is cut off the filename. } var Dir : PathStr; Name : NameStr; Ext : ExtStr; begin FSplit(Path,Dir,Name,Ext); if Suf<>Ext then Name:=Name+Ext; BaseName:=Name; end; function GetEnv(EnvVar: String): String; var p:pchar; begin p:=beos.GetEnv(EnvVar); if p=nil then GetEnv:='' else GetEnv:=StrPas(p); end; end.