home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1993-10-23 | 16.3 KB | 641 lines |
- IMPLEMENTATION MODULE DosFile;
- (*__NO_CHECKS__*)
- (*****************************************************************************)
- (* "UnixToDos()" basiert auf der MiNTLIB von Eric R. Smith *)
- (* --------------------------------------------------------------------------*)
- (* STATUS: IN ARBEIT *)
- (* --------------------------------------------------------------------------*)
- (* 11-Feb-93, Holger Kleinschmidt *)
- (*****************************************************************************)
-
- VAL_INTRINSIC
- CAST_IMPORT
- OSCALL_IMPORT
-
- FROM SYSTEM IMPORT
- (* TYPE *) ADDRESS,
- (* PROC *) ADR;
-
- FROM CTYPE IMPORT
- (* PROC *) TOLOWER, TOUPPER, ISALPHA, TODIGIT, TOCARD;
-
- FROM pSTRING IMPORT
- (* CONST*) EOS,
- (* TYPE *) StrPtr, StrRange,
- (* PROC *) SLEN, COPY, ASSIGN, APPEND, DELETE, EQUAL, EQUALN, UPPER, TOKEN,
- RPOSCHR;
-
- FROM types IMPORT
- (* CONST*) PATHMAX, NULL, DDIRSEP, XDIRSEP, DDRVPOSTFIX, XDEVPREFIX, SUFFIXSEP,
- (* TYPE *) SIGNEDWORD, SIGNEDLONG, UNSIGNEDLONG, UNSIGNEDWORD, FileName,
- PathName;
-
- FROM err IMPORT
- (* CONST*) eRANGE, ENAMETOOLONG, ENOENT,
- (* VAR *) errno;
-
- FROM cmdline IMPORT
- (* PROC *) getenv, GetEnvVar;
-
- #if MINT
- FROM DosSystem IMPORT MiNTVersion;
- #endif
-
- #include "oscalls.m2h"
-
- (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
-
- CONST
- EOKL = LIC(0);
- #if no_MIN_MAX
- MAXCARD = CAST(CARDINAL,-1);
- #else
- MAXCARD = MAX(CARDINAL);
- #endif
-
- #if MINT
- VAR
- MiNT : CARDINAL;
- #endif
-
- (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
-
- PROCEDURE isexec (VAR path : ARRAY OF CHAR;
- default : ARRAY OF CHAR;
- var : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- CONST
-
- VAR sIdx,dIdx : INTEGER;
- l1, l2 : CARDINAL;
- hasExt : BOOLEAN;
- tIdx : CARDINAL;
- ext : FileName;
- token : FileName;
- suffices : PathName;
-
- BEGIN
- sIdx := RPOSCHR(MAXCARD, SUFFIXSEP, path);
- dIdx := RPOSCHR(MAXCARD, DDIRSEP, path);
-
- IF sIdx <= dIdx THEN
- RETURN(FALSE);
- ELSE
- COPY(sIdx+1, MAXCARD, path, ext);
- END;
-
- IF NOT GetEnvVar(var, suffices) THEN
- ASSIGN(default, suffices);
- END;
-
- (* moeglicherweise ist die Nichtunterscheidung von Klein/Grossbuchstaben
- * falsch, keine Ahnung...
- *)
- UPPER(suffices);
- UPPER(ext);
-
- tIdx := 0; l1 := 0;
- WHILE TOKEN(suffices, ";,", tIdx, l1, l2, token) DO
- IF EQUAL(ext, token) THEN
- RETURN(TRUE);
- END;
- END;
- RETURN(FALSE);
- END isexec;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE IsExec ((* EIN/ -- *) VAR path : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- BEGIN
- RETURN(isexec(path, EXECSUFFIX, "SUFFIX"));
- END IsExec;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE IsGEMExec ((* EIN/ -- *) VAR path : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- BEGIN
- RETURN(isexec(path, GEMEXT, "GEMEXT"));
- END IsGEMExec;
-
- (*---------------------------------------------------------------------------*)
- #if GEMDOS
- PROCEDURE IsTOSExec ((* EIN/ -- *) VAR path : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- BEGIN
- RETURN(isexec(path, TOSEXT, "TOSEXT"));
- END IsTOSExec;
- #elif PCDOS
- PROCEDURE IsDOSExec ((* EIN/ -- *) VAR path : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- BEGIN
- RETURN(isexec(path, DOSEXT, "DOSEXT"));
- END IsDOSExec;
- #endif
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE PrefixLen (VAR path : ARRAY OF CHAR): CARDINAL;
- (*T*)
- VAR i : CARDINAL;
- c : CHAR;
- BEGIN
- i := 0;
- REPEAT
- c := path[i];
- INC(i);
- UNTIL (i > VAL(CARDINAL,HIGH(path))) OR (c = EOS) OR (c = DDIRSEP)
- OR (c = XDIRSEP)
- OR (c = DDRVPOSTFIX);
- IF c = DDRVPOSTFIX THEN
- RETURN(i);
- ELSE
- RETURN(0);
- END;
- END PrefixLen;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE IsDosDevice ((* EIN/ -- *) VAR path : ARRAY OF CHAR ): BOOLEAN;
- (*T*)
- VAR i : CARDINAL;
- BEGIN
- i := PrefixLen(path);
- RETURN((i > 2) AND ((i > VAL(CARDINAL,HIGH(path))) OR (path[i] = EOS)));
- END IsDosDevice;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE CompletePath ((* EIN/ -- *) VAR path : ARRAY OF CHAR;
- (* -- /AUS *) VAR full : PathName;
- (* -- /AUS *) VAR len : CARDINAL;
- (* -- /AUS *) VAR err : INTEGER ): BOOLEAN;
-
- (**)
- VAR wres : SIGNEDWORD;
- drv : UNSIGNEDWORD;
- pIdx : CARDINAL;
- fIdx : CARDINAL;
-
- BEGIN
- IF (path[0] = 0C) OR (path[1] <> DDRVPOSTFIX) THEN
- (* Wenn kein Laufwerk angegeben ist, aktuelles Laufwerk ermitteln *)
- Dgetdrv(drv);
- full[0] := TODIGIT(VAL(CARDINAL,drv) + 10);
- pIdx := 0;
- INC(drv); (* fuer "Dgetpath" *)
- ELSE
- (* sonst angegebenes Laufwerk uebernehmen *)
- full[0] := path[0];
- pIdx := 2;
- drv := VAL(UNSIGNEDWORD,TOCARD(path[0]) - 10 + 1);
- END;
- full[1] := DDRVPOSTFIX;
-
- fIdx := 2;
- err := 0;
- IF path[pIdx] <> DDIRSEP THEN
- (* relativer Pfad angegeben -> aktuellen Pfad ermitteln *)
- #if MINT
- IF MiNT >= 96 THEN
- Dgetcwd(ADR(full[2]), drv, PATHMAX+1-2, wres);
- ELSE
- #endif
- Dgetpath(ADR(full[2]), drv, wres);
- #if MINT
- END;
- #endif
- err := INT(wres);
- IF err < 0 THEN
- RETURN(FALSE);
- END;
-
- WHILE (fIdx <= PATHMAX) AND (full[fIdx] <> 0C) DO
- INC(fIdx);
- END;
- IF fIdx > PATHMAX THEN
- (* Ist wahrscheinlich schon zu spaet, da ueber <full> hinaus
- * geschrieben wurde, aber schaden kanns auch nicht.
- *)
- err := eRANGE;
- RETURN(FALSE);
- ELSE
- IF (fIdx = 2) OR (path[pIdx] <> 0C) THEN
- (* Ein Wurzelverzeichnis muss mit einem Backslash gekennzeichnet
- * werden. Wenn ein (relativer) Pfad angegeben war, muss ebenfalls
- * ein Backslash zur Trennung eingefuegt werden.
- *)
- full[fIdx] := DDIRSEP;
- INC(fIdx);
- END;
- END;
- END;
-
- WHILE (pIdx <= VAL(CARDINAL,HIGH(path))) AND (path[pIdx] <> 0C)
- AND (fIdx <= PATHMAX)
- DO
- full[fIdx] := path[pIdx];
- INC(fIdx);
- INC(pIdx);
- END;
-
- IF fIdx > PATHMAX THEN
- err := eRANGE;
- RETURN(FALSE);
- ELSE
- full[fIdx] := 0C;
- len := fIdx;
- RETURN(TRUE);
- END;
- END CompletePath;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE DosToUnix ((* EIN/ -- *) dpath : ARRAY OF CHAR;
- (* -- /AUS *) VAR xpath : ARRAY OF CHAR;
- (* -- /AUS *) VAR xlen : CARDINAL );
- (**)
- VAR dIdx : CARDINAL;
- dLen : CARDINAL;
- pre : CARDINAL;
- c : CHAR;
- drv : CHAR;
- pipe : BOOLEAN;
- device : BOOLEAN;
- tmp : ARRAY [0..9] OF CHAR;
- tmpLen : CARDINAL;
-
- BEGIN
- dIdx := 0;
- WHILE (dIdx <= VAL(CARDINAL,HIGH(dpath))) AND (dpath[dIdx] <> 0C) DO
- (* \ --> / und gegebenenfalls in Kleinbuchstaben wandeln *)
- c := dpath[dIdx];
- IF c = DDIRSEP THEN
- c := XDIRSEP;
- #if MINT
- ELSIF MiNT < 7 THEN
- #else
- ELSE
- #endif
- c := TOLOWER(c);
- END;
- dpath[dIdx] := c;
- INC(dIdx);
- END;
-
- dLen := dIdx;
- pre := PrefixLen(dpath);
- drv := TOUPPER(dpath[0]);
-
- IF pre = 2 THEN
- (* Laufwerk, "x:" *)
- pipe := FALSE;
- device := FALSE;
- dIdx := 2;
- #if MINT
- IF MiNT > 0 THEN
- IF drv = 'Q' THEN
- pipe := TRUE;
- ELSIF drv = 'V' THEN
- device := TRUE;
- ELSIF (MiNT >= 9) AND (drv = 'U') THEN
- c := dpath[0];
- dpath[0] := drv;
- IF EQUALN(7, "U:/pipe", dpath) THEN
- pipe := (dLen = 7) OR (dpath[7] = XDIRSEP);
- IF pipe THEN
- dIdx := 7;
- END;
- ELSIF EQUALN(6, "U:/dev", dpath) THEN
- device := (dLen = 6) OR (dpath[6] = XDIRSEP);
- IF device THEN
- dIdx := 6;
- END;
- END;
- dpath[0] := c;
- END;
- END; (* IF MiNT *)
-
- IF pipe THEN
- tmp := "/pipe";
- tmpLen := 5;
- ELSIF device THEN
- tmp := "/dev";
- tmpLen := 4;
- ELSE
- #endif
- tmp := "/dev/@";
- tmp[5] := drv;
- tmpLen := 6;
- #if MINT
- END; (* IF pipe *)
- #endif
- IF (dIdx < dLen) AND (dpath[dIdx] <> XDIRSEP) THEN
- tmp[tmpLen] := XDIRSEP;
- INC(tmpLen);
- END;
- ELSIF pre = 1 THEN
- (* duerfte nicht auftreten, ":xxx" *)
- tmp[0] := XDIRSEP;
- tmp[1] := EOS;
- tmpLen := 1;
- dIdx := 1;
- ELSE
- dIdx := 0; (* nichts vom "DOS"-Pfad loeschen *)
- IF pre > 2 THEN
- IF EQUAL("con:", dpath) THEN
- ASSIGN("/dev/tty", xpath);
- xlen := 8;
- RETURN;
- ELSE
- tmp := "/dev/";
- tmpLen := 5;
- dpath[pre-1] := EOS; (* den Doppelpunkt loeschen *)
- END;
- END;
- END; (* IF pre *)
-
- DELETE(0, dIdx, dpath);
- ASSIGN(tmp, xpath);
- APPEND(dpath, xpath);
- xlen := dLen - dIdx + tmpLen;
- END DosToUnix;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE UnixToDos ((* EIN/ -- *) xpath : ARRAY OF CHAR;
- (* -- /AUS *) VAR dpath : PathName;
- (* -- /AUS *) VAR dot : BOOLEAN;
- (* -- /AUS *) VAR done : BOOLEAN );
-
- (**)
- VAR xIdx : CARDINAL;
- xLen : CARDINAL;
- dIdx : CARDINAL;
- wres : SIGNEDWORD;
- ROOT : BOOLEAN;
- c : CHAR;
-
- BEGIN
- Dgetpath(ADR(dpath[0]), 0, wres);
- ROOT := dpath[0] = 0C;
-
- dpath[0] := 0C;
- done := FALSE;
- dot := FALSE;
-
- xIdx := 0;
- dIdx := 0;
- xLen := SLEN(xpath);
- IF xLen = 0 THEN
- errno := ENOENT;
- RETURN;
- END;
-
- IF EQUALN(5, XDEVPREFIX, xpath) THEN
- (* xpath = /dev/... *)
- IF (xLen > 5) AND ISALPHA(xpath[5]) AND ( (xLen = 6)
- OR (xpath[6] = XDIRSEP)
- OR (xpath[6] = DDIRSEP))
- THEN
- (* "GEMDOS"-Laufwerksbezeichner: /dev/A, /dev/A/..., /dev/A\... --> A: *)
- dpath[0] := xpath[5];
- dpath[1] := DDRVPOSTFIX;
- dIdx := 2;
- xIdx := 6;
- #if MINT
- ELSIF MiNT > 0 THEN
- xIdx := 5;
- (* Geraete sind bei MiNT ueber Laufwerk 'V' oder 'U' ansprechbar:
- * /dev/con --> V:\con, bzw. U:\dev\con
- *)
- IF MiNT >= 9 THEN
- ASSIGN("U:\dev\\", dpath); (* \\ wegen Praeprozessor... *)
- dIdx := 7;
- ELSE
- ASSIGN("V:\\", dpath); (* ... *)
- dIdx := 3;
- END;
- #endif
- ELSE
- IF EQUAL("/dev/tty", xpath) THEN
- ASSIGN("con:", dpath);
- done := TRUE;
- ELSE
- IF xpath[xLen-1] <> DDRVPOSTFIX THEN
- dIdx := 1; (* Flag: ":" anfuegen *)
- END;
- IF xLen - 5 + dIdx <= PATHMAX THEN
- COPY(5, xLen, xpath, dpath); (* /dev/ ueberspringen *)
- IF dIdx = 1 THEN
- dpath[xLen-5] := DDRVPOSTFIX;
- dpath[xLen-4] := EOS;
- END;
- done := TRUE;
- END;
- END;
- RETURN;
- END;
- #if MINT
- ELSIF (MiNT > 0) AND EQUALN(6, "/pipe/", xpath) THEN
- xIdx := 6;
- (* Pipes koenne je nach MiNT-Version ueber Laufwerk Q: oder U:
- * angesprochen werden: /pipe/... --> Q:\..., oder U:\pipe\...
- *)
- IF MiNT >= 9 THEN
- ASSIGN("U:\pipe\\", dpath);
- dIdx := 8;
- ELSE
- ASSIGN("Q:\\", dpath);
- dIdx := 3;
- END;
- #endif
- ELSIF ((xpath[0] = DDIRSEP) OR (xpath[0] = XDIRSEP)) AND (ROOTDIR <> 0C) THEN
- dpath[0] := ROOTDIR;
- dpath[1] := DDRVPOSTFIX;
- dIdx := 2;
- END;
-
- WHILE (dIdx <= PATHMAX) AND (xIdx < xLen) DO
- c := xpath[xIdx];
- IF c = XDIRSEP THEN (* / --> \ *)
- c := DDIRSEP;
- END;
- dpath[dIdx] := c;
- INC(xIdx);
- INC(dIdx);
- END;
-
- (* Die Zuweisung an CHAR-Variable steht hier nur, weil der nachfolgende
- * Ausdruck moeglicherweise zu komplex fuer den einen oder anderen
- * Compiler ist (-> TDI).
- *)
- IF dIdx > 1 THEN
- c := dpath[dIdx-2];
- ELSE
- c := 0C;
- END;
- dot := (dIdx > 0)
- AND (dpath[dIdx-1] = '.')
- AND ((dIdx = 1)
- OR (c = DDIRSEP)
- OR (c = DDRVPOSTFIX)
- OR (c = '.')
- AND ((dIdx = 2)
- OR (dpath[dIdx-3] = DDIRSEP)
- OR (dpath[dIdx-3] = DDRVPOSTFIX)));
-
- (* Da bei "GEMDOS" die Eintraege "." und ".." im Hauptverzeichnis nicht
- * existieren, werden sie durch das Hauptverzeichnis ersetzt, falls mit
- * Sicherheit festgestellt werden kann, dass das Hauptverzeichnis gemeint ist.
- * Dies ist auch korrekt, wenn ein Dateisystem benutzt wird, dass diese
- * Eintraege hat, da sie aufs Hauptverzeichnis verweisen.
- *
- * Es gibt folgende Faelle:
- * - "\.", "\..", absoluter Pfad
- * hier kann sofort korrigiert werden.
- *
- * - ".", "..", relativer Pfad
- * hier muss zuerst festgestellt werden, ob das aktuelle Verzeichnis
- * das Hauptverzeichnis ist.
- *
- * - alle anderen Faelle (wenn "." oder ".." als Teil einer Pfadangabe
- * auftreten, auch wenn nur ein Laufwerk angegeben ist) werden hier
- * nicht korrigiert, da dies einen grossen Aufwand bedeutet, aber
- * seltener auftritt.
- *)
-
- c := dpath[0];
-
- IF dot AND (
- (*"."*) (dIdx = 1) AND ROOT
- (*"\."*) OR (dIdx = 2) AND ( (c = DDIRSEP)
- (*".."*) OR (c = '.') AND ROOT)
- (*"\.."*) OR (dIdx = 3) AND (c = DDIRSEP) AND (dpath[1] = '.'))
- THEN
- dpath[0] := DDIRSEP;
- dIdx := 1;
- dot := FALSE; (* wurde durch Wurzelverzeichnis ersetzt *)
- END;
-
- IF dIdx <= PATHMAX THEN
- dpath[dIdx] := 0C;
- done := TRUE;
- ELSE
- dpath[0] := 0C;
- errno := ENAMETOOLONG;
- END;
- END UnixToDos;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE FindFirst ((* EIN/ -- *) VAR path : PathName;
- (* EIN/ -- *) attr : FileAttribute;
- (* EIN/AUS *) VAR dta : DTA;
- (* -- /AUS *) VAR res : INTEGER ): BOOLEAN;
- (*T*)
- VAR olddta : ADDRESS;
- wres : SIGNEDWORD;
-
- BEGIN
- Fgetdta(olddta);
- Fsetdta(ADR(dta));
- Fsfirst(ADR(path), CAST(UNSIGNEDWORD,attr), wres);
- Fsetdta(olddta);
- res := INT(wres);
- IF wres < 0 THEN
- RETURN(FALSE);
- ELSE
- RETURN(TRUE);
- END;
- END FindFirst;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE FindNext ((* EIN/AUS *) VAR dta : DTA;
- (* -- /AUS *) VAR res : INTEGER ): BOOLEAN;
- (*T*)
- VAR olddta : ADDRESS;
- wres : SIGNEDWORD;
-
- BEGIN
- Fgetdta(olddta);
- Fsetdta(ADR(dta));
- Fsnext(wres);
- Fsetdta(olddta);
- res := INT(wres);
- IF wres < 0 THEN
- RETURN(FALSE);
- ELSE
- RETURN(TRUE);
- END;
- END FindNext;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE Seek ((* EIN/ -- *) hndl : INTEGER;
- (* EIN/ -- *) off : SIGNEDLONG;
- (* EIN/ -- *) mode : CARDINAL;
- (* -- /AUS *) VAR pos : SIGNEDLONG;
- (* -- /AUS *) VAR done : BOOLEAN );
- (*T*)
- VAR lres : SIGNEDLONG;
-
- BEGIN
- Fseek(off, VAL(SIGNEDWORD,hndl), VAL(UNSIGNEDWORD,mode), lres);
- pos := lres;
- done := lres >= EOKL;
- END Seek;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE IsDevice ((* EIN/ -- *) h : INTEGER ): BOOLEAN;
- (*T*)
- VAR old : SIGNEDLONG;
- lres : SIGNEDLONG;
- done : BOOLEAN;
-
- BEGIN
- Seek(h, 0, 1, old, done);
- Seek(h, 1, 0, lres, done);
- Seek(h, old, 0, old, done);
-
- RETURN(lres = LIC(0));
- END IsDevice;
-
- (*===========================================================================*)
-
- VAR xmode : StrPtr;
- i : StrRange;
- wres : UNSIGNEDWORD;
-
- BEGIN (* DosFile *)
- INODE := 32 (* ?? *);
- ROOTDIR := 0C;
- xmode := getenv("UNIXMODE");
- IF xmode <> NULL THEN
- i := 0;
- WHILE xmode^[i] <> 0C DO
- IF (xmode^[i] = 'r') AND (xmode^[i+1] <> 0C) THEN
- ROOTDIR := TOLOWER(xmode^[i+1]);
- END;
- INC(i);
- END;
- END;
-
- IF (getenv("STDERR") = NULL) AND IsDevice(2) THEN
- (* siehe Profibuch von 1992 *)
- Fforce(2, -1, wres);
- END;
- #if MINT
- MiNT := MiNTVersion();
-
- IF (ROOTDIR = 0C) AND (MiNT >= 9) THEN
- Dgetdrv(wres);
- IF wres = 20(*U*) THEN
- ROOTDIR := 'u';
- END;
- END;
- #endif
- END DosFile.
-