int ignorecase; // PK3 ignores case
int numfiles;
packfile_t *files;
- mempool_t *mempool;
struct pack_s *next;
} pack_t;
*/
mempool_t *fs_mempool;
-mempool_t *pak_mempool;
int fs_filesize;
#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;
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;
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;
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;
// 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;
*/
void FS_AddGameHierarchy (const char *dir)
{
+#ifndef WIN32
const char *homedir;
-
- strlcpy (com_modname, dir, sizeof (com_modname));
+#endif
// 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
}
searchpath_t *search;
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, ".");
+ strcpy(fs_gamedir, "");
+
+#ifdef MACOSX
+ // FIXME: is there a better way to find the directory outside the .app?
+ if (strstr(com_argv[0], ".app/"))
+ {
+ char *split;
+ char temp[4096];
+ split = strstr(com_argv[0], ".app/");
+ while (split > com_argv[0] && *split != '/')
+ split--;
+ strlcpy(fs_basedir, com_argv[0], sizeof(fs_basedir));
+ fs_basedir[split - com_argv[0]] = 0;
+ }
+#endif
PK3_OpenLibrary ();
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]);
// 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 (gamedirname2)
FS_AddGameHierarchy (gamedirname2);
}
+ // set the com_modname (reported in server info)
+ strlcpy(com_modname, gamedirname1, sizeof(com_modname));
+
// -game <gamedir>
// Adds basedir/gamedir as an override game
// LordHavoc: now supports multiple -game directories
i++;
fs_modified = true;
FS_AddGameHierarchy (com_argv[i]);
- Cvar_SetQuick (&scr_screenshot_name, com_modname);
+ // update the com_modname
+ strlcpy (com_modname, com_argv[i], sizeof (com_modname));
}
}
unlink (va("%s/qconsole.log", fs_gamedir));
}
+void FS_Init_Commands(void)
+{
+ Cvar_RegisterVariable (&scr_screenshot_name);
+
+ Cmd_AddCommand ("path", FS_Path_f);
+ Cmd_AddCommand ("dir", FS_Dir_f);
+ Cmd_AddCommand ("ls", FS_Ls_f);
+
+ // set the default screenshot name to either the mod name or the
+ // gamemode screenshot name
+ if (fs_modified)
+ Cvar_SetQuick (&scr_screenshot_name, com_modname);
+ else
+ Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
+}
+
/*
================
FS_Shutdown
*/
void FS_Shutdown (void)
{
- Mem_FreePool (&pak_mempool);
Mem_FreePool (&fs_mempool);
}
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;
}
}
+#ifndef WIN32
+ if (nonblocking)
+ opt |= O_NONBLOCK;
+#endif
+
file = Mem_Alloc (fs_mempool, sizeof (*file));
memset (file, 0, sizeof (*file));
file->ungetc = EOF;
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;
}
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;
{
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...
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;
// 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;
*/
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;
{
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;
if (buffersize == 0)
return done;
}
- else
- done = 0;
// NOTE: at this point, the read buffer is always empty
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
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;
====================
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;
====================
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;
}
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))
}
+/*
+====================
+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
qfile_t *file;
qbyte *buf;
- file = FS_Open (path, "rb", quiet);
+ file = FS_Open (path, "rb", quiet, false);
if (!file)
return NULL;
{
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);