# 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;
}
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"))
{
- fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
- if(fs_selfpack)
+ 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"))
+ {
+ 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)
+ FS_AddSelfPack();
+ if (!COM_CheckParm("-noopt"))
{
- new_argv[0] = "dummy";
- com_argc = 1;
+ char *buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
+ if(buf)
+ COM_InsertFlags(buf);
+ Mem_Free(buf);
}
- else
- {
- memcpy((char *)(&new_argv[0]), &com_argv[0], sizeof(*com_argv) * com_argc);
- }
- 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);
}
// 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);
// 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)write (file->handle, (const unsigned char *)data + written, chunk);
+ 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 (result != chunk)
break;
}
- file->position = lseek (file->handle, 0, SEEK_CUR);
+ file->position = FILEDESC_SEEK (file->handle, 0, SEEK_CUR);
if (file->real_length < file->position)
file->real_length = file->position;
{
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
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;
}