home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
program
/
m2posx02
/
file.ipp
< prev
next >
Wrap
Text File
|
1993-10-23
|
28KB
|
1,142 lines
IMPLEMENTATION MODULE file;
(*__NO_CHECKS__*)
(*****************************************************************************)
(* Basiert auf der MiNTLIB von Eric R. Smith *)
(* --------------------------------------------------------------------------*)
(* STATUS: OK *)
(* --------------------------------------------------------------------------*)
(* 12-Feb-93, Holger Kleinschmidt *)
(*****************************************************************************)
VAL_INTRINSIC
CAST_IMPORT
OSCALL_IMPORT
FROM SYSTEM IMPORT
(* TYPE *) ADDRESS,
(* PROC *) ADR;
FROM CTYPE IMPORT
(* PROC *) TOUPPER, TOCARD;
FROM pSTRING IMPORT
(* CONST*) EOS,
(* PROC *) SLEN, APPEND;
FROM types IMPORT
(* CONST*) DDRVPOSTFIX, DDIRSEP,
(* TYPE *) SIGNEDWORD, UNSIGNEDWORD, SIGNEDLONG, UNSIGNEDLONG, WORDSET,
PathName, uidT, gidT, inoT, timeT, offT, sizeT, ssizeT, devT;
FROM err IMPORT
(* CONST*) eOK, eFILNF,
EACCES, EFAULT, EEXIST, ENOSYS, EBADF, ENOENT, ESPIPE, EINVAL,
(* VAR *) errno;
FROM DosSystem IMPORT
(* PROC *) DosVersion;
#if MINT
FROM DosSystem IMPORT MiNTVersion;
#endif
FROM DosFile IMPORT
(* CONST*) FINDALL,
(* TYPE *) DTA, FileAttributes, FileAttribute,
(* VAR *) INODE,
(* PROC *) IsDevice, IsDosDevice, UnixToDos, FindFirst, Seek, IsExec;
FROM sys IMPORT
(* PROC *) time;
#include "oscalls.m2h"
(*==========================================================================*)
CONST
EOKL = LIC(0);
BLKSIZE = 1024;
LBLKSIZE = 256; (* BLKSIZE DIV 4 *)
STDPERM = modeT{sIRUSR,sIWUSR,sIRGRP,sIWGRP,sIROTH,sIWOTH};
VAR
UMASK : modeT;
zerofill : ARRAY [0..LBLKSIZE-1] OF UNSIGNEDLONG;
#if MINT
MiNT : CARDINAL;
#endif
VAR
DOSVersion : CARDINAL;
(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
PROCEDURE icreate (VAR path : PathName;
mode : modeT;
VAR hnd : SIGNEDWORD;
VAR done : BOOLEAN);
VAR lres : SIGNEDLONG;
wres : SIGNEDWORD;
attr : FileAttribute;
BEGIN
mode := mode - UMASK; (* schadet nix, wenn "MiNT" laeuft *)
IF sIWUSR IN mode THEN
attr := FileAttribute{};
ELSE
attr := FileAttribute{faRDONLY};
END;
Fcreate(ADR(path), CAST(UNSIGNEDWORD,attr), lres);
done := lres >= LIC(0);
hnd := VAL(SIGNEDWORD,lres);
#if MINT
IF done AND (MiNT >= 9) THEN
Fchmod(ADR(path), CAST(UNSIGNEDWORD,mode), wres);
END;
#endif
END icreate;
(*--------------------------------------------------------------------------*)
PROCEDURE iopen (VAR path : PathName;
acc : OpenMode;
VAR hnd : SIGNEDWORD;
VAR done : BOOLEAN);
VAR lres : SIGNEDLONG;
BEGIN
acc := acc * oACCMODE; (* zur Zeit noch *)
Fopen(ADR(path), CAST(UNSIGNEDWORD,acc), lres);
done := lres >= LIC(0);;
hnd := VAL(SIGNEDWORD,lres);
END iopen;
(*--------------------------------------------------------------------------*)
PROCEDURE iclose ( h : SIGNEDWORD;
VAR err : SIGNEDWORD;
VAR done : BOOLEAN );
VAR wres : SIGNEDWORD;
BEGIN
Fclose(h, wres);
err := wres;
done := err = eOK;
END iclose;
(*--------------------------------------------------------------------------*)
PROCEDURE idelete (VAR path : PathName;
VAR err : SIGNEDWORD;
VAR done : BOOLEAN );
VAR wres : SIGNEDWORD;
BEGIN
Fdelete(ADR(path), wres);
err := wres;
done := err = eOK;
END idelete;
(*--------------------------------------------------------------------------*)
PROCEDURE creat ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) mode : modeT ): INTEGER;
(*T*)
VAR wres : SIGNEDWORD;
done : BOOLEAN;
dot : BOOLEAN;
attr : FileAttribute;
path0 : PathName;
BEGIN
UnixToDos(file, path0, dot, done);
IF NOT done THEN
RETURN(MINHANDLE-1);
END;
idelete(path0, wres, done);
IF (wres = eFILNF) OR (wres = eOK) THEN
icreate(path0, mode, wres, done);
END;
IF done THEN
RETURN(INT(wres));
ELSE
errno := INT(wres);
RETURN(MINHANDLE-1);
END;
END creat;
(*--------------------------------------------------------------------------*)
PROCEDURE open ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) access : OpenMode;
(* EIN/ -- *) mode : modeT ): INTEGER;
(*T*)
(*
Oeffne Datei
WENN Zugriffsmodus ungleich Nur-Lesen ODER Datei existiert noch nicht
WENN Datei erstellt werden soll
WENN Exclusiver-Zugriffsmodus UND Datei existiert
Datei schliessen, Fehler
ENDE
ODER WENN Datei nicht existiert
Fehler
ENDE
WENN Datei gekuerzt werden soll UND Datei existiert (nicht Geraet)
ODER Datei bisher nicht existiert
WENN Datei existiert
Datei schliessen
Datei loeschen
ENDE
Datei mit entsprechenden Attributen neu anlegen
WENN Datei angelegt
Datei schliessen
Datei mit entsprechendem Zugriffsmodus oeffnen
ENDE
ENDE
ENDE
*)
VAR wres : SIGNEDWORD;
handle : SIGNEDWORD;
lres : SIGNEDLONG;
dot : BOOLEAN;
done : BOOLEAN;
path0 : PathName;
BEGIN
UnixToDos(file, path0, dot, done);
IF NOT done THEN
RETURN(MINHANDLE-1);
END;
iopen(path0, access, handle, done);
IF (access * oACCMODE <> oRDONLY) OR NOT done THEN
IF oCREAT IN access THEN
IF done AND (oEXCL IN access) THEN
iclose(handle, wres, done);
errno := EEXIST;
RETURN(MINHANDLE-1);
END;
ELSIF NOT done THEN
errno := INT(handle);
RETURN(MINHANDLE-1);
END;
IF (oTRUNC IN access) AND (handle >= 0) OR NOT done THEN
IF done THEN
iclose(handle, wres, done);
idelete(path0, wres, done);
IF done AND (oTRUNC IN access) AND (handle >= 0) THEN
(* Datei war schon vorhanden. Eigentlich sollten die
* alten Attribute uebernommen werden...
* Zumindest wird aber nicht das <mode>-Argument benutzt.
*)
Fcreate(ADR(path0), 0, lres);
done := lres >= LIC(0);
handle := VAL(SIGNEDWORD,lres);
END;
ELSE
icreate(path0, mode, handle, done);
END;
IF done THEN
iclose(handle, wres, done);
iopen(path0, access, handle, done);
END;
END;
END;
IF done THEN
RETURN(INT(handle));
ELSE
errno := INT(handle);
RETURN(MINHANDLE-1);
END;
END open;
(*--------------------------------------------------------------------------*)
PROCEDURE close ((* EIN/ -- *) h : INTEGER ): INTEGER;
(*T*)
VAR wres : SIGNEDWORD;
done : BOOLEAN;
BEGIN
iclose(VAL(SIGNEDWORD,h), wres, done);
IF done THEN
RETURN(0);
ELSE
errno := INT(wres);
RETURN(-1);
END;
END close;
(*--------------------------------------------------------------------------*)
PROCEDURE read ((* EIN/ -- *) h : INTEGER;
(* EIN/ -- *) buf : ADDRESS;
(* EIN/ -- *) len : sizeT ): ssizeT;
(*T*)
VAR lres : SIGNEDLONG;
BEGIN
Fread(VAL(SIGNEDWORD,h), VAL(SIGNEDLONG,len), buf, lres);
IF lres < EOKL THEN
errno := INT(lres);
RETURN(-1);
ELSE
RETURN(VAL(ssizeT,lres));
END;
END read;
(*--------------------------------------------------------------------------*)
PROCEDURE write ((* EIN/ -- *) h : INTEGER;
(* EIN/ -- *) buf : ADDRESS;
(* EIN/ -- *) len : sizeT ): ssizeT;
(*T*)
VAR lres : SIGNEDLONG;
BEGIN
Fwrite(VAL(SIGNEDWORD,h), VAL(SIGNEDLONG,len), buf, lres);
IF lres < EOKL THEN
errno := INT(lres);
RETURN(-1);
ELSE
RETURN(VAL(ssizeT,lres));
END;
END write;
(*--------------------------------------------------------------------------*)
PROCEDURE lseek ((* EIN/ -- *) h : INTEGER;
(* EIN/ -- *) off : offT;
(* EIN/ -- *) mode : SeekMode ): offT;
(*T*)
CONST ERANGEL = LIC(-64);
EACCDNL = LIC(-36);
VAR lres : SIGNEDLONG;
curPos : SIGNEDLONG;
newPos : SIGNEDLONG;
len : SIGNEDLONG;
done : BOOLEAN;
BEGIN
len := VAL(SIGNEDLONG,off);
IF len <= LIC(0) THEN
(* Datei braucht nicht verlaengert zu werden *)
Seek(h, len, ORD(mode), lres, done);
IF done THEN
RETURN(VAL(offT,lres));
#if MINT
ELSIF (MiNT > 0) AND (lres = EACCDNL) THEN
errno := ESPIPE;
#endif
ELSE
errno := INT(lres);
END;
RETURN(-1);
END;
(* Augenblickliche Position feststellen, bei 'SeekEnd' gleich
* ans Ende der Datei.
*)
IF mode = SeekEnd THEN
Seek(h, 0, ORD(SeekEnd), curPos, done);
ELSE
Seek(h, 0, ORD(SeekCur), curPos, done);
END;
IF NOT done THEN
#if MINT
IF (MiNT > 0) AND (curPos = EACCDNL) THEN
errno := ESPIPE;
ELSE
#endif
errno := INT(curPos);
#if MINT
END;
#endif
RETURN(-1);
END;
(* gewuenschte Position berechnen. 'SeekEnd' und 'SeekCur' koennen
* gleichbehandelt werden, da der Zeiger bei 'SeekEnd' schon am
* Ende der Datei steht.
*)
IF mode = SeekSet THEN
newPos := len;
ELSE
newPos := curPos + len;
END;
(* Bei 'SeekCur' und 'SeekSet' kann es sein (ist auch meistens der Fall),
* dass die gewuenschte Position innerhalb der bestehenden Datei liegt.
* Deswegen wird zuerst versucht, die gewuenschte Position direkt
* anzufahren. Wenn dabei ein "Range-Fehler" auftritt, muss die Datei
* verlaengert werden.
*)
IF mode <> SeekEnd THEN
Seek(h, len, ORD(mode), curPos, done);
IF curPos = newPos THEN
RETURN(VAL(offT,curPos));
ELSIF NOT done AND (curPos <> ERANGEL) THEN
errno := INT(curPos);
RETURN(-1);
END;
Seek(h, 0, ORD(SeekEnd), curPos, done);
END;
(* Solange Nullbytes schreiben, bis die Datei auf die gewuenschte
* Laenge gebracht ist.
*)
REPEAT
len := newPos - curPos;
IF len > VAL(SIGNEDLONG,BLKSIZE) THEN
len := VAL(SIGNEDLONG,BLKSIZE);
END;
Fwrite(VAL(SIGNEDWORD,h), len, ADR(zerofill), lres);
IF lres <> len THEN
IF lres >= EOKL THEN
RETURN(VAL(offT,curPos + lres));
ELSE
errno := INT(lres);
RETURN(VAL(offT,curPos));
END;
END;
INC(curPos, len);
UNTIL curPos >= newPos;
RETURN(VAL(offT,curPos));
END lseek;
(*--------------------------------------------------------------------------*)
PROCEDURE dup ((* EIN/ -- *) h : INTEGER ): INTEGER;
(*T*)
CONST FDUPFD = 0;
VAR lres : SIGNEDLONG;
BEGIN
#if MINT
IF MiNT > 0 THEN
Fcntl(VAL(SIGNEDWORD,h), LIC(6), FDUPFD, lres);
ELSE
#endif
Fdup(VAL(SIGNEDWORD,h), lres);
#if MINT
END;
#endif
IF lres < EOKL THEN
errno := INT(lres);
RETURN(-1);
ELSE
RETURN(INT(lres));
END;
END dup;
(*--------------------------------------------------------------------------*)
PROCEDURE dup2 ((* EIN/ -- *) h : INTEGER;
(* EIN/ -- *) h2 : INTEGER ): INTEGER;
(*T*)
VAR wres : SIGNEDWORD;
done : BOOLEAN;
BEGIN
IF h = h2 THEN
RETURN(h2);
END;
(* Das Schliessen eines Standardkanals macht eine vorherige
* Umleitung rueckgaengig. Ist aber erst seit dem "GEMDOS" des TOS 1.04
* anwendbar.
*)
IF DOSVersion >= 1500H THEN
iclose(VAL(SIGNEDWORD,h2), wres, done);
END;
Fforce(VAL(SIGNEDWORD,h2), VAL(SIGNEDWORD,h), wres);
IF wres < eOK THEN
errno := INT(wres);
RETURN(-1);
ELSE
RETURN(h2);
END;
END dup2;
(*--------------------------------------------------------------------------*)
PROCEDURE isatty ((* EIN/ -- *) h : INTEGER ): BOOLEAN;
(*T*)
BEGIN
RETURN(IsDevice(h));
END isatty;
(*--------------------------------------------------------------------------*)
PROCEDURE umask ((* EIN/ -- *) excl : modeT ): modeT;
(*T*)
VAR oldmask : modeT;
wres : UNSIGNEDWORD;
BEGIN
oldmask := UMASK;
UMASK := excl;
#if MINT
IF MiNT >= 9 THEN
Pumask(CAST(UNSIGNEDWORD,excl), wres);
RETURN(CAST(modeT,wres));
ELSE
#endif
RETURN(oldmask);
#if MINT
END;
#endif
END umask;
(*---------------------------------------------------------------------------*)
PROCEDURE chmod ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) mode : modeT ): INTEGER;
(*T*)
CONST Set = 1;
VAR wres : SIGNEDWORD;
err : INTEGER;
dot : BOOLEAN;
done : BOOLEAN;
dta : DTA;
attr : FileAttribute;
path0 : PathName;
BEGIN
UnixToDos(file, path0, dot, done);
IF NOT done THEN
RETURN(-1);
END;
#if MINT
IF MiNT >= 9 THEN
Fchmod(ADR(path0), CAST(UNSIGNEDWORD,mode), wres);
IF wres < eOK THEN
errno := INT(wres);
RETURN(-1);
ELSE
RETURN(0);
END;
END;
#endif
IF FindFirst(path0, FINDALL, dta, err) THEN
attr := dta.attr;
IF faSUBDIR IN attr THEN
(* Verzeichnisse in Ruhe lassen (duerfen keine weiteren Attribute haben)*)
RETURN(0);
END;
IF faCHANGED IN attr THEN
(* Archivbit nicht veraendern *)
attr := FileAttribute{faRDONLY, faCHANGED};
ELSE
attr := FileAttribute{faRDONLY};
END;
IF sIWUSR IN mode THEN
EXCL(attr, faRDONLY);
END;
Fattrib(ADR(path0), Set, CAST(UNSIGNEDWORD,attr), wres);
IF wres < eOK THEN
errno := INT(wres);
RETURN(-1);
ELSE
RETURN(0);
END;
ELSE
errno := err;
RETURN(-1);
END;
END chmod;
(*--------------------------------------------------------------------------*)
PROCEDURE chown ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) uid : uidT;
(* EIN/ -- *) gid : gidT ): INTEGER;
(*T*)
#if MINT
VAR wres : SIGNEDWORD;
dot : BOOLEAN;
done : BOOLEAN;
path0 : PathName;
#endif
BEGIN
#if MINT
IF MiNT >= 9 THEN
UnixToDos(file, path0, dot, done);
IF NOT done THEN
RETURN(-1);
END;
Fchown(ADR(path0), VAL(UNSIGNEDWORD,uid), VAL(UNSIGNEDWORD,gid), wres);
IF wres < eOK THEN
errno := INT(wres);
RETURN(-1);
ELSE
RETURN(0);
END;
END;
#endif
IF (uid <> 0) OR (gid <> 0) THEN
errno := EINVAL;
RETURN(-1);
ELSE
RETURN(0);
END;
END chown;
(*--------------------------------------------------------------------------*)
PROCEDURE utime ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) times : UTimeBuf ): INTEGER;
(*T*)
VAR datime : timeT;
wres : SIGNEDWORD;
dot : BOOLEAN;
done : BOOLEAN;
path0 : PathName;
BEGIN
UnixToDos(file, path0, dot, done);
IF NOT done THEN
RETURN(-1);
END;
WITH times DO
IF modtime.cmp = LC(0) THEN
time(modtime);
END;
datime.date := modtime.time;
datime.time := modtime.date;
END;
iopen(path0, oRDWR, wres, done);
IF done THEN
Fdatime(ADR(datime), wres, 1);
iclose(wres, wres, done);
END;
IF done THEN
RETURN(0);
ELSE
errno := INT(wres);
RETURN(-1);
END;
END utime;
(*---------------------------------------------------------------------------*)
PROCEDURE pipe ((* -- /AUS *) VAR ph : PipeBuf ): INTEGER;
(**)
#if MINT
VAR handle : ARRAY [0..1] OF SIGNEDWORD;
wres : SIGNEDWORD;
#endif
BEGIN
ph.readh := 0;
ph.writeh := 0;
#if MINT
IF MiNT > 0 THEN
Fpipe(ADR(handle), wres);
IF wres < eOK THEN
errno := INT(wres);
RETURN(-1);
ELSE
ph.readh := handle[0];
ph.writeh := handle[1];
RETURN(0);
END;
END;
#endif
errno := ENOSYS;
RETURN(-1);
END pipe;
(*---------------------------------------------------------------------------*)
#if MINT
PROCEDURE MiNTstat ( hndl : BOOLEAN;
sym : BOOLEAN;
h : INTEGER;
VAR path : ARRAY OF CHAR;
VAR st : StatRec ): INTEGER;
(*T*)
CONST
FSTAT = 00004600H;
VAR
lres : SIGNEDLONG;
xattr : RECORD
mode : modeT;
index : UNSIGNEDLONG;
dev : UNSIGNEDWORD;
res1 : UNSIGNEDWORD;
nlink : UNSIGNEDWORD;
uid : UNSIGNEDWORD;
gid : UNSIGNEDWORD;
size : SIGNEDLONG;
blksize : SIGNEDLONG;
nblocks : SIGNEDLONG;
mtime : WORDSET;
mdate : WORDSET;
atime : WORDSET;
adate : WORDSET;
ctime : WORDSET;
cdate : WORDSET;
attr : WORDSET;
res2 : SIGNEDWORD;
res3 : ARRAY [0..1] OF SIGNEDLONG;
END;
BEGIN
IF hndl THEN
Fcntl(VAL(SIGNEDWORD,h), ADR(xattr), FSTAT, lres);
ELSE
Fxattr(VAL(UNSIGNEDWORD,sym), ADR(path), ADR(xattr), lres);
END;
IF lres < EOKL THEN
errno := INT(lres);
RETURN(-1);
END;
WITH st DO
WITH xattr DO
stMode := mode;
stIno := index;
stDev := dev;
stNlink := nlink;
stUid := uid;
stGid := gid;
stSize := size;
stMtime.time := mtime;
stMtime.date := mdate;
stAtime.time := atime;
stAtime.date := adate;
stCtime.time := ctime;
stCtime.date := cdate;
END;
END;
RETURN(0);
END MiNTstat;
(*--------------------------------------------------------------------------*)
#endif
#if has_REF
PROCEDURE istat (REF name : ARRAY OF CHAR;
#else
PROCEDURE istat (VAR name : ARRAY OF CHAR;
#endif
VAR st : StatRec;
sym : BOOLEAN ): INTEGER;
(*T*)
CONST DIRSIZE = 1024;
VAR dta : DTA;
drive : UNSIGNEDWORD;
date : UNSIGNEDWORD;
err : INTEGER;
wres : SIGNEDWORD;
pLen : CARDINAL;
path0 : PathName;
c : CHAR;
ROOT : BOOLEAN;
DOT : BOOLEAN;
drv : BOOLEAN;
#if MINT
spcdrv : BOOLEAN;
#endif
BEGIN
UnixToDos(name, path0, DOT, drv);
IF NOT drv THEN
RETURN(-1);
END;
#if MINT
IF MiNT >= 9 THEN
RETURN(MiNTstat(FALSE, sym, 0, path0, st));
END;
#endif
pLen := SLEN(path0);
st.stUid := 0;
st.stGid := 0;
IF IsDosDevice(path0) THEN
WITH st DO
stIno := VAL(inoT,INODE); INC(INODE);
stMode := sIFCHR + STDPERM;
stDev := 0;
Tgettime(date);
stMtime.time := CAST(WORDSET,date);
Tgetdate(date);
stMtime.date := CAST(WORDSET,date);
stAtime.cmp := stMtime.cmp;
stCtime.cmp := stMtime.cmp;
stNlink := 1;
stSize := 0;
END;
RETURN(0);
END;
IF path0[1] = DDRVPOSTFIX THEN
st.stDev := VAL(devT,TOCARD(path0[0]) - 10);
drv := TRUE;
ELSE
Dgetdrv(drive);
st.stDev := VAL(devT,drive);
drv := FALSE;
END;
c := path0[0];
(* Hauptverzeichnisse muessen gesondert behandelt werden, da sie nicht
* wie Unterverzeichnisse in der Baumstruktur eingebunden sind - sie
* haben kein Erstellungsdatum und besitzen nicht die Eintraege
* "." und ".." zur Verkettung.
*)
IF (pLen = 1) AND (c = DDIRSEP)
OR drv AND (pLen = 3) AND (path0[2] = DDIRSEP)
THEN
(* Ein Hauptverzeichnis ist direkt angegeben, deshalb sind keine
* weiteren Tests noetig.
*)
ROOT := TRUE;
ELSE
IF path0[pLen-1] = DDIRSEP THEN
(* Verzeichnisse nicht extra kennzeichnen.
* 'pLen' ist mindestens zwei, da der Fall 'pLen' = 1
* oben abgefangen wird.
*)
path0[pLen-1] := EOS;
DEC(pLen);
ELSIF drv AND (pLen = 2) THEN
(* "Fsfirst("x:")" funktioniert nicht *)
path0[2] := '.';
path0[3] := EOS;
DOT := TRUE;
END;
IF DOT THEN
APPEND("\*.*", path0);
(* Den ersten Eintrag suchen, sodass bei allen Verzeichnissen - ausser
* den Hauptverzeichnissen - der Eintrag "." gefunden wird.
* (Bei "..\*.*" wird das "." des uebergeordneten Verzeichnisses
* gefunden.)
*)
END;
IF FindFirst(path0, FINDALL, dta, err) THEN
ROOT := DOT AND ((dta.name[0] <> '.') OR (dta.name[1] <> 0C));
(* nicht-leeres Hauptverzeichnis, falls der erste Eintrag nicht
* mit einem Punkt beginnt (normaler Dateiname), oder nach dem Punkt
* nicht beendet ist (dann kann es nicht "." sein, das in allen
* Verzeichnissen zuerst steht.
*)
ELSE
(* Wenn kein Eintrag gefunden wird und "." oder ".." angegeben
* wurden, handelt es sich um ein leeres Hauptverzeichnis,
* ansonsten ist ein Fehler aufgetreten (angegebene Datei wurde
* nicht gefunden).
*)
IF DOT AND (err = eFILNF) THEN
ROOT := TRUE;
ELSE
errno := err;
RETURN(-1);
END;
END;
END;
IF ROOT THEN
(* Einem Hauptverzeichnis lassen sich leider kaum Informationen
* entlocken.
*)
WITH st DO
stIno := 2;
stSize := DIRSIZE;
stNlink := 2;
stMode := sIFDIR + STDPERM + modeT{sIXUSR, sIXGRP, sIXOTH};
stMtime.cmp := 0;
stAtime.cmp := 0;
stCtime.cmp := 0;
END;
RETURN(0);
END;
WITH st DO
stIno := VAL(inoT,INODE); INC(INODE);
stMtime.date := dta.date;
stMtime.time := dta.time;
stAtime := stMtime;
stCtime := stMtime;
IF faSUBDIR IN dta.attr THEN
stSize := DIRSIZE;
stNlink := 2;
ELSE
stSize := dta.size;
stNlink := 1;
END;
#if MINT
IF MiNT > 0 THEN
spcdrv := TRUE;
IF stDev = 16 (*Q:\xxx*) THEN
stMode := sIFIFO + STDPERM;
ELSIF stDev = 21 (*V:\xxx*) THEN
stMode := sIFCHR + STDPERM;
ELSIF stDev = 23 (*X:\xxx*) THEN
stMode := modeT{Type14, Type15, sIRUSR, sIWUSR};
ELSE
spcdrv := FALSE;
END;
ELSE
spcdrv := FALSE;
END;
IF NOT spcdrv THEN
#endif
IF faSUBDIR IN dta.attr THEN
stMode := sIFDIR + STDPERM + modeT{sIXUSR, sIXGRP, sIXOTH};
ELSIF IsExec(path0) THEN
stMode := sIFREG + STDPERM + modeT{sIXUSR, sIXGRP, sIXOTH};
ELSE
stMode := sIFREG + STDPERM;
END;
#if MINT
END;
#endif
IF faRDONLY IN dta.attr THEN
stMode := stMode - modeT{sIWUSR, sIWGRP, sIWOTH};
END;
END; (* WITH st *)
RETURN(0);
END istat;
(*--------------------------------------------------------------------------*)
PROCEDURE stat ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* -- /AUS *) VAR st : StatRec ): INTEGER;
(*T*)
BEGIN
RETURN(istat(file, st, FALSE));
END stat;
(*--------------------------------------------------------------------------*)
PROCEDURE lstat ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* -- /AUS *) VAR st : StatRec ): INTEGER;
(*T*)
BEGIN
RETURN(istat(file, st, TRUE));
END lstat;
(*--------------------------------------------------------------------------*)
PROCEDURE fstat ((* EIN/ -- *) hndl : INTEGER;
(* -- /AUS *) VAR st : StatRec ): INTEGER;
(*T*)
#if MINT
CONST
EACCDNL = LIC(-36);
FIFOSIZE = 1024;
#endif
VAR drive : UNSIGNEDWORD;
date : UNSIGNEDWORD;
err : INTEGER;
pos : SIGNEDLONG;
size : SIGNEDLONG;
done : BOOLEAN;
time : ARRAY [0..1] OF WORDSET;
lres : SIGNEDLONG;
magic : UNSIGNEDWORD;
dummy : ARRAY [0..0] OF CHAR;
BEGIN
#if MINT
IF MiNT >= 9 THEN
RETURN(MiNTstat(TRUE, FALSE, hndl, dummy, st));
END;
#endif
WITH st DO
IF IsDevice(hndl) THEN
stMode := sIFCHR + STDPERM;
stSize := 0;
Tgettime(date);
stMtime.time := CAST(WORDSET,date);
Tgetdate(date);
stMtime.date := CAST(WORDSET,date);
stAtime.cmp := stMtime.cmp;
stCtime.cmp := stMtime.cmp;
ELSE
Fdatime(ADR(time), VAL(SIGNEDWORD,hndl), 0);
stMtime.time := time[0];
stMtime.date := time[1];
stAtime.cmp := stMtime.cmp;
stCtime.cmp := stMtime.cmp;
Seek(hndl, 0, ORD(SeekCur), pos, done);
IF done THEN
Seek(hndl, 0, ORD(SeekEnd), size, done);
stSize := size;
Seek(hndl, 0, ORD(SeekSet), size, done);
Fread(VAL(SIGNEDWORD,hndl), LC(2), ADR(magic), lres);
IF (lres = LIC(2)) AND ((magic = 601AH) OR (magic = 2321H))(* #! *) THEN
stMode := sIFREG + STDPERM + modeT{sIXUSR, sIXGRP, sIXOTH};
ELSE
stMode := sIFREG + STDPERM;
END;
Seek(hndl, pos, ORD(SeekSet), size, done);
#if MINT
ELSIF (MiNT > 0) AND (pos = EACCDNL) THEN
stSize := FIFOSIZE;
stMode := sIFIFO + STDPERM;
#endif
ELSE
errno := EBADF;
RETURN(-1);
END;
END;
Dgetdrv(drive);
stUid := 0;
stGid := 0;
stDev := VAL(devT,drive);
stNlink := 1;
stIno := VAL(inoT,INODE); INC(INODE);
END; (* WITH *)
RETURN(0);
END fstat;
(*--------------------------------------------------------------------------*)
PROCEDURE sISCHR ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFCHR);
END sISCHR;
(*--------------------------------------------------------------------------*)
PROCEDURE sISDIR ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFDIR);
END sISDIR;
(*--------------------------------------------------------------------------*)
PROCEDURE sISBLK ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFBLK);
END sISBLK;
(*--------------------------------------------------------------------------*)
PROCEDURE sISREG ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFREG);
END sISREG;
(*--------------------------------------------------------------------------*)
PROCEDURE sISFIFO ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFIFO);
END sISFIFO;
(*--------------------------------------------------------------------------*)
PROCEDURE sISLNK ((* EIN/ -- *) stMode : modeT ): BOOLEAN;
BEGIN
RETURN(stMode * sIFMT = sIFLNK);
END sISLNK;
(*--------------------------------------------------------------------------*)
PROCEDURE access ((* EIN/ -- *) REF file : ARRAY OF CHAR;
(* EIN/ -- *) acc : AccessMode ): INTEGER;
(*T*)
VAR dta : DTA;
st : StatRec;
#if MINT
wres : UNSIGNEDWORD;
#endif
BEGIN
IF istat(file, st, FALSE) < 0 THEN
RETURN(-1);
ELSIF acc = fOK THEN
RETURN(0);
END;
#if MINT
IF MiNT > 0 THEN
Pgetuid(wres);
END;
IF (MiNT < 9) OR (VAL(uidT,wres) = st.stUid) THEN
#endif
IF acc <= CAST(AccessMode,VAL(UNSIGNEDWORD,
CAST(UNSIGNEDWORD,st.stMode * sIRWXU) DIV 64))
THEN
RETURN(0);
ELSE
errno := EACCES;
RETURN(-1);
END;
#if MINT
END;
Pgetgid(wres);
IF VAL(gidT,wres) = st.stGid THEN
IF acc <= CAST(AccessMode,VAL(UNSIGNEDWORD,
CAST(UNSIGNEDWORD,st.stMode * sIRWXG) DIV 8))
THEN
RETURN(0);
ELSE
errno := EACCES;
RETURN(-1);
END;
END;
IF acc <= CAST(AccessMode,st.stMode * sIRWXO) THEN
RETURN(0);
ELSE
errno := EACCES;
RETURN(-1);
END;
#endif
END access;
(*==========================================================================*)
VAR
i : UNSIGNEDWORD;
BEGIN (* file *)
FOR i := 0 TO LBLKSIZE - 1 DO
zerofill[i] := 0;
END;
DOSVersion := DosVersion();
#if MINT
MiNT := MiNTVersion();
IF MiNT >= 9 THEN
Pumask(0, i);
UMASK := CAST(modeT,i);
Pumask(CAST(UNSIGNEDWORD,UMASK), i);
ELSE
#endif
UMASK := modeT{};
#if MINT
END;
#endif
END file.