X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=fs.c;h=39a5aecadd1a68ed823dba01022c27540505f162;hp=b47d611700e848c96f472b7941f87015205143dc;hb=cf61c6c2365bf16570498041673304235ec3f155;hpb=a04a82ca4a9ab7e55d6425bb29f67f929a3f3f45 diff --git a/fs.c b/fs.c index b47d6117..39a5aeca 100644 --- a/fs.c +++ b/fs.c @@ -218,7 +218,6 @@ typedef struct pack_s int ignorecase; // PK3 ignores case int numfiles; packfile_t *files; - mempool_t *mempool; struct pack_s *next; } pack_t; @@ -258,7 +257,6 @@ VARIABLES */ mempool_t *fs_mempool; -mempool_t *pak_mempool; int fs_filesize; @@ -555,13 +553,12 @@ pack_t *FS_LoadPackPK3 (const char *packfile) #endif // Create a package structure in memory - pack = Mem_Alloc (pak_mempool, sizeof (pack_t)); + pack = Mem_Alloc(fs_mempool, sizeof (pack_t)); pack->ignorecase = true; // PK3 ignores case strlcpy (pack->filename, packfile, sizeof (pack->filename)); pack->handle = packhandle; pack->numfiles = eocd.nbentries; - pack->mempool = Mem_AllocPool (packfile, 0, NULL); - pack->files = Mem_Alloc (pack->mempool, eocd.nbentries * sizeof(packfile_t)); + pack->files = Mem_Alloc(fs_mempool, eocd.nbentries * sizeof(packfile_t)); pack->next = packlist; packlist = pack; @@ -749,13 +746,12 @@ pack_t *FS_LoadPackPAK (const char *packfile) if (numpackfiles > MAX_FILES_IN_PACK) Sys_Error ("%s has %i files", packfile, numpackfiles); - pack = Mem_Alloc(pak_mempool, sizeof (pack_t)); + pack = Mem_Alloc(fs_mempool, sizeof (pack_t)); pack->ignorecase = false; // PAK is case sensitive strlcpy (pack->filename, packfile, sizeof (pack->filename)); pack->handle = packhandle; pack->numfiles = 0; - pack->mempool = Mem_AllocPool(packfile, 0, NULL); - pack->files = Mem_Alloc(pack->mempool, numpackfiles * sizeof(packfile_t)); + pack->files = Mem_Alloc(fs_mempool, numpackfiles * sizeof(packfile_t)); pack->next = packlist; packlist = pack; @@ -807,7 +803,7 @@ void FS_AddGameDirectory (const char *dir) pak = FS_LoadPackPAK (pakfile); if (pak) { - search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); + search = Mem_Alloc(fs_mempool, sizeof(searchpath_t)); search->pack = pak; search->next = fs_searchpaths; fs_searchpaths = search; @@ -826,7 +822,7 @@ void FS_AddGameDirectory (const char *dir) pak = FS_LoadPackPK3 (pakfile); if (pak) { - search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); + search = Mem_Alloc(fs_mempool, sizeof(searchpath_t)); search->pack = pak; search->next = fs_searchpaths; fs_searchpaths = search; @@ -839,7 +835,7 @@ void FS_AddGameDirectory (const char *dir) // Add the directory to the search path // (unpacked files have the priority over packed files) - search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); + search = Mem_Alloc(fs_mempool, sizeof(searchpath_t)); strlcpy (search->filename, dir, sizeof (search->filename)); search->next = fs_searchpaths; fs_searchpaths = search; @@ -853,17 +849,21 @@ FS_AddGameHierarchy */ void FS_AddGameHierarchy (const char *dir) { +#ifndef WIN32 const char *homedir; +#endif strlcpy (com_modname, dir, sizeof (com_modname)); // Add the common game directory FS_AddGameDirectory (va("%s/%s", fs_basedir, dir)); +#ifndef WIN32 // Add the personal game directory homedir = getenv ("HOME"); if (homedir != NULL && homedir[0] != '\0') FS_AddGameDirectory (va("%s/.%s/%s", homedir, gameuserdirname, dir)); +#endif } @@ -903,7 +903,6 @@ void FS_Init (void) searchpath_t *search; fs_mempool = Mem_AllocPool("file management", 0, NULL); - pak_mempool = Mem_AllocPool("paks", 0, NULL); Cvar_RegisterVariable (&scr_screenshot_name); @@ -940,7 +939,7 @@ void FS_Init (void) if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') break; - search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); + search = Mem_Alloc(fs_mempool, sizeof(searchpath_t)); if (!strcasecmp (FS_FileExtension(com_argv[i]), "pak")) { search->pack = FS_LoadPackPAK (com_argv[i]); @@ -1001,7 +1000,6 @@ FS_Shutdown */ void FS_Shutdown (void) { - Mem_FreePool (&pak_mempool); Mem_FreePool (&fs_mempool); } @@ -1012,7 +1010,7 @@ FS_SysOpen Internal function used to create a qfile_t and open the relevant non-packed file on disk ==================== */ -static qfile_t* FS_SysOpen (const char* filepath, const char* mode) +static qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblocking) { qfile_t* file; int mod, opt; @@ -1053,6 +1051,11 @@ static qfile_t* FS_SysOpen (const char* filepath, const char* mode) } } +#ifndef WIN32 + if (nonblocking) + opt |= O_NONBLOCK; +#endif + file = Mem_Alloc (fs_mempool, sizeof (*file)); memset (file, 0, sizeof (*file)); file->ungetc = EOF; @@ -1064,12 +1067,13 @@ static qfile_t* FS_SysOpen (const char* filepath, const char* mode) return NULL; } - // For files opened in read mode, we now need to get the length - if (mod == O_RDONLY) - { - file->real_length = lseek (file->handle, 0, SEEK_END); + file->real_length = lseek (file->handle, 0, SEEK_END); + + // For files opened in append mode, we start at the end of the file + if (mod & O_APPEND) + file->position = file->real_length; + else lseek (file->handle, 0, SEEK_SET); - } return file; } @@ -1291,7 +1295,7 @@ Look for a file in the search paths and open it in read-only mode Sets fs_filesize =========== */ -qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet) +qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet, qboolean nonblocking) { searchpath_t *search; int pack_ind; @@ -1310,7 +1314,7 @@ qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet) { char path [MAX_OSPATH]; dpsnprintf (path, sizeof (path), "%s/%s", search->filename, filename); - return FS_SysOpen (path, "rb"); + return FS_SysOpen (path, "rb", nonblocking); } // So, we found it in a package... @@ -1333,7 +1337,7 @@ FS_Open Open a file. The syntax is the same as fopen ==================== */ -qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet) +qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet, qboolean nonblocking) { qfile_t* file; @@ -1354,11 +1358,11 @@ qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet) // Create directories up to the file FS_CreatePath (real_path); - return FS_SysOpen (real_path, mode); + return FS_SysOpen (real_path, mode, nonblocking); } // Else, we look at the various search paths and open the file in read-only mode - file = FS_OpenReadFile (filepath, quiet); + file = FS_OpenReadFile (filepath, quiet, nonblocking); if (file != NULL) fs_filesize = file->real_length; @@ -1398,7 +1402,21 @@ Write "datasize" bytes into a file */ size_t FS_Write (qfile_t* file, const void* data, size_t datasize) { - ssize_t result = write (file->handle, data, datasize); + ssize_t result; + + // If necessary, seek to the exact file position we're supposed to be + if (file->buff_ind != file->buff_len) + lseek (file->handle, file->buff_ind - file->buff_len, SEEK_CUR); + + // Purge cached data + FS_Purge (file); + + // Write the buffer and update the position + result = write (file->handle, data, datasize); + file->position = lseek (file->handle, 0, SEEK_CUR); + if (file->real_length < file->position) + file->real_length = file->position; + if (result < 0) return 0; @@ -1417,12 +1435,26 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) { size_t count, done; + if (buffersize == 0) + return 0; + + // Get rid of the ungetc character + if (file->ungetc != EOF) + { + ((char*)buffer)[0] = file->ungetc; + buffersize--; + file->ungetc = EOF; + done = 1; + } + else + done = 0; + // First, we copy as many bytes as we can from "buff" if (file->buff_ind < file->buff_len) { count = file->buff_len - file->buff_ind; - done = (buffersize > count) ? count : buffersize; + done += (buffersize > count) ? count : buffersize; memcpy (buffer, &file->buff[file->buff_ind], done); file->buff_ind += done; @@ -1430,8 +1462,6 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) if (buffersize == 0) return done; } - else - done = 0; // NOTE: at this point, the read buffer is always empty @@ -1455,9 +1485,8 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) done += nb; file->position += nb; - // Invalidate the output data (for FS_Seek) - file->buff_len = 0; - file->buff_ind = 0; + // Purge cached data + FS_Purge (file); } } else @@ -1549,9 +1578,8 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) count = buffersize - ztk->zstream.avail_out; file->position += count; - // Invalidate the output data (for FS_Seek) - file->buff_len = 0; - file->buff_ind = 0; + // Purge cached data + FS_Purge (file); } done += count; @@ -1629,19 +1657,14 @@ int FS_VPrintf (qfile_t* file, const char* format, va_list ap) ==================== FS_Getc -Get stored ungetc character or the next character of a file +Get the next character of a file ==================== */ int FS_Getc (qfile_t* file) { char c; - if (file->ungetc != EOF) - { - c = file->ungetc; - file->ungetc = EOF; - } - else if (FS_Read (file, &c, 1) != 1) + if (FS_Read (file, &c, 1) != 1) return EOF; return c; @@ -1652,12 +1675,17 @@ int FS_Getc (qfile_t* file) ==================== FS_UnGetc -Put a character back into the Getc buffer (only supports one character!) +Put a character back into the read buffer (only supports one character!) ==================== */ -void FS_UnGetc (qfile_t* file, unsigned char c) +int FS_UnGetc (qfile_t* file, unsigned char c) { + // If there's already a character waiting to be read + if (file->ungetc != EOF) + return EOF; + file->ungetc = c; + return c; } @@ -1674,11 +1702,6 @@ int FS_Seek (qfile_t* file, long offset, int whence) qbyte* buffer; size_t buffersize; - // if this is an uncompressed real file we can just call the kernel seek - // (necessary when writing files) - if (file->offset == 0 && ! (file->flags & QFILE_FLAG_DEFLATED)) - return lseek (file->handle, offset, whence); - // Compute the file offset switch (whence) { @@ -1707,9 +1730,8 @@ int FS_Seek (qfile_t* file, long offset, int whence) return 0; } - // Invalidate the read buffer contents - file->buff_ind = 0; - file->buff_len = 0; + // Purge cached data + FS_Purge (file); // Unpacked or uncompressed files can seek directly if (! (file->flags & QFILE_FLAG_DEFLATED)) @@ -1772,12 +1794,22 @@ Give the current position in a file */ long FS_Tell (qfile_t* file) { - // if this is an uncompressed real file we can just call the kernel tell - // (necessary when writing files) - if (file->offset == 0 && ! (file->flags & QFILE_FLAG_DEFLATED)) - return lseek (file->handle, 0, SEEK_CUR); - else - return file->position - file->buff_len + file->buff_ind; + return file->position - file->buff_len + file->buff_ind; +} + + +/* +==================== +FS_Purge + +Erases any buffered input or output data +==================== +*/ +void FS_Purge (qfile_t* file) +{ + file->buff_len = 0; + file->buff_ind = 0; + file->ungetc = EOF; } @@ -1794,7 +1826,7 @@ qbyte *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet) qfile_t *file; qbyte *buf; - file = FS_Open (path, "rb", quiet); + file = FS_Open (path, "rb", quiet, false); if (!file) return NULL; @@ -1819,7 +1851,7 @@ qboolean FS_WriteFile (const char *filename, void *data, int len) { qfile_t *file; - file = FS_Open (filename, "wb", false); + file = FS_Open (filename, "wb", false, false); if (!file) { Con_Printf("FS_WriteFile: failed on %s\n", filename);