X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=fs.c;h=39a5aecadd1a68ed823dba01022c27540505f162;hb=138ae5bad85c0c2b77a1c9a312bab39a5560ac48;hp=c6742d390f527d0ac44c2ac2d3f4346d036b3497;hpb=5e50ce0968fe5404bc5872337ed882f2505dcc9c;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index c6742d39..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; @@ -803,11 +799,11 @@ void FS_AddGameDirectory (const char *dir) { if (matchpattern(current->text, "*.pak", true)) { - snprintf (pakfile, sizeof (pakfile), "%s/%s", dir, current->text); + dpsnprintf (pakfile, sizeof (pakfile), "%s/%s", dir, current->text); 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; @@ -822,11 +818,11 @@ void FS_AddGameDirectory (const char *dir) { if (matchpattern(current->text, "*.pk3", true)) { - snprintf (pakfile, sizeof (pakfile), "%s/%s", dir, current->text); + dpsnprintf (pakfile, sizeof (pakfile), "%s/%s", dir, current->text); 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; } @@ -1260,7 +1264,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) else { char netpath[MAX_OSPATH]; - snprintf(netpath, sizeof(netpath), "%s/%s", search->filename, name); + dpsnprintf(netpath, sizeof(netpath), "%s/%s", search->filename, name); if (FS_SysFileExists (netpath)) { if (!quiet) @@ -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; @@ -1309,8 +1313,8 @@ qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet) if (pack_ind < 0) { char path [MAX_OSPATH]; - snprintf (path, sizeof (path), "%s/%s", search->filename, filename); - return FS_SysOpen (path, "rb"); + dpsnprintf (path, sizeof (path), "%s/%s", search->filename, filename); + 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; @@ -1349,16 +1353,16 @@ qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet) char real_path [MAX_OSPATH]; // Open the file on disk directly - snprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath); + dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath); // 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; @@ -1604,19 +1632,24 @@ Print a string into a file int FS_VPrintf (qfile_t* file, const char* format, va_list ap) { int len; - char tempstring [1024]; + size_t buff_size; + char *tempbuff = NULL; - len = vsnprintf (tempstring, sizeof(tempstring), format, ap); - if (len >= sizeof (tempstring)) + buff_size = 1024; + tempbuff = Mem_Alloc (tempmempool, buff_size); + len = dpvsnprintf (tempbuff, buff_size, format, ap); + while (len < 0) { - char *temp = Mem_Alloc (tempmempool, len + 1); - len = vsnprintf (temp, len + 1, format, ap); - len = write (file->handle, temp, len); - Mem_Free (temp); - return len; + Mem_Free (tempbuff); + buff_size *= 2; + tempbuff = Mem_Alloc (tempmempool, buff_size); + len = dpvsnprintf (tempbuff, buff_size, format, ap); } - return write (file->handle, tempstring, len); + len = write (file->handle, tempbuff, len); + Mem_Free (tempbuff); + + return len; } @@ -1624,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; @@ -1647,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; } @@ -1697,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)) @@ -1766,6 +1798,21 @@ long FS_Tell (qfile_t* file) } +/* +==================== +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; +} + + /* ============ FS_LoadFile @@ -1779,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; @@ -1804,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); @@ -2019,12 +2066,12 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) else { // get a directory listing and look at each name - snprintf(netpath, sizeof (netpath), "%s/%s", searchpath->filename, basepath); + dpsnprintf(netpath, sizeof (netpath), "%s/%s", searchpath->filename, basepath); if ((dir = listdirectory(netpath))) { for (dirfile = dir;dirfile;dirfile = dirfile->next) { - snprintf(temp, sizeof(temp), "%s/%s", basepath, dirfile->text); + dpsnprintf(temp, sizeof(temp), "%s/%s", basepath, dirfile->text); if (matchpattern(temp, (char *)pattern, true)) { for (listtemp = liststart;listtemp;listtemp = listtemp->next)