X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=157a9c7b7cd501c6c92634efd06187b6e363c984;hb=82a3d4bc9eaf276b248205567c254bea70c97a94;hp=089fb3dc2679ae3ac385ff366ea195b9906ea34c;hpb=426d3967446d906a9612ae09e6748d3dad26c60f;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index 089fb3dc..157a9c7b 100644 --- a/fs.c +++ b/fs.c @@ -43,6 +43,16 @@ #include "fs.h" +// use syscalls instead of f* functions +#define FS_USESYSCALLS + +// Win32 requires us to add O_BINARY, but the other OSes don't have it +#ifdef FS_USESYSCALLS +# ifndef O_BINARY +# define O_BINARY 0 +# endif +#endif + /* @@ -150,7 +160,11 @@ typedef struct struct qfile_s { fs_flags_t flags; +#ifdef FS_USESYSCALLS + int stream; +#else FILE* stream; +#endif size_t length; // file size on disk (PACKED only) size_t offset; // offset into a package (PACKED only) size_t position; // current position in the file (PACKED only) @@ -210,7 +224,11 @@ typedef struct typedef struct pack_s { char filename [MAX_OSPATH]; +#ifdef FS_USESYSCALLS + int handle; +#else FILE *handle; +#endif int ignorecase; // PK3 ignores case int numfiles; packfile_t *files; @@ -359,15 +377,23 @@ PK3_GetEndOfCentralDir Extract the end of the central directory from a PK3 package ==================== */ +#ifdef FS_USESYSCALLS +qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk3_endOfCentralDir_t *eocd) +#else qboolean PK3_GetEndOfCentralDir (const char *packfile, FILE *packhandle, pk3_endOfCentralDir_t *eocd) +#endif { long filesize, maxsize; qbyte *buffer, *ptr; int ind; // Get the package size +#ifdef FS_USESYSCALLS + filesize = lseek (packhandle, 0, SEEK_END); +#else fseek (packhandle, 0, SEEK_END); - filesize = ftell (packhandle); + filesize = ftell(packhandle); +#endif if (filesize < ZIP_END_CDIR_SIZE) return false; @@ -377,8 +403,13 @@ qboolean PK3_GetEndOfCentralDir (const char *packfile, FILE *packhandle, pk3_end else maxsize = ZIP_MAX_COMMENTS_SIZE + ZIP_END_CDIR_SIZE; buffer = Mem_Alloc (tempmempool, maxsize); +#ifdef FS_USESYSCALLS + lseek (packhandle, filesize - maxsize, SEEK_SET); + if (read (packhandle, buffer, maxsize) != (ssize_t) maxsize) +#else fseek (packhandle, filesize - maxsize, SEEK_SET); - if (fread (buffer, 1, maxsize, packhandle) != (unsigned long) maxsize) + if (fread (buffer, 1, maxsize, packhandle) != (size_t) maxsize) +#endif { Mem_Free (buffer); return false; @@ -431,8 +462,13 @@ int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd) // Load the central directory in memory central_dir = Mem_Alloc (tempmempool, eocd->cdir_size); +#ifdef FS_USESYSCALLS + lseek (pack->handle, eocd->cdir_offset, SEEK_SET); + read (pack->handle, central_dir, eocd->cdir_size); +#else fseek (pack->handle, eocd->cdir_offset, SEEK_SET); fread (central_dir, 1, eocd->cdir_size, pack->handle); +#endif // Extract the files properties // The parsing is done "by hand" because some fields have variable sizes and @@ -521,14 +557,24 @@ Create a package entry associated with a PK3 file */ pack_t *FS_LoadPackPK3 (const char *packfile) { +#ifdef FS_USESYSCALLS + int packhandle; +#else FILE *packhandle; +#endif pk3_endOfCentralDir_t eocd; pack_t *pack; int real_nb_files; +#ifdef FS_USESYSCALLS + packhandle = open (packfile, O_RDONLY | O_BINARY); + if (packhandle < 0) + return NULL; +#else packhandle = fopen (packfile, "rb"); if (!packhandle) return NULL; +#endif if (! PK3_GetEndOfCentralDir (packfile, packhandle, &eocd)) Sys_Error ("%s is not a PK3 file", packfile); @@ -539,10 +585,10 @@ pack_t *FS_LoadPackPK3 (const char *packfile) // We only need to do this test if MAX_FILES_IN_PACK is lesser than 65535 // since eocd.nbentries is an unsigned 16 bits integer - #if MAX_FILES_IN_PACK < 65535 +#if MAX_FILES_IN_PACK < 65535 if (eocd.nbentries > MAX_FILES_IN_PACK) Sys_Error ("%s contains too many files (%hu)", packfile, eocd.nbentries); - #endif +#endif // Create a package structure in memory pack = Mem_Alloc (pak_mempool, sizeof (pack_t)); @@ -581,8 +627,13 @@ void PK3_GetTrueFileOffset (packfile_t *file, pack_t *pack) return; // Load the local file description +#ifdef FS_USESYSCALLS + lseek (pack->handle, file->offset, SEEK_SET); + count = read (pack->handle, buffer, ZIP_LOCAL_CHUNK_BASE_SIZE); +#else fseek (pack->handle, file->offset, SEEK_SET); count = fread (buffer, 1, ZIP_LOCAL_CHUNK_BASE_SIZE, pack->handle); +#endif if (count != ZIP_LOCAL_CHUNK_BASE_SIZE || BuffBigLong (buffer) != ZIP_DATA_HEADER) Sys_Error ("Can't retrieve file %s in package %s", file->name, pack->filename); @@ -614,28 +665,29 @@ static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack, size_t realsize, file_flags_t flags) { int (*strcmp_funct) (const char* str1, const char* str2); - size_t left, right, middle; - int diff; + int left, right, middle; packfile_t *file; strcmp_funct = pack->ignorecase ? strcasecmp : strcmp; // Look for the slot we should put that file into (binary search) left = 0; - right = pack->numfiles; - while (left != right) + right = pack->numfiles - 1; + while (left <= right) { - middle = (left + right - 1) / 2; + int diff; + + middle = (left + right) / 2; diff = strcmp_funct (pack->files[middle].name, name); // If we found the file, there's a problem if (!diff) - Sys_Error ("Package %s contains several time the file %s\n", + Sys_Error ("Package %s contains the file %s several times\n", pack->filename, name); // If we're too far in the list if (diff > 0) - right = middle; + right = middle - 1; else left = middle + 1; } @@ -717,15 +769,25 @@ pack_t *FS_LoadPackPAK (const char *packfile) { dpackheader_t header; int i, numpackfiles; +#ifdef FS_USESYSCALLS + int packhandle; +#else FILE *packhandle; +#endif pack_t *pack; dpackfile_t *info; // temporary alloc, allowing huge pack directories +#ifdef FS_USESYSCALLS + packhandle = open (packfile, O_RDONLY | O_BINARY); + if (packhandle < 0) + return NULL; + read (packhandle, (void *)&header, sizeof(header)); +#else packhandle = fopen (packfile, "rb"); if (!packhandle) return NULL; - fread ((void *)&header, 1, sizeof(header), packhandle); +#endif if (memcmp(header.id, "PACK", 4)) Sys_Error ("%s is not a packfile", packfile); header.dirofs = LittleLong (header.dirofs); @@ -750,8 +812,13 @@ pack_t *FS_LoadPackPAK (const char *packfile) packlist = pack; info = Mem_Alloc(tempmempool, sizeof(*info) * numpackfiles); +#ifdef FS_USESYSCALLS + lseek (packhandle, header.dirofs, SEEK_SET); + read (packhandle, (void *)info, header.dirlen); +#else fseek (packhandle, header.dirofs, SEEK_SET); fread ((void *)info, 1, header.dirlen, packhandle); +#endif // parse the directory for (i = 0;i < numpackfiles;i++) @@ -786,14 +853,6 @@ void FS_AddGameDirectory (char *dir) strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); -#ifndef AKVERSION - // add the directory to the search path - search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); - strlcpy (search->filename, dir, sizeof (search->filename)); - search->next = fs_searchpaths; - fs_searchpaths = search; -#endif - list = listdirectory(dir); // add any PAK package in the directory @@ -835,14 +894,12 @@ void FS_AddGameDirectory (char *dir) } freedirectory(list); -// Unpacked files have the priority over packed files if AKVERSION is defined -#ifdef AKVERSION - // add the directory to the search path + // Add the directory to the search path + // (unpacked files have the priority over packed files) search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); strlcpy (search->filename, dir, sizeof (search->filename)); search->next = fs_searchpaths; fs_searchpaths = search; -#endif } @@ -902,7 +959,7 @@ void FS_Init (void) // -basedir // Overrides the system supplied base directory (under GAMENAME) -// COMMANDLINEOPTION: -basedir chooses what base directory the game data is in, inside this there should be a data directory for the game (for example id1) +// COMMANDLINEOPTION: Filesystem: -basedir chooses what base directory the game data is in, inside this there should be a data directory for the game (for example id1) i = COM_CheckParm ("-basedir"); if (i && i < com_argc-1) { @@ -914,7 +971,7 @@ void FS_Init (void) // -path [] ... // Fully specifies the exact search path, overriding the generated one -// COMMANDLINEOPTION: -path specifies the full search path manually, overriding the generated one, example: -path c:\quake\id1 c:\quake\pak0.pak c:\quake\pak1.pak (not recommended) +// COMMANDLINEOPTION: Filesystem: -path specifies the full search path manually, overriding the generated one, example: -path c:\quake\id1 c:\quake\pak0.pak c:\quake\pak1.pak (not recommended) i = COM_CheckParm ("-path"); if (i) { @@ -974,6 +1031,10 @@ void FS_Init (void) Cvar_SetQuick (&scr_screenshot_name, com_modname); } } + + // If "-condebug" is in the command line, remove the previous log file + if (COM_CheckParm ("-condebug") != 0) + unlink (va("%s/qconsole.log", fs_gamedir)); } @@ -991,12 +1052,28 @@ static qfile_t* FS_SysOpen (const char* filepath, const char* mode) file = Mem_Alloc (fs_mempool, sizeof (*file)); memset (file, 0, sizeof (*file)); +#ifdef FS_USESYSCALLS + if (strchr(mode, 'r')) + file->stream = open (filepath, O_RDONLY | O_BINARY); + else if (strchr(mode, 'w')) + file->stream = open (filepath, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0666); + else if (strchr(mode, 'a')) + file->stream = open (filepath, O_RDWR | O_BINARY | O_CREAT | O_APPEND, 0666); + else + file->stream = -1; + if (file->stream < 0) + { + Mem_Free (file); + return NULL; + } +#else file->stream = fopen (filepath, mode); if (!file->stream) { Mem_Free (file); return NULL; } +#endif return file; } @@ -1022,14 +1099,23 @@ qfile_t *FS_OpenRead (const char *path, int offs, int len) if (offs < 0 || len < 0) { // We set fs_filesize here for normal files +#ifdef FS_USESYSCALLS + fs_filesize = lseek (file->stream, 0, SEEK_END); + lseek (file->stream, 0, SEEK_SET); +#else fseek (file->stream, 0, SEEK_END); fs_filesize = ftell (file->stream); fseek (file->stream, 0, SEEK_SET); +#endif } // Packed file else { +#ifdef FS_USESYSCALLS + lseek (file->stream, offs, SEEK_SET); +#else fseek (file->stream, offs, SEEK_SET); +#endif file->flags |= FS_FLAG_PACKED; file->length = len; @@ -1055,7 +1141,6 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) { searchpath_t *search; pack_t *pak; - int (*strcmp_funct) (const char* str1, const char* str2); // search through the path, one element at a time for (search = fs_searchpaths;search;search = search->next) @@ -1063,26 +1148,27 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) // is the element a pak file? if (search->pack) { - size_t left, right, middle; + int (*strcmp_funct) (const char* str1, const char* str2); + int left, right, middle; pak = search->pack; strcmp_funct = pak->ignorecase ? strcasecmp : strcmp; // Look for the file (binary search) left = 0; - right = pak->numfiles; - while (left != right) + right = pak->numfiles - 1; + while (left <= right) { int diff; - middle = (left + right - 1) / 2; + middle = (left + right) / 2; diff = strcmp_funct (pak->files[middle].name, name); // Found it if (!diff) { if (!quiet) - Sys_Printf("FS_FindFile: %s in %s\n", + Con_DPrintf("FS_FindFile: %s in %s\n", pak->files[middle].name, pak->filename); if (index != NULL) @@ -1092,7 +1178,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) // If we're too far in the list if (diff > 0) - right = middle; + right = middle - 1; else left = middle + 1; } @@ -1104,7 +1190,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) if (FS_SysFileExists (netpath)) { if (!quiet) - Sys_Printf("FS_FindFile: %s\n", netpath); + Con_DPrintf("FS_FindFile: %s\n", netpath); if (index != NULL) *index = -1; @@ -1114,7 +1200,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) } if (!quiet) - Sys_Printf("FS_FindFile: can't find %s\n", name); + Con_DPrintf("FS_FindFile: can't find %s\n", name); if (index != NULL) *index = -1; @@ -1259,7 +1345,11 @@ Close a file */ int FS_Close (qfile_t* file) { +#ifdef FS_USESYSCALLS + if (close (file->stream)) +#else if (fclose (file->stream)) +#endif return EOF; if (file->z) @@ -1282,7 +1372,11 @@ Write "datasize" bytes into a file */ size_t FS_Write (qfile_t* file, const void* data, size_t datasize) { +#ifdef FS_USESYSCALLS + return write (file->stream, data, datasize); +#else return fwrite (data, 1, datasize, file->stream); +#endif } @@ -1300,7 +1394,11 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) // Quick path for unpacked files if (! (file->flags & FS_FLAG_PACKED)) +#ifdef FS_USESYSCALLS + return read (file->stream, buffer, buffersize); +#else return fread (buffer, 1, buffersize, file->stream); +#endif // If the file isn't compressed if (! (file->flags & FS_FLAG_DEFLATED)) @@ -1310,7 +1408,11 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) if (buffersize > count) buffersize = count; +#ifdef FS_USESYSCALLS + nb = read (file->stream, buffer, buffersize); +#else nb = fread (buffer, 1, buffersize, file->stream); +#endif file->position += nb; return nb; @@ -1348,7 +1450,11 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) remain = file->length - ztk->in_position; count = (remain > sizeof (ztk->input)) ? sizeof (ztk->input) : remain; +#ifdef FS_USESYSCALLS + read (file->stream, ztk->input, count); +#else fread (ztk->input, 1, count, file->stream); +#endif // Update indexes and counters ztk->in_ind = 0; @@ -1423,7 +1529,11 @@ Flush the file output stream */ int FS_Flush (qfile_t* file) { +#ifdef FS_USESYSCALLS + return 0; +#else return fflush (file->stream); +#endif } @@ -1452,7 +1562,7 @@ int FS_Printf(qfile_t* file, const char* format, ...) va_list args; va_start (args, format); - result = vfprintf (file->stream, format, args); + result = FS_VPrintf(file, format, args); va_end (args); return result; @@ -1468,7 +1578,26 @@ Print a string into a file */ int FS_VPrintf(qfile_t* file, const char* format, va_list ap) { +#ifdef FS_USESYSCALLS +{ + int len; + char tempstring[1024]; + len = vsnprintf (tempstring, sizeof(tempstring), format, ap); + if (len >= sizeof(tempstring)) + { + int result; + char *temp = Mem_Alloc(tempmempool, len + 1); + len = vsnprintf (temp, len + 1, format, ap); + result = write (file->stream, temp, len); + Mem_Free(temp); + return result; + } + else + return write (file->stream, tempstring, len); +} +#else return vfprintf (file->stream, format, ap); +#endif } @@ -1501,7 +1630,15 @@ int FS_Seek (qfile_t* file, long offset, int whence) { // Quick path for unpacked files if (! (file->flags & FS_FLAG_PACKED)) +#ifdef FS_USESYSCALLS + { + if (lseek (file->stream, offset, whence) == -1) + return -1; + return 0; + } +#else return fseek (file->stream, offset, whence); +#endif // Seeking in compressed files is more a hack than anything else, // but we need to support it, so here it is. @@ -1548,7 +1685,11 @@ int FS_Seek (qfile_t* file, long offset, int whence) ztk->out_max = 0; ztk->out_position = 0; file->position = 0; +#ifdef FS_USESYSCALLS + lseek (file->stream, file->offset, SEEK_SET); +#else fseek (file->stream, file->offset, SEEK_SET); +#endif // Reset the Zlib stream ztk->zstream.next_in = ztk->input; @@ -1592,8 +1733,13 @@ int FS_Seek (qfile_t* file, long offset, int whence) if (offset < 0 || offset > (long) file->length) return -1; +#ifdef FS_USESYSCALLS + if (lseek (file->stream, file->offset + offset, SEEK_SET) == -1) + return -1; +#else if (fseek (file->stream, file->offset + offset, SEEK_SET) == -1) return -1; +#endif file->position = offset; return 0; } @@ -1611,7 +1757,11 @@ long FS_Tell (qfile_t* file) if (file->flags & FS_FLAG_PACKED) return file->position; +#ifdef FS_USESYSCALLS + return lseek (file->stream, 0, SEEK_CUR); +#else return ftell (file->stream); +#endif } @@ -1627,8 +1777,10 @@ char* FS_Gets (qfile_t* file, char* buffer, int buffersize) size_t ind; // Quick path for unpacked files +#ifndef FS_USESYSCALLS if (! (file->flags & FS_FLAG_PACKED)) return fgets (buffer, buffersize, file->stream); +#endif for (ind = 0; ind < (size_t) buffersize - 1; ind++) { @@ -1706,6 +1858,7 @@ FS_Eof Extract a line from a file ==================== */ +// FIXME: remove this function? int FS_Eof (qfile_t* file) { if (file->flags & FS_FLAG_PACKED) @@ -1716,7 +1869,12 @@ int FS_Eof (qfile_t* file) return (file->position == file->length); } +#ifdef FS_USESYSCALLS + Sys_Error("FS_Eof: not implemented using syscalls\n"); + return false; +#else return feof (file->stream); +#endif } @@ -1956,7 +2114,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) if (liststart == NULL) liststart = listcurrent; if (!quiet) - Sys_Printf("SearchPackFile: %s : %s\n", pak->filename, temp); + Con_DPrintf("SearchPackFile: %s : %s\n", pak->filename, temp); } } // strip off one path element at a time until empty @@ -1995,7 +2153,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) if (liststart == NULL) liststart = listcurrent; if (!quiet) - Sys_Printf("SearchDirFile: %s\n", temp); + Con_DPrintf("SearchDirFile: %s\n", temp); } } }