X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=218a85e4b6dd3410e9617e4fea7d7f6d37b4b32c;hb=8d7671158db57358a5f7eec510adbd05cdf62189;hp=093d0ac9ad3a7cec37d5bd7d803d6d9efaf3e164;hpb=1e1dbc1c5b89ae4ab8cdd9b32dc6413c67f5dd84;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index 093d0ac9..218a85e4 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 @@ -317,11 +333,7 @@ Unload the Zlib DLL */ void PK3_CloseLibrary (void) { - if (!zlib_dll) - return; - - Sys_UnloadLibrary (zlib_dll); - zlib_dll = NULL; + Sys_UnloadLibrary (&zlib_dll); } @@ -335,7 +347,6 @@ Try to load the Zlib DLL qboolean PK3_OpenLibrary (void) { const char* dllname; - const dllfunction_t *func; // Already loaded? if (zlib_dll) @@ -343,31 +354,20 @@ qboolean PK3_OpenLibrary (void) #ifdef WIN32 dllname = "zlib.dll"; +#elif defined(MACOSX) + dllname = "libz.dylib"; #else dllname = "libz.so"; #endif - // Initializations - for (func = zlibfuncs; func && func->name != NULL; func++) - *func->funcvariable = NULL; - // Load the DLL - if (! (zlib_dll = Sys_LoadLibrary (dllname))) + if (! Sys_LoadLibrary (dllname, &zlib_dll, zlibfuncs)) { - Con_Printf("Can't find %s. Compressed files support disabled\n", dllname); + Con_Printf ("Compressed files support disabled\n"); return false; } - // Get the function adresses - for (func = zlibfuncs; func && func->name != NULL; func++) - if (!(*func->funcvariable = (void *) Sys_GetProcAddress (zlib_dll, func->name))) - { - Con_Printf("missing function \"%s\" - broken Zlib library!\n", func->name); - PK3_CloseLibrary (); - return false; - } - - Con_Printf("%s loaded. Compressed files support enabled\n", dllname); + Con_Printf ("Compressed files support enabled\n"); return true; } @@ -379,15 +379,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; @@ -397,8 +405,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; @@ -451,8 +464,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 @@ -527,7 +545,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; } @@ -541,14 +561,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); @@ -559,10 +589,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)); @@ -570,13 +600,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); @@ -601,8 +631,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); @@ -634,28 +669,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; } @@ -737,15 +773,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); @@ -764,14 +810,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++) @@ -806,14 +857,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 @@ -855,14 +898,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 } @@ -886,7 +927,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++) @@ -906,54 +947,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] == '-') @@ -977,7 +1003,42 @@ void FS_Init (void) search->next = fs_searchpaths; fs_searchpaths = search; } + return; } + + // start up with GAMENAME by default (id1) + strlcpy (com_modname, GAMENAME, sizeof (com_modname)); + FS_AddGameDirectory (va("%s/"GAMENAME, fs_basedir)); + Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname); + + // add the game-specific path, if any + 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 + // 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; + strlcpy (com_modname, com_argv[i], sizeof (com_modname)); + FS_AddGameDirectory (va("%s/%s", fs_basedir, 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)); } @@ -995,12 +1056,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; } @@ -1026,14 +1103,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; @@ -1044,6 +1130,39 @@ 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 to parent directory + // after all these checks we're pretty sure it's a / separated filename + // and won't do much if any harm + return false; +} + /* ==================== @@ -1059,7 +1178,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) @@ -1067,26 +1185,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) @@ -1096,7 +1215,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; } @@ -1108,7 +1227,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; @@ -1118,7 +1237,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; @@ -1235,6 +1354,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')) { @@ -1263,7 +1388,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) @@ -1286,7 +1415,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 } @@ -1304,7 +1437,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)) @@ -1314,7 +1451,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; @@ -1352,7 +1493,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; @@ -1427,7 +1572,11 @@ Flush the file output stream */ int FS_Flush (qfile_t* file) { +#ifdef FS_USESYSCALLS + return 0; +#else return fflush (file->stream); +#endif } @@ -1456,13 +1605,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 @@ -1492,7 +1673,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. @@ -1539,7 +1728,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; @@ -1583,8 +1776,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; } @@ -1602,7 +1800,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 } @@ -1618,8 +1820,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++) { @@ -1697,6 +1901,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) @@ -1707,7 +1912,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 } @@ -1918,7 +2128,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) if (separator < colon) separator = colon; basepathlength = separator - pattern; - basepath = Z_Malloc(basepathlength + 1); + basepath = Mem_Alloc (tempmempool, basepathlength + 1); if (basepathlength) memcpy(basepath, pattern, basepathlength); basepath[basepathlength] = 0; @@ -1947,7 +2157,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 @@ -1986,7 +2196,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); } } } @@ -2022,7 +2232,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) stringlistfree(liststart); } - Z_Free(basepath); + Mem_Free(basepath); return search; } @@ -2043,7 +2253,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;