Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

vfile.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  VFILE.C                                                                             */
00003 /*                                                                                      */
00004 /*  Author: Eli Boling                                                                  */
00005 /*  Description: Virtual file implementation                                            */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #define WIN32_LEAN_AND_MEAN
00023 #include        <windows.h>
00024 
00025 #include        <stdio.h>
00026 #include        <assert.h>
00027 #include        <stdarg.h>
00028 #include        <string.h>
00029 
00030 #include        "basetype.h"
00031 #include        "ram.h"
00032 
00033 #include        "vfile.h"
00034 #include        "vfile._h"
00035 
00036 #include        "fsdos.h"
00037 #include        "fsmemory.h"
00038 #include        "fsvfs.h"
00039 //
00040 // add include files for file types here
00041 
00042 typedef struct  FSSearchList
00043 {
00044         geVFile *                               FS;
00045         struct FSSearchList *   Next;
00046 }       FSSearchList;
00047 
00048 
00049 typedef struct  geVFile
00050 {
00051         geVFile_TypeIdentifier          SystemType;
00052         const geVFile_SystemAPIs *      APIs;
00053         void *                                          FSData;
00054         geVFile *                                       Context;
00055         FSSearchList *                          SearchList;
00056         CRITICAL_SECTION                        CriticalSection;
00057         geVFile *                                       BaseFile;
00058 }       geVFile;
00059 
00060 typedef struct  geVFile_Finder
00061 {
00062         const geVFile_SystemAPIs *      APIs;
00063         void *                                          Data;
00064 }       geVFile_Finder;
00065 
00066 static  geVFile_SystemAPIs **           RegisteredAPIs;
00067 static  int                                                     SystemCount;
00068 static  geBoolean                                       BuiltInAPIsRegistered = GE_FALSE;
00069 
00070 #ifndef NDEBUG
00071 static  geBoolean                                       SystemInitialized = GE_FALSE;
00072 #endif
00073 
00074 static  CRITICAL_SECTION                        MainCriticalSection;
00075 
00076 static  geBoolean GENESISCC geVFile_RegisterFileSystemInternal(const geVFile_SystemAPIs *APIs, geVFile_TypeIdentifier *Type)
00077 {
00078         geVFile_SystemAPIs **   NewList;
00079 
00080         NewList = geRam_Realloc(RegisteredAPIs, sizeof(*RegisteredAPIs) * (SystemCount + 1));
00081         if      (!NewList)
00082                 return GE_FALSE;
00083 
00084         RegisteredAPIs = NewList;
00085 #pragma message ("Casting away const in geVFile_RegisterFileSystem")
00086         RegisteredAPIs[SystemCount++] = (geVFile_SystemAPIs *)APIs;
00087         *Type = SystemCount;
00088 
00089         return GE_TRUE;
00090 }
00091 
00092 void GENESISCC geVFile_CloseAPI (void)
00093 {
00094         geRam_Free(RegisteredAPIs);
00095 }
00096 
00097 static  geBoolean       RegisterBuiltInAPIs(void)
00098 {
00099         geVFile_TypeIdentifier  Type;
00100 
00101         if      (BuiltInAPIsRegistered == GE_TRUE)
00102                 return GE_TRUE;
00103 
00104         if      (geVFile_RegisterFileSystemInternal(FSDos_GetAPIs(), &Type) == GE_FALSE)
00105                 return GE_FALSE;
00106         if      (Type != GE_VFILE_TYPE_DOS)
00107                 return GE_FALSE;
00108 
00109         if      (geVFile_RegisterFileSystemInternal(FSMemory_GetAPIs(), &Type) == GE_FALSE)
00110                 return GE_FALSE;
00111         if      (Type != GE_VFILE_TYPE_MEMORY)
00112                 return GE_FALSE;
00113 
00114         if      (geVFile_RegisterFileSystemInternal(FSVFS_GetAPIs(), &Type) == GE_FALSE)
00115                 return GE_FALSE;
00116         if      (Type != GE_VFILE_TYPE_VIRTUAL)
00117                 return GE_FALSE;
00118 
00119 //  Register New APIs here
00120 /*      if      (geVFile_RegisterFileSystemInternal(FSVCFS_GetAPIs(), &Type) == GE_FALSE)
00121                 return GE_FALSE;
00122         if      (Type != GE_VFILE_TYPE_CVIRTUAL)
00123                 return GE_FALSE;
00124 */
00125         BuiltInAPIsRegistered = GE_TRUE;
00126 
00127         return GE_TRUE;
00128 }
00129 
00130 GENESISAPI geBoolean GENESISCC geVFile_RegisterFileSystem(const geVFile_SystemAPIs *APIs, geVFile_TypeIdentifier *Type)
00131 {
00132         geBoolean       Result;
00133 
00134         assert(APIs);
00135         assert(Type);
00136 
00137         if      (RegisterBuiltInAPIs() == GE_FALSE)
00138                 return GE_FALSE;
00139 
00140         Result = geVFile_RegisterFileSystemInternal(APIs, Type);
00141 
00142         return Result;
00143 }
00144 
00145 static  geBoolean       GENESISCC       CheckOpenFlags(unsigned int OpenModeFlags)
00146 {
00147         int                     FlagCount;
00148         unsigned int    AccessFlags;
00149 
00150         // Test to see that the open mode for this thing is mutually exclusive in
00151         // the proper flags.
00152         FlagCount = 0;
00153         AccessFlags = OpenModeFlags & (GE_VFILE_OPEN_READONLY | GE_VFILE_OPEN_UPDATE | GE_VFILE_OPEN_CREATE);
00154         if      (AccessFlags & GE_VFILE_OPEN_READONLY)
00155                 FlagCount++;
00156         if      (AccessFlags & GE_VFILE_OPEN_UPDATE)
00157                 FlagCount++;
00158         if      (AccessFlags & GE_VFILE_OPEN_CREATE)
00159                 FlagCount++;
00160 
00161         if      (FlagCount != 1 && !(OpenModeFlags & GE_VFILE_OPEN_DIRECTORY))
00162                 return GE_FALSE;
00163 
00164         return GE_TRUE;
00165 }
00166 
00167 GENESISAPI geVFile * GENESISCC geVFile_OpenNewSystem(
00168         geVFile *                               FS,
00169         geVFile_TypeIdentifier  FileSystemType,
00170         const char *                    Name,
00171         void *                                  Context,
00172         unsigned int                    OpenModeFlags)
00173 {
00174         const geVFile_SystemAPIs *      APIs;
00175         geVFile *                                       File;
00176         void *                                          FSData;
00177         geVFile *                                       BaseFile;
00178 
00179 
00180         if      (RegisterBuiltInAPIs() == GE_FALSE)
00181                 return GE_FALSE;
00182 
00183         if      ((FileSystemType == 0) || (FileSystemType > SystemCount))
00184                 return NULL;
00185 
00186         if      (CheckOpenFlags(OpenModeFlags) == GE_FALSE)
00187                 return NULL;
00188 
00189         // Sugarcoating support for a taste test
00190         if      (FS == NULL && (FileSystemType == GE_VFILE_TYPE_VIRTUAL
00191 //
00192 // add tests for file types here
00193 
00194 //              || FileSystemType == GE_VFILE_TYPE_CVIRTUAL
00195 
00196                 ))
00197         {
00198                 assert(Name);
00199                 BaseFile = geVFile_OpenNewSystem(NULL,
00200                                                                                  GE_VFILE_TYPE_DOS,
00201                                                                                  Name,
00202                                                                                  NULL,
00203                                                                                  OpenModeFlags & ~GE_VFILE_OPEN_DIRECTORY);
00204                 if      (!BaseFile)
00205                         return NULL;
00206                 FS = BaseFile;
00207                 Name = NULL;
00208         }
00209         else
00210                 BaseFile = NULL;
00211 
00212         APIs = RegisteredAPIs[FileSystemType - 1];
00213         assert(APIs);
00214         FSData = APIs->OpenNewSystem(FS, Name, Context, OpenModeFlags);
00215 
00216         if      (!FSData)
00217         {
00218                 if      (BaseFile)
00219                         geVFile_Close(BaseFile);
00220                 return NULL;
00221         }
00222 
00223         File = geRam_Allocate(sizeof(*File));
00224         if      (!File)
00225         {
00226                 if      (BaseFile)
00227                         geVFile_Close(BaseFile);
00228                 APIs->Close(FSData);
00229                 return NULL;
00230         }
00231 
00232         File->SystemType =      FileSystemType;
00233         File->APIs =            APIs;
00234         File->FSData =          FSData;
00235         File->SearchList =      geRam_Allocate(sizeof(*File->SearchList));
00236         File->BaseFile =        BaseFile;
00237 
00238         if      (!File->SearchList)
00239         {
00240                 if      (BaseFile)
00241                         geVFile_Close(BaseFile);
00242                 geRam_Free(File);
00243                 APIs->Close(FSData);
00244                 return NULL;
00245         }
00246 
00247         File->SearchList->FS    = File;
00248         File->SearchList->Next  = NULL;
00249 
00250         return File;
00251 }
00252 
00253 GENESISAPI geBoolean GENESISCC geVFile_UpdateContext(geVFile *FS, void *Context, int ContextSize)
00254 {
00255         assert(FS);
00256         assert(Context);
00257 
00258         return FS->APIs->UpdateContext(FS, FS->FSData, Context, ContextSize);
00259 }
00260 
00261 GENESISAPI geVFile * GENESISCC geVFile_Open(
00262         geVFile *               FS,
00263         const char *    Name,
00264         unsigned int    OpenModeFlags)
00265 {
00266         FSSearchList *  SearchList;
00267         geVFile *               StartContext;
00268         geVFile *               File;
00269         void *                  FSData;
00270 
00271         assert(Name);
00272 
00273         if      (!FS)
00274                 return NULL;
00275 
00276         if      (CheckOpenFlags(OpenModeFlags) == GE_FALSE)
00277                 return NULL;
00278 
00279         StartContext = FS;
00280 
00281         SearchList = FS->SearchList;
00282         assert(SearchList);
00283         assert(SearchList->FS == FS);
00284         if      (!(OpenModeFlags & GE_VFILE_OPEN_CREATE))
00285         {
00286                 while   (SearchList)
00287                 {
00288                         FS = SearchList->FS;
00289                         if      (FS->APIs->FileExists(FS, FS->FSData, Name))
00290                                 break;
00291                         SearchList = SearchList->Next;
00292                 }
00293         }
00294 
00295         if      (!SearchList)
00296                 return NULL;
00297 
00298         FSData = FS->APIs->Open(FS, FS->FSData, Name, NULL, OpenModeFlags);
00299         if      (!FSData)
00300                 return NULL;
00301 
00302         File = geRam_Allocate(sizeof(*File));
00303         if      (!File)
00304         {
00305                 FS->APIs->Close(FSData);
00306                 return NULL;
00307         }
00308 
00309         memset(File, 0, sizeof(*File));
00310 
00311         File->SystemType =      0;
00312         File->APIs =            FS->APIs;
00313         File->FSData =          FSData;
00314         File->SearchList =      geRam_Allocate(sizeof(*File->SearchList));
00315         File->Context =         FS;
00316 
00317         if      (!File->SearchList)
00318         {
00319                 geRam_Free(File);
00320                 FS->APIs->Close(FSData);
00321                 return NULL;
00322         }
00323 
00324         File->SearchList->FS    = File;
00325         File->SearchList->Next  = StartContext->SearchList;
00326 
00327         return File;
00328 }
00329 
00330 GENESISAPI geVFile * GENESISCC geVFile_GetContext(const geVFile *File)
00331 {
00332         assert(File);
00333 
00334         return File->Context;
00335 }
00336 
00337 static  void                    DestroySearchList(FSSearchList *SearchList)
00338 {
00339         while   (SearchList)
00340         {
00341                 FSSearchList *  Temp;
00342 
00343                 Temp = SearchList;
00344                 SearchList = SearchList->Next;
00345                 geRam_Free(Temp);
00346         }
00347 }
00348 
00349 static  FSSearchList *  CopySearchList(const FSSearchList *SearchList)
00350 {
00351         FSSearchList *  NewList;
00352         FSSearchList *  Tail;
00353 
00354         NewList = Tail = NULL;
00355         while   (SearchList)
00356         {
00357                 FSSearchList *  Temp;
00358 
00359                 Temp = geRam_Allocate(sizeof(*Tail));
00360                 if      (!Temp)
00361                 {
00362                         DestroySearchList(NewList);
00363                         return NULL;
00364                 }
00365                 if      (Tail)
00366                         Tail->Next = Temp;
00367                 else
00368                 {
00369                         assert(!NewList);
00370                         NewList = Temp;
00371                 }
00372                 Tail = Temp;
00373                 Tail->FS = SearchList->FS;
00374                 Tail->Next = NULL;
00375                 SearchList = SearchList->Next;
00376         }
00377         return NewList;
00378 }
00379 
00380 GENESISAPI geBoolean GENESISCC geVFile_AddPath(geVFile *FS1, const geVFile *FS2, geBoolean Append)
00381 {
00382         FSSearchList *  SearchList;
00383 
00384         assert(FS1);
00385         assert(FS2);
00386 
00387         SearchList = CopySearchList(FS2->SearchList);
00388         if      (!SearchList)
00389                 return GE_FALSE;
00390 
00391         if      (Append == GE_FALSE)
00392         {
00393                 SearchList->Next = FS1->SearchList;
00394                 FS1->SearchList = SearchList;
00395         }
00396         else
00397         {
00398                 FSSearchList    Temp;
00399                 FSSearchList *  pTemp;
00400 
00401                 Temp.Next = FS1->SearchList;
00402                 pTemp = &Temp;
00403                 while   (pTemp->Next)
00404                 {
00405                         pTemp = pTemp->Next;
00406                 }
00407 
00408                 pTemp->Next = SearchList;
00409         }
00410 
00411         return GE_TRUE;
00412 }
00413 
00414 GENESISAPI geBoolean GENESISCC geVFile_DeleteFile(geVFile *FS, const char *FileName)
00415 {
00416         assert(FS);
00417         assert(FileName);
00418 
00419         return FS->APIs->DeleteFile(FS, FS->FSData, FileName);
00420 }
00421 
00422 GENESISAPI geBoolean GENESISCC geVFile_RenameFile(geVFile *FS, const char *FileName, const char *NewName)
00423 {
00424         assert(FS);
00425         assert(FileName);
00426         assert(NewName);
00427 
00428         return FS->APIs->RenameFile(FS, FS->FSData, FileName, NewName);
00429 }
00430 
00431 GENESISAPI geBoolean GENESISCC geVFile_FileExists(geVFile *FS, const char *FileName)
00432 {
00433         return FS->APIs->FileExists(FS, FS->FSData, FileName);
00434 }
00435 
00436 GENESISAPI geBoolean GENESISCC geVFile_Close(geVFile *File)
00437 {
00438         assert(File);
00439 
00440         File->APIs->Close(File->FSData);
00441 
00442         if      (File->BaseFile)
00443                 geVFile_Close(File->BaseFile);
00444 
00445         geRam_Free(File->SearchList);
00446         geRam_Free(File);
00447 #pragma message ("Need to propagate returns through VFile_Close")
00448         return GE_TRUE;
00449 }
00450 
00451 
00452 GENESISAPI geBoolean GENESISCC geVFile_GetS(geVFile *File, void *Buff, int MaxLen)
00453 {
00454         assert(File);
00455         assert(Buff);
00456 
00457         if      (MaxLen == 0)
00458                 return GE_FALSE;
00459 
00460         return File->APIs->GetS(File->FSData, Buff, MaxLen);
00461 }
00462 
00463 GENESISAPI geBoolean GENESISCC geVFile_Read(geVFile *File, void *Buff, int Count)
00464 {
00465         assert(File);
00466         assert(Buff);
00467 
00468         if      (Count == 0)
00469                 return GE_TRUE;
00470 
00471         return File->APIs->Read(File->FSData, Buff, Count);
00472 }
00473 
00474 GENESISAPI geBoolean GENESISCC geVFile_Write(geVFile *File, const void *Buff, int Count)
00475 {
00476         assert(File);
00477         assert(Buff);
00478 
00479         if      (Count == 0)
00480                 return GE_TRUE;
00481 
00482         return File->APIs->Write(File->FSData, Buff, Count);
00483 }
00484 
00485 GENESISAPI geBoolean GENESISCC geVFile_Seek(geVFile *File, int Where, geVFile_Whence Whence)
00486 {
00487         assert(File);
00488 
00489         return File->APIs->Seek(File->FSData, Where, Whence);
00490 }
00491 
00492 GENESISAPI geBoolean GENESISCC geVFile_Printf(geVFile *File, const char *Format, ...)
00493 {
00494         char    Temp[8096];
00495         va_list ArgPtr;
00496 
00497         assert(File);
00498         assert(Format);
00499 
00500         va_start(ArgPtr, Format);
00501         vsprintf(Temp, Format, ArgPtr);
00502         va_end(ArgPtr);
00503 
00504         return File->APIs->Write(File->FSData, &Temp[0], strlen(Temp));
00505 }
00506 
00507 GENESISAPI geBoolean GENESISCC geVFile_EOF   (const geVFile *File)
00508 {
00509         assert(File);
00510         
00511         return File->APIs->Eof(File->FSData);
00512 }
00513 
00514 GENESISAPI geBoolean GENESISCC geVFile_Tell  (const geVFile *File, long *Position)
00515 {
00516         assert(File);
00517         
00518         return File->APIs->Tell(File->FSData, Position);
00519 }
00520 
00521 GENESISAPI geBoolean GENESISCC geVFile_Size  (const geVFile *File, long *Size)
00522 {
00523         assert(File);
00524         
00525         return File->APIs->Size(File->FSData, Size);
00526 }
00527 
00528 GENESISAPI geBoolean GENESISCC geVFile_GetProperties(const geVFile *File, geVFile_Properties *Properties)
00529 {
00530         assert(File);
00531         
00532         return File->APIs->GetProperties(File->FSData, Properties);
00533 }
00534 
00535 GENESISAPI geBoolean GENESISCC geVFile_SetSize(geVFile *File, long Size)
00536 {
00537         assert(File);
00538         
00539         return File->APIs->SetSize(File->FSData, Size);
00540 }
00541 
00542 GENESISAPI geBoolean GENESISCC geVFile_SetAttributes(geVFile *File, geVFile_Attributes Attributes)
00543 {
00544         assert(File);
00545         
00546         return File->APIs->SetAttributes(File->FSData, Attributes);
00547 }
00548 
00549 GENESISAPI geBoolean GENESISCC geVFile_SetTime(geVFile *File, const geVFile_Time *Time)
00550 {
00551         assert(File);
00552         
00553         return File->APIs->SetTime(File->FSData, Time);
00554 }
00555 
00556 GENESISAPI geBoolean GENESISCC geVFile_SetHints(geVFile *File, const geVFile_Hints *Hints)
00557 {
00558         assert(File);
00559 
00560         return File->APIs->SetHints(File->FSData, Hints);
00561 }
00562 
00563 GENESISAPI geVFile_Finder * GENESISCC geVFile_CreateFinder(
00564         geVFile *FileSystem,
00565         const char *FileSpec)
00566 {
00567         geVFile_Finder *        Finder;
00568 
00569         assert(FileSystem);
00570         assert(FileSpec);
00571 
00572         Finder = geRam_Allocate(sizeof(*Finder));
00573         if      (!Finder)
00574                 return Finder;
00575 
00576         Finder->Data = FileSystem->APIs->FinderCreate(FileSystem, FileSystem->FSData, FileSpec);
00577         if      (!Finder->Data)
00578         {
00579                 geRam_Free(Finder);
00580                 return NULL;
00581         }
00582 
00583         Finder->APIs = FileSystem->APIs;
00584 
00585         return Finder;
00586 }
00587 
00588 GENESISAPI void GENESISCC geVFile_DestroyFinder(geVFile_Finder *Finder)
00589 {
00590         assert(Finder);
00591         assert(Finder->APIs);
00592 
00593         Finder->APIs->FinderDestroy(Finder->Data);
00594         geRam_Free(Finder);
00595 }
00596 
00597 GENESISAPI geBoolean GENESISCC geVFile_FinderGetNextFile(geVFile_Finder *Finder)
00598 {
00599         assert(Finder);
00600         assert(Finder->APIs);
00601         assert(Finder->Data);
00602         return Finder->APIs->FinderGetNextFile(Finder->Data);
00603 }
00604 
00605 GENESISAPI geBoolean GENESISCC geVFile_FinderGetProperties(const geVFile_Finder *Finder, geVFile_Properties *Properties)
00606 {
00607         assert(Finder);
00608         assert(Finder->APIs);
00609         assert(Finder->Data);
00610 
00611         return Finder->APIs->FinderGetProperties(Finder->Data, Properties);
00612 }
00613 
00614 
00615 GENESISAPI void GENESISCC geVFile_TimeToWin32FileTime(const geVFile_Time *Time, LPFILETIME Win32FileTime)
00616 {
00617         *Win32FileTime = *(LPFILETIME)Time;
00618 }

Generated on Tue Sep 30 12:36:36 2003 for GTestAndEngine by doxygen 1.3.2