File.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646
  1. //---------------------------------------------------------------------------
  2. //
  3. // file.cpp - This file contains the class functions for File
  4. //
  5. // The File class simply calls the Windows file functions.
  6. // It is purely a wrapper.
  7. //
  8. // The mmFile Class is a wrapper for the Win32 Memory Mapped
  9. // file functionality. It is used exactly the same as above class.
  10. //
  11. //---------------------------------------------------------------------------//
  12. // Copyright (C) Microsoft Corporation. All rights reserved. //
  13. //===========================================================================//
  14. //---------------------------------------------------------------------------
  15. // Include files
  16. #ifndef FILE_H
  17. #include "file.h"
  18. #endif
  19. #ifndef HEAP_H
  20. #include "heap.h"
  21. #endif
  22. #ifndef FFILE_H
  23. #include "ffile.h"
  24. #endif
  25. #ifndef PACKET_H
  26. #include "packet.h"
  27. #endif
  28. #ifndef FASTFILE_H
  29. #include "fastfile.h"
  30. #endif
  31. #ifndef UTILITIES_H
  32. #include "utilities.h"
  33. #endif
  34. #include <string.h>
  35. #include <io.h>
  36. #include <ctype.h>
  37. #include <windows.h>
  38. #ifndef _MBCS
  39. #include <gameos.hpp>
  40. #else
  41. #include <assert.h>
  42. #define gosASSERT assert
  43. #define gos_Malloc malloc
  44. #define gos_Free free
  45. #endif
  46. //-----------------
  47. // Static Variables
  48. unsigned long File::lastError = NO_ERR;
  49. bool File::logFileTraffic = FALSE;
  50. FilePtr fileTrafficLog = NULL;
  51. char CDInstallPath[1024];
  52. void EnterWindowMode();
  53. void EnterFullScreenMode();
  54. void __stdcall ExitGameOS();
  55. extern char FileMissingString[];
  56. extern char CDMissingString[];
  57. extern char MissingTitleString[];
  58. #undef INVALID_HANDLE_VALUE
  59. #define INVALID_HANDLE_VALUE -1
  60. //---------------------------------------------------------------------------
  61. void createTrafficLog (void)
  62. {
  63. if (fileTrafficLog && fileTrafficLog->isOpen())
  64. return;
  65. fileTrafficLog = new File;
  66. fileTrafficLog->create("filetraffic.log");
  67. }
  68. //---------------------------------------------------------------------------
  69. // Global Functions
  70. long fileExists (char* fName)
  71. {
  72. struct _stat st;
  73. if (_stat(fName,&st) != -1)
  74. {
  75. return 1;
  76. }
  77. long fastFileHandle = -1;
  78. FastFilePtr fastFile = FastFileFind(fName,fastFileHandle);
  79. if (fastFile)
  80. return 2;
  81. return 0;
  82. }
  83. //---------------------------------------------------------------------------
  84. long fileExistsOnCD (char* fName)
  85. {
  86. //Just add the CD path here and see if its there.
  87. char bigPath[2048];
  88. strcpy(bigPath,CDInstallPath);
  89. strcat(bigPath,fName);
  90. struct _stat st;
  91. if (_stat(bigPath,&st) != -1)
  92. {
  93. return 1;
  94. }
  95. return 0;
  96. }
  97. //---------------------------------------------------------------------------
  98. bool file1OlderThan2 (char* file1, char* file2)
  99. {
  100. if ((fileExists(file1) == 1) && (fileExists(file2) == 1))
  101. {
  102. struct _stat st1, st2;
  103. _stat(file1,&st1);
  104. _stat(file2,&st2);
  105. if (st1.st_mtime < st2.st_mtime)
  106. return true;
  107. }
  108. return false;
  109. }
  110. //---------------------------------------------------------------------------
  111. // class File member functions
  112. void *File::operator new (size_t mySize)
  113. {
  114. void *result = NULL;
  115. result = systemHeap->Malloc(mySize);
  116. return(result);
  117. }
  118. //---------------------------------------------------------------------------
  119. void File::operator delete (void *us)
  120. {
  121. systemHeap->Free(us);
  122. }
  123. //---------------------------------------------------------------------------
  124. File::File (void)
  125. {
  126. fileName = NULL;
  127. fileMode = NOMODE;
  128. handle = -1;
  129. length = 0;
  130. logicalPosition = 0;
  131. bufferResult = 0;
  132. parent = NULL;
  133. parentOffset = 0;
  134. physicalLength = 0;
  135. childList = NULL;
  136. numChildren = 0;
  137. inRAM = FALSE;
  138. fileImage = NULL;
  139. fastFile = NULL;
  140. }
  141. //---------------------------------------------------------------------------
  142. inline void File::setup (void)
  143. {
  144. logicalPosition = 0;
  145. //----------------------------------------------------------------------
  146. //This is only called from an open with a filename, not a file pointer.
  147. // ie. It assumes we are the parent.
  148. if (isOpen())
  149. length = fileSize();
  150. else
  151. length = 0;
  152. parent = NULL;
  153. parentOffset = 0;
  154. physicalLength = length;
  155. childList = NULL;
  156. numChildren = 0;
  157. }
  158. //---------------------------------------------------------------------------
  159. File::~File (void)
  160. {
  161. close();
  162. }
  163. //---------------------------------------------------------------------------
  164. bool File::eof (void)
  165. {
  166. return (logicalPosition >= getLength());
  167. }
  168. //---------------------------------------------------------------------------
  169. long File::open (const char* fName, FileMode _mode, long numChild)
  170. {
  171. gosASSERT( !isOpen() );
  172. //-------------------------------------------------------------
  173. long fNameLength = strlen(fName);
  174. fileName = (char *)systemHeap->Malloc(fNameLength+1);
  175. gosASSERT(fileName != NULL);
  176. strncpy(fileName,fName,fNameLength+1);
  177. fileMode = _mode;
  178. _fmode = _O_BINARY;
  179. _strlwr(fileName);
  180. if (fileMode == CREATE)
  181. {
  182. handle = _creat(fileName,_S_IWRITE);
  183. if (handle == INVALID_HANDLE_VALUE)
  184. {
  185. lastError = errno;
  186. return lastError;
  187. }
  188. }
  189. else
  190. {
  191. //----------------------------------------------------------------
  192. //-- First, see if file is in normal place. Useful for patches!!
  193. handle = _open(fileName,_O_RDONLY);
  194. //------------------------------------------
  195. //-- Next, see if file is in fastFile.
  196. if (handle == INVALID_HANDLE_VALUE)
  197. {
  198. lastError = errno;
  199. fastFile = FastFileFind(fileName,fastFileHandle);
  200. if (!fastFile)
  201. {
  202. //Not in main installed directory and not in fastfile. Look on CD.
  203. char actualPath[2048];
  204. strcpy(actualPath,CDInstallPath);
  205. strcat(actualPath,fileName);
  206. handle = _open(actualPath,_O_RDONLY);
  207. if (handle == INVALID_HANDLE_VALUE)
  208. {
  209. bool openFailed = false;
  210. bool alreadyFullScreen = (Environment.fullScreen != 0);
  211. while (handle == INVALID_HANDLE_VALUE)
  212. {
  213. openFailed = true;
  214. //OK, check to see if the CD is actually present.
  215. // Do this by checking for tgl.fst on the CD Path.
  216. // If its there, the CD is present BUT the file is missing.
  217. // MANY files in MechCommander 2 are LEGALLY missing!
  218. // Tell it to the art staff.
  219. char testCDPath[2048];
  220. strcpy(testCDPath,CDInstallPath);
  221. strcat(testCDPath,"tgl.fst");
  222. DWORD findCD = fileExists(testCDPath);
  223. if (findCD == 1) //File exists. CD is in drive. Return 2 to indicate file not found.
  224. return 2;
  225. EnterWindowMode();
  226. char data[2048];
  227. sprintf(data,FileMissingString,fileName,CDMissingString);
  228. DWORD result1 = MessageBox(NULL,data,MissingTitleString,MB_OKCANCEL | MB_ICONWARNING);
  229. if (result1 == IDCANCEL)
  230. {
  231. ExitGameOS();
  232. return (2); //File not found. Never returns though!
  233. }
  234. handle = _open(actualPath,_O_RDONLY);
  235. }
  236. if (openFailed && (Environment.fullScreen == 0) && alreadyFullScreen)
  237. EnterFullScreenMode();
  238. }
  239. else
  240. {
  241. if (logFileTraffic && (handle != INVALID_HANDLE_VALUE))
  242. {
  243. if (!fileTrafficLog)
  244. {
  245. createTrafficLog();
  246. }
  247. char msg[300];
  248. sprintf(msg,"CFHandle Length: %010d File: %s",fileSize(),fileName);
  249. fileTrafficLog->writeLine(msg);
  250. }
  251. setup();
  252. //------------------------------------------------------------
  253. // NEW FUNCTIONALITY!!!
  254. //
  255. // Each file may have a number of files open as children which
  256. // use the parent's handle for reads and writes. This would
  257. // allow us to open a packet file and read a packet as a fitIni
  258. // or allow us to write a packet as a fit ini and so forth.
  259. //
  260. // It also allows us to use the packet file extensions as tree
  261. // files to avoid the ten thousand file syndrome.
  262. //
  263. // There is now an open which takes a FilePtr and a size.
  264. maxChildren = numChild;
  265. childList = (FilePtr *)systemHeap->Malloc(sizeof(FilePtr) * maxChildren);
  266. if (!childList)
  267. {
  268. return(NO_RAM_FOR_CHILD_LIST);
  269. }
  270. numChildren = 0;
  271. for (long i=0;i<(long)maxChildren;i++)
  272. {
  273. childList[i] = NULL;
  274. }
  275. return (NO_ERR);
  276. }
  277. }
  278. if (logFileTraffic)
  279. {
  280. if (!fileTrafficLog)
  281. {
  282. createTrafficLog();
  283. }
  284. char msg[300];
  285. sprintf(msg,"FASTF Length: %010d File: %s",fileSize(),fileName);
  286. fileTrafficLog->writeLine(msg);
  287. }
  288. //---------------------------------------------------------------------
  289. //-- FastFiles are all compressed. Must read in entire chunk into RAM
  290. //-- Then close fastfile!!!!!
  291. inRAM = TRUE;
  292. fileImage = (unsigned char *)malloc(fileSize());
  293. if (fileImage)
  294. {
  295. fastFile->readFast(fastFileHandle,fileImage,fileSize());
  296. physicalLength = getLength();
  297. //------------------------------------
  298. //-- Image is in RAM. Shut the file.
  299. //fastFile->closeFast(fastFileHandle);
  300. //fastFile = NULL;
  301. //fastFileHandle = -1;
  302. logicalPosition = 0;
  303. }
  304. return NO_ERR;
  305. }
  306. else
  307. {
  308. if (logFileTraffic && (handle != INVALID_HANDLE_VALUE))
  309. {
  310. if (!fileTrafficLog)
  311. {
  312. createTrafficLog();
  313. }
  314. char msg[300];
  315. sprintf(msg,"CFHandle Length: %010d File: %s",fileSize(),fileName);
  316. fileTrafficLog->writeLine(msg);
  317. }
  318. setup();
  319. //------------------------------------------------------------
  320. // NEW FUNCTIONALITY!!!
  321. //
  322. // Each file may have a number of files open as children which
  323. // use the parent's handle for reads and writes. This would
  324. // allow us to open a packet file and read a packet as a fitIni
  325. // or allow us to write a packet as a fit ini and so forth.
  326. //
  327. // It also allows us to use the packet file extensions as tree
  328. // files to avoid the ten thousand file syndrome.
  329. //
  330. // There is now an open which takes a FilePtr and a size.
  331. maxChildren = numChild;
  332. childList = (FilePtr *)systemHeap->Malloc(sizeof(FilePtr) * maxChildren);
  333. if (!childList)
  334. {
  335. return(NO_RAM_FOR_CHILD_LIST);
  336. }
  337. numChildren = 0;
  338. for (long i=0;i<(long)maxChildren;i++)
  339. {
  340. childList[i] = NULL;
  341. }
  342. return (NO_ERR);
  343. }
  344. }
  345. return(NO_ERR);
  346. }
  347. //---------------------------------------------------------------------------
  348. long File::open (FilePtr _parent, unsigned long fileSize, long numChild)
  349. {
  350. if (_parent && (_parent->fastFile == NULL))
  351. {
  352. parent = _parent;
  353. if (parent->getFileMode() != READ)
  354. {
  355. return(CANT_WRITE_TO_CHILD);
  356. }
  357. physicalLength = fileSize;
  358. parentOffset = parent->getLogicalPosition();
  359. logicalPosition = 0;
  360. //-------------------------------------------------------------
  361. fileName = parent->getFilename();
  362. fileMode = parent->getFileMode();
  363. handle = parent->getFileHandle();
  364. if (logFileTraffic)
  365. {
  366. if (!fileTrafficLog)
  367. {
  368. createTrafficLog();
  369. }
  370. char msg[300];
  371. sprintf(msg,"CHILD Length: %010d File: %s",fileSize,_parent->getFilename());
  372. fileTrafficLog->writeLine(msg);
  373. }
  374. long result = parent->addChild(this);
  375. if (result != NO_ERR)
  376. return(result);
  377. //------------------------------------------------------------
  378. // NEW FUNCTIONALITY!!!
  379. //
  380. // Each file may have a number of files open as children which
  381. // use the parent's handle for reads and writes. This would
  382. // allow us to open a packet file and read a packet as a fitIni
  383. // or allow us to write a packet as a fit ini and so forth.
  384. //
  385. // It also allows us to use the packet file extensions as tree
  386. // files to avoid the ten thousand file syndrome.
  387. //
  388. // There is now an open which takes a FilePtr and a size.
  389. //
  390. // IF a numChild parameter is passed in as -1, we want this file in RAM!!
  391. // This means NO CHILDREN!!!!!!!!!!!!!
  392. if (numChild != -1)
  393. {
  394. maxChildren = numChild;
  395. childList = (FilePtr *)systemHeap->Malloc(sizeof(FilePtr) * maxChildren);
  396. gosASSERT(childList != NULL);
  397. numChildren = 0;
  398. for (long i=0;i<(long)maxChildren;i++)
  399. {
  400. childList[i] = NULL;
  401. }
  402. }
  403. else
  404. {
  405. maxChildren = 0;
  406. inRAM = TRUE;
  407. unsigned long result = 0;
  408. fileImage = (MemoryPtr)malloc(fileSize);
  409. if (!fileImage)
  410. inRAM = FALSE;
  411. if (_parent->getFileClass() == PACKETFILE)
  412. {
  413. result = ((PacketFilePtr)_parent)->readPacket(((PacketFilePtr)_parent)->getCurrentPacket(),fileImage);
  414. }
  415. else
  416. {
  417. result = _read(handle,fileImage,fileSize);
  418. if (result != fileSize)
  419. lastError = errno;
  420. }
  421. }
  422. }
  423. else
  424. {
  425. return(PARENT_NULL);
  426. }
  427. return(NO_ERR);
  428. }
  429. long File::open(const char* buffer, int bufferLength )
  430. {
  431. if ( buffer && bufferLength > 0 )
  432. {
  433. fileImage = (unsigned char*)buffer;
  434. physicalLength = bufferLength;
  435. logicalPosition = 0;
  436. fileMode = RDWRITE;
  437. inRAM = true;
  438. }
  439. else// fail on NULL
  440. {
  441. return FILE_NOT_OPEN;
  442. }
  443. return NO_ERR;
  444. }
  445. //---------------------------------------------------------------------------
  446. long File::create (const char* fName)
  447. {
  448. return (open(fName,CREATE));
  449. }
  450. long File::createWithCase( char* fName )
  451. {
  452. gosASSERT( !isOpen() );
  453. //-------------------------------------------------------------
  454. long fNameLength = strlen(fName);
  455. fileName = (char *)systemHeap->Malloc(fNameLength+1);
  456. gosASSERT(fileName != NULL);
  457. strncpy(fileName,fName,fNameLength+1);
  458. fileMode = CREATE;
  459. _fmode = _O_BINARY;
  460. handle = _creat(fileName,_S_IWRITE);
  461. if (handle == INVALID_HANDLE_VALUE)
  462. {
  463. lastError = errno;
  464. return lastError;
  465. }
  466. return 0;
  467. }
  468. //---------------------------------------------------------------------------
  469. long File::addChild (FilePtr child)
  470. {
  471. if (maxChildren)
  472. {
  473. for (long i=0;i < (long)maxChildren;i++)
  474. {
  475. if (childList[i] == NULL)
  476. {
  477. childList[i] = child;
  478. return NO_ERR;
  479. }
  480. }
  481. }
  482. return(TOO_MANY_CHILDREN);
  483. }
  484. //---------------------------------------------------------------------------
  485. void File::removeChild (FilePtr child)
  486. {
  487. if (maxChildren)
  488. {
  489. if (childList)
  490. {
  491. for (long i=0;i < (long)maxChildren;i++)
  492. {
  493. if (childList[i] == child)
  494. {
  495. childList[i] = NULL;
  496. break;
  497. }
  498. }
  499. }
  500. }
  501. }
  502. //---------------------------------------------------------------------------
  503. void File::close (void)
  504. {
  505. //------------------------------------------------------------------------
  506. // First, close us if we are the parent. Otherwise, just NULL the handle
  507. // DO NOT CALL CLOSE IF WE ARE A CHILD!!
  508. //
  509. // The actual stored filename is also in the parent. Everyone else just has
  510. // pointer and, as such, only the parent frees the memory.
  511. bool bFast = false;
  512. if ((parent == NULL) && (fileName != NULL))
  513. {
  514. systemHeap->Free(fileName);
  515. }
  516. fileName = NULL;
  517. length = 0;
  518. if (isOpen())
  519. {
  520. if ((parent == NULL) && (handle != NULL) && (-1 != handle))
  521. _close(handle);
  522. handle = NULL;
  523. if (fastFile)
  524. {
  525. fastFile->closeFast(fastFileHandle);
  526. bFast = true; // save that it was a fast file
  527. }
  528. fastFile = NULL; //DO NOT DELETE THE FASTFILE!!!!!!!!!!!!!
  529. fastFileHandle = -1;
  530. }
  531. //---------------------------------------------------------------------
  532. // Check if we have any children and close them. This will set their
  533. // handle to NULL and their filename to NULL. It will also close any
  534. // of THEIR children.
  535. if (maxChildren)
  536. {
  537. if (childList)
  538. {
  539. for (long i=0;i<(long)maxChildren;i++)
  540. {
  541. if (childList[i])
  542. childList[i]->close();
  543. }
  544. }
  545. if (childList)
  546. systemHeap->Free(childList);
  547. }
  548. if (parent != NULL)
  549. parent->removeChild(this);
  550. childList = NULL;
  551. numChildren = 0;
  552. if (inRAM && (bFast || parent)) // don't want to delete memFiles
  553. {
  554. if (fileImage)
  555. free(fileImage);
  556. fileImage = NULL;
  557. inRAM = FALSE;
  558. }
  559. }
  560. //---------------------------------------------------------------------------
  561. void File::deleteFile (void)
  562. {
  563. //--------------------------------------------------------------
  564. // Must be the ultimate parent to delete this file. Close will
  565. // make sure all of the children close themselves.
  566. if (isOpen() && (parent == NULL))
  567. close();
  568. }
  569. long newPosition = 0;
  570. //---------------------------------------------------------------------------
  571. long File::seek (long pos, long from)
  572. {
  573. switch (from)
  574. {
  575. case SEEK_SET:
  576. if (pos > (long)getLength())
  577. {
  578. return READ_PAST_EOF_ERR;
  579. }
  580. break;
  581. case SEEK_END:
  582. if ((abs(pos) > (long)getLength()) || (pos > 0))
  583. {
  584. return READ_PAST_EOF_ERR;
  585. }
  586. break;
  587. case SEEK_CUR:
  588. if (pos+logicalPosition > getLength())
  589. {
  590. return READ_PAST_EOF_ERR;
  591. }
  592. break;
  593. }
  594. if (inRAM && fileImage)
  595. {
  596. if (parent)
  597. {
  598. switch (from)
  599. {
  600. case SEEK_SET:
  601. newPosition = pos;
  602. break;
  603. case SEEK_END:
  604. newPosition = getLength()+parentOffset;
  605. newPosition += pos;
  606. break;
  607. case SEEK_CUR:
  608. newPosition += pos;
  609. break;
  610. }
  611. }
  612. else
  613. {
  614. switch (from)
  615. {
  616. case SEEK_SET:
  617. newPosition = pos;
  618. break;
  619. case SEEK_END:
  620. newPosition = getLength() + pos;
  621. break;
  622. case SEEK_CUR:
  623. newPosition += pos;
  624. break;
  625. }
  626. }
  627. if (newPosition == -1)
  628. {
  629. return (INVALID_SEEK_ERR);
  630. }
  631. logicalPosition = newPosition;
  632. }
  633. else if (fastFile)
  634. {
  635. newPosition = fastFile->seekFast(fastFileHandle,pos,from);
  636. logicalPosition = newPosition;
  637. }
  638. else
  639. {
  640. if (parent)
  641. {
  642. switch (from)
  643. {
  644. case SEEK_SET:
  645. _lseek(handle,pos+parentOffset,SEEK_SET);
  646. newPosition = pos;
  647. break;
  648. case SEEK_END:
  649. _lseek(handle,getLength()+parentOffset,SEEK_SET);
  650. _lseek(handle,pos,SEEK_CUR);
  651. newPosition = getLength() + pos;
  652. break;
  653. case SEEK_CUR:
  654. _lseek(handle,pos,SEEK_CUR);
  655. newPosition = logicalPosition + pos;
  656. break;
  657. }
  658. }
  659. else
  660. {
  661. newPosition = _lseek(handle,pos,from);
  662. }
  663. if (newPosition == -1)
  664. {
  665. return (INVALID_SEEK_ERR);
  666. }
  667. logicalPosition = newPosition;
  668. }
  669. return (NO_ERR);
  670. }
  671. //---------------------------------------------------------------------------
  672. long File::read (unsigned long pos, MemoryPtr buffer, long length)
  673. {
  674. long result = 0;
  675. if (inRAM && fileImage)
  676. {
  677. char *readAddress = ((char *)fileImage)+pos;
  678. memcpy((char *)buffer,readAddress,length);
  679. return(length);
  680. }
  681. else if (fastFile)
  682. {
  683. if (logicalPosition != pos)
  684. fastFile->seekFast(fastFileHandle,pos);
  685. result = fastFile->readFast(fastFileHandle,buffer,length);
  686. }
  687. else
  688. {
  689. if (isOpen())
  690. {
  691. if (logicalPosition != pos)
  692. seek(pos);
  693. result = _read(handle,buffer,length);
  694. if (result != length)
  695. lastError = errno;
  696. }
  697. else
  698. {
  699. lastError = FILE_NOT_OPEN;
  700. }
  701. }
  702. return(result);
  703. }
  704. //---------------------------------------------------------------------------
  705. unsigned char File::readByte (void)
  706. {
  707. unsigned char value = 0;
  708. long result = 0;
  709. if (inRAM && fileImage)
  710. {
  711. char *readAddress = (char*)fileImage+logicalPosition;
  712. memcpy((char *)&value,readAddress,sizeof(value));
  713. logicalPosition += sizeof(value);
  714. }
  715. else if (fastFile)
  716. {
  717. result = fastFile->readFast(fastFileHandle,(char *)&value,sizeof(value));
  718. logicalPosition += sizeof(value);
  719. }
  720. else
  721. {
  722. if (isOpen())
  723. {
  724. result = _read(handle,(&value),sizeof(value));
  725. logicalPosition += sizeof(value);
  726. if (result != sizeof(value))
  727. lastError = errno;
  728. }
  729. else
  730. {
  731. lastError = FILE_NOT_OPEN;
  732. }
  733. }
  734. return value;
  735. }
  736. //---------------------------------------------------------------------------
  737. short File::readWord (void)
  738. {
  739. short value = 0;
  740. long result =0;
  741. if (inRAM && fileImage)
  742. {
  743. char *readAddress = (char*)fileImage+logicalPosition;
  744. memcpy((char *)(&value),readAddress,sizeof(value));
  745. logicalPosition += sizeof(value);
  746. }
  747. else if (fastFile)
  748. {
  749. result = fastFile->readFast(fastFileHandle,(char *)&value,sizeof(value));
  750. logicalPosition += sizeof(value);
  751. }
  752. else
  753. {
  754. if (isOpen())
  755. {
  756. result = _read(handle,(&value),sizeof(value));
  757. logicalPosition += sizeof(value);
  758. if (result != sizeof(value))
  759. lastError = errno;
  760. }
  761. else
  762. {
  763. lastError = FILE_NOT_OPEN;
  764. }
  765. }
  766. return value;
  767. }
  768. //---------------------------------------------------------------------------
  769. short File::readShort (void)
  770. {
  771. return (readWord());
  772. }
  773. //---------------------------------------------------------------------------
  774. long File::readLong (void)
  775. {
  776. long value = 0;
  777. unsigned long result = 0;
  778. if (inRAM && fileImage)
  779. {
  780. char *readAddress = (char*)fileImage+logicalPosition;
  781. memcpy((char *)(&value),readAddress,sizeof(value));
  782. logicalPosition += sizeof(value);
  783. }
  784. else if (fastFile)
  785. {
  786. result = fastFile->readFast(fastFileHandle,(char *)&value,sizeof(value));
  787. logicalPosition += sizeof(value);
  788. }
  789. else
  790. {
  791. if (isOpen())
  792. {
  793. result = _read(handle,(&value),sizeof(value));
  794. logicalPosition += sizeof(value);
  795. if (result != sizeof(value))
  796. lastError = errno;
  797. }
  798. else
  799. {
  800. lastError = FILE_NOT_OPEN;
  801. }
  802. }
  803. return value;
  804. }
  805. bool isNAN(float *pFloat)
  806. {
  807. /* We're assuming ansi/ieee 754 floating point representation. See http://www.research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html. */
  808. BYTE *byteArray = (BYTE *)pFloat;
  809. if ((0x7f == (0x7f & byteArray[3])) && (0x80 == (0x80 & byteArray[2]))) {
  810. if (0x80 == (0x80 & byteArray[3])) {
  811. /* if the mantissa is a 1 followed by all zeros in this case then it is technically
  812. "Indeterminate" rather than an NaN, but we'll just count it as a NaN here. */
  813. return true;
  814. } else {
  815. return true;
  816. }
  817. }
  818. return false;
  819. }
  820. float File::readFloat( void )
  821. {
  822. float value = 0;
  823. unsigned long result = 0;
  824. if (inRAM && fileImage)
  825. {
  826. char *readAddress = (char*)fileImage+logicalPosition;
  827. memcpy((char *)(&value),readAddress,sizeof(value));
  828. logicalPosition += sizeof(value);
  829. }
  830. else if (fastFile)
  831. {
  832. result = fastFile->readFast(fastFileHandle,(char *)&value,sizeof(value));
  833. logicalPosition += sizeof(value);
  834. }
  835. else
  836. {
  837. if (isOpen())
  838. {
  839. result = _read(handle,(&value),sizeof(value));
  840. logicalPosition += sizeof(value);
  841. if (result != sizeof(value))
  842. lastError = errno;
  843. }
  844. else
  845. {
  846. lastError = FILE_NOT_OPEN;
  847. }
  848. }
  849. if (isNAN(&value)) {
  850. gosASSERT(false);
  851. value = 1.0/*arbitrary value that seems safe*/;
  852. }
  853. return value;
  854. }
  855. //---------------------------------------------------------------------------
  856. long File::readString (MemoryPtr buffer)
  857. {
  858. long last = 0;
  859. if (isOpen())
  860. {
  861. for(;;)
  862. {
  863. byte ch = readByte();
  864. buffer[last] = ch;
  865. if (ch)
  866. ++last;
  867. else
  868. break;
  869. }
  870. }
  871. else
  872. {
  873. lastError = FILE_NOT_OPEN;
  874. }
  875. return last;
  876. }
  877. //---------------------------------------------------------------------------
  878. long File::read (MemoryPtr buffer, long length)
  879. {
  880. long result = 0;
  881. if (inRAM && fileImage)
  882. {
  883. char *readAddress = (char *)fileImage+logicalPosition;
  884. memcpy((char *)buffer,readAddress,length);
  885. logicalPosition += length;
  886. return(length);
  887. }
  888. else if (fastFile)
  889. {
  890. result = fastFile->readFast(fastFileHandle,buffer,length);
  891. logicalPosition += result;
  892. }
  893. else
  894. {
  895. if (isOpen())
  896. {
  897. result = _read(handle,buffer,length);
  898. if (result != length)
  899. lastError = errno;
  900. else
  901. logicalPosition += result;
  902. }
  903. else
  904. {
  905. lastError = FILE_NOT_OPEN;
  906. }
  907. }
  908. return result;
  909. }
  910. //---------------------------------------------------------------------------
  911. long File::readRAW (unsigned long * &buffer, UserHeapPtr heap)
  912. {
  913. long result = 0;
  914. if (fastFile && heap && fastFile->isLZCompressed())
  915. {
  916. long lzSizeNeeded = fastFile->lzSizeFast(fastFileHandle);
  917. buffer = (unsigned long *)heap->Malloc(lzSizeNeeded);
  918. result = fastFile->readFastRAW(fastFileHandle,buffer,lzSizeNeeded);
  919. logicalPosition += result;
  920. }
  921. return result;
  922. }
  923. //---------------------------------------------------------------------------
  924. long File::readLine (MemoryPtr buffer, long maxLength)
  925. {
  926. long i = 0;
  927. if (inRAM && fileImage)
  928. {
  929. if (isOpen())
  930. {
  931. unsigned char *readAddress = (unsigned char *)fileImage+logicalPosition;
  932. while ((i<maxLength) && ((i+logicalPosition) < fileSize()) && readAddress[i]!='\r' )
  933. i++;
  934. memcpy( buffer, readAddress, i );
  935. buffer[i++]=0;
  936. logicalPosition+=i;
  937. if ( logicalPosition > fileSize() )
  938. return READ_PAST_EOF_ERR;
  939. if( readAddress[i]=='\n' )
  940. logicalPosition+=1;
  941. }
  942. else
  943. {
  944. lastError = FILE_NOT_OPEN;
  945. }
  946. }
  947. else if (fastFile)
  948. {
  949. long bytesread;
  950. bytesread = fastFile->readFast(fastFileHandle,buffer,maxLength);
  951. if (maxLength > bytesread)
  952. maxLength = bytesread;
  953. while ((i<maxLength) && (buffer[i]!='\r'))
  954. i++;
  955. buffer[i++]=0;
  956. logicalPosition += i;
  957. if( buffer[i]=='\n' )
  958. logicalPosition+=1;
  959. fastFile->seekFast(fastFileHandle,logicalPosition);
  960. }
  961. else
  962. {
  963. if (isOpen())
  964. {
  965. long bytesread;
  966. bytesread = _read(handle,buffer,maxLength);
  967. if( maxLength > bytesread )
  968. maxLength=bytesread;
  969. while( i<maxLength && buffer[i]!='\r' )
  970. i++;
  971. buffer[i++]=0;
  972. logicalPosition+=i;
  973. if( buffer[i]=='\n' )
  974. logicalPosition+=1;
  975. seek(logicalPosition);
  976. }
  977. else
  978. {
  979. lastError = FILE_NOT_OPEN;
  980. }
  981. }
  982. return i;
  983. }
  984. //---------------------------------------------------------------------------
  985. long File::readLineEx (MemoryPtr buffer, long maxLength)
  986. {
  987. long i = 0;
  988. if (inRAM && fileImage)
  989. {
  990. if (isOpen())
  991. {
  992. unsigned char *readAddress = (unsigned char *)fileImage+logicalPosition;
  993. while( i<maxLength && readAddress[i]!='\n' )
  994. i++;
  995. i++; //Include Newline
  996. memcpy( buffer, readAddress, i );
  997. buffer[i++]=0;
  998. logicalPosition+=(i-1);
  999. }
  1000. else
  1001. {
  1002. lastError = FILE_NOT_OPEN;
  1003. }
  1004. }
  1005. else if (fastFile)
  1006. {
  1007. long bytesread;
  1008. bytesread = fastFile->readFast(fastFileHandle,buffer,maxLength);
  1009. if (maxLength > bytesread)
  1010. maxLength = bytesread;
  1011. while ((i<maxLength) && (buffer[i]!='\n'))
  1012. i++;
  1013. i++; //Include Newline
  1014. buffer[i++]=0;
  1015. logicalPosition += (i-1);
  1016. fastFile->seekFast(fastFileHandle,logicalPosition);
  1017. }
  1018. else
  1019. {
  1020. if (isOpen())
  1021. {
  1022. long bytesread = _read(handle,buffer,maxLength);
  1023. if( maxLength > bytesread )
  1024. maxLength=bytesread;
  1025. while( i<maxLength && buffer[i]!='\n' )
  1026. i++;
  1027. i++;
  1028. buffer[i++]=0;
  1029. logicalPosition+= (i-1);
  1030. seek(logicalPosition);
  1031. }
  1032. else
  1033. {
  1034. lastError = FILE_NOT_OPEN;
  1035. }
  1036. }
  1037. return i;
  1038. }
  1039. //---------------------------------------------------------------------------
  1040. long File::write (unsigned long pos, MemoryPtr buffer, long bytes)
  1041. {
  1042. unsigned long result = 0;
  1043. if (parent == NULL)
  1044. {
  1045. if (isOpen())
  1046. {
  1047. if (logicalPosition != pos)
  1048. seek(pos);
  1049. if ( inRAM )
  1050. {
  1051. if ( logicalPosition + bytes > physicalLength )
  1052. return BAD_WRITE_ERR;
  1053. memcpy( fileImage + logicalPosition, buffer, bytes );
  1054. result = bytes;
  1055. }
  1056. else
  1057. {
  1058. result = _write(handle,buffer,bytes);
  1059. if (result != length)
  1060. lastError = errno;
  1061. }
  1062. }
  1063. else
  1064. {
  1065. lastError = FILE_NOT_OPEN;
  1066. }
  1067. }
  1068. else
  1069. {
  1070. lastError = CANT_WRITE_TO_CHILD;
  1071. }
  1072. return(result);
  1073. }
  1074. //---------------------------------------------------------------------------
  1075. long File::writeByte (byte value)
  1076. {
  1077. long result = 0;
  1078. if (parent == NULL)
  1079. {
  1080. if (isOpen())
  1081. {
  1082. if ( inRAM )
  1083. {
  1084. if ( logicalPosition + sizeof(byte) > physicalLength )
  1085. return BAD_WRITE_ERR;
  1086. memcpy( fileImage + logicalPosition, &value, sizeof( byte ) );
  1087. result = sizeof( byte );
  1088. }
  1089. else
  1090. result = _write(handle,(&value),sizeof(value));
  1091. if (result == sizeof(value))
  1092. {
  1093. logicalPosition += sizeof(value);
  1094. result = NO_ERR;
  1095. }
  1096. else
  1097. {
  1098. result = BAD_WRITE_ERR;
  1099. }
  1100. }
  1101. else
  1102. {
  1103. lastError = FILE_NOT_OPEN;
  1104. }
  1105. }
  1106. else
  1107. {
  1108. lastError = CANT_WRITE_TO_CHILD;
  1109. }
  1110. return(result);
  1111. }
  1112. //---------------------------------------------------------------------------
  1113. long File::writeWord (short value)
  1114. {
  1115. unsigned long result = 0;
  1116. if (parent == NULL)
  1117. {
  1118. if (isOpen())
  1119. {
  1120. if ( inRAM )
  1121. {
  1122. if ( logicalPosition + sizeof( short ) > physicalLength )
  1123. return BAD_WRITE_ERR;
  1124. memcpy( fileImage + logicalPosition, &value, sizeof( short ) );
  1125. result = sizeof( value );
  1126. }
  1127. else
  1128. result = _write(handle,(&value),sizeof(value));
  1129. if (result == sizeof(value))
  1130. {
  1131. logicalPosition += sizeof(value);
  1132. result = NO_ERR;
  1133. }
  1134. else
  1135. {
  1136. result = BAD_WRITE_ERR;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. lastError = FILE_NOT_OPEN;
  1142. }
  1143. }
  1144. else
  1145. {
  1146. lastError = CANT_WRITE_TO_CHILD;
  1147. }
  1148. return(result);
  1149. }
  1150. //---------------------------------------------------------------------------
  1151. long File::writeShort (short value)
  1152. {
  1153. long result = writeWord(value);
  1154. return(result);
  1155. }
  1156. //---------------------------------------------------------------------------
  1157. long File::writeLong (long value)
  1158. {
  1159. unsigned long result = 0;
  1160. if (parent == NULL)
  1161. {
  1162. if (isOpen())
  1163. {
  1164. if ( inRAM )
  1165. {
  1166. if ( logicalPosition + sizeof( value ) > physicalLength )
  1167. return BAD_WRITE_ERR;
  1168. memcpy( fileImage + logicalPosition, &value, sizeof( value ) );
  1169. result = sizeof( value );
  1170. }
  1171. else
  1172. result = _write(handle,(&value),sizeof(value));
  1173. if (result == sizeof(value))
  1174. {
  1175. logicalPosition += sizeof(value);
  1176. result = NO_ERR;
  1177. }
  1178. else
  1179. {
  1180. result = BAD_WRITE_ERR;
  1181. }
  1182. }
  1183. else
  1184. {
  1185. lastError = FILE_NOT_OPEN;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. lastError = CANT_WRITE_TO_CHILD;
  1191. }
  1192. return(result);
  1193. }
  1194. //---------------------------------------------------------------------------
  1195. long File::writeFloat (float value)
  1196. {
  1197. unsigned long result = 0;
  1198. gosASSERT(!isNAN(&value));
  1199. if (parent == NULL)
  1200. {
  1201. if (isOpen())
  1202. {
  1203. if ( inRAM )
  1204. {
  1205. if ( logicalPosition + sizeof( value ) > physicalLength )
  1206. return BAD_WRITE_ERR;
  1207. memcpy( fileImage + logicalPosition, &value, sizeof( value ) );
  1208. result = sizeof( value );
  1209. }
  1210. else
  1211. result = _write(handle,(&value),sizeof(float));
  1212. if (result == sizeof(float))
  1213. {
  1214. logicalPosition += sizeof(float);
  1215. result = NO_ERR;
  1216. }
  1217. else
  1218. {
  1219. result = BAD_WRITE_ERR;
  1220. }
  1221. }
  1222. else
  1223. {
  1224. lastError = FILE_NOT_OPEN;
  1225. }
  1226. }
  1227. else
  1228. {
  1229. lastError = CANT_WRITE_TO_CHILD;
  1230. }
  1231. return(result);
  1232. }
  1233. //---------------------------------------------------------------------------
  1234. long File::writeString (char *buffer)
  1235. {
  1236. long result = -1;
  1237. if (parent == NULL)
  1238. {
  1239. if (isOpen())
  1240. {
  1241. char *ch = buffer;
  1242. for(; *ch; ++ch)
  1243. writeByte((byte)* ch);
  1244. return ch - buffer;
  1245. }
  1246. else
  1247. {
  1248. lastError = FILE_NOT_OPEN;
  1249. }
  1250. }
  1251. else
  1252. {
  1253. lastError = CANT_WRITE_TO_CHILD;
  1254. }
  1255. return(result);
  1256. }
  1257. //---------------------------------------------------------------------------
  1258. long File::writeLine (char *buffer)
  1259. {
  1260. long result = -1;
  1261. if (parent == NULL)
  1262. {
  1263. if (isOpen())
  1264. {
  1265. char *ch = buffer;
  1266. for(; *ch; ++ch)
  1267. writeByte((byte)* ch);
  1268. writeByte('\r');
  1269. writeByte('\n');
  1270. return ch - buffer;
  1271. }
  1272. else
  1273. {
  1274. lastError = FILE_NOT_OPEN;
  1275. }
  1276. }
  1277. else
  1278. {
  1279. lastError = CANT_WRITE_TO_CHILD;
  1280. }
  1281. return(result);
  1282. }
  1283. //---------------------------------------------------------------------------
  1284. long File::write (MemoryPtr buffer, long bytes)
  1285. {
  1286. long result = 0;
  1287. if (parent == NULL)
  1288. {
  1289. if (isOpen())
  1290. {
  1291. if ( inRAM )
  1292. {
  1293. if ( logicalPosition + bytes > physicalLength )
  1294. return BAD_WRITE_ERR;
  1295. memcpy( fileImage + logicalPosition, buffer, bytes );
  1296. result = bytes;
  1297. }
  1298. else
  1299. {
  1300. result = _write(handle,buffer,bytes);
  1301. if (result != bytes)
  1302. {
  1303. lastError = errno;
  1304. return result;
  1305. }
  1306. }
  1307. logicalPosition += result;
  1308. }
  1309. else
  1310. {
  1311. lastError = FILE_NOT_OPEN;
  1312. }
  1313. }
  1314. else
  1315. {
  1316. lastError = CANT_WRITE_TO_CHILD;
  1317. }
  1318. return result;
  1319. }
  1320. //---------------------------------------------------------------------------
  1321. bool File::isOpen (void)
  1322. {
  1323. return ((handle != NULL && handle != -1) || (fileImage != NULL));
  1324. }
  1325. //---------------------------------------------------------------------------
  1326. char* File::getFilename (void)
  1327. {
  1328. return (fileName);
  1329. }
  1330. //---------------------------------------------------------------------------
  1331. time_t File::getFileMTime (void)
  1332. {
  1333. time_t mTime;
  1334. if (isOpen())
  1335. {
  1336. struct _stat st;
  1337. _fstat(handle,&st);
  1338. mTime = st.st_mtime;
  1339. //Time\Date Stamp is WAY out of line.
  1340. // Return January 1, 1970
  1341. if (mTime == -1)
  1342. mTime = 0;
  1343. }
  1344. return mTime;
  1345. }
  1346. //---------------------------------------------------------------------------
  1347. unsigned long File::getLength (void)
  1348. {
  1349. if (fastFile && (length == 0))
  1350. {
  1351. length = fastFile->sizeFast(fastFileHandle);
  1352. }
  1353. else if ((length == 0) && (parent || inRAM))
  1354. {
  1355. length = physicalLength;
  1356. }
  1357. else if (isOpen() && ((length == 0) || (fileMode > READ) && !inRAM))
  1358. {
  1359. /* _fstat() was being used to get the length of the file, but it was wrong. It was
  1360. not giving the *logical* size, which is what we want. */
  1361. length = _filelength(handle);
  1362. }
  1363. return length;
  1364. }
  1365. //---------------------------------------------------------------------------
  1366. unsigned long File::fileSize (void)
  1367. {
  1368. return getLength();
  1369. }
  1370. //---------------------------------------------------------------------------
  1371. unsigned long File::getNumLines (void)
  1372. {
  1373. unsigned long currentPos = logicalPosition;
  1374. unsigned long numLines = 0;
  1375. seek(0);
  1376. for (unsigned long i=0;i<getLength();i++)
  1377. {
  1378. unsigned char check1 = readByte();
  1379. if (check1 == '\n')
  1380. numLines++;
  1381. }
  1382. seek(currentPos);
  1383. return numLines;
  1384. }
  1385. //---------------------------------------------------------------------------
  1386. void File::seekEnd (void)
  1387. {
  1388. seek(0,SEEK_END);
  1389. }
  1390. //---------------------------------------------------------------------------
  1391. void File::skip (long bytesToSkip)
  1392. {
  1393. if (bytesToSkip)
  1394. {
  1395. seek(logicalPosition+bytesToSkip);
  1396. }
  1397. }
  1398. //---------------------------------------------------------------------------