X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=233800ef19157efda9f411569d52a38eae91174b;hb=cc80439f0427f96ce65dbc8c2175853dd9d48aa3;hp=e180f13d4ce077518f88b6e45e12fa0c7e096dc6;hpb=9842ecc109d38eed8bb547787657d2099ae2f999;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index e180f13d..233800ef 100644 --- a/fs.c +++ b/fs.c @@ -25,8 +25,6 @@ #include "quakedef.h" -#include -#include #include #include @@ -45,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 + /* @@ -152,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) @@ -212,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; @@ -262,7 +278,7 @@ int fs_filesize; pack_t *packlist = NULL; -searchpath_t *fs_searchpaths; +searchpath_t *fs_searchpaths = NULL; #define MAX_FILES_IN_PACK 65536 @@ -330,20 +346,25 @@ Try to load the Zlib DLL */ qboolean PK3_OpenLibrary (void) { - const char* dllname; + const char* dllnames [] = + { +#ifdef WIN32 + "zlib.dll", +#elif defined(MACOSX) + "libz.dylib", +#else + "libz.so.1", + "libz.so", +#endif + NULL + }; // Already loaded? if (zlib_dll) return true; -#ifdef WIN32 - dllname = "zlib.dll"; -#else - dllname = "libz.so"; -#endif - // Load the DLL - if (! Sys_LoadLibrary (dllname, &zlib_dll, zlibfuncs)) + if (! Sys_LoadLibrary (dllnames, &zlib_dll, zlibfuncs)) { Con_Printf ("Compressed files support disabled\n"); return false; @@ -361,15 +382,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; @@ -379,8 +408,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; @@ -433,8 +467,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 @@ -509,7 +548,9 @@ int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd) remaining -= count; } - Mem_Free (central_dir); + // If the package is empty, central_dir is NULL here + if (central_dir != NULL) + Mem_Free (central_dir); return pack->numfiles; } @@ -523,14 +564,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); @@ -541,10 +592,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)); @@ -552,13 +603,13 @@ pack_t *FS_LoadPackPK3 (const char *packfile) strlcpy (pack->filename, packfile, sizeof (pack->filename)); pack->handle = packhandle; pack->numfiles = eocd.nbentries; - pack->mempool = Mem_AllocPool (packfile); + pack->mempool = Mem_AllocPool (packfile, 0, NULL); pack->files = Mem_Alloc (pack->mempool, eocd.nbentries * sizeof(packfile_t)); pack->next = packlist; packlist = pack; real_nb_files = PK3_BuildFileList (pack, &eocd); - if (real_nb_files <= 0) + if (real_nb_files < 0) Sys_Error ("%s is not a valid PK3 file", packfile); Con_Printf("Added packfile %s (%i files)\n", packfile, real_nb_files); @@ -583,8 +634,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); @@ -616,28 +672,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; } @@ -719,15 +776,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); @@ -746,14 +813,19 @@ pack_t *FS_LoadPackPAK (const char *packfile) strlcpy (pack->filename, packfile, sizeof (pack->filename)); pack->handle = packhandle; pack->numfiles = 0; - pack->mempool = Mem_AllocPool(packfile); + pack->mempool = Mem_AllocPool(packfile, 0, NULL); pack->files = Mem_Alloc(pack->mempool, numpackfiles * sizeof(packfile_t)); pack->next = packlist; 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++) @@ -779,7 +851,7 @@ Sets fs_gamedir, adds the directory to the head of the path, then loads and adds pak1.pak pak2.pak ... ================ */ -void FS_AddGameDirectory (char *dir) +void FS_AddGameDirectory (const char *dir) { stringlist_t *list, *current; searchpath_t *search; @@ -788,14 +860,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 @@ -837,14 +901,33 @@ 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 +} + + +/* +================ +FS_AddGameHierarchy +================ +*/ +void FS_AddGameHierarchy (const char *dir) +{ + const char *homedir; + + strlcpy (com_modname, dir, sizeof (com_modname)); + + // Add the common game directory + FS_AddGameDirectory (va("%s/%s", fs_basedir, dir)); + + // Add the personal game directory + homedir = getenv ("HOME"); + if (homedir != NULL && homedir[0] != '\0') + FS_AddGameDirectory (va("%s/.darkplaces/%s", homedir, dir)); } @@ -868,7 +951,7 @@ char *FS_FileExtension (const char *in) separator = backslash; if (separator < colon) separator = colon; - if (dot < separator) + if (dot == NULL || dot < separator) return ""; dot++; for (i = 0;i < 7 && dot[i];i++) @@ -888,54 +971,39 @@ void FS_Init (void) int i; searchpath_t *search; - fs_mempool = Mem_AllocPool("file management"); - pak_mempool = Mem_AllocPool("paks"); + fs_mempool = Mem_AllocPool("file management", 0, NULL); + pak_mempool = Mem_AllocPool("paks", 0, NULL); + + Cvar_RegisterVariable (&scr_screenshot_name); Cmd_AddCommand ("path", FS_Path_f); Cmd_AddCommand ("dir", FS_Dir_f); Cmd_AddCommand ("ls", FS_Ls_f); strcpy(fs_basedir, "."); + strcpy(fs_gamedir, "."); PK3_OpenLibrary (); // -basedir // Overrides the system supplied base directory (under GAMENAME) +// 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) - strlcpy (fs_basedir, com_argv[i+1], sizeof (fs_basedir)); - - i = strlen (fs_basedir); - if (i > 0 && (fs_basedir[i-1] == '\\' || fs_basedir[i-1] == '/')) - fs_basedir[i-1] = 0; - - // start up with GAMENAME by default (id1) - strlcpy (com_modname, GAMENAME, sizeof (com_modname)); - FS_AddGameDirectory (va("%s/"GAMENAME, fs_basedir)); - if (gamedirname[0]) - { - fs_modified = true; - strlcpy (com_modname, gamedirname, sizeof (com_modname)); - FS_AddGameDirectory (va("%s/%s", fs_basedir, gamedirname)); - } - - // -game - // Adds basedir/gamedir as an override game - i = COM_CheckParm ("-game"); if (i && i < com_argc-1) { - fs_modified = true; - strlcpy (com_modname, com_argv[i+1], sizeof (com_modname)); - FS_AddGameDirectory (va("%s/%s", fs_basedir, com_argv[i+1])); + strlcpy (fs_basedir, com_argv[i+1], sizeof (fs_basedir)); + i = strlen (fs_basedir); + if (i > 0 && (fs_basedir[i-1] == '\\' || fs_basedir[i-1] == '/')) + fs_basedir[i-1] = 0; } // -path [] ... // Fully specifies the exact search path, overriding the generated one +// 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) { fs_modified = true; - fs_searchpaths = NULL; while (++i < com_argc) { if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') @@ -959,9 +1027,51 @@ void FS_Init (void) search->next = fs_searchpaths; fs_searchpaths = search; } + return; } + + // start up with GAMENAME by default (id1) + FS_AddGameHierarchy (GAMENAME); + Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname); + + // add the game-specific path, if any + if (gamedirname[0]) + { + fs_modified = true; + FS_AddGameHierarchy (gamedirname); + } + + // -game + // Adds basedir/gamedir as an override game + // LordHavoc: now supports multiple -game directories + for (i = 1;i < com_argc;i++) + { + if (!com_argv[i]) + continue; + if (!strcmp (com_argv[i], "-game") && i < com_argc-1) + { + i++; + fs_modified = true; + FS_AddGameHierarchy (com_argv[i]); + 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)); } +/* +================ +FS_Shutdown +================ +*/ +void FS_Shutdown (void) +{ + Mem_FreePool (&pak_mempool); + Mem_FreePool (&fs_mempool); +} /* ==================== @@ -977,12 +1087,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; } @@ -1008,14 +1134,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; @@ -1026,6 +1161,42 @@ qfile_t *FS_OpenRead (const char *path, int offs, int len) return file; } +/* +==================== +FS_CheckNastyPath + +Return true if the path should be rejected due to one of the following: +1: path elements that are non-portable +2: path elements that would allow access to files outside the game directory, + or are just not a good idea for a mod to be using. +==================== +*/ +int FS_CheckNastyPath (const char *path) +{ + // Windows: don't allow \ in filenames (windows-only), period. + // (on Windows \ is a directory separator, but / is also supported) + if (strstr(path, "\\")) + return 1; // non-portable + // Mac: don't allow Mac-only filenames - : is a directory separator + // instead of /, but we rely on / working already, so there's no reason to + // support a Mac-only path + // Amiga and Windows: : tries to go to root of drive + if (strstr(path, ":")) + return 1; // non-portable attempt to go to root of drive + // Amiga: // is parent directory + if (strstr(path, "//")) + return 1; // non-portable attempt to go to parent directory + // all: don't allow going to current directory (./) or parent directory (../ or /../) + if (strstr(path, "./")) + return 2; // attempt to go outside the game directory + // Windows and UNIXes: don't allow absolute paths + if (path[0] == '/') + return 2; // attempt to go outside the game directory + // after all these checks we're pretty sure it's a / separated filename + // and won't do much if any harm + return false; +} + /* ==================== @@ -1041,7 +1212,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) @@ -1049,26 +1219,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) @@ -1078,7 +1249,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; } @@ -1090,7 +1261,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; @@ -1100,7 +1271,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; @@ -1217,6 +1388,12 @@ Open a file. The syntax is the same as fopen */ qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet) { + if (FS_CheckNastyPath(filepath)) + { + Con_Printf("FS_Open(\"%s\", \"%s\", %s): nasty filename rejected\n", filepath, mode, quiet ? "true" : "false"); + return NULL; + } + // If the file is opened in "write" or "append" mode if (strchr (mode, 'w') || strchr (mode, 'a')) { @@ -1245,7 +1422,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) @@ -1268,7 +1449,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 } @@ -1286,7 +1471,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)) @@ -1296,7 +1485,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; @@ -1334,7 +1527,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; @@ -1409,7 +1606,11 @@ Flush the file output stream */ int FS_Flush (qfile_t* file) { +#ifdef FS_USESYSCALLS + return 0; +#else return fflush (file->stream); +#endif } @@ -1438,13 +1639,45 @@ 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; } +/* +==================== +FS_VPrintf + +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 +} + + /* ==================== FS_Getc @@ -1474,7 +1707,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. @@ -1521,7 +1762,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; @@ -1565,8 +1810,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; } @@ -1584,7 +1834,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 } @@ -1600,8 +1854,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++) { @@ -1679,6 +1935,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) @@ -1689,7 +1946,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 } @@ -1929,7 +2191,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 @@ -1968,7 +2230,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); } } } @@ -2025,7 +2287,7 @@ int FS_ListDirectory(const char *pattern, int oneperline) const char *name; char linebuf[4096]; fssearch_t *search; - search = FS_Search(pattern, true, false); + search = FS_Search(pattern, true, true); if (!search) return 0; numfiles = search->numfilenames;