Boston, MA 02111-1307, USA
*/
-#ifdef __APPLE__
-// include SDL for IPHONEOS code
-# include <TargetConditionals.h>
-# if TARGET_OS_IPHONE
-# include <SDL.h>
-# endif
-#endif
-
#include <limits.h>
#include <fcntl.h>
#endif
#include "quakedef.h"
+
+#if TARGET_OS_IPHONE
+// include SDL for IPHONEOS code
+# include <SDL.h>
+#endif
+
#include "thread.h"
#include "fs.h"
# define dup _dup
#endif
+#if USE_RWOPS
+# include <SDL.h>
+typedef SDL_RWops *filedesc_t;
+# define FILEDESC_INVALID NULL
+# define FILEDESC_ISVALID(fd) ((fd) != NULL)
+# define FILEDESC_READ(fd,buf,count) ((fs_offset_t)SDL_RWread(fd, buf, 1, count))
+# define FILEDESC_WRITE(fd,buf,count) ((fs_offset_t)SDL_RWwrite(fd, buf, 1, count))
+# define FILEDESC_CLOSE SDL_RWclose
+# define FILEDESC_SEEK SDL_RWseek
+static filedesc_t FILEDESC_DUP(const char *filename, filedesc_t fd) {
+ filedesc_t new_fd = SDL_RWFromFile(filename, "rb");
+ if (SDL_RWseek(new_fd, SDL_RWseek(fd, 0, RW_SEEK_CUR), RW_SEEK_SET) < 0) {
+ SDL_RWclose(new_fd);
+ return NULL;
+ }
+ return new_fd;
+}
+# define unlink(name) Con_DPrintf("Sorry, no unlink support when trying to unlink %s.\n", (name))
+#else
+typedef int filedesc_t;
+# define FILEDESC_INVALID -1
+# define FILEDESC_ISVALID(fd) ((fd) != -1)
+# define FILEDESC_READ read
+# define FILEDESC_WRITE write
+# define FILEDESC_CLOSE close
+# define FILEDESC_SEEK lseek
+static filedesc_t FILEDESC_DUP(const char *filename, filedesc_t fd) {
+ return dup(fd);
+}
+#endif
+
/** \page fs File System
All of Quake's data access is through a hierchal file system, but the contents
struct qfile_s
{
int flags;
- int handle; ///< file descriptor
+ filedesc_t handle; ///< file descriptor
fs_offset_t real_length; ///< uncompressed file size (for files opened in "read" mode)
fs_offset_t position; ///< current position in the file
fs_offset_t offset; ///< offset into the package (0 if external file)
{
char filename [MAX_OSPATH];
char shortname [MAX_QPATH];
- int handle;
+ filedesc_t handle;
int ignorecase; ///< PK3 ignores case
int numfiles;
qboolean vpack;
Extract the end of the central directory from a PK3 package
====================
*/
-static qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk3_endOfCentralDir_t *eocd)
+static qboolean PK3_GetEndOfCentralDir (const char *packfile, filedesc_t packhandle, pk3_endOfCentralDir_t *eocd)
{
fs_offset_t filesize, maxsize;
unsigned char *buffer, *ptr;
int ind;
// Get the package size
- filesize = lseek (packhandle, 0, SEEK_END);
+ filesize = FILEDESC_SEEK (packhandle, 0, SEEK_END);
if (filesize < ZIP_END_CDIR_SIZE)
return false;
else
maxsize = ZIP_MAX_COMMENTS_SIZE + ZIP_END_CDIR_SIZE;
buffer = (unsigned char *)Mem_Alloc (tempmempool, maxsize);
- lseek (packhandle, filesize - maxsize, SEEK_SET);
- if (read (packhandle, buffer, maxsize) != (fs_offset_t) maxsize)
+ FILEDESC_SEEK (packhandle, filesize - maxsize, SEEK_SET);
+ if (FILEDESC_READ (packhandle, buffer, maxsize) != (fs_offset_t) maxsize)
{
Mem_Free (buffer);
return false;
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(read (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
+ if (FILEDESC_SEEK (pack->handle, eocd->cdir_offset, SEEK_SET) == -1)
+ {
+ Mem_Free (central_dir);
+ return -1;
+ }
+ if(FILEDESC_READ (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
{
Mem_Free (central_dir);
return -1;
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;
Create a package entry associated with a PK3 file
====================
*/
-static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qboolean silent)
+static pack_t *FS_LoadPackPK3FromFD (const char *packfile, filedesc_t packhandle, qboolean silent)
{
pk3_endOfCentralDir_t eocd;
pack_t *pack;
{
if(!silent)
Con_Printf ("%s is not a PK3 file\n", packfile);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
if (eocd.disknum != 0 || eocd.cdir_disknum != 0)
{
Con_Printf ("%s is a multi-volume ZIP archive\n", packfile);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
if (eocd.nbentries > MAX_FILES_IN_PACK)
{
Con_Printf ("%s contains too many files (%hu)\n", packfile, eocd.nbentries);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
#endif
if (real_nb_files < 0)
{
Con_Printf ("%s is not a valid PK3 file\n", packfile);
- close(pack->handle);
+ FILEDESC_CLOSE(pack->handle);
Mem_Free(pack);
return NULL;
}
Con_DPrintf("Added packfile %s (%i files)\n", packfile, real_nb_files);
return pack;
}
+
+static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qboolean nonblocking);
static pack_t *FS_LoadPackPK3 (const char *packfile)
{
- int packhandle;
- packhandle = FS_SysOpenFD (packfile, "rb", false);
- if (packhandle < 0)
+ filedesc_t packhandle;
+ packhandle = FS_SysOpenFiledesc (packfile, "rb", false);
+ if (!FILEDESC_ISVALID(packhandle))
return NULL;
return FS_LoadPackPK3FromFD(packfile, packhandle, false);
}
return true;
// Load the local file description
- lseek (pack->handle, pfile->offset, SEEK_SET);
- count = read (pack->handle, buffer, ZIP_LOCAL_CHUNK_BASE_SIZE);
+ if (FILEDESC_SEEK (pack->handle, pfile->offset, SEEK_SET) == -1)
+ {
+ Con_Printf ("Can't seek in package %s\n", pack->filename);
+ return false;
+ }
+ count = FILEDESC_READ (pack->handle, buffer, ZIP_LOCAL_CHUNK_BASE_SIZE);
if (count != ZIP_LOCAL_CHUNK_BASE_SIZE || BuffBigLong (buffer) != ZIP_DATA_HEADER)
{
Con_Printf ("Can't retrieve file %s in package %s\n", pfile->name, pack->filename);
}
+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
{
dpackheader_t header;
int i, numpackfiles;
- int packhandle;
+ filedesc_t packhandle;
pack_t *pack;
dpackfile_t *info;
- packhandle = FS_SysOpenFD(packfile, "rb", false);
- if (packhandle < 0)
+ packhandle = FS_SysOpenFiledesc(packfile, "rb", false);
+ if (!FILEDESC_ISVALID(packhandle))
return NULL;
- if(read (packhandle, (void *)&header, sizeof(header)) != sizeof(header))
+ if(FILEDESC_READ (packhandle, (void *)&header, sizeof(header)) != sizeof(header))
{
Con_Printf ("%s is not a packfile\n", packfile);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
if (memcmp(header.id, "PACK", 4))
{
Con_Printf ("%s is not a packfile\n", packfile);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
header.dirofs = LittleLong (header.dirofs);
if (header.dirlen % sizeof(dpackfile_t))
{
Con_Printf ("%s has an invalid directory size\n", packfile);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
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);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
info = (dpackfile_t *)Mem_Alloc(tempmempool, sizeof(*info) * numpackfiles);
- lseek (packhandle, header.dirofs, SEEK_SET);
- if(header.dirlen != read (packhandle, (void *)info, header.dirlen))
+ FILEDESC_SEEK (packhandle, header.dirofs, SEEK_SET);
+ if(header.dirlen != FILEDESC_READ (packhandle, (void *)info, header.dirlen))
{
Con_Printf("%s is an incomplete PAK, not loading\n", packfile);
Mem_Free(info);
- close(packhandle);
+ FILEDESC_CLOSE(packhandle);
return NULL;
}
pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
- pack->ignorecase = false; // PAK is case sensitive
+ pack->ignorecase = true; // PAK is sensitive in Quake1 but insensitive in Quake2
strlcpy (pack->filename, packfile, sizeof (pack->filename));
pack->handle = packhandle;
pack->numfiles = 0;
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);
}
pack->vpack = true;
pack->ignorecase = false;
strlcpy (pack->filename, dirname, sizeof(pack->filename));
- pack->handle = -1;
+ pack->handle = FILEDESC_INVALID;
pack->numfiles = -1;
pack->files = NULL;
Con_DPrintf("Added packfile %s (virtual pack)\n", dirname);
if(!search->pack->vpack)
{
// close the file
- close(search->pack->handle);
+ FILEDESC_CLOSE(search->pack->handle);
// free any memory associated with it
if (search->pack->files)
Mem_Free(search->pack->files);
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
{
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);
+ }
+
+#ifndef USE_RWOPS
+ // 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);
}
}
+#endif
}
static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize)
// see if we can write to this path (note: won't create path)
#ifdef WIN32
// no access() here, we must try to open the file for appending
- fd = FS_SysOpenFD(va(vabuf, sizeof(vabuf), "%s%s/config.cfg", userdir, gamedirname1), "a", false);
+ fd = FS_SysOpenFiledesc(va(vabuf, sizeof(vabuf), "%s%s/config.cfg", userdir, gamedirname1), "a", false);
if(fd >= 0)
- close(fd);
+ FILEDESC_CLOSE(fd);
#else
// on Unix, we don't need to ACTUALLY attempt to open the file
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)
{
*fs_userdir = 0; // user wants roaming installation, no userdir
else
{
+#ifdef DP_FS_USERDIR
+ strlcpy(fs_userdir, DP_FS_USERDIR, sizeof(fs_userdir));
+#else
int dirmode;
int highestuserdirmode = USERDIRMODE_COUNT - 1;
int preferreduserdirmode = USERDIRMODE_COUNT - 1;
int userdirstatus[USERDIRMODE_COUNT];
-#ifdef WIN32
+# ifdef WIN32
// historical behavior...
if (!strcmp(gamedirname1, "id1"))
preferreduserdirmode = USERDIRMODE_NOHOME;
-#endif
+# endif
// check what limitations the user wants to impose
if (COM_CheckParm("-home")) preferreduserdirmode = USERDIRMODE_HOME;
if (COM_CheckParm("-mygames")) preferreduserdirmode = USERDIRMODE_MYGAMES;
// and finally, we picked one...
FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir));
Con_DPrintf("userdir %i is the winner\n", dirmode);
+#endif
}
// if userdir equal to basedir, clear it to avoid confusion later
Thread_DestroyMutex(fs_mutex);
}
-int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
+static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qboolean nonblocking)
{
- int handle = -1;
+ filedesc_t handle = FILEDESC_INVALID;
int mod, opt;
unsigned int ind;
qboolean dolock = false;
break;
default:
Con_Printf ("FS_SysOpen(%s, %s): invalid mode\n", filepath, mode);
- return -1;
+ return FILEDESC_INVALID;
}
for (ind = 1; mode[ind] != '\0'; ind++)
{
opt |= O_NONBLOCK;
if(COM_CheckParm("-readonly") && mod != O_RDONLY)
- return -1;
+ return FILEDESC_INVALID;
-#ifdef WIN32
-# if _MSC_VER >= 1400
+#if USE_RWOPS
+ if (dolock)
+ return FILEDESC_INVALID;
+ handle = SDL_RWFromFile(filepath, mode);
+#else
+# ifdef WIN32
+# if _MSC_VER >= 1400
_sopen_s(&handle, filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
-# else
+# else
handle = _sopen (filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
-# endif
-#else
+# endif
+# else
handle = open (filepath, mod | opt, 0666);
if(handle >= 0 && dolock)
{
l.l_len = 0;
if(fcntl(handle, F_SETLK, &l) == -1)
{
- close(handle);
+ FILEDESC_CLOSE(handle);
handle = -1;
}
}
+# endif
#endif
return handle;
}
+int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
+{
+#ifdef USE_RWOPS
+ return -1;
+#else
+ return FS_SysOpenFiledesc(filepath, mode, nonblocking);
+#endif
+}
+
/*
====================
FS_SysOpen
file = (qfile_t *)Mem_Alloc (fs_mempool, sizeof (*file));
file->ungetc = EOF;
- file->handle = FS_SysOpenFD(filepath, mode, nonblocking);
- if (file->handle < 0)
+ file->handle = FS_SysOpenFiledesc(filepath, mode, nonblocking);
+ if (!FILEDESC_ISVALID(file->handle))
{
Mem_Free (file);
return NULL;
file->filename = Mem_strdup(fs_mempool, filepath);
- file->real_length = lseek (file->handle, 0, SEEK_END);
+ file->real_length = FILEDESC_SEEK (file->handle, 0, SEEK_END);
// For files opened in append mode, we start at the end of the file
if (mode[0] == 'a')
file->position = file->real_length;
else
- lseek (file->handle, 0, SEEK_SET);
+ FILEDESC_SEEK (file->handle, 0, SEEK_SET);
return file;
}
static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
{
packfile_t *pfile;
- int dup_handle;
+ filedesc_t dup_handle;
qfile_t* file;
pfile = &pack->files[pack_ind];
}
#endif
- // LordHavoc: lseek affects all duplicates of a handle so we do it before
+ // LordHavoc: FILEDESC_SEEK affects all duplicates of a handle so we do it before
// the dup() call to avoid having to close the dup_handle on error here
- if (lseek (pack->handle, pfile->offset, SEEK_SET) == -1)
+ if (FILEDESC_SEEK (pack->handle, pfile->offset, SEEK_SET) == -1)
{
Con_Printf ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %08x%08x)\n",
pfile->name, pack->filename, (unsigned int)(pfile->offset >> 32), (unsigned int)(pfile->offset));
return NULL;
}
- dup_handle = dup (pack->handle);
- if (dup_handle < 0)
+ dup_handle = FILEDESC_DUP (pack->filename, pack->handle);
+ if (!FILEDESC_ISVALID(dup_handle))
{
Con_Printf ("FS_OpenPackedFile: can't dup package's handle (pack: %s)\n", pack->filename);
return NULL;
if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK)
{
Con_Printf ("FS_OpenPackedFile: inflate init error (file: %s)\n", pfile->name);
- close(dup_handle);
+ FILEDESC_CLOSE(dup_handle);
Mem_Free(file);
return NULL;
}
return 0;
}
- if (close (file->handle))
+ if (FILEDESC_CLOSE (file->handle))
return EOF;
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);
}
*/
fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize)
{
- fs_offset_t result;
+ fs_offset_t written = 0;
// 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 (FILEDESC_SEEK (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);
// Write the buffer and update the position
- result = write (file->handle, data, (fs_offset_t)datasize);
- file->position = lseek (file->handle, 0, SEEK_CUR);
+ // LordHavoc: to hush a warning about passing size_t to an unsigned int parameter on Win64 we do this as multiple writes if the size would be too big for an integer (we never write that big in one go, but it's a theory)
+ while (written < (fs_offset_t)datasize)
+ {
+ // figure out how much to write in one chunk
+ fs_offset_t maxchunk = 1<<30; // 1 GiB
+ int chunk = (int)min((fs_offset_t)datasize - written, maxchunk);
+ int result = (int)FILEDESC_WRITE (file->handle, (const unsigned char *)data + written, chunk);
+ // if at least some was written, add it to our accumulator
+ if (result > 0)
+ written += result;
+ // if the result is not what we expected, consider the write to be incomplete
+ if (result != chunk)
+ break;
+ }
+ file->position = FILEDESC_SEEK (file->handle, 0, SEEK_CUR);
if (file->real_length < file->position)
file->real_length = file->position;
- if (result < 0)
- return 0;
-
- return result;
+ // note that this will never be less than 0 even if the write failed
+ return written;
}
{
if (count > (fs_offset_t)buffersize)
count = (fs_offset_t)buffersize;
- lseek (file->handle, file->offset + file->position, SEEK_SET);
- nb = read (file->handle, &((unsigned char*)buffer)[done], count);
+ if (FILEDESC_SEEK (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 = FILEDESC_READ (file->handle, &((unsigned char*)buffer)[done], count);
if (nb > 0)
{
done += nb;
{
if (count > (fs_offset_t)sizeof (file->buff))
count = (fs_offset_t)sizeof (file->buff);
- lseek (file->handle, file->offset + file->position, SEEK_SET);
- nb = read (file->handle, file->buff, count);
+ if (FILEDESC_SEEK (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 = FILEDESC_READ (file->handle, file->buff, count);
if (nb > 0)
{
file->buff_len = nb;
count = (fs_offset_t)(ztk->comp_length - ztk->in_position);
if (count > (fs_offset_t)sizeof (ztk->input))
count = (fs_offset_t)sizeof (ztk->input);
- lseek (file->handle, file->offset + (fs_offset_t)ztk->in_position, SEEK_SET);
- if (read (file->handle, ztk->input, count) != count)
+ FILEDESC_SEEK (file->handle, file->offset + (fs_offset_t)ztk->in_position, SEEK_SET);
+ if (FILEDESC_READ (file->handle, ztk->input, count) != count)
{
Con_Printf ("FS_Read: unexpected end of file\n");
break;
buff_size *= 2;
}
- len = write (file->handle, tempbuff, len);
+ len = FILEDESC_WRITE (file->handle, tempbuff, len);
Mem_Free (tempbuff);
return len;
// Unpacked or uncompressed files can seek directly
if (! (file->flags & QFILE_FLAG_DEFLATED))
{
- if (lseek (file->handle, file->offset + offset, SEEK_SET) == -1)
+ if (FILEDESC_SEEK (file->handle, file->offset + offset, SEEK_SET) == -1)
return -1;
file->position = offset;
return 0;
ztk->in_len = 0;
ztk->in_position = 0;
file->position = 0;
- lseek (file->handle, file->offset, SEEK_SET);
+ if (FILEDESC_SEEK (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.
+============
+*/
+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
stringlist_t dirlist;
const char *slash, *backslash, *colon, *separator;
char *basepath;
- char temp[MAX_OSPATH];
for (i = 0;pattern[i] == '.' || pattern[i] == ':' || pattern[i] == '/' || pattern[i] == '\\';i++)
;
pak = searchpath->pack;
for (i = 0;i < pak->numfiles;i++)
{
+ char temp[MAX_OSPATH];
strlcpy(temp, pak->files[i].name, sizeof(temp));
while (temp[0])
{
// for each entry in matchedSet try to open the subdirectories specified in subpath
for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) {
+ char temp[MAX_OSPATH];
strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
strlcat( temp, subpath, sizeof(temp) );
listdirectory( &foundSet, searchpath->filename, temp );
for (dirlistindex = 0;dirlistindex < matchedSet.numstrings;dirlistindex++)
{
- const char *temp = matchedSet.strings[dirlistindex];
- if (matchpattern(temp, (char *)pattern, true))
+ const char *matchtemp = matchedSet.strings[dirlistindex];
+ if (matchpattern(matchtemp, (char *)pattern, true))
{
for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++)
- if (!strcmp(resultlist.strings[resultlistindex], temp))
+ if (!strcmp(resultlist.strings[resultlistindex], matchtemp))
break;
if (resultlistindex == resultlist.numstrings)
{
- stringlistappend(&resultlist, temp);
+ stringlistappend(&resultlist, matchtemp);
if (!quiet && developer_loading.integer)
- Con_Printf("SearchDirFile: %s\n", temp);
+ Con_Printf("SearchDirFile: %s\n", matchtemp);
}
}
}
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)
}
strm.next_in = (unsigned char*)data;
- strm.avail_in = size;
+ strm.avail_in = (unsigned int)size;
tmp = (unsigned char *) Mem_Alloc(tempmempool, size);
if(!tmp)
}
strm.next_out = tmp;
- strm.avail_out = size;
+ strm.avail_out = (unsigned int)size;
if(qz_deflate(&strm, Z_FINISH) != Z_STREAM_END)
{
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);
}
strm.next_in = (unsigned char*)data;
- strm.avail_in = size;
+ strm.avail_in = (unsigned int)size;
do
{
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;
}