Listing: 1 IMPLEMENTATION MODULE HandleIO; 2 (* 3 * REPERTOIRE 4 * Release 1.6 5 * By Charles Bradford and Cole Brecheen 6 * (c) Copyright 1985-1992 PMI 7 * Green Bay, Wisconsin 8 * All rights reserved 9 * (414) 468-6040 10 * 11 * $Header: D:/logfiles/mods/handleio.mov 1.5 17 Mar 1991 17:54:52 coleb $ 12 * 13 *) 14 15 16 (*EntryDiag: 17 IMPORT Diagnostics; 18 :EntryDiag*) 19 20 IMPORT FAPI; 21 IMPORT ByteFiddler; 22 IMPORT Drectory; 23 IMPORT EnvironUtils; 24 IMPORT ErrorManager; 25 IMPORT LowLevel; 26 IMPORT M2Strings; 27 IMPORT Numbers; 28 IMPORT NumTypes; 29 IMPORT StrEdit; 30 IMPORT StringIO; 31 IMPORT SYSTEM; 32 IMPORT VStorage; 33 34 VAR 35 Initialized : BOOLEAN; 36 37 PROCEDURE Init(); 38 BEGIN 39 IF Initialized THEN 40 RETURN; 41 ELSE 42 Initialized := TRUE; 43 END; 44 (*EntryDiag: 45 Diagnostics.Init(); 46 :EntryDiag*) 47 48 ByteFiddler.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 49 Drectory.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 50 EnvironUtils.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 51 ErrorManager.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 52 LowLevel.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 53 M2Strings.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 54 Numbers.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 55 NumTypes.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 56 StrEdit.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 57 StringIO.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 58 VStorage.Init(); ***** ^ not supported yet ***** ^ not supported yet ***** ^ not supported yet 59 (*EntryDiag: 60 Diagnostics.diagS( 'Entering HandleIO', '' ); 61 :EntryDiag*) 62 DefaultFileAttribute := BITSET{}; ***** ^ undeclared identifier ***** ^ undeclared identifier 63 (*Normal--not system, hidden, or ReadOnly.*) 64 DefaultFileMode := BITSET{ 6, 1 }; 65 (* Open for Read/Write access; allow all access requests from other 66 processes. *) 67 (* 68 DefaultFileMode := BITSET{ 5, 1 }; 69 (* Open for Read/Write access; deny write access requests by 70 other processes, but allow read access requests. Commented out 71 because it seems always to cause the CreateFile operation to 72 fail with an error 32, File Sharing Violation. Doesn't interfere 73 with OpenFile operation. *) 74 *) 75 (*EntryDiag: 76 Diagnostics.diagS( 'Exiting HandleIO', '' ); 77 :EntryDiag*) 78 END Init; 79 80 81 PROCEDURE OpenFile(VAR FileHandle : CARDINAL; fname : ARRAY OF CHAR) : 82 CARDINAL; 83 VAR 84 ErrorReturn: CARDINAL; 85 LongZero, Reserved: LONGINT; 86 OpenFlag: BITSET; 87 ActionTaken: CARDINAL; 88 filen : ARRAY [0..79] OF CHAR; 89 BEGIN 90 StrEdit.AssignStr(fname, filen); 91 FileHandle := 0; 92 93 OpenFlag := {0}; (* Open if it does exist; fail if it doesn't *) 94 LongZero := VAL(LONGINT, 0); 95 Reserved := VAL(LONGINT, 0); 96 ErrorReturn := FAPI.DOSOPEN( SYSTEM.ADR(filen), 97 SYSTEM.ADR(FileHandle), SYSTEM.ADR(ActionTaken), 98 LongZero, FAPI.FILE_NORMAL, 99 FAPI.USHORT(OpenFlag), FAPI.USHORT(DefaultFileMode), Reserved ); 100 RETURN ErrorReturn; 101 END OpenFile; 102 103 104 PROCEDURE FindFile(VAR FileHandle : CARDINAL; 105 VAR fname: ARRAY OF CHAR; 106 EnvironVariable : ARRAY OF CHAR) : CARDINAL; 107 VAR 108 SavedMessage : CARDINAL; 109 name,PathName, ProgName, prefix, PathStr : ARRAY [0..128] OF CHAR; 110 DriveLetter: CHAR; 111 112 PROCEDURE SplitFirstDir(VAR str1, str2 : ARRAY OF CHAR); 113 VAR 114 lngth1, ndx : CARDINAL; 115 BEGIN 116 StrEdit.CutLeadingChars(' ', str1); 117 lngth1 := M2Strings.Length(str1); 118 ndx := M2Strings.Pos(';', str1); 119 IF (lngth1=0) OR (ndx=0) THEN 120 IF ndx=0 THEN 121 M2Strings.Delete(str1, 0, 1); 122 (*If str1 starts with a semicolon, get rid of it so it 123 won't mess us up next time.*) 124 END; 125 StrEdit.SetLength(str2, 0); 126 RETURN; 127 END; 128 IF ndx>HIGH(str1) THEN 129 ndx := HIGH(str1)-1; 130 (*We always want ndx to point to the last real character 131 of the first directory name in str1. If there's only 132 one directory name in str1--i.e., if there's no 133 semicolon in str1--ndx should point to the last 134 character of str1. If there is a semicolon in str1, 135 ndx should point to the character immediately preceding 136 it.*) 137 ELSE 138 DEC(ndx); 139 END; 140 M2Strings.Copy(str1, 0, ndx+1, str2); 141 StrEdit.CutTrailingChars(' ', str2); 142 IF (str2[M2Strings.Length(str2)-1]#'\') THEN 143 StrEdit.Append(str2, '\'); 144 END; 145 M2Strings.Delete(str1, 0, ndx+1); 146 END SplitFirstDir; 147 148 PROCEDURE DirRemoved(VAR FileName : ARRAY OF CHAR) : BOOLEAN; 149 VAR 150 SlashSpot, ColonSpot : CARDINAL; 151 tmp : BOOLEAN; 152 BEGIN 153 tmp := FALSE; 154 SlashSpot := M2Strings.Pos('\', FileName); 155 WHILE SlashSpot<=HIGH(FileName) DO 156 tmp := TRUE; 157 M2Strings.Delete(FileName, 0, SlashSpot+1); 158 SlashSpot := M2Strings.Pos('\', FileName); 159 END; 160 ColonSpot := M2Strings.Pos(':', FileName); 161 IF ColonSpot<=HIGH(FileName) THEN 162 M2Strings.Delete(FileName, 0, ColonSpot+1); 163 tmp := FALSE; 164 END; 165 RETURN (tmp); 166 END DirRemoved; 167 168 BEGIN 169 M2Strings.Assign(fname,name); 170 SavedMessage := OpenFile(FileHandle, fname); 171 (*First we look for the file in any directory specified in 172 fname. If no directory is specified in fname, we'll be 173 looking in the current directory of the current drive at 174 this step.*) 175 IF SavedMessage # StringIO.NoError THEN 176 (*First check the directory in which the program is 177 stored.*) 178 EnvironUtils.GetExeName(PathStr); 179 Drectory.GetDrivePathAndName( PathStr, DriveLetter, 180 PathName, ProgName ); 181 M2Strings.Insert( ':', PathName, 0 ); 182 M2Strings.Insert( DriveLetter, PathName, 0 ); 183 IF DirRemoved(fname) THEN 184 (*We do this to strip the old prefix out of fname.*) 185 END; 186 StrEdit.Append( PathName, fname ); 187 SavedMessage := OpenFile(FileHandle, PathName); 188 IF (SavedMessage#StringIO.NoError) THEN 189 (* We do this to make sure we search the current 190 directory before moving on to a path search.*) 191 SavedMessage := OpenFile(FileHandle, fname); 192 END; 193 EnvironUtils.ReadEnvironment(EnvironVariable, PathStr); 194 END; 195 WHILE (SavedMessage#StringIO.NoError) AND 196 (M2Strings.Length(PathStr)>0) DO 197 SplitFirstDir(PathStr, prefix); 198 M2Strings.Assign(name,fname); 199 M2Strings.Insert(prefix, fname, 0); 200 SavedMessage := OpenFile(FileHandle, fname); 201 IF SavedMessage = StringIO.NoError THEN 202 RETURN (SavedMessage); 203 ELSE 204 IF DirRemoved(fname) THEN 205 (*We do this to strip the old prefix out of fname.*) 206 END; 207 END; 208 END; 209 RETURN (SavedMessage); 210 END FindFile; 211 212 213 PROCEDURE CreateFile( VAR FileHandle : CARDINAL; fname : 214 ARRAY OF CHAR ) : CARDINAL; 215 VAR 216 ErrorReturn, ActionTaken: CARDINAL; 217 OpenFlag: BITSET; 218 Reserved: LONGINT; 219 filen : ARRAY [0..79] OF CHAR; 220 BEGIN 221 StrEdit.AssignStr(fname, filen); 222 FileHandle := 0; 223 OpenFlag := {1, 4}; 224 (* create if the file does not exist; truncate if it does exist *) 225 Reserved := VAL(LONGINT, 0); 226 ErrorReturn := FAPI.DOSOPEN( SYSTEM.ADR(filen), 227 SYSTEM.ADR(FileHandle), SYSTEM.ADR(ActionTaken), VAL(LONGINT, 0), 228 FAPI.FILE_NORMAL, FAPI.USHORT(OpenFlag), 229 FAPI.USHORT(DefaultFileMode), Reserved ); 230 RETURN ErrorReturn; 231 END CreateFile; 232 233 234 PROCEDURE CreateUniqueFile(VAR FileHandle : CARDINAL; VAR fname : 235 ARRAY OF CHAR) : CARDINAL; 236 VAR 237 filen, TryName : ARRAY [0..79] OF CHAR; 238 h,m,s,hs: CARDINAL; 239 BEGIN 240 (*RETURN ( StringIO.BadFunction); *) 241 (* not implimented in OS/2 *) 242 IF( fname[0]#0C) AND (fname[M2Strings.Length(fname)-1]#'\') 243 THEN (* if not nil string make sure end with \ *) 244 StrEdit.Append(fname,'\'); 245 END; 246 StrEdit.AssignStr(fname, filen); 247 IF TRUE (*MajorVersion < 3*) THEN 248 REPEAT 249 EnvironUtils.GetTime( h, m, s, hs, TryName ); 250 StrEdit.DeleteChar(':', TryName ); 251 StrEdit.DeleteChar(' ', TryName ); 252 StrEdit.Append( TryName, '13852940' ); 253 StrEdit.SetLength( TryName, 12); 254 TryName[8] := '.'; 255 M2Strings.Insert( fname, TryName, 0 ); 256 UNTIL NOT FileExists( TryName ); 257 StrEdit.AssignStr( TryName, filen ); 258 StrEdit.AssignStr( TryName, fname ); 259 (* added 10 July 87 *) 260 RETURN CreateFile( FileHandle, fname ); 261 (* changed from filen 10 July 87 *) 262 END; 263 RETURN StringIO.NoError; 264 265 END CreateUniqueFile; 266 267 268 PROCEDURE CloseHandle(FileHandle : CARDINAL) : CARDINAL; 269 VAR 270 ErrorReturn: CARDINAL; 271 BEGIN 272 ErrorReturn := FAPI.DOSCLOSE(FileHandle); 273 IF ErrorReturn # 0 THEN 274 ErrorManager.WarnNumber( 'DOSCLOSE error', ErrorReturn ); 275 END; 276 RETURN ErrorReturn; 277 END CloseHandle; 278 279 280 PROCEDURE GetFilePtr(FileHandle : CARDINAL) : LONGINT; 281 (*Returns the current DOS position in the file 282 identified by FileHandle.*) 283 VAR 284 CurrentPTR: LONGINT; 285 ErrorReturn: CARDINAL; 286 BEGIN 287 ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0), 288 1, SYSTEM.ADR(CurrentPTR)); 289 IF ErrorReturn # 0 THEN 290 ErrorManager.WarnNumber("DosChgFilePtr error", ErrorReturn ); 291 END; 292 RETURN CurrentPTR; 293 END GetFilePtr; 294 295 296 PROCEDURE FileLengthWithMove(FileHandle : CARDINAL) : LONGINT; 297 (*Returns the number of bytes in the file identified by 298 FileHandle and leaves pointer at the file end.*) 299 VAR 300 CurrentPTR: LONGINT; 301 ErrorReturn: CARDINAL; 302 BEGIN 303 ErrorReturn :=FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0), 304 2, SYSTEM.ADR(CurrentPTR)); 305 IF ErrorReturn # 0 THEN 306 ErrorManager.WarnNumber("DosChgFilePtr error", ErrorReturn ); 307 END; 308 RETURN CurrentPTR; 309 END FileLengthWithMove; 310 311 312 PROCEDURE FileLength(FileHandle : CARDINAL) : LONGINT; 313 (*Returns the number of bytes in the file identified by 314 FileHandle.*) 315 VAR 316 answer, oldpos : LONGINT; 317 BEGIN 318 (* First, save current position so we can restore the pointer 319 to its original location at the end.*) 320 oldpos := GetFilePtr(FileHandle); 321 (* now check file size with move to file end *) 322 answer := FileLengthWithMove(FileHandle); 323 (* now, restore the file pointer to where it was *) 324 SetFilePtr(FileHandle, FromStart, oldpos); 325 RETURN (answer); 326 END FileLength; 327 328 329 PROCEDURE EndReached(FileHandle : CARDINAL) : BOOLEAN; 330 VAR 331 curpos : LONGINT; 332 ErrorReturn, BytesRead: CARDINAL; 333 x : ARRAY [0..1] OF CHAR; 334 BEGIN 335 ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, VAL(LONGINT, 0), 336 1, SYSTEM.ADR(curpos)); 337 (* Get current position. *) 338 ErrorReturn := FAPI.DOSREAD( FileHandle, SYSTEM.ADR(x), 1, 339 SYSTEM.ADR(BytesRead)); 340 (* Try to read one byte. *) 341 IF BytesRead = 1 THEN 342 (* Read was successful, so we must not have reached the end. *) 343 ErrorReturn := FAPI.DOSCHGFILEPTR( FileHandle, curpos, 344 0, SYSTEM.ADR(curpos)); 345 (* Move file pointer back to its original position. *) 346 RETURN FALSE; 347 ELSE 348 RETURN TRUE; 349 END; 350 END EndReached; 351 352 353 PROCEDURE FileExists(fname : ARRAY OF CHAR) : BOOLEAN; 354 VAR 355 FileAttribute: CARDINAL; 356 Reserved: LONGINT; 357 filen : ARRAY [0..79] OF CHAR; 358 BEGIN 359 StrEdit.AssignStr(fname, filen); 360 Reserved := VAL(LONGINT, 0); 361 IF FAPI.DOSQFILEMODE( SYSTEM.ADR(filen), 362 SYSTEM.ADR(FileAttribute), Reserved)= 0 THEN 363 RETURN TRUE; 364 ELSE 365 RETURN FALSE; 366 END; 367 END FileExists; 368 369 370 PROCEDURE SetFilePtr(FileHandle : CARDINAL; Origin : FileOffSet; 371 OffSet : LONGINT); 372 VAR 373 NewPtr : LONGINT; 374 ErrorReturn: CARDINAL; 375 BEGIN 376 (* what if file length is zero??*) 377 ErrorReturn := FAPI.DOSCHGFILEPTR(FileHandle, OffSet, ORD(Origin), 378 SYSTEM.ADR(NewPtr)); 379 IF ErrorReturn # 0 THEN 380 ErrorManager.WarnNumber( "DosChgFilePtr error", ErrorReturn ); 381 END; 382 END SetFilePtr; 383 384 385 PROCEDURE OpenForAppending( name : ARRAY OF CHAR; VAR handl : CARDINAL); 386 VAR 387 TmpName, msg: ARRAY [0..79] OF CHAR; 388 BEGIN 389 StrEdit.AssignStr( name, TmpName ); 390 IF FindFile( handl, TmpName, "path") <> StringIO.NoError THEN 391 IF CreateFile( handl, TmpName) <> StringIO.NoError THEN 392 StrEdit.AssignStr( "Cannot create ", msg); 393 StrEdit.Append( msg, TmpName ); 394 StrEdit.Append( msg, '.' ); 395 ErrorManager.WARN( msg ); 396 END; 397 ELSE 398 SetFilePtr( handl, FromEnd, NumTypes.L0); 399 END; 400 END OpenForAppending; 401 402 403 PROCEDURE BlockRead(FileHandle : CARDINAL; ptr : SYSTEM.ADDRESS; size : 404 CARDINAL) : CARDINAL; 405 VAR 406 ErrorReturn, BytesRead: CARDINAL; 407 BEGIN 408 ErrorReturn := FAPI.DOSREAD( FileHandle, ptr, size, 409 SYSTEM.ADR(BytesRead)); 410 IF ErrorReturn # 0 THEN 411 ErrorManager.WarnNumber( "DOSREAD error", ErrorReturn ); 412 END; 413 (* Looks like something may be wrong here. *) 414 IF BytesRead < size THEN 415 IF BytesRead = 0 THEN 416 RETURN (StringIO.EndOfFile); 417 ELSE 418 RETURN (StringIO.PartialRead); 419 END; 420 END; 421 RETURN ErrorReturn; 422 END BlockRead; 423 424 425 PROCEDURE BlockWrite(FileHandle : CARDINAL; ptr : SYSTEM.ADDRESS; size : 426 CARDINAL) : CARDINAL; 427 VAR 428 ErrorReturn, BytesWritten: CARDINAL; 429 BEGIN 430 ErrorReturn := FAPI.DOSWRITE(FileHandle, ptr, size, 431 SYSTEM.ADR(BytesWritten)); 432 IF ErrorReturn # 0 THEN 433 ErrorManager.WarnNumber( 'DOSWRITE error', ErrorReturn ); 434 END; 435 RETURN ErrorReturn; 436 END BlockWrite; 437 438 439 PROCEDURE NewHandleCopy( OldHandle: CARDINAL; 440 VAR NewHandle: CARDINAL ): CARDINAL; 441 (*Duplicates an open file handle and returns a new handle 442 number that refers to the same file or device. Useful for 443 updating files without closing them.*) 444 VAR 445 ErrorReturn: CARDINAL; 446 BEGIN 447 NewHandle := 0FFFFH; 448 ErrorReturn := FAPI.DOSDUPHANDLE(OldHandle, SYSTEM.ADR(NewHandle)); 449 RETURN ErrorReturn; 450 END NewHandleCopy; 451 452 453 PROCEDURE ForceHandleCopy( OldHandle, NewHandle: CARDINAL): 454 CARDINAL; 455 (*Similar to NewHandleCopy, but makes an existing handle 456 (NewHandle) refer to another one (OldHandle). Closes 457 NewHandle first, and then reopens it as a copy of 458 OldHandle. Useful for dynamic I/O redirection.*) 459 VAR 460 ErrorReturn: CARDINAL; 461 BEGIN 462 ErrorReturn := FAPI.DOSDUPHANDLE(OldHandle, SYSTEM.ADR(NewHandle)); 463 RETURN ErrorReturn; 464 END ForceHandleCopy; 465 466 467 PROCEDURE UpdateDisk( FileHandle: CARDINAL ); 468 (*Writes a file's current buffers to the disk and writes its 469 current length and time to the directory without requiring 470 it to be closed.*) 471 VAR 472 ErrorCode, 473 TmpHandle: CARDINAL; 474 BEGIN 475 ErrorCode:=FAPI.DOSBUFRESET( FileHandle ); 476 IF ErrorCode # 0 THEN 477 ErrorManager.WarnNumber('UpdateDisk Error',ErrorCode ); 478 END; 479 480 (* IF NewHandleCopy( FileHandle, TmpHandle ) = StringIO.NoError THEN 481 StringIO.PrintMessage( CloseHandle(TmpHandle) ); 482 END;*) 483 END UpdateDisk; 484 485 PROCEDURE FillFile( FileHandle: CARDINAL; NumberOfBytes: 486 CARDINAL; TheByte: CHAR ): CARDINAL; 487 VAR 488 TmpAdr: SYSTEM.ADDRESS; 489 SavedMessage: CARDINAL; 490 BEGIN 491 IF NOT VStorage.DosAvail( NumberOfBytes ) THEN 492 RETURN StringIO.TooLittleMemory; 493 END; 494 VStorage.DosAlloc( TmpAdr, NumberOfBytes ); 495 LowLevel.Fill( TmpAdr, NumberOfBytes, TheByte ); 496 SavedMessage := BlockWrite( FileHandle, TmpAdr, 497 NumberOfBytes ); 498 VStorage.DosDealloc( TmpAdr, NumberOfBytes ); 499 RETURN SavedMessage; 500 END FillFile; 501 502 503 504 BEGIN 505 Initialized := FALSE; 506 Init(); 507 Init(); 508 END HandleIO. 35 errors