]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - fs.c
removed an unused function I thought I removed in the previous commit
[xonotic/darkplaces.git] / fs.c
diff --git a/fs.c b/fs.c
index 0ffff63c1f2031b185a521448708c337e7662598..39a5aecadd1a68ed823dba01022c27540505f162 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -151,6 +151,7 @@ struct qfile_s
        size_t                  real_length;                    // uncompressed file size (for files opened in "read" mode)
        size_t                  position;                               // current position in the file
        size_t                  offset;                                 // offset into the package (0 if external file)
+       int                             ungetc;                                 // single stored character from ungetc, cleared to EOF when read
 
        // Contents buffer
        size_t                  buff_ind, buff_len;             // buffer current index and length
@@ -217,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;
 
@@ -257,7 +257,6 @@ VARIABLES
 */
 
 mempool_t *fs_mempool;
-mempool_t *pak_mempool;
 
 int fs_filesize;
 
@@ -554,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;
 
@@ -748,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;
 
@@ -802,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;
@@ -821,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;
@@ -838,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;
@@ -852,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/.darkplaces/%s", homedir, dir));
+               FS_AddGameDirectory (va("%s/.%s/%s", homedir, gameuserdirname, dir));
+#endif
 }
 
 
@@ -902,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);
 
@@ -939,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]);
@@ -960,15 +960,16 @@ void FS_Init (void)
                return;
        }
 
-       // start up with GAMENAME by default (id1)
-       FS_AddGameHierarchy (GAMENAME);
+       // add the game-specific paths
+       // gamedirname1 (typically id1)
+       FS_AddGameHierarchy (gamedirname1);
        Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
 
        // add the game-specific path, if any
-       if (gamedirname[0])
+       if (gamedirname2)
        {
                fs_modified = true;
-               FS_AddGameHierarchy (gamedirname);
+               FS_AddGameHierarchy (gamedirname2);
        }
 
        // -game <gamedir>
@@ -999,7 +1000,6 @@ FS_Shutdown
 */
 void FS_Shutdown (void)
 {
-       Mem_FreePool (&pak_mempool);
        Mem_FreePool (&fs_mempool);
 }
 
@@ -1010,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;
@@ -1051,8 +1051,14 @@ 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;
 
        file->handle = open (filepath, mod | opt, 0666);
        if (file->handle < 0)
@@ -1061,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;
 }
@@ -1112,6 +1119,7 @@ qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
        file->real_length = pfile->realsize;
        file->offset = pfile->offset;
        file->position = 0;
+       file->ungetc = EOF;
 
        if (lseek (file->handle, file->offset, SEEK_SET) == -1)
                Sys_Error ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %d)",
@@ -1256,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)
@@ -1287,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;
@@ -1305,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...
@@ -1329,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;
 
@@ -1345,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;
 
@@ -1394,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;
 
@@ -1413,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;
 
@@ -1426,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
 
@@ -1451,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
@@ -1545,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;
@@ -1600,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;
 }
 
 
@@ -1634,6 +1671,24 @@ int FS_Getc (qfile_t* file)
 }
 
 
+/*
+====================
+FS_UnGetc
+
+Put a character back into the read buffer (only supports one character!)
+====================
+*/
+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;
+}
+
+
 /*
 ====================
 FS_Seek
@@ -1675,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))
@@ -1746,81 +1800,16 @@ long FS_Tell (qfile_t* file)
 
 /*
 ====================
-FS_Gets
+FS_Purge
 
-Extract a line from a file
+Erases any buffered input or output data
 ====================
 */
-char* FS_Gets (qfile_t* file, char* buffer, size_t buffersize)
-{
-       size_t ind;
-
-       for (ind = 0; ind < (size_t) buffersize - 1; ind++)
-       {
-               int c = FS_Getc (file);
-               switch (c)
-               {
-                       // End of file
-                       case EOF:
-                               if (!ind)
-                                       return NULL;
-
-                               buffer[ind] = '\0';
-                               return buffer;
-
-                       // End of line
-                       case '\r':
-                       case '\n':
-                               buffer[ind] = '\n';
-                               buffer[ind + 1] = '\0';
-                               return buffer;
-
-                       default:
-                               buffer[ind] = c;
-               }
-
-       }
-
-       buffer[buffersize - 1] = '\0';
-       return buffer;
-}
-
-
-/*
-==========
-FS_Getline
-
-Dynamic length version of fgets. DO NOT free the buffer.
-==========
-*/
-char *FS_Getline (qfile_t *file)
+void FS_Purge (qfile_t* file)
 {
-       static int  size = 256;
-       static char *buf = 0;
-       char        *t;
-       int         len;
-
-       if (!buf)
-               buf = Mem_Alloc (fs_mempool, size);
-
-       if (!FS_Gets (file, buf, size))
-               return 0;
-
-       len = strlen (buf);
-       while (buf[len - 1] != '\n' && buf[len - 1] != '\r')
-       {
-               t = Mem_Alloc (fs_mempool, size + 256);
-               memcpy(t, buf, size);
-               Mem_Free(buf);
-               size += 256;
-               buf = t;
-               if (!FS_Gets (file, buf + len, size - len))
-                       break;
-               len = strlen (buf);
-       }
-       while ((len = strlen(buf)) && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
-               buf[len - 1] = 0;
-       return buf;
+       file->buff_len = 0;
+       file->buff_ind = 0;
+       file->ungetc = EOF;
 }
 
 
@@ -1837,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;
 
@@ -1862,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);
@@ -2077,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)