| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- IMPLEMENTATION MODULE HandleIO;
- (*
- * REPERTOIRE
- * Release 1.6
- * By Charles Bradford and Cole Brecheen
- * (c) Copyright 1985-1992 PMI
- * Green Bay, Wisconsin
- * All rights reserved
- * (414) 468-6040
- *
- * $Header: D:/logfiles/mods/handleio.mov 1.5 17 Mar 1991 17:54:52 coleb $
- *
- *)
- (*EntryDiag:
- IMPORT Diagnostics;
- :EntryDiag*)
- IMPORT FAPI;
- IMPORT ByteFiddler;
- IMPORT Drectory;
- IMPORT EnvironUtils;
- IMPORT ErrorManager;
- IMPORT LowLevel;
- IMPORT M2Strings;
- IMPORT Numbers;
- IMPORT NumTypes;
- IMPORT StrEdit;
- IMPORT StringIO;
- IMPORT SYSTEM;
- IMPORT VStorage;
- VAR
- Initialized : BOOLEAN;
- PROCEDURE Init();
- BEGIN
- IF Initialized THEN
- RETURN;
- ELSE
- Initialized := TRUE;
- END;
- (*EntryDiag:
- Diagnostics.Init();
- :EntryDiag*)
- ByteFiddler.Init();
- Drectory.Init();
- EnvironUtils.Init();
- ErrorManager.Init();
- LowLevel.Init();
- M2Strings.Init();
- Numbers.Init();
- NumTypes.Init();
- StrEdit.Init();
- StringIO.Init();
- VStorage.Init();
- (*EntryDiag:
- Diagnostics.diagS( 'Entering HandleIO', '' );
- :EntryDiag*)
- DefaultFileAttribute := BITSET{};
- (*Normal--not system, hidden, or ReadOnly.*)
- DefaultFileMode := BITSET{ 6, 1 };
- (* Open for Read/Write access; allow all access requests from other
- processes. *)
- (*
- DefaultFileMode := BITSET{ 5, 1 };
- (* Open for Read/Write access; deny write access requests by
- other processes, but allow read access requests. Commented out
- because it seems always to cause the CreateFile operation to
- fail with an error 32, File Sharing Violation. Doesn't interfere
- with OpenFile operation. *)
- *)
- (*EntryDiag:
- Diagnostics.diagS( 'Exiting HandleIO', '' );
- :EntryDiag*)
- END Init;
- PROCEDURE OpenFile(VAR FileHandle : CARDINAL; fname : ARRAY OF CHAR) :
- CARDINAL;
- VAR
- ErrorReturn: CARDINAL;
- LongZero, Reserved: LONGINT;
- OpenFlag: BITSET;
- ActionTaken: CARDINAL;
- filen : ARRAY [0..79] OF CHAR;
- BEGIN
- StrEdit.AssignStr(fname, filen);
- FileHandle := 0;
- OpenFlag := {0}; (* Open if it does exist; fail if it doesn't *)
- LongZero := VAL(LONGINT, 0);
- Reserved := VAL(LONGINT, 0);
- ErrorReturn := FAPI.DOSOPEN( SYSTEM.ADR(filen),
- SYSTEM.ADR(FileHandle), SYSTEM.ADR(ActionTaken),
- LongZero, FAPI.FILE_NORMAL,
- FAPI.USHORT(OpenFlag), FAPI.USHORT(DefaultFileMode), Reserved );
- RETURN ErrorReturn;
- END OpenFile;
- PROCEDURE FindFile(VAR FileHandle : CARDINAL;
- VAR fname: ARRAY OF CHAR;
- EnvironVariable : ARRAY OF CHAR) : CARDINAL;
- VAR
- SavedMessage : CARDINAL;
- name,PathName, ProgName, prefix, PathStr : ARRAY [0..128] OF CHAR;
- DriveLetter: CHAR;
- PROCEDURE SplitFirstDir(VAR str1, str2 : ARRAY OF CHAR);
- VAR
- lngth1, ndx : CARDINAL;
- BEGIN
- StrEdit.CutLeadingChars(' ', str1);
- lngth1 := M2Strings.Length(str1);
- ndx := M2Strings.Pos(';', str1);
- IF (lngth1=0) OR (ndx=0) THEN
- IF ndx=0 THEN
- M2Strings.Delete(str1, 0, 1);
- (*If str1 starts with a semicolon, get rid of it so it
- won't mess us up next time.*)
- END;
- StrEdit.SetLength(str2, 0);
- RETURN;
- END;
- IF ndx>HIGH(str1) THEN
- ndx := HIGH(str1)-1;
- (*We always want ndx to point to the last real character
- of the first directory name in str1. If there's only
- one directory name in str1--i.e., if there's no
- semicolon in str1--ndx should point to the last
- character of str1. If there is a semicolon in str1,
- ndx should point to the character immediately preceding
- it.*)
- ELSE
- DEC(ndx);
- END;
- M2Strings.Copy(str1, 0, ndx+1, str2);
- StrEdit.CutTrailingChars(' ', str2);
- IF (str2[M2Strings.Length(str2)-1]#'\') THEN
- StrEdit.Append(str2, '\');
- END;
- M2Strings.Delete(str1, 0, ndx+1);
- END SplitFirstDir;
- PROCEDURE DirRemoved(VAR FileName : ARRAY OF CHAR) : BOOLEAN;
- VAR
- SlashSpot, ColonSpot : CARDINAL;
- tmp : BOOLEAN;
- BEGIN
- tmp := FALSE;
- SlashSpot := M2Strings.Pos('\', FileName);
- WHILE SlashSpot<=HIGH(FileName) DO
- tmp := TRUE;
- M2Strings.Delete(FileName, 0, SlashSpot+1);
- SlashSpot := M2Strings.Pos('\', FileName);
- END;
- ColonSpot := M2Strings.Pos(':', FileName);
- IF ColonSpot<=HIGH(FileName) THEN
- M2Strings.Delete(FileName, 0, ColonSpot+1);
- tmp := FALSE;
- END;
- RETURN (tmp);
- END DirRemoved;
- BEGIN
- M2Strings.Assign(fname,name);
- SavedMessage := OpenFile(FileHandle, fname);
- (*First we look for the file in any directory specified in
- fname. If no directory is specified in fname, we'll be
- looking in the current directory of the current drive at
- this step.*)
- IF SavedMessage # StringIO.NoError THEN
- (*First check the directory in which the program is
- stored.*)
- EnvironUtils.GetExeName(PathStr);
- Drectory.GetDrivePathAndName( PathStr, DriveLetter,
- PathName, ProgName );
- M2Strings.Insert( ':', PathName, 0 );
- M2Strings.Insert( DriveLetter, PathName, 0 );
- IF DirRemoved(fname) THEN
- (*We do this to strip the old prefix out of fname.*)
- END;
- StrEdit.Append( PathName, fname );
- SavedMessage := OpenFile(FileHandle, PathName);
- IF (SavedMessage#StringIO.NoError) THEN
- (* We do this to make sure we search the current
- directory before moving on to a path search.*)
- SavedMessage := OpenFile(FileHandle, fname);
- END;
- EnvironUtils.ReadEnvironment(EnvironVariable, PathStr);
- END;
- WHILE (SavedMessage#StringIO.NoError) AND
- (M2Strings.Length(PathStr)>0) DO
- SplitFirstDir(PathStr, prefix);
- M2Strings.Assign(name,fname);
- M2Strings.Insert(prefix, fname, 0);
- SavedMessage := OpenFile(FileHandle, fname);
- IF SavedMessage = StringIO.NoError THEN
- RETURN (SavedMessage);
- ELSE
- IF DirRemoved(fname) THEN
- (*We do this to strip the old prefix out of fname.*)
- END;
- END;
- END;
- RETURN (SavedMessage);
- END FindFile;
- PROCEDURE CreateFile( VAR FileHandle : CARDINAL; fname :
- ARRAY OF CHAR ) : CARDINAL;
- VAR
- ErrorReturn, ActionTaken: CARDINAL;
- OpenFlag: BITSET;
- Reserved: LONGINT;
- filen : ARRAY [0..79] OF CHAR;
- BEGIN
- StrEdit.AssignStr(fname, filen);
- FileHandle := 0;
- OpenFlag := {1, 4};
- (* create if the file does not exist; truncate if it does exist *)
- Reserved := VAL(LONGINT, 0);
- ErrorReturn := FAPI.DOSOPEN( SYSTEM.ADR(filen),
- SYSTEM.ADR(FileHandle), SYSTEM.ADR(ActionTaken), VAL(LONGINT, 0),
- FAPI.FILE_NORMAL, FAPI.USHORT(OpenFlag),
- FAPI.USHORT(DefaultFileMode), Reserved );
- RETURN ErrorReturn;
- END CreateFile;
- PROCEDURE CreateUniqueFile(VAR FileHandle : CARDINAL; VAR fname :
- ARRAY OF CHAR) : CARDINAL;
- VAR
- filen, TryName : ARRAY [0..79] OF CHAR;
- h,m,s,hs: CARDINAL;
- BEGIN
- (*RETURN ( StringIO.BadFunction); *)
- (* not implimented in OS/2 *)
- IF( fname[0]#0C) AND (fname[M2Strings.Length(fname)-1]#'\')
- THEN (* if not nil string make sure end with \ *)
- StrEdit.Append(fname,'\');
- END;
- StrEdit.AssignStr(fname, filen);
- IF TRUE (*MajorVersion < 3*) THEN
- REPEAT
- EnvironUtils.GetTime( h, m, s, hs, TryName );
- StrEdit.DeleteChar(':', TryName );
- StrEdit.DeleteChar(' ', TryName );
- StrEdit.Append( TryName, '13852940' );
- StrEdit.SetLength( TryName, 12);
- TryName[8] := '.';
- M2Strings.Insert( fname, TryName, 0 );
- UNTIL NOT FileExists( TryName );
- StrEdit.AssignStr( TryName, filen );
- StrEdit.AssignStr( TryName, fname );
- (* added 10 July 87 *)
- RETURN CreateFile( FileHandle, fname );
- (* changed from filen 10 July 87 *)
- END;
- RETURN StringIO.NoError;
- END CreateUniqueFile;
- PROCEDURE CloseHandle(FileHandle : CARDINAL) : CARDINAL;
- VAR
- ErrorReturn: CARDINAL;
- BEGIN
- ErrorReturn := FAPI.DOSCLOSE(FileHandle);
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber( 'DOSCLOSE error', ErrorReturn );
- END;
- RETURN ErrorReturn;
- END CloseHandle;
- PROCEDURE GetFilePtr(FileHandle : CARDINAL) : LONGINT;
- (*Returns the current DOS position in the file
- identified by FileHandle.*)
- VAR
- CurrentPTR: LONGINT;
- ErrorReturn: CARDINAL;
- BEGIN
- ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0),
- 1, SYSTEM.ADR(CurrentPTR));
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber("DosChgFilePtr error", ErrorReturn );
- END;
- RETURN CurrentPTR;
- END GetFilePtr;
- PROCEDURE FileLengthWithMove(FileHandle : CARDINAL) : LONGINT;
- (*Returns the number of bytes in the file identified by
- FileHandle and leaves pointer at the file end.*)
- VAR
- CurrentPTR: LONGINT;
- ErrorReturn: CARDINAL;
- BEGIN
- ErrorReturn :=FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0),
- 2, SYSTEM.ADR(CurrentPTR));
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber("DosChgFilePtr error", ErrorReturn );
- END;
- RETURN CurrentPTR;
- END FileLengthWithMove;
- PROCEDURE FileLength(FileHandle : CARDINAL) : LONGINT;
- (*Returns the number of bytes in the file identified by
- FileHandle.*)
- VAR
- answer, oldpos : LONGINT;
- BEGIN
- (* First, save current position so we can restore the pointer
- to its original location at the end.*)
- oldpos := GetFilePtr(FileHandle);
- (* now check file size with move to file end *)
- answer := FileLengthWithMove(FileHandle);
- (* now, restore the file pointer to where it was *)
- SetFilePtr(FileHandle, FromStart, oldpos);
- RETURN (answer);
- END FileLength;
- PROCEDURE EndReached(FileHandle : CARDINAL) : BOOLEAN;
- VAR
- curpos : LONGINT;
- ErrorReturn, BytesRead: CARDINAL;
- x : ARRAY [0..1] OF CHAR;
- BEGIN
- ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0),
- 1, SYSTEM.ADR(curpos));
- (* Get current position. *)
- ErrorReturn := FAPI.DOSREAD( FileHandle, SYSTEM.ADR(x), 1,
- SYSTEM.ADR(BytesRead));
- (* Try to read one byte. *)
- IF BytesRead = 1 THEN
- (* Read was successful, so we must not have reached the end. *)
- ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, curpos,
- 0, SYSTEM.ADR(curpos));
- (* Move file pointer back to its original position. *)
- RETURN FALSE;
- ELSE
- RETURN TRUE;
- END;
- END EndReached;
- PROCEDURE FileExists(fname : ARRAY OF CHAR) : BOOLEAN;
- VAR
- FileAttribute: CARDINAL;
- Reserved: LONGINT;
- filen : ARRAY [0..79] OF CHAR;
- BEGIN
- StrEdit.AssignStr(fname, filen);
- Reserved := VAL(LONGINT, 0);
- IF FAPI.DOSQFILEMODE( SYSTEM.ADR(filen),
- SYSTEM.ADR(FileAttribute), Reserved)= 0 THEN
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END;
- END FileExists;
- PROCEDURE SetFilePtr(FileHandle : CARDINAL; Origin : FileOffSet;
- OffSet : LONGINT);
- VAR
- NewPtr : LONGINT;
- ErrorReturn: CARDINAL;
- BEGIN
- (* what if file length is zero??*)
- ErrorReturn := FAPI.DOSCHGFILEPTR(FileHandle, OffSet, ORD(Origin),
- SYSTEM.ADR(NewPtr));
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber( "DosChgFilePtr error", ErrorReturn );
- END;
- END SetFilePtr;
- PROCEDURE OpenForAppending( name : ARRAY OF CHAR; VAR handl : CARDINAL);
- VAR
- TmpName, msg: ARRAY [0..79] OF CHAR;
- BEGIN
- StrEdit.AssignStr( name, TmpName );
- IF FindFile( handl, TmpName, "path") <> StringIO.NoError THEN
- IF CreateFile( handl, TmpName) <> StringIO.NoError THEN
- StrEdit.AssignStr( "Cannot create ", msg);
- StrEdit.Append( msg, TmpName );
- StrEdit.Append( msg, '.' );
- ErrorManager.WARN( msg );
- END;
- ELSE
- SetFilePtr( handl, FromEnd, NumTypes.L0);
- END;
- END OpenForAppending;
- PROCEDURE BlockRead(FileHandle : CARDINAL; ptr : SYSTEM.ADDRESS; size :
- CARDINAL) : CARDINAL;
- VAR
- ErrorReturn, BytesRead: CARDINAL;
- BEGIN
- ErrorReturn := FAPI.DOSREAD( FileHandle, ptr, size,
- SYSTEM.ADR(BytesRead));
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber( "DOSREAD error", ErrorReturn );
- END;
- (* Looks like something may be wrong here. *)
- IF BytesRead < size THEN
- IF BytesRead = 0 THEN
- RETURN (StringIO.EndOfFile);
- ELSE
- RETURN (StringIO.PartialRead);
- END;
- END;
- RETURN ErrorReturn;
- END BlockRead;
- PROCEDURE BlockWrite(FileHandle : CARDINAL; ptr : SYSTEM.ADDRESS; size :
- CARDINAL) : CARDINAL;
- VAR
- ErrorReturn, BytesWritten: CARDINAL;
- BEGIN
- ErrorReturn := FAPI.DOSWRITE(FileHandle, ptr, size,
- SYSTEM.ADR(BytesWritten));
- IF ErrorReturn # 0 THEN
- ErrorManager.WarnNumber( 'DOSWRITE error', ErrorReturn );
- END;
- RETURN ErrorReturn;
- END BlockWrite;
- PROCEDURE NewHandleCopy( OldHandle: CARDINAL;
- VAR NewHandle: CARDINAL ): CARDINAL;
- (*Duplicates an open file handle and returns a new handle
- number that refers to the same file or device. Useful for
- updating files without closing them.*)
- VAR
- ErrorReturn: CARDINAL;
- BEGIN
- NewHandle := 0FFFFH;
- ErrorReturn := FAPI.DOSDUPHANDLE(OldHandle, SYSTEM.ADR(NewHandle));
- RETURN ErrorReturn;
- END NewHandleCopy;
- PROCEDURE ForceHandleCopy( OldHandle, NewHandle: CARDINAL):
- CARDINAL;
- (*Similar to NewHandleCopy, but makes an existing handle
- (NewHandle) refer to another one (OldHandle). Closes
- NewHandle first, and then reopens it as a copy of
- OldHandle. Useful for dynamic I/O redirection.*)
- VAR
- ErrorReturn: CARDINAL;
- BEGIN
- ErrorReturn := FAPI.DOSDUPHANDLE(OldHandle, SYSTEM.ADR(NewHandle));
- RETURN ErrorReturn;
- END ForceHandleCopy;
- PROCEDURE UpdateDisk( FileHandle: CARDINAL );
- (*Writes a file's current buffers to the disk and writes its
- current length and time to the directory without requiring
- it to be closed.*)
- VAR
- ErrorCode,
- TmpHandle: CARDINAL;
- BEGIN
- ErrorCode:=FAPI.DOSBUFRESET( FileHandle );
- IF ErrorCode # 0 THEN
- ErrorManager.WarnNumber('UpdateDisk Error',ErrorCode );
- END;
- (* IF NewHandleCopy( FileHandle, TmpHandle ) = StringIO.NoError THEN
- StringIO.PrintMessage( CloseHandle(TmpHandle) );
- END;*)
- END UpdateDisk;
- PROCEDURE FillFile( FileHandle: CARDINAL; NumberOfBytes:
- CARDINAL; TheByte: CHAR ): CARDINAL;
- VAR
- TmpAdr: SYSTEM.ADDRESS;
- SavedMessage: CARDINAL;
- BEGIN
- IF NOT VStorage.DosAvail( NumberOfBytes ) THEN
- RETURN StringIO.TooLittleMemory;
- END;
- VStorage.DosAlloc( TmpAdr, NumberOfBytes );
- LowLevel.Fill( TmpAdr, NumberOfBytes, TheByte );
- SavedMessage := BlockWrite( FileHandle, TmpAdr,
- NumberOfBytes );
- VStorage.DosDealloc( TmpAdr, NumberOfBytes );
- RETURN SavedMessage;
- END FillFile;
- BEGIN
- Initialized := FALSE;
- Init();
- Init();
- END HandleIO.
|