rawfilem.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : G *
  23. * *
  24. * $Archive:: /G/wdump/RAWFILEM.CPP $*
  25. * *
  26. * $Author:: Eric_c $*
  27. * *
  28. * $Modtime:: 7/28/97 3:36p $*
  29. * *
  30. * $Revision:: 3 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * RawFileMClass::Bias -- Bias a file with a specific starting position and length. *
  35. * RawFileMClass::Close -- Perform a closure of the file. *
  36. * RawFileMClass::Create -- Creates an empty file. *
  37. * RawFileMClass::Delete -- Deletes the file object from the disk. *
  38. * RawFileMClass::Error -- Handles displaying a file error message. *
  39. * RawFileMClass::Get_Date_Time -- Gets the date and time the file was last modified. *
  40. * RawFileMClass::Is_Available -- Checks to see if the specified file is available to open. *
  41. * RawFileMClass::Open -- Assigns name and opens file in one operation. *
  42. * RawFileMClass::Open -- Opens the file object with the rights specified. *
  43. * RawFileMClass::RawFileMClass -- Simple constructor for a file object. *
  44. * RawFileMClass::Raw_Seek -- Performs a seek on the unbiased file *
  45. * RawFileMClass::Read -- Reads the specified number of bytes into a memory buffer. *
  46. * RawFileMClass::Seek -- Reposition the file pointer as indicated. *
  47. * RawFileMClass::Set_Date_Time -- Sets the date and time the file was last modified. *
  48. * RawFileMClass::Set_Name -- Manually sets the name for a file object. *
  49. * RawFileMClass::Size -- Determines size of file (in bytes). *
  50. * RawFileMClass::Write -- Writes the specified data to the buffer specified. *
  51. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  52. #include "always.h"
  53. #include "rawfilem.h"
  54. #include <direct.h>
  55. #include <share.h>
  56. #include <stddef.h>
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include <string.h>
  60. /***********************************************************************************************
  61. * RawFileMClass::Error -- Handles displaying a file error message. *
  62. * *
  63. * Display an error message as indicated. If it is allowed to retry, then pressing a key *
  64. * will return from this function. Otherwise, it will exit the program with "exit()". *
  65. * *
  66. * INPUT: error -- The error number (same as the DOSERR.H error numbers). *
  67. * *
  68. * canretry -- Can this routine exit normally so that retrying can occur? If this is *
  69. * false, then the program WILL exit in this routine. *
  70. * *
  71. * filename -- Optional filename to report with this error. If no filename is *
  72. * supplied, then no filename is listed in the error message. *
  73. * *
  74. * OUTPUT: none, but this routine might not return at all if the "canretry" parameter is *
  75. * false or the player pressed ESC. *
  76. * *
  77. * WARNINGS: This routine may not return at all. It handles being in text mode as well as *
  78. * if in a graphic mode. *
  79. * *
  80. * HISTORY: *
  81. * 10/17/1994 JLB : Created. *
  82. *=============================================================================================*/
  83. void RawFileMClass::Error(int, int, char const * )
  84. {
  85. }
  86. /***********************************************************************************************
  87. * RawFileMClass::RawFileMClass -- Simple constructor for a file object. *
  88. * *
  89. * This constructor is called when a file object is created with a supplied filename, but *
  90. * not opened at the same time. In this case, an assumption is made that the supplied *
  91. * filename is a constant string. A duplicate of the filename string is not created since *
  92. * it would be wasteful in that case. *
  93. * *
  94. * INPUT: filename -- The filename to assign to this file object. *
  95. * *
  96. * OUTPUT: none *
  97. * *
  98. * WARNINGS: none *
  99. * *
  100. * HISTORY: *
  101. * 10/17/1994 JLB : Created. *
  102. *=============================================================================================*/
  103. RawFileMClass::RawFileMClass(char const * filename) :
  104. Rights(0),
  105. BiasStart(0),
  106. BiasLength(-1),
  107. Handle(NULL_HANDLE),
  108. Filename(filename),
  109. Date(0),
  110. Time(0),
  111. Allocated(false)
  112. {
  113. }
  114. /***********************************************************************************************
  115. * RawFileMClass::Set_Name -- Manually sets the name for a file object. *
  116. * *
  117. * This routine will set the name for the file object to the name specified. This name is *
  118. * duplicated in free store. This allows the supplied name to be a temporarily constructed *
  119. * text string. Setting the name in this fashion doesn't affect the closed or opened state *
  120. * of the file. *
  121. * *
  122. * INPUT: filename -- The filename to assign to this file object. *
  123. * *
  124. * OUTPUT: Returns with a pointer to the allocated copy of this filename. This pointer is *
  125. * guaranteed to remain valid for the duration of this file object or until the name *
  126. * is changed -- whichever is sooner. *
  127. * *
  128. * WARNINGS: Because of the allocation this routine must perform, memory could become *
  129. * fragmented. *
  130. * *
  131. * HISTORY: *
  132. * 10/17/1994 JLB : Created. *
  133. *=============================================================================================*/
  134. char const * RawFileMClass::Set_Name(char const * filename)
  135. {
  136. if (Filename != NULL && Allocated) {
  137. free((char *)Filename);
  138. Filename = NULL;
  139. Allocated = false;
  140. }
  141. if (filename == NULL) return(NULL);
  142. Bias(0);
  143. Filename = strdup(filename);
  144. if (Filename == NULL) {
  145. Error(ENOMEM, false, filename);
  146. }
  147. Allocated = true;
  148. return(Filename);
  149. }
  150. /***********************************************************************************************
  151. * RawFileMClass::Open -- Assigns name and opens file in one operation. *
  152. * *
  153. * This routine will assign the specified filename to the file object and open it at the *
  154. * same time. If the file object was already open, then it will be closed first. If the *
  155. * file object was previously assigned a filename, then it will be replaced with the new *
  156. * name. Typically, this routine is used when an anonymous file object has been crated and *
  157. * now it needs to be assigned a name and opened. *
  158. * *
  159. * INPUT: filename -- The filename to assign to this file object. *
  160. * *
  161. * rights -- The open file access rights to use. *
  162. * *
  163. * OUTPUT: bool; Was the file opened? The return value of this is moot, since the open file *
  164. * is designed to never return unless it succeeded. *
  165. * *
  166. * WARNINGS: none *
  167. * *
  168. * HISTORY: *
  169. * 10/17/1994 JLB : Created. *
  170. *=============================================================================================*/
  171. int RawFileMClass::Open(char const * filename, int rights)
  172. {
  173. Set_Name(filename);
  174. return(Open(rights));
  175. }
  176. /***********************************************************************************************
  177. * RawFileMClass::Open -- Opens the file object with the rights specified. *
  178. * *
  179. * This routine is used to open the specified file object with the access rights indicated. *
  180. * This only works if the file has already been assigned a filename. It is guaranteed, by *
  181. * the error handler, that this routine will always return with success. *
  182. * *
  183. * INPUT: rights -- The file access rights to use when opening this file. This is a *
  184. * combination of READ and/or WRITE bit flags. *
  185. * *
  186. * OUTPUT: bool; Was the file opened successfully? This will always return true by reason of *
  187. * the error handler. *
  188. * *
  189. * WARNINGS: none *
  190. * *
  191. * HISTORY: *
  192. * 10/17/1994 JLB : Created. *
  193. *=============================================================================================*/
  194. int RawFileMClass::Open(int rights)
  195. {
  196. Close();
  197. /*
  198. ** Verify that there is a filename associated with this file object. If not, then this is a
  199. ** big error condition.
  200. */
  201. if (Filename == NULL) {
  202. Error(ENOENT, false);
  203. }
  204. /*
  205. ** Record the access rights used for this open call. These rights will be used if the
  206. ** file object is duplicated.
  207. */
  208. Rights = rights;
  209. /*
  210. ** Repetitively try to open the file. Abort if a fatal error condition occurs.
  211. */
  212. for (;;) {
  213. /*
  214. ** Try to open the file according to the access rights specified.
  215. */
  216. switch (rights) {
  217. /*
  218. ** If the access rights are not recognized, then report this as
  219. ** an invalid access code.
  220. */
  221. default:
  222. Error_Number = EINVAL;
  223. break;
  224. case READ:
  225. Handle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  226. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  227. break;
  228. case WRITE:
  229. Handle = CreateFileA(Filename, GENERIC_WRITE, 0,
  230. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  231. break;
  232. case READ|WRITE:
  233. Handle = CreateFileA(Filename, GENERIC_READ | GENERIC_WRITE, 0,
  234. NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  235. break;
  236. }
  237. /*
  238. ** Biased files must be positioned past the bias start position.
  239. */
  240. if (BiasStart != 0 || BiasLength != -1) {
  241. Seek(0, SEEK_SET);
  242. }
  243. /*
  244. ** If the handle indicates the file is not open, then this is an error condition.
  245. ** For the case of the file cannot be found, then allow a retry. All other cases
  246. ** are fatal.
  247. */
  248. if (Handle == NULL_HANDLE) {
  249. return(false);
  250. // Error(GetLastError(), false, Filename);
  251. // continue;
  252. }
  253. break;
  254. }
  255. return(true);
  256. }
  257. /***********************************************************************************************
  258. * RawFileMClass::Is_Available -- Checks to see if the specified file is available to open. *
  259. * *
  260. * This routine will examine the disk system to see if the specified file can be opened *
  261. * or not. Use this routine before opening a file in order to make sure that is available *
  262. * or to perform other necessary actions. *
  263. * *
  264. * INPUT: force -- Should this routine keep retrying until the file becomes available? If *
  265. * in this case it doesn't become available, then the program will abort. *
  266. * *
  267. * OUTPUT: bool; Is the file available to be opened? *
  268. * *
  269. * WARNINGS: Depending on the parameter passed in, this routine may never return. *
  270. * *
  271. * HISTORY: *
  272. * 10/18/1994 JLB : Created. *
  273. *=============================================================================================*/
  274. bool RawFileMClass::Is_Available(int forced)
  275. {
  276. if (Filename == NULL) return(false);
  277. /*
  278. ** If the file is already open, then is must have already passed the availability check.
  279. ** Return true in this case.
  280. */
  281. if (Is_Open()) return(true);
  282. /*
  283. ** If this is a forced check, then go through the normal open channels, since those
  284. ** channels ensure that the file must exist.
  285. */
  286. if (forced) {
  287. RawFileMClass::Open(READ);
  288. RawFileMClass::Close();
  289. return(true);
  290. }
  291. /*
  292. ** Perform a raw open of the file. If this open fails for ANY REASON, including a missing
  293. ** CD-ROM, this routine will return a failure condition. In all but the missing file
  294. ** condition, go through the normal error recover channels.
  295. */
  296. for (;;) {
  297. Handle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ,
  298. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  299. if (Handle == NULL_HANDLE) {
  300. return(false);
  301. }
  302. break;
  303. }
  304. /*
  305. ** Since the file could be opened, then close it and return that the file exists.
  306. */
  307. if (!CloseHandle(Handle)) {
  308. Error(GetLastError(), false, Filename);
  309. }
  310. Handle = NULL_HANDLE;
  311. return(true);
  312. }
  313. /***********************************************************************************************
  314. * RawFileMClass::Close -- Perform a closure of the file. *
  315. * *
  316. * Close the file object. In the rare case of an error, handle it as appropriate. *
  317. * *
  318. * INPUT: none *
  319. * *
  320. * OUTPUT: none *
  321. * *
  322. * WARNINGS: Some rare error conditions may cause this routine to abort the program. *
  323. * *
  324. * HISTORY: *
  325. * 10/18/1994 JLB : Created. *
  326. *=============================================================================================*/
  327. void RawFileMClass::Close(void)
  328. {
  329. /*
  330. ** If the file is open, then close it. If the file is already closed, then just return. This
  331. ** isn't considered an error condition.
  332. */
  333. if (Is_Open()) {
  334. /*
  335. ** Try to close the file. If there was an error (who knows what that could be), then
  336. ** call the error routine.
  337. */
  338. if (!CloseHandle(Handle)) {
  339. Error(GetLastError(), false, Filename);
  340. }
  341. /*
  342. ** At this point the file must have been closed. Mark the file as empty and return.
  343. */
  344. Handle = NULL_HANDLE;
  345. }
  346. }
  347. /***********************************************************************************************
  348. * RawFileMClass::Read -- Reads the specified number of bytes into a memory buffer. *
  349. * *
  350. * This routine will read the specified number of bytes and place the data into the buffer *
  351. * indicated. It is legal to call this routine with a request for more bytes than are in *
  352. * the file. This condition can result in fewer bytes being read than requested. Determine *
  353. * this by examining the return value. *
  354. * *
  355. * INPUT: buffer -- Pointer to the buffer to read data into. If NULL is passed, no read *
  356. * is performed. *
  357. * *
  358. * size -- The number of bytes to read. If NULL is passed, then no read is *
  359. * performed. *
  360. * *
  361. * OUTPUT: Returns with the number of bytes read into the buffer. If this number is less *
  362. * than requested, it indicates that the file has been exhausted. *
  363. * *
  364. * WARNINGS: none *
  365. * *
  366. * HISTORY: *
  367. * 10/18/1994 JLB : Created. *
  368. *=============================================================================================*/
  369. int RawFileMClass::Read(void * buffer, int size)
  370. {
  371. long bytesread = 0; // Running count of the number of bytes read into the buffer.
  372. int opened = false; // Was the file opened by this routine?
  373. /*
  374. ** If the file isn't opened, open it. This serves as a convenience
  375. ** for the programmer.
  376. */
  377. if (!Is_Open()) {
  378. /*
  379. ** The error check here is moot. Open will never return unless it succeeded.
  380. */
  381. if (!Open(READ)) {
  382. return(0);
  383. }
  384. opened = true;
  385. }
  386. /*
  387. ** A biased file has the requested read length limited to the bias length of
  388. ** the file.
  389. */
  390. if (BiasLength != -1) {
  391. int remainder = BiasLength - Seek(0);
  392. size = size < remainder ? size : remainder;
  393. }
  394. long total = 0;
  395. while (size > 0) {
  396. bytesread = 0;
  397. if (!ReadFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
  398. size -= bytesread;
  399. total += bytesread;
  400. Error(GetLastError(), true, Filename);
  401. continue;
  402. }
  403. size -= bytesread;
  404. total += bytesread;
  405. if (bytesread == 0) break;
  406. }
  407. bytesread = total;
  408. /*
  409. ** Close the file if it was opened by this routine and return
  410. ** the actual number of bytes read into the buffer.
  411. */
  412. if (opened) Close();
  413. return(bytesread);
  414. }
  415. /***********************************************************************************************
  416. * RawFileMClass::Write -- Writes the specified data to the buffer specified. *
  417. * *
  418. * This routine will write the data specified to the file. *
  419. * *
  420. * INPUT: buffer -- The buffer that holds the data to write. *
  421. * *
  422. * size -- The number of bytes to write to the file. *
  423. * *
  424. * OUTPUT: Returns with the number of bytes written to the file. This routine catches the *
  425. * case of a disk full condition, so this routine will always return with the number *
  426. * matching the size request. *
  427. * *
  428. * WARNINGS: A fatal file condition could cause this routine to never return. *
  429. * *
  430. * HISTORY: *
  431. * 10/18/1994 JLB : Created. *
  432. *=============================================================================================*/
  433. int RawFileMClass::Write(void const * buffer, int size)
  434. {
  435. long bytesread = 0;
  436. int opened = false; // Was the file manually opened?
  437. /*
  438. ** Check to open status of the file. If the file is open, then merely write to
  439. ** it. Otherwise, open the file for writing and then close the file when the
  440. ** output is finished.
  441. */
  442. if (!Is_Open()) {
  443. if (!Open(WRITE)) {
  444. return(0);
  445. }
  446. opened = true;
  447. }
  448. if (!WriteFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
  449. Error(GetLastError(), false, Filename);
  450. }
  451. /*
  452. ** Fixup the bias length if necessary.
  453. */
  454. if (BiasLength != -1) {
  455. if (Raw_Seek(0) > BiasStart+BiasLength) {
  456. BiasLength = Raw_Seek(0) - BiasStart;
  457. }
  458. }
  459. /*
  460. ** If this routine had to open the file, then close it before returning.
  461. */
  462. if (opened) {
  463. Close();
  464. }
  465. /*
  466. ** Return with the number of bytes written. This will always be the number of bytes
  467. ** requested, since the case of the disk being full is caught by this routine.
  468. */
  469. return(bytesread);
  470. }
  471. /***********************************************************************************************
  472. * RawFileMClass::Seek -- Reposition the file pointer as indicated. *
  473. * *
  474. * Use this routine to move the filepointer to the position indicated. It can move either *
  475. * relative to current position or absolute from the beginning or ending of the file. This *
  476. * routine will only return if it successfully performed the seek. *
  477. * *
  478. * INPUT: pos -- The position to seek to. This is interpreted as relative to the position *
  479. * indicated by the "dir" parameter. *
  480. * *
  481. * dir -- The relative position to relate the seek to. This can be either SEEK_SET *
  482. * for the beginning of the file, SEEK_CUR for the current position, or *
  483. * SEEK_END for the end of the file. *
  484. * *
  485. * OUTPUT: This routine returns the position that the seek ended up at. *
  486. * *
  487. * WARNINGS: If there was a file error, then this routine might never return. *
  488. * *
  489. * HISTORY: *
  490. * 10/18/1994 JLB : Created. *
  491. *=============================================================================================*/
  492. int RawFileMClass::Seek(int pos, int dir)
  493. {
  494. /*
  495. ** A file that is biased will have a seek operation modified so that the file appears to
  496. ** exist only within the bias range. All bytes outside of this range appear to be
  497. ** non-existant.
  498. */
  499. if (BiasLength != -1) {
  500. switch (dir) {
  501. case SEEK_SET:
  502. if (pos > BiasLength) {
  503. pos = BiasLength;
  504. }
  505. pos += BiasStart;
  506. break;
  507. case SEEK_CUR:
  508. break;
  509. case SEEK_END:
  510. dir = SEEK_SET;
  511. pos += BiasStart + BiasLength;
  512. // pos = (pos <= BiasStart+BiasLength) ? pos : BiasStart+BiasLength;
  513. // pos = (pos >= BiasStart) ? pos : BiasStart;
  514. break;
  515. }
  516. /*
  517. ** Perform the modified raw seek into the file.
  518. */
  519. long newpos = Raw_Seek(pos, dir) - BiasStart;
  520. /*
  521. ** Perform a final double check to make sure the file position fits with the bias range.
  522. */
  523. if (newpos < 0) {
  524. newpos = Raw_Seek(BiasStart, SEEK_SET) - BiasStart;
  525. }
  526. if (newpos > BiasLength) {
  527. newpos = Raw_Seek(BiasStart+BiasLength, SEEK_SET) - BiasStart;
  528. }
  529. return(newpos);
  530. }
  531. /*
  532. ** If the file is not biased in any fashion, then the normal seek logic will
  533. ** work just fine.
  534. */
  535. return(Raw_Seek(pos, dir));
  536. }
  537. /***********************************************************************************************
  538. * RawFileMClass::Size -- Determines size of file (in bytes). *
  539. * *
  540. * Use this routine to determine the size of the file. The file must exist or this is an *
  541. * error condition. *
  542. * *
  543. * INPUT: none *
  544. * *
  545. * OUTPUT: Returns with the number of bytes in the file. *
  546. * *
  547. * WARNINGS: This routine handles error conditions and will not return unless the file *
  548. * exists and can successfully be queried for file length. *
  549. * *
  550. * HISTORY: *
  551. * 10/18/1994 JLB : Created. *
  552. *=============================================================================================*/
  553. int RawFileMClass::Size(void)
  554. {
  555. int size = 0;
  556. /*
  557. ** A biased file already has its length determined.
  558. */
  559. if (BiasLength != -1) {
  560. return(BiasLength);
  561. }
  562. /*
  563. ** If the file is open, then proceed normally.
  564. */
  565. if (Is_Open()) {
  566. size = GetFileSize(Handle, NULL);
  567. /*
  568. ** If there was in internal error, then call the error function.
  569. */
  570. if (size == 0xFFFFFFFF) {
  571. Error(GetLastError(), false, Filename);
  572. }
  573. } else {
  574. /*
  575. ** If the file wasn't open, then open the file and call this routine again. Count on
  576. ** the fact that the open function must succeed.
  577. */
  578. if (Open()) {
  579. size = Size();
  580. /*
  581. ** Since we needed to open the file we must remember to close the file when the
  582. ** size has been determined.
  583. */
  584. Close();
  585. }
  586. }
  587. BiasLength = size-BiasStart;
  588. return(BiasLength);
  589. }
  590. /***********************************************************************************************
  591. * RawFileMClass::Create -- Creates an empty file. *
  592. * *
  593. * This routine will create an empty file from the file object. The file object's filename *
  594. * must already have been assigned before this routine will function. *
  595. * *
  596. * INPUT: none *
  597. * *
  598. * OUTPUT: bool; Was the file successfully created? This routine will always return true. *
  599. * *
  600. * WARNINGS: A fatal error condition could occur with this routine. Especially if the disk *
  601. * is full or a read-only media was selected. *
  602. * *
  603. * HISTORY: *
  604. * 10/18/1994 JLB : Created. *
  605. *=============================================================================================*/
  606. int RawFileMClass::Create(void)
  607. {
  608. Close();
  609. if (Open(WRITE)) {
  610. /*
  611. ** A biased file must be at least as long as the bias offset. Seeking to the
  612. ** appropriate start offset has the effect of lengthening the file to the
  613. ** correct length.
  614. */
  615. if (BiasLength != -1) {
  616. Seek(0, SEEK_SET);
  617. }
  618. Close();
  619. return(true);
  620. }
  621. return(false);
  622. }
  623. /***********************************************************************************************
  624. * RawFileMClass::Delete -- Deletes the file object from the disk. *
  625. * *
  626. * This routine will delete the file object from the disk. If the file object doesn't *
  627. * exist, then this routine will return as if it had succeeded (since the effect is the *
  628. * same). *
  629. * *
  630. * INPUT: none *
  631. * *
  632. * OUTPUT: bool; Was the file deleted? If the file was already missing, the this value will *
  633. * be false. *
  634. * *
  635. * WARNINGS: none *
  636. * *
  637. * HISTORY: *
  638. * 10/18/1994 JLB : Created. *
  639. *=============================================================================================*/
  640. int RawFileMClass::Delete(void)
  641. {
  642. /*
  643. ** If the file was open, then it must be closed first.
  644. */
  645. Close();
  646. /*
  647. ** If there is no filename associated with this object, then this indicates a fatal error
  648. ** condition. Report this and abort.
  649. */
  650. if (!Filename) {
  651. Error(ENOENT, false);
  652. }
  653. /*
  654. ** Repetitively try to delete the file if possible. Either return with success, or
  655. ** abort the program with an error.
  656. */
  657. for (;;) {
  658. /*
  659. ** If the file is already missing, then return with this fact. No action is necessary.
  660. ** This can occur as this section loops if the file exists on a floppy and the floppy
  661. ** was removed, the file deleted on another machine, and then the floppy was
  662. ** reinserted. Admittedly, this is a rare case, but is handled here.
  663. */
  664. if (!Is_Available()) {
  665. return(false);
  666. }
  667. if (!DeleteFile(Filename)) {
  668. Error(GetLastError(), false, Filename);
  669. return(false);
  670. }
  671. break;
  672. }
  673. /*
  674. ** DOS reports that the file was successfully deleted. Return with this fact.
  675. */
  676. return(true);
  677. }
  678. /***********************************************************************************************
  679. * RawFileMClass::Get_Date_Time -- Gets the date and time the file was last modified. *
  680. * *
  681. * Use this routine to get the date and time of the file. *
  682. * *
  683. * INPUT: none *
  684. * *
  685. * OUTPUT: Returns with the file date and time as a long. *
  686. * Use the YEAR(long), MONTH(),.... *
  687. * *
  688. * WARNINGS: none *
  689. * *
  690. * HISTORY: *
  691. * 11/14/1995 DRD : Created. *
  692. * 07/13/1996 JLB : Handles win32 method. *
  693. *=============================================================================================*/
  694. unsigned long RawFileMClass::Get_Date_Time(void)
  695. {
  696. BY_HANDLE_FILE_INFORMATION info;
  697. if (GetFileInformationByHandle(Handle, &info)) {
  698. WORD dosdate;
  699. WORD dostime;
  700. FileTimeToDosDateTime(&info.ftLastWriteTime, &dosdate, &dostime);
  701. return((dosdate << 16) | dostime);
  702. }
  703. return(0);
  704. }
  705. /***********************************************************************************************
  706. * RawFileMClass::Set_Date_Time -- Sets the date and time the file was last modified. *
  707. * *
  708. * Use this routine to set the date and time of the file. *
  709. * *
  710. * INPUT: the file date and time as a long *
  711. * *
  712. * OUTPUT: successful or not if the file date and time was changed. *
  713. * *
  714. * WARNINGS: none *
  715. * *
  716. * HISTORY: *
  717. * 11/14/1995 DRD : Created. *
  718. * 07/13/1996 JLB : Handles win 32 method *
  719. *=============================================================================================*/
  720. bool RawFileMClass::Set_Date_Time(unsigned long datetime)
  721. {
  722. if (RawFileMClass::Is_Open()) {
  723. BY_HANDLE_FILE_INFORMATION info;
  724. if (GetFileInformationByHandle(Handle, &info)) {
  725. FILETIME filetime;
  726. if (DosDateTimeToFileTime((WORD)(datetime >> 16), (WORD)(datetime & 0x0FFFF), &filetime)) {
  727. return(SetFileTime(Handle, &info.ftCreationTime, &filetime, &filetime) != 0);
  728. }
  729. }
  730. }
  731. return(false);
  732. }
  733. /***********************************************************************************************
  734. * RawFileMClass::Bias -- Bias a file with a specific starting position and length. *
  735. * *
  736. * This will bias a file by giving it an artificial starting position and length. By *
  737. * using this routine, it is possible to 'fool' the file into ignoring a header and *
  738. * trailing extra data. An example of this would be a file inside of a mixfile. *
  739. * *
  740. * INPUT: start -- The starting offset that will now be considered the start of the *
  741. * file. *
  742. * *
  743. * length -- The forced length of the file. For files that are opened for write, *
  744. * this serves as the artificial constraint on the file's length. For *
  745. * files opened for read, this limits the usable file size. *
  746. * *
  747. * OUTPUT: none *
  748. * *
  749. * WARNINGS: none *
  750. * *
  751. * HISTORY: *
  752. * 06/02/1996 JLB : Created. *
  753. *=============================================================================================*/
  754. void RawFileMClass::Bias(int start, int length)
  755. {
  756. if (start == 0) {
  757. BiasStart = 0;
  758. BiasLength = -1;
  759. return;
  760. }
  761. BiasLength = RawFileMClass::Size();
  762. BiasStart += start;
  763. if (length != -1) {
  764. BiasLength = BiasLength < length ? BiasLength : length;
  765. }
  766. BiasLength = BiasLength > 0 ? BiasLength : 0;
  767. /*
  768. ** Move the current file offset to a legal position if necessary and the
  769. ** file was open.
  770. */
  771. if (Is_Open()) {
  772. RawFileMClass::Seek(0, SEEK_SET);
  773. }
  774. }
  775. /***********************************************************************************************
  776. * RawFileMClass::Raw_Seek -- Performs a seek on the unbiased file *
  777. * *
  778. * This will perform a seek on the file as if it were unbiased. This is in spite of any *
  779. * bias setting the file may have. The ability to perform a raw seek in this fasion is *
  780. * necessary to maintain the bias ability. *
  781. * *
  782. * INPUT: pos -- The position to seek the file relative to the "dir" parameter. *
  783. * *
  784. * dir -- The origin of the seek operation. *
  785. * *
  786. * OUTPUT: Returns with the new position of the seek operation. *
  787. * *
  788. * WARNINGS: none *
  789. * *
  790. * HISTORY: *
  791. * 08/04/1996 JLB : Created. *
  792. *=============================================================================================*/
  793. int RawFileMClass::Raw_Seek(int pos, int dir)
  794. {
  795. /*
  796. ** If the file isn't opened, then this is a fatal error condition.
  797. */
  798. if (!Is_Open()) {
  799. Error(EBADF, false, Filename);
  800. }
  801. switch (dir) {
  802. case SEEK_SET:
  803. dir = FILE_BEGIN;
  804. break;
  805. case SEEK_CUR:
  806. dir = FILE_CURRENT;
  807. break;
  808. case SEEK_END:
  809. dir = FILE_END;
  810. break;
  811. }
  812. pos = SetFilePointer(Handle, pos, NULL, dir);
  813. /*
  814. ** If there was an error in the seek, then bail with an error condition.
  815. */
  816. if (pos == 0xFFFFFFFF) {
  817. Error(GetLastError(), false, Filename);
  818. }
  819. /*
  820. ** Return with the new position of the file. This will range between zero and the number of
  821. ** bytes the file contains.
  822. */
  823. return(pos);
  824. }