Mem_Free (buffer);
+ if (
+ eocd->cdir_size > filesize ||
+ eocd->cdir_offset >= filesize ||
+ eocd->cdir_offset + eocd->cdir_size > filesize
+ )
+ {
+ // Obviously invalid central directory.
+ return false;
+ }
+
return true;
}
// Load the central directory in memory
central_dir = (unsigned char *)Mem_Alloc (tempmempool, eocd->cdir_size);
- lseek (pack->handle, eocd->cdir_offset, SEEK_SET);
+ if (lseek (pack->handle, eocd->cdir_offset, SEEK_SET) == -1)
+ {
+ Mem_Free (central_dir);
+ return -1;
+ }
if(read (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
{
Mem_Free (central_dir);
if ((ptr[8] & 0x21) == 0 && (ptr[38] & 0x18) == 0)
{
// Still enough bytes for the name?
- if (remaining < namesize || namesize >= (int)sizeof (*pack->files))
+ if (namesize < 0 || remaining < namesize || namesize >= (int)sizeof (*pack->files))
{
Mem_Free (central_dir);
return -1;
}
+static void FS_mkdir (const char *path)
+{
+ if(COM_CheckParm("-readonly"))
+ return;
+
+#if WIN32
+ if (_mkdir (path) == -1)
+#else
+ if (mkdir (path, 0777) == -1)
+#endif
+ {
+ // No logging for this. The only caller is FS_CreatePath (which
+ // calls it in ways that will intentionally produce EEXIST),
+ // and its own callers always use the directory afterwards and
+ // thus will detect failure that way.
+ }
+}
+
+
/*
============
FS_CreatePath
numpackfiles = header.dirlen / sizeof(dpackfile_t);
- if (numpackfiles > MAX_FILES_IN_PACK)
+ if (numpackfiles < 0 || numpackfiles > MAX_FILES_IN_PACK)
{
Con_Printf ("%s has %i files\n", packfile, numpackfiles);
close(packhandle);
fs_offset_t offset = (unsigned int)LittleLong (info[i].filepos);
fs_offset_t size = (unsigned int)LittleLong (info[i].filelen);
+ // Ensure a zero terminated file name (required by format).
+ info[i].name[sizeof(info[i].name) - 1] = 0;
+
FS_AddFileToPack (info[i].name, pack, offset, size, size, PACKFILE_FLAG_TRUEOFFS);
}
const char *FS_CheckGameDir(const char *gamedir)
{
const char *ret;
- char buf[8192];
+ static char buf[8192];
char vabuf[1024];
if (FS_CheckNastyPath(gamedir, true))
#endif
*/
+static void COM_InsertFlags(const char *buf) {
+ const char *p;
+ char *q;
+ const char **new_argv;
+ int i = 0;
+ int args_left = 256;
+ new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*com_argv) * (com_argc + args_left + 2));
+ if(com_argc == 0)
+ new_argv[0] = "dummy"; // Can't really happen.
+ else
+ new_argv[0] = com_argv[0];
+ ++i;
+ p = buf;
+ while(COM_ParseToken_Console(&p))
+ {
+ size_t sz = strlen(com_token) + 1; // shut up clang
+ if(i > args_left)
+ break;
+ q = (char *)Mem_Alloc(fs_mempool, sz);
+ strlcpy(q, com_token, sz);
+ new_argv[i] = q;
+ ++i;
+ }
+ // Now: i <= args_left + 1.
+ if (com_argc >= 1)
+ {
+ memcpy((char *)(&new_argv[i]), &com_argv[1], sizeof(*com_argv) * (com_argc - 1));
+ i += com_argc - 1;
+ }
+ // Now: i <= args_left + (com_argc || 1).
+ new_argv[i] = NULL;
+ com_argv = new_argv;
+ com_argc = i;
+}
+
/*
================
FS_Init_SelfPack
================
*/
+static unsigned char *FS_SysLoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer);
void FS_Init_SelfPack (void)
{
PK3_OpenLibrary ();
fs_mempool = Mem_AllocPool("file management", 0, NULL);
- if(com_selffd >= 0)
+
+ // Load darkplaces.opt from the FS.
+ if (!COM_CheckParm("-noopt"))
+ {
+ char *buf = (char *) FS_SysLoadFile("darkplaces.opt", tempmempool, true, NULL);
+ if(buf)
+ COM_InsertFlags(buf);
+ Mem_Free(buf);
+ }
+
+ // Provide the SelfPack.
+ if (!COM_CheckParm("-noselfpack"))
{
- fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
- if(fs_selfpack)
+ if (com_selffd >= 0)
{
- char *buf, *q;
- const char *p;
- FS_AddSelfPack();
- buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
- if(buf)
+ fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
+ if(fs_selfpack)
{
- const char **new_argv;
- int i = 0;
- int args_left = 256;
- new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*com_argv) * (com_argc + args_left + 2));
- if(com_argc == 0)
- {
- new_argv[0] = "dummy";
- com_argc = 1;
- }
- else
+ FS_AddSelfPack();
+ if (!COM_CheckParm("-noopt"))
{
- memcpy((char *)(&new_argv[0]), &com_argv[0], sizeof(*com_argv) * com_argc);
+ char *buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
+ if(buf)
+ COM_InsertFlags(buf);
+ Mem_Free(buf);
}
- p = buf;
- while(COM_ParseToken_Console(&p))
- {
- size_t sz = strlen(com_token) + 1; // shut up clang
- if(i >= args_left)
- break;
- q = (char *)Mem_Alloc(fs_mempool, sz);
- strlcpy(q, com_token, sz);
- new_argv[com_argc + i] = q;
- ++i;
- }
- new_argv[i+com_argc] = NULL;
- com_argv = new_argv;
- com_argc = com_argc + i;
}
- Mem_Free(buf);
}
}
}
if(access(va(vabuf, sizeof(vabuf), "%s%s/", userdir, gamedirname1), W_OK | X_OK) >= 0)
fd = 1;
else
- fd = 0;
+ fd = -1;
#endif
if(fd >= 0)
{
if (file->filename)
{
if (file->flags & QFILE_FLAG_REMOVE)
- remove(file->filename);
+ {
+ if (remove(file->filename) == -1)
+ {
+ // No need to report this. If removing a just
+ // written file failed, this most likely means
+ // someone else deleted it first - which we
+ // like.
+ }
+ }
Mem_Free((void *) file->filename);
}
// 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);
+ {
+ if (lseek (file->handle, file->buff_ind - file->buff_len, SEEK_CUR) == -1)
+ {
+ Con_Printf("WARNING: could not seek in %s.\n", file->filename);
+ }
+ }
// Purge cached data
FS_Purge (file);
{
if (count > (fs_offset_t)buffersize)
count = (fs_offset_t)buffersize;
- lseek (file->handle, file->offset + file->position, SEEK_SET);
+ if (lseek (file->handle, file->offset + file->position, SEEK_SET) == -1)
+ {
+ // Seek failed. When reading from a pipe, and
+ // the caller never called FS_Seek, this still
+ // works fine. So no reporting this error.
+ }
nb = read (file->handle, &((unsigned char*)buffer)[done], count);
if (nb > 0)
{
{
if (count > (fs_offset_t)sizeof (file->buff))
count = (fs_offset_t)sizeof (file->buff);
- lseek (file->handle, file->offset + file->position, SEEK_SET);
+ if (lseek (file->handle, file->offset + file->position, SEEK_SET) == -1)
+ {
+ // Seek failed. When reading from a pipe, and
+ // the caller never called FS_Seek, this still
+ // works fine. So no reporting this error.
+ }
nb = read (file->handle, file->buff, count);
if (nb > 0)
{
ztk->in_len = 0;
ztk->in_position = 0;
file->position = 0;
- lseek (file->handle, file->offset, SEEK_SET);
+ if (lseek (file->handle, file->offset, SEEK_SET) == -1)
+ Con_Printf("IMPOSSIBLE: couldn't seek in already opened pk3 file.\n");
// Reset the Zlib stream
ztk->zstream.next_in = ztk->input;
/*
============
-FS_LoadFile
+FS_LoadAndCloseQFile
-Filename are relative to the quake directory.
+Loads full content of a qfile_t and closes it.
Always appends a 0 byte.
============
*/
-unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+static unsigned char *FS_LoadAndCloseQFile (qfile_t *file, const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
{
- qfile_t *file;
unsigned char *buf = NULL;
fs_offset_t filesize = 0;
- file = FS_OpenVirtualFile(path, quiet);
if (file)
{
filesize = file->real_length;
}
+/*
+============
+FS_LoadFile
+
+Filename are relative to the quake directory.
+Always appends a 0 byte.
+============
+*/
+unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+ qfile_t *file = FS_OpenVirtualFile(path, quiet);
+ return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
+/*
+============
+FS_SysLoadFile
+
+Filename are OS paths.
+Always appends a 0 byte.
+============
+*/
+static unsigned char *FS_SysLoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+ qfile_t *file = FS_SysOpen(path, "rb", false);
+ return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
/*
============
FS_WriteFile
// if path doesn't have a .EXT, append extension
// (extension should include the .)
- src = path + strlen(path) - 1;
+ src = path + strlen(path);
while (*src != '/' && src != path)
{
return FS_SysFileType (path) != FS_FILETYPE_NONE;
}
-void FS_mkdir (const char *path)
-{
- if(COM_CheckParm("-readonly"))
- return;
-
-#if WIN32
- _mkdir (path);
-#else
- mkdir (path, 0777);
-#endif
-}
-
/*
===========
FS_Search
int diff;
middle = (left + right) / 2;
- diff = !strcmp_funct (pak->files[middle].name, "gfx/pop.lmp");
+ diff = strcmp_funct (pak->files[middle].name, "gfx/pop.lmp");
// Found it
if (!diff)
return NULL;
}
- if(deflated_size)
- *deflated_size = (size_t)strm.total_out;
+ *deflated_size = (size_t)strm.total_out;
memcpy(out, tmp, strm.total_out);
Mem_Free(tmp);
memcpy(out, outbuf.data, outbuf.cursize);
Mem_Free(outbuf.data);
- if(inflated_size)
- *inflated_size = (size_t)outbuf.cursize;
+ *inflated_size = (size_t)outbuf.cursize;
return out;
}