DRECTORY.MOD 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. IMPLEMENTATION MODULE Drectory;
  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/drectory.mov 1.8 17 Mar 1991 18:00:54 coleb $
  12. *
  13. *)
  14. IMPORT ByteFiddler;
  15. IMPORT EnvironUtils;
  16. IMPORT ErrorManager;
  17. IMPORT HandleIO;
  18. IMPORT LowLevel;
  19. IMPORT M2Strings;
  20. IMPORT Numbers;
  21. IMPORT NumTypes;
  22. IMPORT PosUtils;
  23. IMPORT StrConv;
  24. IMPORT StrEdit;
  25. IMPORT StringIO;
  26. IMPORT VStorage;
  27. IMPORT FAPI;
  28. IMPORT SYSTEM;
  29. VAR
  30. Initialized : BOOLEAN;
  31. PROCEDURE Init();
  32. BEGIN
  33. IF Initialized THEN
  34. RETURN;
  35. ELSE
  36. Initialized := TRUE;
  37. END;
  38. ByteFiddler.Init();
  39. EnvironUtils.Init();
  40. ErrorManager.Init();
  41. HandleIO.Init();
  42. LowLevel.Init();
  43. M2Strings.Init();
  44. Numbers.Init();
  45. NumTypes.Init();
  46. PosUtils.Init();
  47. StrConv.Init();
  48. StrEdit.Init();
  49. StringIO.Init();
  50. VStorage.Init();
  51. END Init;
  52. CONST
  53. blank = ' ';
  54. null = '';
  55. semicolon = ';';
  56. backslash = '\';
  57. fwdslash = '/';
  58. byte1 = 0;
  59. OrdA = 65;
  60. TYPE
  61. ModeSetCaster =
  62. RECORD
  63. CASE : BOOLEAN OF
  64. TRUE :
  65. a : ModeSet;
  66. | FALSE :
  67. b : BITSET;
  68. END;
  69. END;
  70. (*==================== Utility Procedures =====================*)
  71. PROCEDURE LastByte( FileHandle: CARDINAL ): CHAR;
  72. VAR
  73. bufch: CHAR;
  74. BEGIN
  75. HandleIO.SetFilePtr(FileHandle, HandleIO.FromEnd, Numbers.Li( -1) );
  76. StringIO.PrintMessage(HandleIO.BlockRead( FileHandle,
  77. SYSTEM.ADR(bufch), 1 ));
  78. RETURN bufch;
  79. END LastByte;
  80. (*================== Exported Procedures ==================*)
  81. PROCEDURE AddBlockToFile(FileName : ARRAY OF CHAR;
  82. FileHandle : CARDINAL; BlockAdr: SYSTEM.ADDRESS;
  83. BlockSize: CARDINAL );
  84. VAR
  85. AlreadyOpen : BOOLEAN;
  86. EofChar: CHAR;
  87. BEGIN
  88. EofChar := CHR(26);
  89. IF (M2Strings.Length(FileName)=0) OR (FileHandle>4) THEN
  90. AlreadyOpen := TRUE;
  91. ELSE
  92. AlreadyOpen := FALSE;
  93. StringIO.PrintMessage(HandleIO.OpenFile(FileHandle,FileName));
  94. END;
  95. IF LastByte( FileHandle ) = CHR(26) THEN
  96. HandleIO.SetFilePtr(FileHandle, HandleIO.FromEnd, Numbers.Li( -1) );
  97. (*Back up to write over the eof.*)
  98. StringIO.PrintMessage(
  99. HandleIO.BlockWrite( FileHandle, BlockAdr, BlockSize ));
  100. StringIO.PrintMessage(
  101. HandleIO.BlockWrite( FileHandle, SYSTEM.ADR(EofChar), 1 ));
  102. (*Write a new eof.*)
  103. ELSE
  104. HandleIO.SetFilePtr(FileHandle, HandleIO.FromEnd, NumTypes.L0 );
  105. (*Don't back up to write over the eof.*)
  106. StringIO.PrintMessage(
  107. HandleIO.BlockWrite( FileHandle, BlockAdr, BlockSize ));
  108. END;
  109. IF AlreadyOpen THEN
  110. HandleIO.UpdateDisk( FileHandle )
  111. ELSE
  112. StringIO.PrintMessage(HandleIO.CloseHandle(FileHandle));
  113. (*Updates the file's directory entry.*)
  114. END;
  115. END AddBlockToFile;
  116. PROCEDURE AddToFile(FileName : ARRAY OF CHAR; FileHandle : CARDINAL;
  117. message : ARRAY OF CHAR);
  118. BEGIN
  119. (*AddToFile*)
  120. AddBlockToFile( FileName, FileHandle, SYSTEM.ADR(message),
  121. M2Strings.Length(message) );
  122. END AddToFile;
  123. PROCEDURE ChDir(DirName : ARRAY OF CHAR) : CARDINAL;
  124. VAR
  125. ErrorReturn :CARDINAL;
  126. Reserved:LONGINT;
  127. BEGIN
  128. ErrorReturn := FAPI.DOSCHDIR(SYSTEM.ADR(DirName), Reserved);
  129. RETURN ErrorReturn;
  130. END ChDir;
  131. PROCEDURE CopyFile(OldHandle : CARDINAL; NewFileName : ARRAY OF CHAR) :
  132. CARDINAL;
  133. TYPE
  134. memptr =
  135. RECORD
  136. addr : LowLevel.Address8086;
  137. size : CARDINAL;
  138. END;
  139. VAR
  140. TheDrive : CHAR;
  141. MemoryPtr : memptr;
  142. NewHandle : CARDINAL;
  143. SavedMessage : CARDINAL;
  144. FreeBytes, FileSize, BytesToBeFreed, BytesToRead : LONGINT;
  145. PROCEDURE ReadOldFile(VAR MemoryPtr : memptr);
  146. VAR
  147. BytesRead,ErrorReturn:CARDINAL;
  148. BytesAvailable : CARDINAL;
  149. BEGIN
  150. (*ReadOldFile*)
  151. IF BytesToRead <= Numbers.Lc( 0 ) THEN
  152. MemoryPtr.addr.x := NIL;
  153. RETURN;
  154. END;
  155. BytesAvailable := EnvironUtils.MemAvail( 10000);
  156. WITH MemoryPtr DO
  157. IF BytesToRead > Numbers.Lc( BytesAvailable ) THEN
  158. size := BytesAvailable;
  159. ELSE
  160. size := Numbers.C( BytesToRead );
  161. END;
  162. VStorage.DosAlloc(addr.a, size);
  163. END;
  164. ErrorReturn := FAPI.DOSREAD(OldHandle, MemoryPtr.addr.a,
  165. MemoryPtr.size, SYSTEM.ADR(BytesRead));
  166. IF BytesRead < MemoryPtr.size THEN
  167. IF BytesRead = 0 THEN
  168. StringIO.PrintMessage (StringIO.EndOfFile);
  169. ELSE
  170. StringIO.PrintMessage (StringIO.PartialRead);
  171. END;
  172. ELSE
  173. IF ErrorReturn # 0 THEN
  174. StringIO.PrintMessage(ErrorReturn);
  175. ELSE
  176. BytesToRead := BytesToRead - Numbers.Lc( MemoryPtr.size );
  177. (* Can't use DEC here because JPI doesn't allow LONGINTs
  178. to be decremented by CARDINAL values. *)
  179. END;
  180. END;
  181. END ReadOldFile;
  182. PROCEDURE WriteNewFile(MemoryPtr : memptr);
  183. VAR
  184. ErrorReturn, BytesWritten: CARDINAL;
  185. BEGIN
  186. (*WriteNewFile*)
  187. IF MemoryPtr.addr.x=NIL THEN
  188. RETURN;
  189. END;
  190. ErrorReturn := FAPI.DOSWRITE( NewHandle, MemoryPtr.addr.a,
  191. MemoryPtr.size, SYSTEM.ADR(BytesWritten) );
  192. IF BytesWritten < MemoryPtr.size THEN
  193. ErrorManager.WARN('No room to write.');
  194. END;
  195. IF ErrorReturn # 0 THEN
  196. StringIO.PrintMessage(ErrorReturn);
  197. END;
  198. VStorage.DosDealloc(MemoryPtr.addr.x, MemoryPtr.size);
  199. END WriteNewFile;
  200. PROCEDURE SetDateAndTime();
  201. VAR
  202. month, day, year, hours, minutes, seconds : CARDINAL;
  203. BEGIN
  204. GetFileDateAndTime(OldHandle, month, day, year, hours, minutes,
  205. seconds);
  206. (*
  207. Diagnostics.diagC( 'month', month );
  208. Diagnostics.diagC( 'day', day );
  209. Diagnostics.diagC( 'year', year );
  210. Diagnostics.diagC( 'hours', hours );
  211. Diagnostics.diagC( 'minutes', minutes );
  212. Diagnostics.diagC( 'seconds', seconds );
  213. *)
  214. SetFileDateAndTime(NewHandle, month, day, year, hours, minutes,
  215. seconds);
  216. END SetDateAndTime;
  217. BEGIN
  218. (*CopyFile*)
  219. BytesToBeFreed := Numbers.Lc( 0 );
  220. FileSize := HandleIO.FileLength(OldHandle);
  221. BytesToRead := FileSize;
  222. IF M2Strings.Pos(':',NewFileName)=(1+byte1) THEN
  223. TheDrive := NewFileName[0+byte1];
  224. ELSE
  225. TheDrive := 'Z';
  226. (*Determines the drive to which we're copying.
  227. 'Z' means "default drive" to FreeDiskSpace.*)
  228. END;
  229. SavedMessage := FreeDiskSpace(TheDrive,FreeBytes);
  230. IF SavedMessage # StringIO.NoError THEN
  231. RETURN SavedMessage;
  232. END;
  233. SavedMessage := HandleIO.OpenFile(NewHandle,NewFileName);
  234. IF SavedMessage = StringIO.NoError THEN
  235. BytesToBeFreed := HandleIO.FileLength(NewHandle);
  236. SavedMessage := HandleIO.CloseHandle(NewHandle);
  237. ELSE
  238. IF (SavedMessage # StringIO.FileNotFound) AND
  239. (SavedMessage # 110) THEN (* explicit fail command *)
  240. RETURN SavedMessage;
  241. END;
  242. END;
  243. IF FileSize > (FreeBytes + BytesToBeFreed) THEN
  244. SavedMessage := StringIO.AccessDenied;
  245. (*This will have to stand for 'Not enough room.'*)
  246. RETURN SavedMessage;
  247. END;
  248. SavedMessage := HandleIO.CreateFile( NewHandle, NewFileName );
  249. IF SavedMessage # StringIO.NoError THEN
  250. RETURN SavedMessage;
  251. END;
  252. REPEAT
  253. ReadOldFile(MemoryPtr);
  254. WriteNewFile(MemoryPtr);
  255. UNTIL BytesToRead <= Numbers.Lc( 0 );
  256. SetDateAndTime();
  257. RETURN HandleIO.CloseHandle(NewHandle);
  258. END CopyFile;
  259. (*
  260. We can't use this, unfortunately, because DOSCOPY isn't FAPI, and
  261. the Logitech linker can't handle unresolved symbols, even if the
  262. references aren't going to get linked in.
  263. PROCEDURE CopyFile2( SourceName, TargetName: ARRAY OF CHAR ): CARDINAL;
  264. VAR
  265. OldFileHandle, ErrorReturn, OSversion: CARDINAL;
  266. Reserved: LONGINT;
  267. BEGIN
  268. FAPI.DOSGETVERSION( SYSTEM.ADR(OSversion) );
  269. IF OSversion >= 10 THEN
  270. (* We're under some version of OS/2 *)
  271. Reserved := NumTypes.L0;
  272. ErrorReturn := FAPI.DOSCOPY( SYSTEM.ADR(SourceName),
  273. SYSTEM.ADR(TargetName), BITSET(0), Reserved );
  274. ELSE
  275. ErrorReturn := HandleIO.OpenFile( OldFileHandle, SourceName );
  276. IF ErrorReturn # 0 THEN
  277. ErrorManager.WarnNumber( 'CopyFile2 error', ErrorReturn );
  278. END;
  279. ErrorReturn := CopyFile( OldFileHandle, TargetName );
  280. END;
  281. RETURN ErrorReturn;
  282. END CopyFile2;
  283. *)
  284. PROCEDURE DeleteFile(FileName : ARRAY OF CHAR) : CARDINAL;
  285. VAR
  286. ErrorReturn:CARDINAL;
  287. Reserved:LONGINT;
  288. LocalStr: ARRAY [0..79] OF CHAR;
  289. BEGIN
  290. M2Strings.Assign( FileName, LocalStr );
  291. (*We assign to the local string to guarantee that it ends
  292. with a null byte.*)
  293. Reserved := VAL(LONGINT,0);
  294. ErrorReturn := FAPI.DOSDELETE(SYSTEM.ADR(FileName), Reserved);
  295. (* IF ErrorReturn # 0 THEN
  296. ErrorManager.WarnNumber( "DOSDELETE error", ErrorReturn );
  297. END; let it return error JEM 2/4/92 *)
  298. RETURN ErrorReturn;
  299. END DeleteFile;
  300. PROCEDURE FindFirstFile(FileSpec : ARRAY OF
  301. CHAR; VAR DirHandle: CARDINAL; VAR
  302. FileInfo : FileInfoRec) : CARDINAL;
  303. VAR
  304. ErrorReturn : CARDINAL;
  305. Reserved : LONGINT;
  306. SearchCount : CARDINAL;
  307. FileInfoRecord : FAPI.FILEFINDBUF;
  308. TmpSet : FAPI.USHORT;
  309. TmpStr : ARRAY [0..80] OF CHAR;
  310. BEGIN
  311. (*FindFirstFile*)
  312. StrEdit.AssignStr(FileSpec, TmpStr);
  313. (*We have to assign to a local string because the string that
  314. comes in through the parameter list may not be null terminated. *)
  315. TmpSet := FAPI.FILE_READONLY + FAPI.FILE_HIDDEN +
  316. FAPI.FILE_SYSTEM + FAPI.FILE_DIRECTORY;
  317. SearchCount := 1;
  318. Reserved :=VAL(LONGINT,0);
  319. ErrorReturn := FAPI.DOSFINDFIRST( SYSTEM.ADR(TmpStr),
  320. SYSTEM.ADR(DirHandle), TmpSet,
  321. SYSTEM.ADR(FileInfoRecord), SYSTEM.SIZE(FileInfoRecord),
  322. SYSTEM.ADR(SearchCount), Reserved);
  323. IF ErrorReturn # 0 THEN
  324. RETURN ErrorReturn;
  325. END;
  326. WITH FileInfo DO
  327. ByteFiddler.CardinalToTime( CARDINAL(FileInfoRecord.ftimeLastWrite),
  328. hour, minute, second );
  329. ByteFiddler.CardinalToDate( CARDINAL(FileInfoRecord.fdateLastWrite),
  330. month, day, year );
  331. size := FileInfoRecord.cbFile;
  332. attribute := ModeSet(FileInfoRecord.attrFile);
  333. M2Strings.Assign( FileInfoRecord.achName, name );
  334. END;
  335. RETURN StringIO.NoError;
  336. END FindFirstFile;
  337. PROCEDURE FindNextFile( DirHandle: CARDINAL;
  338. VAR FileInfo : FileInfoRec) : CARDINAL;
  339. VAR
  340. ErrorReturn : CARDINAL;
  341. Reserved : LONGINT;
  342. SearchCount : CARDINAL;
  343. FileInfoRecord : FAPI.FILEFINDBUF;
  344. BEGIN
  345. SearchCount := 1;
  346. ErrorReturn := FAPI.DOSFINDNEXT( DirHandle,
  347. SYSTEM.ADR(FileInfoRecord), SYSTEM.SIZE(FileInfoRecord),
  348. SYSTEM.ADR(SearchCount) );
  349. IF ErrorReturn # 0 THEN
  350. RETURN ErrorReturn;
  351. END;
  352. WITH FileInfo DO
  353. ByteFiddler.CardinalToTime( CARDINAL(FileInfoRecord.ftimeLastWrite),
  354. hour, minute, second );
  355. ByteFiddler.CardinalToDate( CARDINAL(FileInfoRecord.fdateLastWrite),
  356. month, day, year );
  357. size := FileInfoRecord.cbFile;
  358. attribute := ModeSet(FileInfoRecord.attrFile);
  359. StrEdit.AssignStr( FileInfoRecord.achName, name );
  360. END;
  361. RETURN StringIO.NoError;
  362. END FindNextFile;
  363. PROCEDURE FreeDiskSpace(DriveLetter : CHAR; VAR FreeBytes : LONGINT) :
  364. CARDINAL;
  365. VAR
  366. DriveNum, ErrorReturn: CARDINAL;
  367. Level1Data:FAPI.FSALLOCATE;
  368. BEGIN
  369. FreeBytes := Numbers.Lc( 0 );
  370. DriveLetter := CAP(DriveLetter);
  371. IF (DriveLetter < 'A') OR (DriveLetter > 'Z') THEN
  372. (* 26 July 87: changed from AND at suggestion of Marc
  373. Scheuner and Gregor Kley. *)
  374. ErrorManager.WARN('Invalid drive specification');
  375. END;
  376. IF DriveLetter='Z' THEN
  377. (*'Z' means default drive*)
  378. DriveNum := 0;
  379. ELSE
  380. DriveNum := ORD(DriveLetter)-64;
  381. END;
  382. (*turns an A into a 1, etc*)
  383. ErrorReturn := FAPI.DOSQFSINFO( DriveNum,
  384. 1, SYSTEM.ADR(Level1Data), SYSTEM.SIZE(Level1Data));
  385. IF ErrorReturn # 0 THEN
  386. RETURN ErrorReturn;
  387. ELSE
  388. FreeBytes := (Level1Data.cUnitAvail) *
  389. (Numbers.Lc (Level1Data.cbSector) *
  390. Level1Data.cSectorUnit);
  391. RETURN StringIO.NoError;
  392. END;
  393. END FreeDiskSpace;
  394. PROCEDURE GetCurrentDir(TheDrive : CHAR; VAR ThePath : ARRAY OF CHAR) :
  395. CARDINAL;
  396. VAR
  397. ErrorReturn, PathLength, DriveNum:CARDINAL;
  398. cnt : CARDINAL;
  399. BEGIN
  400. TheDrive := CAP(TheDrive);
  401. IF TheDrive = 'Z' THEN
  402. DriveNum := 0;
  403. ELSE
  404. DriveNum := ((ORD(TheDrive)-OrdA)+1);
  405. END;
  406. PathLength := HIGH( ThePath ) + 1;
  407. ErrorReturn := FAPI.DOSQCURDIR(DriveNum, SYSTEM.ADR(ThePath),
  408. SYSTEM.ADR(PathLength) );
  409. M2Strings.Insert( backslash, ThePath, 0 );
  410. RETURN ErrorReturn;
  411. END GetCurrentDir;
  412. PROCEDURE GetDefaultDrive() : CHAR;
  413. (*Returns the current default drive as an upper case letter.*)
  414. VAR
  415. DriveNum, ErrorReturn: CARDINAL;
  416. LogicalDriveMap: FAPI.ULONG;
  417. BEGIN
  418. ErrorReturn := FAPI.DOSQCURDISK( SYSTEM.ADR(DriveNum),
  419. SYSTEM.ADR(LogicalDriveMap) );
  420. IF ErrorReturn # 0 THEN
  421. ErrorManager.WarnNumber("DOSQCURDISK Error", ErrorReturn );
  422. END;
  423. RETURN( CHR( ORD(DriveNum) + OrdA - 1 ) );
  424. END GetDefaultDrive;
  425. PROCEDURE GetDiskInfo( TheDrive: CHAR; VAR BytesPerSector,
  426. SectorsPerCluster, ClustersOnDisk: CARDINAL; VAR
  427. KindOfDisk: DiskTypes );
  428. VAR
  429. DriveNum, ErrorReturn: CARDINAL;
  430. FatIDByte: CHAR;
  431. Level1Data: FAPI.FSALLOCATE;
  432. BEGIN
  433. TheDrive := CAP(TheDrive);
  434. IF TheDrive = 'Z' THEN
  435. DriveNum := 0;
  436. ELSE
  437. DriveNum := (ORD(TheDrive) - OrdA) + 1;
  438. END;
  439. ErrorReturn := FAPI.DOSQFSINFO( DriveNum, 1, SYSTEM.ADR(Level1Data),
  440. SYSTEM.SIZE(Level1Data) );
  441. IF ErrorReturn # 0 THEN
  442. ErrorManager.WarnNumber( "DOSQFSINFO error", ErrorReturn );
  443. END;
  444. BytesPerSector := Level1Data.cbSector;
  445. SectorsPerCluster := Numbers.C(Level1Data.cSectorUnit);
  446. ClustersOnDisk := Numbers.C(Level1Data.cUnit);
  447. KindOfDisk := unknown;
  448. END GetDiskInfo;
  449. PROCEDURE GetDirFromList( PathStyleStr: ARRAY OF CHAR; whichDir: CARDINAL;
  450. VAR output: ARRAY OF CHAR ): BOOLEAN;
  451. VAR
  452. StartSpot, EndSpot, inStrLngth: CARDINAL;
  453. BEGIN
  454. inStrLngth := M2Strings.Length(PathStyleStr);
  455. output[0] := 0C;
  456. IF whichDir = 0 THEN
  457. RETURN( FALSE );
  458. END;
  459. IF whichDir = 1 THEN
  460. StartSpot := LowLevel.ScanEQ( inStrLngth, '=',
  461. SYSTEM.ADR(PathStyleStr) );
  462. IF StartSpot >= inStrLngth THEN
  463. StartSpot := 0;
  464. END;
  465. ELSE
  466. StartSpot := PosUtils.FindNthPattern(semicolon, whichDir - 1,
  467. PathStyleStr);
  468. IF StartSpot >= inStrLngth THEN
  469. RETURN( FALSE );
  470. END;
  471. END;
  472. EndSpot := PosUtils.FindNthPattern(semicolon, whichDir, PathStyleStr);
  473. IF EndSpot >= inStrLngth THEN
  474. IF PosUtils.LastNonMatching(blank, PathStyleStr) = semicolon THEN
  475. RETURN( FALSE );
  476. END;
  477. EndSpot := inStrLngth;
  478. END;
  479. (* At this point, EndSpot is either sitting on the trailing null
  480. or on the semicolon following the directory name we want to
  481. copy out. *)
  482. M2Strings.Copy( PathStyleStr, StartSpot, EndSpot - StartSpot,
  483. output );
  484. IF PosUtils.LastNonMatching(blank, output) # backslash THEN
  485. StrEdit.Append( output, backslash );
  486. END;
  487. RETURN( TRUE );
  488. END GetDirFromList;
  489. PROCEDURE GetDrivePathAndName( FileSpec: ARRAY OF CHAR; VAR
  490. DriveLetter: CHAR; VAR PathName, FileName : ARRAY OF CHAR);
  491. VAR
  492. TmpStr : ARRAY [0..79] OF CHAR;
  493. spot: CARDINAL;
  494. SavedMessage: CARDINAL;
  495. BEGIN
  496. (*GetDrivePathAndName*)
  497. StrEdit.AssignStr( null, PathName );
  498. StrEdit.AssignStr( null, FileName );
  499. DriveLetter := 'Z';
  500. spot := 0;
  501. WHILE spot+1 <= M2Strings.Length(FileSpec) DO
  502. IF FileSpec[spot] = ':' THEN
  503. DriveLetter := FileSpec[ spot - 1 ];
  504. M2Strings.Delete(FileSpec, 0, 1 + spot);
  505. spot := 0;
  506. ELSIF (FileSpec[spot]=backslash) OR (FileSpec[spot]=fwdslash) THEN
  507. M2Strings.Copy(FileSpec, 0, spot + 1, TmpStr);
  508. StrEdit.Append(PathName, TmpStr);
  509. M2Strings.Delete(FileSpec, 0, 1 + spot);
  510. spot := 0;
  511. ELSE
  512. INC(spot);
  513. END;
  514. END;
  515. IF DriveLetter = 'Z' THEN
  516. DriveLetter := GetDefaultDrive();
  517. END;
  518. IF M2Strings.Length(PathName) = 0 THEN
  519. SavedMessage := GetCurrentDir( DriveLetter, PathName );
  520. IF SavedMessage # StringIO.NoError THEN
  521. StringIO.PrintMessage( SavedMessage );
  522. HALT();
  523. (*This error shouldn't be possible.*)
  524. END;
  525. IF PathName[ M2Strings.Length(PathName) - 1 ] # backslash THEN
  526. StrEdit.Append( PathName, backslash );
  527. END;
  528. END;
  529. IF (M2Strings.Length(FileSpec) > 0) AND (NOT (PosUtils.Present('*',
  530. FileSpec))) AND (NOT (PosUtils.Present('?', FileSpec))) THEN
  531. StrEdit.AssignStr( FileSpec, FileName );
  532. END;
  533. END GetDrivePathAndName;
  534. PROCEDURE GetFileDateAndTime(FileHandle : CARDINAL; VAR month,
  535. day, year, hours, minutes, seconds : CARDINAL);
  536. VAR
  537. ErrorReturn: CARDINAL;
  538. FileInfoRec: FAPI.FILEFINDBUF;
  539. BEGIN
  540. (*GetFileDateAndTime*)
  541. LowLevel.Fill( SYSTEM.ADR(FileInfoRec), SYSTEM.SIZE(FileInfoRec), 0C );
  542. ErrorReturn := FAPI.DOSQFILEINFO( FileHandle, 1,
  543. SYSTEM.ADR(FileInfoRec), SYSTEM.SIZE(FileInfoRec) );
  544. (*
  545. Diagnostics.diagC( 'FileHandle', FileHandle );
  546. Diagnostics.diagC( 'fdateCreation', FileInfoRec.fdateCreation );
  547. Diagnostics.diagC( 'ftimeCreation', FileInfoRec.ftimeCreation );
  548. Diagnostics.diagC( 'fdateLastAccess', FileInfoRec.fdateLastAccess );
  549. Diagnostics.diagC( 'ftimeLastAccess', FileInfoRec.ftimeLastAccess );
  550. Diagnostics.diagC( 'fdateLastWrite', FileInfoRec.fdateLastWrite );
  551. Diagnostics.diagC( 'ftimeLastWrite', FileInfoRec.ftimeLastWrite );
  552. Diagnostics.diagL( 'file', FileInfoRec.file );
  553. Diagnostics.diagL( 'fileAlloc', FileInfoRec.fileAlloc );
  554. Diagnostics.diagC( 'attrFile', FileInfoRec.attrFile );
  555. Diagnostics.diagC( 'cname', ORD(FileInfoRec.cname) );
  556. Diagnostics.diagS( 'name', FileInfoRec.name );
  557. Diagnostics.diagBlock( 'FileInfoRec', SYSTEM.ADR(FileInfoRec), SYSTEM.SIZE(FileInfoRec) );
  558. *)
  559. IF ErrorReturn # 0 THEN
  560. ErrorManager.WarnNumber( "GetFileDateAndTime error ", ErrorReturn );
  561. ELSE
  562. ByteFiddler.CardinalToTime( CARDINAL(FileInfoRec.ftimeLastWrite),
  563. hours, minutes, seconds );
  564. ByteFiddler.CardinalToDate( CARDINAL(FileInfoRec.fdateLastWrite),
  565. month, day, year );
  566. END;
  567. END GetFileDateAndTime;
  568. PROCEDURE GetFileMode(FileName : ARRAY OF CHAR; VAR TheSet : ModeSet) :
  569. CARDINAL;
  570. VAR
  571. ErrorReturn: CARDINAL;
  572. DosFileAttr: FAPI.USHORT;
  573. Reserved: LONGINT;
  574. TmpSet: ModeSetCaster;
  575. LocalStr: ARRAY [0..79] OF CHAR;
  576. BEGIN
  577. TmpSet.a := ModeSet{};
  578. M2Strings.Assign( FileName, LocalStr );
  579. ErrorReturn:= FAPI.DOSQFILEMODE(SYSTEM.ADR(LocalStr),
  580. SYSTEM.ADR(DosFileAttr), Reserved);
  581. IF ErrorReturn # 0 THEN
  582. TheSet := TmpSet.a;
  583. ErrorManager.WarnNumber("DosQFileMode error", ErrorReturn );
  584. RETURN ErrorReturn;
  585. ELSE
  586. TmpSet.b := BITSET(CARDINAL(DosFileAttr));
  587. TheSet := TmpSet.a;
  588. RETURN StringIO.NoError;
  589. END;
  590. END GetFileMode;
  591. PROCEDURE MkDir(DirName : ARRAY OF CHAR) : CARDINAL;
  592. VAR
  593. Reserved:LONGINT;
  594. ErrorReturn:CARDINAL;
  595. LocalStr: ARRAY [0..79] OF CHAR;
  596. BEGIN
  597. M2Strings.Assign( DirName, LocalStr );
  598. ErrorReturn := FAPI.DOSMKDIR(SYSTEM.ADR(LocalStr),Reserved);
  599. RETURN ErrorReturn;
  600. END MkDir;
  601. PROCEDURE RenameFile(OldFileName, NewFileName : ARRAY OF CHAR) :
  602. CARDINAL;
  603. VAR
  604. ErrorReturn:CARDINAL;
  605. dumstr : ARRAY [0..5] OF CHAR;
  606. LocalStr1, LocalStr2: ARRAY [0..79] OF CHAR;
  607. BEGIN
  608. M2Strings.Assign( OldFileName, LocalStr1 );
  609. M2Strings.Assign( NewFileName, LocalStr2 );
  610. IF M2Strings.Pos(':',LocalStr2) = 1 THEN
  611. M2Strings.Delete(LocalStr2, 0, 2);
  612. END;
  613. IF M2Strings.Pos(':',LocalStr1) = 1 THEN
  614. M2Strings.Copy(LocalStr1, 0, 2, dumstr);
  615. (* 26 July 87: changed from 1, 2 at suggestion of Marc
  616. Scheuner and Gregor Kley. *)
  617. M2Strings.Insert(dumstr, LocalStr2, 0+byte1);
  618. END;
  619. ErrorReturn := FAPI.DOSMOVE( SYSTEM.ADR(LocalStr1),
  620. SYSTEM.ADR(LocalStr2), NumTypes.L0);
  621. RETURN ErrorReturn;
  622. END RenameFile;
  623. PROCEDURE RmDir(DirName : ARRAY OF CHAR) : CARDINAL;
  624. VAR
  625. ErrorReturn: CARDINAL;
  626. Reserved: LONGINT;
  627. LocalStr: ARRAY [0..79] OF CHAR;
  628. BEGIN
  629. M2Strings.Assign( DirName, LocalStr );
  630. ErrorReturn := FAPI.DOSRMDIR(SYSTEM.ADR(LocalStr),
  631. Reserved);
  632. RETURN ErrorReturn;
  633. END RmDir;
  634. PROCEDURE SetDefaultDrive(DriveLetter : CHAR);
  635. (*Needs to return an ErrorMessage so that you can
  636. determine how many drives there are in the system.*)
  637. VAR
  638. ErrorReturn: CARDINAL;
  639. DriveNum: CARDINAL;
  640. BEGIN
  641. DriveLetter := CAP(DriveLetter);
  642. IF (DriveLetter<'A') OR (DriveLetter>'Z') THEN
  643. StringIO.PrintMessage(StringIO.InvalidDrive);
  644. END;
  645. DriveNum := (ORD(DriveLetter)-OrdA);
  646. ErrorReturn := FAPI.DOSSELECTDISK(DriveNum);
  647. IF ErrorReturn # 0 THEN
  648. StringIO.PrintMessage(ErrorReturn);
  649. END;
  650. END SetDefaultDrive;
  651. PROCEDURE SetFileDateAndTime(FileHandle, month, day, year, hours,
  652. minutes, seconds : CARDINAL);
  653. VAR
  654. ErrorReturn: CARDINAL;
  655. FileInfoRec: FAPI.FILEFINDBUF;
  656. BEGIN
  657. (*SetFileDateAndTime*)
  658. LowLevel.Fill( SYSTEM.ADR(FileInfoRec), SYSTEM.SIZE(FileInfoRec), 0C );
  659. FileInfoRec.fdateLastWrite := FAPI.FDATE(ByteFiddler.DateToCardinal(month, day,
  660. year));
  661. FileInfoRec.ftimeLastWrite := FAPI.FTIME(ByteFiddler.TimeToCardinal(hours,
  662. minutes, seconds));
  663. ErrorReturn := FAPI.DOSSETFILEINFO( FileHandle, 1,
  664. SYSTEM.ADR(FileInfoRec), SYSTEM.TSIZE(FAPI.FILEFINDBUF) );
  665. IF ErrorReturn # 0 THEN
  666. ErrorManager.WarnNumber( 'SetFileDateAndTime error', ErrorReturn );
  667. END;
  668. END SetFileDateAndTime;
  669. PROCEDURE SetFileMode(FileName : ARRAY OF CHAR; TheSet : ModeSet) :
  670. CARDINAL;
  671. VAR
  672. ErrorReturn: CARDINAL;
  673. Reserved: LONGINT;
  674. TmpSet: ModeSetCaster;
  675. LocalStr: ARRAY [0..79] OF CHAR;
  676. BEGIN
  677. TmpSet.a := TheSet;
  678. M2Strings.Assign( FileName, LocalStr );
  679. ErrorReturn := FAPI.DOSSETFILEMODE(SYSTEM.ADR(LocalStr),
  680. FAPI.FILE_NORMAL, Reserved);
  681. RETURN ErrorReturn;
  682. END SetFileMode;
  683. PROCEDURE SetFileLength( TheHandle:CARDINAL;length:LONGINT):CARDINAL;
  684. BEGIN
  685. RETURN FAPI.DOSNEWSIZE(TheHandle,length);
  686. END SetFileLength;
  687. PROCEDURE ValidFile( fname: ARRAY OF CHAR ): BOOLEAN;
  688. VAR
  689. TmpHandle: CARDINAL;
  690. ErrorReturn: CARDINAL;
  691. BEGIN
  692. IF HandleIO.FileExists( fname ) THEN
  693. RETURN TRUE;
  694. END;
  695. IF HandleIO.CreateFile( TmpHandle, fname ) = StringIO.NoError THEN
  696. ErrorReturn := HandleIO.CloseHandle(TmpHandle);
  697. ErrorReturn := DeleteFile( fname );
  698. RETURN (ErrorReturn = StringIO.NoError);
  699. ELSE
  700. RETURN FALSE;
  701. END;
  702. END ValidFile;
  703. PROCEDURE VolumeLabel(TheDrive : CHAR; VAR TheLabel : ARRAY OF CHAR);
  704. (*Returns the label of the disk in TheDrive.*)
  705. VAR
  706. DriveNum, ErrorReturn: CARDINAL;
  707. Level2Data: FAPI.FSINFO;
  708. cnt : CARDINAL;
  709. nextchar : CHAR;
  710. BEGIN
  711. (*VolumeLabel*)
  712. TheDrive := CAP(TheDrive);
  713. IF TheDrive='Z' THEN
  714. DriveNum := 0;
  715. ELSE
  716. DriveNum := ORD(TheDrive) - OrdA + 1;
  717. (*sets 'A' to 1, 'B' to 2, etc.*)
  718. END;
  719. StrEdit.AssignStr(null, TheLabel);
  720. ErrorReturn := FAPI.DOSQFSINFO( DriveNum,
  721. 2, SYSTEM.ADR(Level2Data), SYSTEM.TSIZE(FAPI.FSINFO));
  722. IF (ErrorReturn = 125) THEN
  723. (* DOSQFSINFO returns 125 if the drive has no volume label.
  724. In this case we set TheLabel to preserve compatibility with
  725. DOS version. *)
  726. StrEdit.AssignStr( 'unlabelled volume', TheLabel );
  727. ELSIF (ErrorReturn # 0) THEN
  728. ErrorManager.WarnNumber( "DosQFSInfo error", ErrorReturn );
  729. ELSE
  730. StrEdit.AssignStr( Level2Data.vol.szVolLabel, TheLabel );
  731. END;
  732. END VolumeLabel;
  733. PROCEDURE FindFiles(FileName : ARRAY OF CHAR; FileProc :
  734. FileInfoProc) : CARDINAL;
  735. VAR
  736. info : FileInfoRec;
  737. DirHandle, result : CARDINAL;
  738. BEGIN
  739. DirHandle := 0FFFFH;
  740. result := FindFirstFile(FileName, DirHandle, info);
  741. IF result=StringIO.NoError THEN
  742. LOOP
  743. IF NOT FileProc(info) THEN
  744. EXIT;
  745. END;
  746. result := FindNextFile(DirHandle, info);
  747. IF result#StringIO.NoError THEN
  748. IF result = StringIO.NoMoreFiles THEN
  749. result := StringIO.NoError;
  750. END;
  751. EXIT;
  752. END;
  753. END;
  754. END;
  755. IF 0 # FAPI.DOSFINDCLOSE( DirHandle ) THEN END;
  756. RETURN result;
  757. END FindFiles;
  758. BEGIN
  759. Initialized := FALSE;
  760. Init();
  761. END Drectory.
  762.