pkgobj/src/Common/FileSys.m3


Copyright (C) 1994, Digital Equipment Corp.
FileSys.m3

MODULE FileSys;

IMPORT OSError, TextList, Rd, Text, Thread, Time, Wr, WeakRef;
IMPORT FileRd, FileWr, FS, Pathname;

PROCEDURE OpenRead(fn: FN) : Rd.T RAISES {OSError.E} =
  VAR rd: Rd.T;
  BEGIN
    IF fn = NIL THEN fn := ""; END;
    rd := FileRd.Open(fn);
    EVAL WeakRef.FromRef(rd, CloseRd);
    RETURN rd;
  END OpenRead;

PROCEDURE OpenWrite(fn: FN) : Wr.T RAISES {OSError.E} =
  VAR wr: Wr.T;
  BEGIN
    IF fn = NIL THEN fn := ""; END;
    wr := FileWr.Open(fn);
    EVAL WeakRef.FromRef(wr, CloseWr);
    RETURN wr;
  END OpenWrite;

PROCEDURE OpenAppend(fn: FN) : Wr.T RAISES {OSError.E} =
  VAR wr: Wr.T;
  BEGIN
    IF fn = NIL THEN fn := ""; END;
    wr := FileWr.OpenAppend(fn);
    EVAL WeakRef.FromRef(wr, CloseWr);
    RETURN wr;
  END OpenAppend;

PROCEDURE CloseRd(<*UNUSED*> READONLY w: WeakRef.T; r: REFANY) =
    <* FATAL Thread.Alerted *>
  BEGIN
    TRY Rd.Close(r); EXCEPT Rd.Failure => END;
  END CloseRd;

PROCEDURE CloseWr(<*UNUSED*> READONLY w: WeakRef.T; r: REFANY) =
    <* FATAL Thread.Alerted *>
  BEGIN
    TRY Wr.Close(r); EXCEPT Wr.Failure => END;
  END CloseWr;

PROCEDURE Enumerate (fn: FN): Enumeration RAISES {OSError.E} =
  VAR
    res, tail, l: TextList.T := NIL;
    t: TEXT;
    i: FS.Iterator;
  BEGIN
    IF fn = NIL THEN fn := ""; END;
    TRY
      i := FS.Iterate(fn);
      WHILE i.next(t) DO
        l := TextList.Cons(t, NIL);
        IF res = NIL THEN
          res := l;
        ELSE
          tail.tail := l;
        END;
        tail := l;
      END;
    FINALLY
      i.close();
    END;
    RETURN res;
  END Enumerate;

PROCEDURE MakeDir (path: FN) RAISES {OSError.E} =
  BEGIN
    FS.CreateDirectory(path);
  END MakeDir;

PROCEDURE SetModifiedDate (path: FN; date: Time.T) RAISES {OSError.E} =
  BEGIN
    FS.SetModificationTime(path, date);
  END SetModifiedDate;

PROCEDURE Rename (source, dest: FN) RAISES {OSError.E} =
  BEGIN
    FS.Rename(source, dest);
  END Rename;

PROCEDURE Remove (path: FN; recursive: BOOLEAN := FALSE)
    RAISES {OSError.E} =
    (* iff recursive, we'll remove entire dir, otherwise the target
       must be a non-directory *)
  VAR waitCtr: CARDINAL;
  CONST WaitInterval = 10;
  PROCEDURE RemoveTreeInternal (thisPath: Text.T) RAISES {OSError.E} =
    VAR
      info: FileInfo;
      eList: TextList.T;
    BEGIN
      DEC (waitCtr);
      IF waitCtr = 0 THEN
        waitCtr := WaitInterval; Thread.Pause (5.0D-2);
      END;
      info := GetInfo(thisPath);
      IF recursive THEN
        IF info.type = FileType.Dir THEN
          EVAL CheckAccess(thisPath, TRUE, TRUE);
          eList := Enumerate(thisPath);
          WHILE eList # NIL DO
            RemoveTreeInternal (Pathname.Join(thisPath, eList.head, NIL));
            eList := eList.tail;
          END;
        END;
      END;
      IF info.type = FileType.Dir THEN
        FS.DeleteDirectory(thisPath);
      ELSE
        FS.DeleteFile(thisPath);
      END;
    END RemoveTreeInternal;
  BEGIN
    waitCtr := WaitInterval;
    IF path = NIL THEN path := ""; END;
    RemoveTreeInternal (path);
  END Remove;

BEGIN
END FileSys.