00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00120
00121
00122
00123
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
00151
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
00190 if (FS == NULL && (FileSystemType == GE_VFILE_TYPE_VIRTUAL
00191
00192
00193
00194
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 }