home *** CD-ROM | disk | FTP | other *** search
- (*-------------------------------------------------------------------------*)
- (* *)
- (* Amiga Oberon Library Module: FileSystem Date: 02-Nov-92 *)
- (* *)
- (* © 1992 by Fridtjof Siebert *)
- (* *)
- (*-------------------------------------------------------------------------*)
-
- (*-------------------------------------------------------------------------
-
- Dieses Modul erleichtert das Arbeiten mit Dateien. Es stellt Prozeduren
- zur Dateiverwaltung zur Verfügung.
-
- Die Geschwindigkeit liegt normalerweise über der von Dos, da beim Lesen
- und Schreiben Puffer verwendet werden.
-
- Die Prozeduren, die ein boolsches Ergebnis liefern, waren immer
- erfolgreich, wenn sie TRUE zurückliefern. Ansonsten steht in der
- Variable File.status die Fehlernummer, die eine genauere Diagnose der
- Fehlerursache erlaubt.
-
- Die Prozedur Delete() macht das gleiche wie Close(), löscht danach aber
- die bearbeitete Datei.
-
- -------------------------------------------------------------------------*)
-
- MODULE FileSystem;
-
- IMPORT d * := Dos,
- e * := Exec,
- sys := SYSTEM,
- BT * := BasicTypes,
- sd := SecureDos;
-
- CONST
- BufSize = 1024;
-
- (* File.status: *)
-
- ok * = 0; (* alles in Ordnung *)
- eof * = 1; (* Dateiende erreicht *)
- readerr * = 2; (* Lesefehler *)
- writeerr * = 3; (* Schreibfehler *)
- onlyread * = 4; (* aus Datei darf nur gelesen werden *)
- onlywrite * = 5; (* in Datei darf nur geschrieben werden *)
- toofar * = 6; (* mit Move, Forward oder Backward zu weit gesprungen *)
- outofmem * = 7; (* kein freier Speicher mehr *)
- cantopen * = 8; (* konnte Datei nicht öffnen *)
- cantlock * = 9; (* konnte Datei nicht locken *)
-
- TYPE
- FilePtr * = POINTER TO File;
- File * = RECORD (BT.ANYDesc)
-
- handle - : d.FileHandlePtr;
- status - : INTEGER;
- write - : BOOLEAN;
- read - : BOOLEAN;
- name - : ARRAY 256 OF CHAR;
-
- buffer : POINTER TO ARRAY BufSize OF sys.BYTE;
- string - : BT.DynString;
- bufpos : INTEGER;
- buflen : LONGINT;
- pos : LONGINT;
- size : LONGINT;
- lastRead : BOOLEAN;
-
- END;
-
- VAR
- info: d.FileInfoBlock;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- (*------ Open: ------*)
-
-
- PROCEDURE Open*(VAR file: File;
- name: ARRAY OF CHAR;
- write: BOOLEAN): BOOLEAN;
-
- (* öffnet die Datei mit dem Namen 'name'. Ist write TRUE, wird die Datei
- neu erzeugt und zum Schreiben geöffnet. Sonst wird sie zum Lesen
- geöffnet. Das Ergebnis ist TRUE, wenn alles ordnungsgemäß verlief. *)
-
- VAR
- mode: INTEGER;
- lock: d.FileLockPtr;
-
- BEGIN
- file.buffer := NIL; file.handle := NIL; lock := NIL;
- LOOP
- NEW(file.buffer);
- COPY(name,file.name);
- IF write THEN mode := d.newFile
- ELSE mode := d.oldFile END;
- file.handle := sd.Open(name,mode);
- IF file.handle = NIL THEN file.status := cantopen; EXIT END;
- IF write THEN
- file.size := 0;
- ELSE
- lock := sd.Lock(name,d.sharedLock);
- IF lock=NIL THEN file.status := cantlock; EXIT END;
- IF ~ d.Examine(lock,info) THEN file.status := cantlock; EXIT END;
- file.size := info.size;
- sd.UnLock(lock);
- END;
- file.bufpos := 0;
- file.buflen := 0;
- file.pos := 0;
- file.write := write;
- file.read := ~ write;
- file.status := ok;
- RETURN TRUE;
- END;
- file.buffer := NIL;
- IF file.handle#NIL THEN sd.Close(file.handle); file.handle := NIL END;
- IF lock#NIL THEN sd.UnLock(lock) END;
- RETURN FALSE;
- END Open;
-
-
- (*------ OpenReadWrite: ------*)
-
-
- PROCEDURE OpenReadWrite*(VAR file: File;
- name: ARRAY OF CHAR): BOOLEAN;
-
- (* öffnet die Datei mit dem Namen 'name' zum wechselnd schreibenden
- und lesenden Zugriff. Das Ergebnis ist TRUE, wenn alles
- ordnungsgemäß verlief. *)
-
- VAR
- lock: d.FileLockPtr;
-
- BEGIN
- file.buffer := NIL; file.handle := NIL; lock := NIL;
- LOOP
- NEW(file.buffer);
- COPY(name,file.name);
- file.handle := sd.Open(name,d.oldFile);
- IF file.handle # NIL THEN
- lock := sd.Lock(name,d.sharedLock);
- IF lock=NIL THEN file.status := cantlock; EXIT END;
- IF ~ d.Examine(lock,info) THEN file.status := cantlock; EXIT END;
- file.size := info.size;
- sd.UnLock(lock);
- ELSE
- file.handle := sd.Open(name,d.newFile);
- IF file.handle = NIL THEN file.status := cantopen; EXIT END;
- file.size := 0;
- END;
- file.bufpos := 0;
- file.buflen := 0;
- file.pos := 0;
- file.write := TRUE;
- file.read := TRUE;
- file.status := ok;
- RETURN TRUE;
- END;
- file.buffer := NIL;
- IF file.handle#NIL THEN sd.Close(file.handle); file.handle := NIL END;
- IF lock#NIL THEN sd.UnLock(lock) END;
- RETURN FALSE;
- END OpenReadWrite;
-
-
- PROCEDURE WriteBuf(VAR file: File): BOOLEAN;
-
- VAR i,j,l: INTEGER;
-
- BEGIN
- i := 0; j := file.bufpos; file.bufpos := 0;
- REPEAT
- l := SHORT(d.Write(file.handle,file.buffer[i],j));
- IF l<0 THEN
- file.status := writeerr;
- RETURN FALSE
- END;
- INC(i,l); DEC(j,l);
- UNTIL j<=0;
- file.status := ok;
- RETURN TRUE;
- END WriteBuf;
-
-
-
- PROCEDURE EmptyWriteBuf(VAR file: File): BOOLEAN;
-
- BEGIN
- IF file.write & (file.bufpos#0) THEN RETURN WriteBuf(file) END;
- file.status := ok;
- RETURN TRUE;
- END EmptyWriteBuf;
-
-
- (*------ Close: ------*)
-
-
- PROCEDURE Close*(VAR file: File): BOOLEAN;
-
- (*
- * schließt die Datei file. Ergebnis ist TRUE, wenn alles korrekt verlief.
- *)
-
- VAR res: BOOLEAN;
-
- BEGIN
- file.status := ok;
- res := TRUE;
- IF file.write & (~ file.read OR ~ file.lastRead) THEN
- res := EmptyWriteBuf(file);
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- sd.Close(file.handle); file.handle := NIL;
- (* $IF GarbageCollector *)
- file.buffer := NIL;
- (* $ELSE *)
- DISPOSE(file.buffer);
- (* $END *)
- file.string := NIL;
- RETURN res;
- END Close;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- (*------ Read: ------*)
-
-
- PROCEDURE Read*(VAR file: File; VAR to: ARRAY OF sys.BYTE): BOOLEAN;
-
- (* liest LEN(to) Bytes aus file nach to. Ergebnis ist TRUE, wenn alles
- korrekt verlieft. *)
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
-
- BEGIN
- IF ~ file.read THEN file.status := onlywrite; RETURN FALSE END;
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- cnt := 0; bufpos := file.bufpos;
- WHILE cnt<LEN(to) DO
- IF (bufpos=file.buflen) THEN
- file.bufpos := 0; bufpos := 0;
- file.buflen := d.Read(file.handle,file.buffer^,BufSize);
- IF file.buflen=0 THEN file.status := eof; RETURN FALSE END;
- IF file.buflen<0 THEN file.status := readerr; RETURN FALSE END;
- END;
- to[cnt] := file.buffer[bufpos];
- INC(cnt); INC(bufpos);
- END;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- file.status := ok;
- RETURN TRUE;
- END Read;
-
-
- (*------ ReadChar: ------*)
-
-
- PROCEDURE ReadChar*(VAR file: File; VAR ch: CHAR): BOOLEAN;
-
- (* liest ein Zeichen aus file. Ergebnis ist TRUE, wenn alles korrekt
- verlieft. *)
-
- BEGIN
- IF ~ file.read THEN file.status := onlywrite; RETURN FALSE END;
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- IF (file.bufpos=file.buflen) THEN
- file.bufpos := 0;
- file.buflen := d.Read(file.handle,file.buffer^,BufSize);
- IF file.buflen=0 THEN file.status := eof; RETURN FALSE END;
- IF file.buflen<0 THEN file.status := readerr; RETURN FALSE END;
- END;
- ch := file.buffer[file.bufpos];
- INC(file.bufpos);
- INC(file.pos);
- file.status := ok;
- RETURN TRUE;
- END ReadChar;
-
-
- (*------ ReadString: ------*)
-
-
- PROCEDURE ReadString*(VAR file: File; VAR to: ARRAY OF CHAR): BOOLEAN;
-
- (* liest einen String aus file nach to. Stringende ist durch 0X oder 0AX
- markiert. Ergebnis ist TRUE, wenn alles korrekt verlieft. *)
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
- eos: BOOLEAN;
-
- BEGIN
- IF ~ file.read THEN file.status := onlywrite; RETURN FALSE END;
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- cnt := 0; bufpos := file.bufpos; eos := FALSE;
- WHILE (cnt<LEN(to)) & ~ eos DO
- IF (bufpos=file.buflen) THEN
- file.bufpos := 0; bufpos := 0;
- file.buflen := d.Read(file.handle,file.buffer^,BufSize);
- IF file.buflen=0 THEN file.status := eof; RETURN FALSE END;
- IF file.buflen<0 THEN file.status := readerr; RETURN FALSE END;
- END;
- to[cnt] := file.buffer[bufpos];
- CASE to[cnt] OF 0X,0AX: eos := TRUE; to[cnt] := 0X | ELSE END;
- INC(cnt); INC(bufpos);
- END;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- file.status := ok;
- RETURN TRUE;
- END ReadString;
-
-
- (*------ ReadLongString: ------*)
-
-
- PROCEDURE ReadLongString*(VAR file: File): BOOLEAN;
-
- (*
- * liest einen String aus file nach file.string. Stringende ist durch 0X oder 0AX
- * markiert. Ergebnis ist TRUE, wenn alles korrekt verlieft.
- *)
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
- eos: BOOLEAN;
- new: BT.DynString;
-
- BEGIN
- IF ~ file.read THEN file.status := onlywrite; RETURN FALSE END;
- IF file.string=NIL THEN
- NEW(file.string,100H);
- END;
- file.string[0] := 0X;
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- cnt := 0; bufpos := file.bufpos; eos := FALSE;
- REPEAT
- IF cnt>=LEN(file.string^) THEN
- NEW(new,2*cnt);
- COPY(file.string^,new^);
- file.string := new;
- END;
- IF (bufpos=file.buflen) THEN
- file.bufpos := 0; bufpos := 0;
- file.buflen := d.Read(file.handle,file.buffer^,BufSize);
- IF file.buflen=0 THEN file.status := eof; file.string[cnt] := 0X; RETURN FALSE END;
- IF file.buflen<0 THEN file.status := readerr; file.string[cnt] := 0X; RETURN FALSE END;
- END;
- file.string[cnt] := file.buffer[bufpos];
- CASE file.string[cnt] OF
- | 0X,0AX:
- eos := TRUE;
- file.string[cnt] := 0X
- ELSE END;
- INC(cnt);
- INC(bufpos);
- UNTIL eos;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- file.status := ok;
- RETURN TRUE;
- END ReadLongString;
-
-
- (*------ ReadBlock: ------*)
-
-
- PROCEDURE ReadBlock*(VAR file: File; to: e.APTR; size: LONGINT): BOOLEAN;
-
- (* liest size Bytes aus file nach to^. Ergebnis ist TRUE, wenn alles
- * korrekt verlieft.
- *)
-
- TYPE
- BytePtr = UNTRACED POINTER TO sys.BYTE;
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
- ptrtob: BytePtr;
-
- BEGIN
- IF ~ file.read THEN file.status := onlywrite; RETURN FALSE END;
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- ptrtob := to;
- cnt := 0; bufpos := file.bufpos;
- WHILE cnt<size DO
- IF (bufpos=file.buflen) THEN
- file.bufpos := 0; bufpos := 0;
- file.buflen := d.Read(file.handle,file.buffer^,BufSize);
- IF file.buflen=0 THEN file.status := eof; RETURN FALSE END;
- IF file.buflen<0 THEN file.status := readerr; RETURN FALSE END;
- END;
- ptrtob^ := file.buffer[bufpos];
- INC(cnt); ptrtob := sys.VAL(BytePtr,sys.VAL(LONGINT,ptrtob)+1); INC(bufpos);
- END;
- file.bufpos := bufpos;
- INC(file.pos,size);
- file.status := ok;
- RETURN TRUE;
- END ReadBlock;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- (*------ Write: ------*)
-
-
- PROCEDURE Write*(VAR file: File; from: ARRAY OF sys.BYTE): BOOLEAN; (* $CopyArrays- *)
-
- (* schreibt LEN(to) Bytes aus from in die Datei file. Ergebnis ist TRUE,
- * wenn alles korrekt verlieft.
- *)
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
-
- BEGIN
- IF ~ file.write THEN file.status := onlyread; RETURN FALSE END;
- IF file.read & file.lastRead THEN
- IF d.Seek(file.handle,file.pos,d.beginning)=0 THEN END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := FALSE;
- END;
- cnt := 0; bufpos := file.bufpos;
- WHILE cnt<LEN(from) DO
- IF (bufpos=BufSize) THEN
- file.bufpos := bufpos;
- bufpos := 0;
- IF ~ WriteBuf(file) THEN RETURN FALSE END;
- END;
- file.buffer[bufpos] := from[cnt];
- INC(cnt); INC(bufpos);
- END;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- IF file.pos>file.size THEN file.size := file.pos END;
- file.status := ok;
- RETURN TRUE;
- END Write;
-
-
- (*------ WriteChar: ------*)
-
-
- PROCEDURE WriteChar*(VAR file: File; ch: CHAR): BOOLEAN;
-
- (* schreibt 1 Char in die Datei file. Ergebnis ist TRUE, wenn alles korrekt
- verlieft. *)
-
- BEGIN
- IF ~ file.write THEN file.status := onlyread; RETURN FALSE END;
- IF file.read & file.lastRead THEN
- IF d.Seek(file.handle,file.pos,d.beginning)=0 THEN END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := FALSE;
- END;
- IF file.bufpos=BufSize THEN
- IF ~ WriteBuf(file) THEN RETURN FALSE END;
- END;
- file.buffer[file.bufpos] := ch;
- INC(file.bufpos);
- INC(file.pos);
- IF file.pos>file.size THEN file.size := file.pos END;
- file.status := ok;
- RETURN TRUE;
- END WriteChar;
-
-
- (*------ WriteString: ------*)
-
-
- PROCEDURE WriteString*(VAR file: File; from: ARRAY OF CHAR): BOOLEAN; (* $CopyArrays- *)
-
- (* schreibt String in die Datei. Danach wird eine LF in die Datei
- geschrieben. Ergebnis ist TRUE, wenn alles korrekt verlieft. *)
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
- eos: BOOLEAN;
-
- BEGIN
- IF ~ file.write THEN file.status := onlyread; RETURN FALSE END;
- IF file.read & file.lastRead THEN
- IF d.Seek(file.handle,file.pos,d.beginning)=0 THEN END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := FALSE;
- END;
- cnt := 0; bufpos := file.bufpos; eos := FALSE;
- WHILE (cnt<LEN(from)) & ~ eos DO
- IF (bufpos=BufSize) THEN
- file.bufpos := bufpos;
- bufpos := 0;
- IF ~ WriteBuf(file) THEN RETURN FALSE END;
- END;
- IF from[cnt] = 0X THEN
- eos := TRUE;
- file.buffer[bufpos] := 0AX;
- ELSE
- file.buffer[bufpos] := from[cnt];
- END;
- INC(cnt); INC(bufpos);
- END;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- IF file.pos>file.size THEN file.size := file.pos END;
- file.status := ok;
- RETURN TRUE;
- END WriteString;
-
-
- (*------ WriteBlock: ------*)
-
-
- PROCEDURE WriteBlock*(VAR file: File; from: e.APTR; size: LONGINT): BOOLEAN;
-
- (* schreibt size Bytes aus from^ in die Datei file. Ergebnis ist TRUE, wenn
- alles korrekt verlieft. *)
-
- TYPE
- BytePtr = UNTRACED POINTER TO sys.BYTE;
-
- VAR
- cnt: LONGINT;
- bufpos: INTEGER;
- ptrtob: BytePtr;
-
- BEGIN
- IF ~ file.write THEN file.status := onlyread; RETURN FALSE END;
- IF file.read & file.lastRead THEN
- IF d.Seek(file.handle,file.pos,d.beginning)=0 THEN END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := FALSE;
- END;
- cnt := 0; bufpos := file.bufpos; ptrtob := from;
- WHILE cnt<size DO
- IF (bufpos=BufSize) THEN
- file.bufpos := bufpos;
- bufpos := 0;
- IF ~ WriteBuf(file) THEN RETURN FALSE END;
- END;
- file.buffer[bufpos] := ptrtob^;
- INC(cnt); INC(bufpos); ptrtob := sys.VAL(BytePtr,sys.VAL(LONGINT,ptrtob)+1);
- END;
- file.bufpos := bufpos;
- INC(file.pos,cnt);
- IF file.pos>file.size THEN file.size := file.pos END;
- file.status := ok;
- RETURN TRUE;
- END WriteBlock;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- (*------ Size: ------*)
-
-
- PROCEDURE Size*(VAR file: File): LONGINT;
-
- (* Ergibt die Größe der Datei *)
-
- BEGIN
- RETURN file.size;
- END Size;
-
-
- (*------ Position: ------*)
-
-
- PROCEDURE Position* (VAR file: File): LONGINT;
-
- (* Ergibt die aktuelle Position innerhalb der Datei *)
-
- BEGIN
- RETURN file.pos;
- END Position;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- (*------ Move: ------*)
-
-
- PROCEDURE Move*(VAR file: File; to: LONGINT): BOOLEAN;
-
- (* spring an die Stelle to (vom Dateianfang ausgehend). Ergebnis ist TRUE,
- wenn alles korrekt verlieft. *)
-
- VAR l: LONGINT;
-
- BEGIN
- IF file.write & ~ file.lastRead THEN
- IF ~ EmptyWriteBuf(file) THEN RETURN FALSE END;
- file.bufpos := 0;
- file.buflen := 0;
- file.lastRead := TRUE;
- END;
- IF (to>file.size) OR (to<0) THEN file.status := toofar; RETURN FALSE END;
- IF d.Seek(file.handle,to,d.beginning)=0 THEN END;
- file.status := ok;
- file.buflen := 0;
- file.bufpos := 0;
- file.pos := to;
- RETURN TRUE;
- END Move;
-
-
- (*------ Forward: ------*)
-
-
- PROCEDURE Forward*(VAR file: File; to: LONGINT): BOOLEAN;
-
- (* überspringt to Bytes. Ergebnis ist TRUE, wenn alles korrekt verlieft. *)
-
- BEGIN
- RETURN Move(file,file.pos+to);
- END Forward;
-
-
- (*------ Backward: ------*)
-
-
- PROCEDURE Backward*(VAR file: File; to: LONGINT): BOOLEAN;
-
- (* springt to Bytes zurück . Ergebnis ist TRUE, wenn alles korrekt
- verlieft. *)
-
- BEGIN
- RETURN Move(file,file.pos-to);
- END Backward;
-
-
- (*-------------------------------------------------------------------------*)
-
- PROCEDURE Delete*(VAR file: File): BOOLEAN;
-
- (* schließt und löscht die Datei *)
-
- BEGIN
- IF file.handle#NIL THEN IF Close(file) THEN END END;
- RETURN d.DeleteFile(file.name);
- END Delete;
-
-
- (*-------------------------------------------------------------------------*)
-
-
- PROCEDURE Exists*(name: ARRAY OF CHAR): BOOLEAN;
-
- (* prüft, ob die Datei mit dem Namen 'name' existiert. *)
-
- VAR lock: d.FileLockPtr;
-
- BEGIN
- lock := sd.Lock(name,d.sharedLock);
- IF lock#NIL THEN
- sd.UnLock(lock); RETURN TRUE
- ELSE
- RETURN FALSE;
- END;
- END Exists;
-
-
- END FileSystem.
-
-
-
-