HANDLEIO.MOD 16 KB

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