work towards a more secure qfs

This commit is contained in:
Bill Currie 2003-02-14 22:36:10 +00:00
parent 68d2167c9e
commit 851d203916
19 changed files with 193 additions and 167 deletions

View file

@ -46,9 +46,16 @@ typedef struct searchpath_s {
typedef struct gamedir_s { typedef struct gamedir_s {
const char *name; const char *name;
const char *gamedir;
const char *path; const char *path;
const char *gamecode; const char *gamecode;
const char *skinpath; struct {
const char *def;
const char *skins;
const char *progs;
const char *sound;
const char *maps;
} dir;
} gamedir_t; } gamedir_t;
extern searchpath_t *qfs_searchpaths; extern searchpath_t *qfs_searchpaths;
@ -60,9 +67,6 @@ extern struct cvar_s *fs_sharepath;
extern int file_from_pak; extern int file_from_pak;
extern int qfs_filesize; extern int qfs_filesize;
extern char qfs_gamedir_path[MAX_OSPATH];
extern char qfs_gamedir_file[MAX_OSPATH];
struct cache_user_s; struct cache_user_s;
char *QFS_CompressPath (const char *pth); char *QFS_CompressPath (const char *pth);
@ -78,7 +82,8 @@ void QFS_StripExtension (const char *in, char *out);
int QFS_NextFilename (char *filename, const char *prefix, const char *ext); int QFS_NextFilename (char *filename, const char *prefix, const char *ext);
const char *QFS_FileExtension (const char *in); const char *QFS_FileExtension (const char *in);
QFile *QFS_WOpen (const char *path, int zip);
int QFS_Rename (const char *old, const char *new);
byte *QFS_LoadFile (const char *path, int usehunk); byte *QFS_LoadFile (const char *path, int usehunk);
byte *QFS_LoadStackFile (const char *path, void *buffer, int bufsize); byte *QFS_LoadStackFile (const char *path, void *buffer, int bufsize);

View file

@ -250,9 +250,10 @@ Condump_f (void)
Con_Printf ("invalid character in filename\n"); Con_Printf ("invalid character in filename\n");
return; return;
} }
snprintf (name, sizeof (name), "%s/%s.txt", qfs_gamedir_path, Cmd_Argv (1)); snprintf (name, sizeof (name), "%s/%s.txt", qfs_gamedir->dir.def,
Cmd_Argv (1));
if (!(file = Qopen (name, "wt"))) { if (!(file = QFS_WOpen (name, 0))) {
Con_Printf ("could not open %s for writing: %s\n", name, Con_Printf ("could not open %s for writing: %s\n", name,
strerror (errno)); strerror (errno));
return; return;
@ -452,8 +453,8 @@ C_Print (const char *fmt, va_list args)
// log all messages to file // log all messages to file
if (con_debuglog) if (con_debuglog)
Sys_DebugLog (va ("%s/qconsole.log", qfs_gamedir_path), Sys_DebugLog (va ("%s/%s/qconsole.log", fs_userpath->string,
"%s", buffer->str); qfs_gamedir->dir.def), "%s", buffer->str);
if (!con_initialized) if (!con_initialized)
return; return;
@ -809,9 +810,9 @@ C_NewMap (void)
{ {
static char old_gamedir[MAX_OSPATH]; static char old_gamedir[MAX_OSPATH];
if (!strequal (old_gamedir, qfs_gamedir_path)) if (!strequal (old_gamedir, qfs_gamedir->gamedir))
Menu_Load (); Menu_Load ();
strcpy (old_gamedir, qfs_gamedir_path); strcpy (old_gamedir, qfs_gamedir->gamedir);
} }
static general_funcs_t plugin_info_general_funcs = { static general_funcs_t plugin_info_general_funcs = {

View file

@ -54,6 +54,7 @@ int fnmatch (const char *__pattern, const char *__string, int __flags);
#endif #endif
#include "QF/csqc.h" #include "QF/csqc.h"
#include "QF/cvar.h"
#include "QF/progs.h" #include "QF/progs.h"
#include "QF/quakefs.h" #include "QF/quakefs.h"
#include "QF/va.h" #include "QF/va.h"
@ -158,7 +159,8 @@ bi_File_Open (progs_t *pr)
goto error; goto error;
if (do_write && !file_writeable (path)) if (do_write && !file_writeable (path))
goto error; goto error;
R_INT (pr) = QFile_open (pr, va ("%s/%s", qfs_gamedir_path, path), mode); R_INT (pr) = QFile_open (pr, va ("%s/%s/%s", fs_userpath->string,
qfs_gamedir->dir.def, path), mode);
free (path); free (path);
return; return;
error: error:

View file

@ -605,7 +605,9 @@ GIB_File_Transform_Path_Secure (dstring_t *path)
return -1; return -1;
/* Qexpand_squiggle (fs_userpath->string, e_dir); */ /* Qexpand_squiggle (fs_userpath->string, e_dir); */
dstring_insertstr (path, 0, "/"); dstring_insertstr (path, 0, "/");
dstring_insertstr (path, 0, /* e_dir */ qfs_gamedir_path); dstring_insertstr (path, 0, /* e_dir */ qfs_gamedir->dir.def);
dstring_insertstr (path, 0, "/");
dstring_insertstr (path, 0, fs_userpath->string);
return 0; return 0;
} }

View file

@ -431,13 +431,9 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i
if (do_cache) { if (do_cache) {
// save out the cached version // save out the cached version
snprintf (fullpath, sizeof (fullpath), "%s/%s", qfs_gamedir_path, snprintf (fullpath, sizeof (fullpath), "%s/%s",
cache); qfs_gamedir->dir.def, cache);
f = Qopen (fullpath, "wbz9"); f = QFS_WOpen (fullpath, 9);
if (!f) {
QFS_CreatePath (fullpath);
f = Qopen (fullpath, "wb");
}
if (f) { if (f) {
struct mdfour md; struct mdfour md;

View file

@ -118,9 +118,6 @@ cvar_t *fs_userpath;
cvar_t *fs_sharepath; cvar_t *fs_sharepath;
cvar_t *fs_dirconf; cvar_t *fs_dirconf;
char qfs_gamedir_file[MAX_OSPATH];
char qfs_gamedir_path[MAX_OSPATH];
int qfs_filesize; int qfs_filesize;
searchpath_t *qfs_searchpaths; searchpath_t *qfs_searchpaths;
@ -282,8 +279,14 @@ qfs_get_gd_params (plitem_t *gdpl, gamedir_t *gamedir, dstring_t *path,
} }
if (!gamedir->gamecode && (p = PL_ObjectForKey (gdpl, "GameCode"))) if (!gamedir->gamecode && (p = PL_ObjectForKey (gdpl, "GameCode")))
gamedir->gamecode = qfs_var_subst (p->data, vars); gamedir->gamecode = qfs_var_subst (p->data, vars);
if (!gamedir->skinpath && (p = PL_ObjectForKey (gdpl, "SkinPath"))) if (!gamedir->dir.skins && (p = PL_ObjectForKey (gdpl, "SkinPath")))
gamedir->skinpath = qfs_var_subst (p->data, vars); gamedir->dir.skins = qfs_var_subst (p->data, vars);
if (!gamedir->dir.progs && (p = PL_ObjectForKey (gdpl, "ProgPath")))
gamedir->dir.progs = qfs_var_subst (p->data, vars);
if (!gamedir->dir.sound && (p = PL_ObjectForKey (gdpl, "SoundPath")))
gamedir->dir.sound = qfs_var_subst (p->data, vars);
if (!gamedir->dir.maps && (p = PL_ObjectForKey (gdpl, "MapPath")))
gamedir->dir.maps = qfs_var_subst (p->data, vars);
} }
static void static void
@ -396,12 +399,22 @@ qfs_build_gamedir (const char **list)
if (qfs_gamedir) { if (qfs_gamedir) {
if (qfs_gamedir->name) if (qfs_gamedir->name)
free ((char *)qfs_gamedir->name); free ((char *)qfs_gamedir->name);
if (qfs_gamedir->gamedir)
free ((char *)qfs_gamedir->gamedir);
if (qfs_gamedir->path) if (qfs_gamedir->path)
free ((char *)qfs_gamedir->path); free ((char *)qfs_gamedir->path);
if (qfs_gamedir->gamecode) if (qfs_gamedir->gamecode)
free ((char *)qfs_gamedir->gamecode); free ((char *)qfs_gamedir->gamecode);
if (qfs_gamedir->skinpath) if (qfs_gamedir->dir.def)
free ((char *)qfs_gamedir->skinpath); free ((char *)qfs_gamedir->dir.def);
if (qfs_gamedir->dir.skins)
free ((char *)qfs_gamedir->dir.skins);
if (qfs_gamedir->dir.progs)
free ((char *)qfs_gamedir->dir.progs);
if (qfs_gamedir->dir.sound)
free ((char *)qfs_gamedir->dir.sound);
if (qfs_gamedir->dir.maps)
free ((char *)qfs_gamedir->dir.maps);
free (qfs_gamedir); free (qfs_gamedir);
} }
@ -432,18 +445,39 @@ qfs_build_gamedir (const char **list)
continue; continue;
} }
Hash_Add (dirs, (void *) name); Hash_Add (dirs, (void *) name);
if (!j) if (!j) {
gamedir->name = strdup (name); gamedir->name = strdup (name);
gamedir->gamedir = strdup (list[j]);
}
qfs_set_var (vars, "gamedir", dir); qfs_set_var (vars, "gamedir", dir);
qfs_get_gd_params (gdpl, gamedir, path, vars); qfs_get_gd_params (gdpl, gamedir, path, vars);
qfs_inherit (qfs_gd_plist, gdpl, gamedir, path, dirs, vars); qfs_inherit (qfs_gd_plist, gdpl, gamedir, path, dirs, vars);
} }
gamedir->path = path->str; gamedir->path = path->str;
for (dir = gamedir->path; *dir && *dir != ':'; dir++)
;
gamedir->dir.def = nva ("%.*s", (int) (dir - gamedir->path),
gamedir->path);
if (!gamedir->dir.skins)
gamedir->dir.skins = nva ("%s/skins", gamedir->dir.def);
if (!gamedir->dir.progs)
gamedir->dir.progs = nva ("%s/progs", gamedir->dir.def);
if (!gamedir->dir.sound)
gamedir->dir.sound = nva ("%s/sound", gamedir->dir.def);
if (!gamedir->dir.maps)
gamedir->dir.maps = nva ("%s/maps", gamedir->dir.def);
qfs_gamedir = gamedir; qfs_gamedir = gamedir;
Sys_DPrintf ("%s\n", qfs_gamedir->name); Sys_DPrintf ("%s\n", qfs_gamedir->name);
Sys_DPrintf (" %s\n", qfs_gamedir->path); Sys_DPrintf (" gamedir : %s\n", qfs_gamedir->gamedir);
Sys_DPrintf (" %s\n", qfs_gamedir->gamecode); Sys_DPrintf (" path : %s\n", qfs_gamedir->path);
Sys_DPrintf (" %s\n", qfs_gamedir->skinpath); Sys_DPrintf (" gamecode: %s\n", qfs_gamedir->gamecode);
Sys_DPrintf (" def : %s\n", qfs_gamedir->dir.def);
Sys_DPrintf (" skins : %s\n", qfs_gamedir->dir.skins);
Sys_DPrintf (" progs : %s\n", qfs_gamedir->dir.progs);
Sys_DPrintf (" sound : %s\n", qfs_gamedir->dir.sound);
Sys_DPrintf (" maps : %s\n", qfs_gamedir->dir.maps);
qfs_process_path (qfs_gamedir->path, dir); qfs_process_path (qfs_gamedir->path, dir);
free (path); free (path);
Hash_DelTable (dirs); Hash_DelTable (dirs);
@ -534,14 +568,11 @@ QFS_WriteFile (const char *filename, void *data, int len)
char name[MAX_OSPATH]; char name[MAX_OSPATH];
QFile *f; QFile *f;
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, filename); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, filename);
f = Qopen (name, "wb"); f = QFS_WOpen (name, 0);
if (!f) { if (!f) {
Sys_mkdir (qfs_gamedir_path); Sys_Error ("Error opening %s", filename);
f = Qopen (name, "wb");
if (!f)
Sys_Error ("Error opening %s", filename);
} }
Sys_Printf ("QFS_WriteFile: %s\n", name); Sys_Printf ("QFS_WriteFile: %s\n", name);
@ -563,14 +594,11 @@ QFS_WriteBuffers (const char *filename, int count, ...)
va_start (args, count); va_start (args, count);
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, filename); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, filename);
f = Qopen (name, "wb"); f = QFS_WOpen (name, 0);
if (!f) { if (!f) {
Sys_mkdir (qfs_gamedir_path); Sys_Error ("Error opening %s", filename);
f = Qopen (name, "wb");
if (!f)
Sys_Error ("Error opening %s", filename);
} }
Sys_Printf ("QFS_WriteBuffers: %s\n", name); Sys_Printf ("QFS_WriteBuffers: %s\n", name);
@ -1043,27 +1071,18 @@ QFS_LoadGameDirectory (const char *dir)
/* /*
QFS_AddDirectory QFS_AddDirectory
Sets qfs_gamedir_path, adds the directory to the head of the path, Adds the directory to the head of the path, then loads and adds pak0.pak
then loads and adds pak1.pak pak2.pak ... pak1.pak ...
*/ */
static void static void
QFS_AddDirectory (const char *dir) QFS_AddDirectory (const char *dir)
{ {
searchpath_t *search; searchpath_t *search;
char *p;
char e_dir[MAX_OSPATH]; char e_dir[MAX_OSPATH];
Qexpand_squiggle (dir, e_dir); Qexpand_squiggle (dir, e_dir);
dir = e_dir; dir = e_dir;
if ((p = strrchr (dir, '/')) != NULL) {
strcpy (qfs_gamedir_file, ++p);
strcpy (qfs_gamedir_path, dir);
} else {
strcpy (qfs_gamedir_file, dir);
strcpy (qfs_gamedir_path, va ("%s/%s", fs_userpath->string, dir));
}
// add the directory to the search path // add the directory to the search path
search = calloc (1, sizeof (searchpath_t)); search = calloc (1, sizeof (searchpath_t));
strcpy (search->filename, dir); strcpy (search->filename, dir);
@ -1222,10 +1241,43 @@ QFS_NextFilename (char *filename, const char *prefix, const char *ext)
digits[0] = i / 100 + '0'; digits[0] = i / 100 + '0';
digits[1] = i / 10 % 10 + '0'; digits[1] = i / 10 % 10 + '0';
digits[2] = i % 10 + '0'; digits[2] = i % 10 + '0';
snprintf (checkname, sizeof (checkname), "%s/%s", qfs_gamedir_path, snprintf (checkname, sizeof (checkname),
"%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def,
filename); filename);
if (Sys_FileTime (checkname) == -1) if (Sys_FileTime (checkname) == -1)
return 1; // file doesn't exist return 1; // file doesn't exist
} }
return 0; return 0;
} }
QFile *
QFS_WOpen (const char *path, int zip)
{
dstring_t *full_path = dstring_new ();
QFile *file;
char mode[4] = "wb\000\000";
if (zip)
mode[2] = bound (1, zip, 9);
dsprintf (full_path, "%s/%s", fs_userpath->string, path);
QFS_CreatePath (full_path->str);
file = Qopen (full_path->str, mode);
dstring_delete (full_path);
return file;
}
int
QFS_Rename (const char *old, const char *new)
{
dstring_t *full_old = dstring_new ();
dstring_t *full_new = dstring_new ();
int ret;
dsprintf (full_old, "%s/%s", fs_userpath->string, old);
dsprintf (full_new, "%s/%s", fs_userpath->string, new);
QFS_CreatePath (full_new->str);
ret = Qrename (full_old->str, full_new->str);
dstring_delete (full_old);
dstring_delete (full_new);
return ret;
}

View file

@ -243,9 +243,8 @@ VID_SetPalette (unsigned char *palette)
} }
d_15to8table[i] = k; d_15to8table[i] = k;
} }
snprintf (s, sizeof (s), "%s/glquake/15to8.pal", qfs_gamedir_path); snprintf (s, sizeof (s), "%s/glquake/15to8.pal", qfs_gamedir->dir.def);
QFS_CreatePath (s); if ((f = QFS_WOpen (s, 0)) != NULL) {
if ((f = Qopen (s, "wb")) != NULL) {
Qwrite (f, d_15to8table, 1 << 15); Qwrite (f, d_15to8table, 1 << 15);
Qclose (f); Qclose (f);
} }

View file

@ -253,7 +253,7 @@ CL_Record_f (void)
} else } else
track = -1; track = -1;
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, Cmd_Argv (1)); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
// start the map up // start the map up
// //
@ -265,13 +265,12 @@ CL_Record_f (void)
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
if (demo_gzip->int_val) { if (demo_gzip->int_val) {
QFS_DefaultExtension (name, ".dem.gz"); QFS_DefaultExtension (name, ".dem.gz");
cls.demofile = Qopen (name, va ("wbz%d", cls.demofile = QFS_WOpen (name, demo_gzip->int_val);
bound (1, demo_gzip->int_val, 9)));
} else } else
#endif #endif
{ {
QFS_DefaultExtension (name, ".dem"); QFS_DefaultExtension (name, ".dem");
cls.demofile = Qopen (name, "wb"); cls.demofile = QFS_WOpen (name, 0);
} }
if (!cls.demofile) { if (!cls.demofile) {

View file

@ -285,8 +285,8 @@ Host_WriteConfiguration (void)
// dedicated servers initialize the host but don't parse and set the // dedicated servers initialize the host but don't parse and set the
// config.cfg cvars // config.cfg cvars
if (host_initialized && !isDedicated && cl_writecfg->int_val) { if (host_initialized && !isDedicated && cl_writecfg->int_val) {
char *path = va ("%s/config.cfg", qfs_gamedir_path); char *path = va ("%s/config.cfg", qfs_gamedir->dir.def);
f = Qopen (path, "w"); f = QFS_WOpen (path, 0);
if (!f) { if (!f) {
Con_Printf ("Couldn't write config.cfg.\n"); Con_Printf ("Couldn't write config.cfg.\n");
return; return;

View file

@ -465,11 +465,11 @@ Host_Savegame_f (void)
} }
} }
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, Cmd_Argv (1)); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
QFS_DefaultExtension (name, ".sav"); QFS_DefaultExtension (name, ".sav");
Con_Printf ("Saving game to %s...\n", name); Con_Printf ("Saving game to %s...\n", name);
f = Qopen (name, "w"); f = QFS_WOpen (name, 0);
if (!f) { if (!f) {
Con_Printf ("ERROR: couldn't open.\n"); Con_Printf ("ERROR: couldn't open.\n");
return; return;
@ -528,7 +528,8 @@ Host_Loadgame_f (void)
cls.demonum = -1; // stop demo loop in case this fails cls.demonum = -1; // stop demo loop in case this fails
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, Cmd_Argv (1)); snprintf (name, sizeof (name), "%s/%s/%s", fs_userpath->string,
qfs_gamedir->dir.def, Cmd_Argv (1));
QFS_DefaultExtension (name, ".sav"); QFS_DefaultExtension (name, ".sav");
// we can't call SCR_BeginLoadingPlaque, because too much stack space has // we can't call SCR_BeginLoadingPlaque, because too much stack space has

View file

@ -539,23 +539,22 @@ CL_Record (const char *argv1)
if (mapname[k] == '.') if (mapname[k] == '.')
mapname[k] = '\0'; mapname[k] = '\0';
snprintf (name, sizeof (name), "%s/%s-%s", qfs_gamedir_path, snprintf (name, sizeof (name), "%s/%s-%s", qfs_gamedir->dir.def,
timestring, mapname); timestring, mapname);
} else { } else {
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, argv1); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, argv1);
} }
// open the demo file // open the demo file
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
if (demo_gzip->int_val) { if (demo_gzip->int_val) {
QFS_DefaultExtension (name, ".qwd.gz"); QFS_DefaultExtension (name, ".qwd.gz");
cls.demofile = Qopen (name, va ("wbz%d", cls.demofile = QFS_WOpen (name, demo_gzip->int_val);
bound (1, demo_gzip->int_val, 9)));
} else } else
#endif #endif
{ {
QFS_DefaultExtension (name, ".qwd"); QFS_DefaultExtension (name, ".qwd");
cls.demofile = Qopen (name, "wb"); cls.demofile = QFS_WOpen (name, 0);
} }
if (!cls.demofile) { if (!cls.demofile) {
Con_Printf ("ERROR: couldn't open.\n"); Con_Printf ("ERROR: couldn't open.\n");
@ -577,7 +576,7 @@ CL_Record (const char *argv1)
MSG_WriteByte (&buf, svc_serverdata); MSG_WriteByte (&buf, svc_serverdata);
MSG_WriteLong (&buf, PROTOCOL_VERSION); MSG_WriteLong (&buf, PROTOCOL_VERSION);
MSG_WriteLong (&buf, cl.servercount); MSG_WriteLong (&buf, cl.servercount);
MSG_WriteString (&buf, qfs_gamedir_file); MSG_WriteString (&buf, qfs_gamedir->gamedir);
if (cl.spectator) if (cl.spectator)
MSG_WriteByte (&buf, cl.playernum | 128); MSG_WriteByte (&buf, cl.playernum | 128);
@ -844,12 +843,12 @@ CL_ReRecord_f (void)
if (cls.demorecording) if (cls.demorecording)
CL_Stop_f (); CL_Stop_f ();
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path, Cmd_Argv (1)); snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
// open the demo file // open the demo file
QFS_DefaultExtension (name, ".qwd"); QFS_DefaultExtension (name, ".qwd");
cls.demofile = Qopen (name, "wb"); cls.demofile = QFS_WOpen (name, 0);
if (!cls.demofile) { if (!cls.demofile) {
Con_Printf ("ERROR: couldn't open.\n"); Con_Printf ("ERROR: couldn't open.\n");
return; return;

View file

@ -1072,13 +1072,11 @@ CL_Download_f (void)
} }
snprintf (cls.downloadname, sizeof (cls.downloadname), "%s/%s", snprintf (cls.downloadname, sizeof (cls.downloadname), "%s/%s",
qfs_gamedir_path, Cmd_Argv (1)); qfs_gamedir->dir.def, Cmd_Argv (1));
QFS_CreatePath (cls.downloadname);
strncpy (cls.downloadtempname, cls.downloadname, strncpy (cls.downloadtempname, cls.downloadname,
sizeof (cls.downloadtempname)); sizeof (cls.downloadtempname));
cls.download = Qopen (cls.downloadname, "wb"); cls.download = QFS_WOpen (cls.downloadname, 0);
if (cls.download) { if (cls.download) {
cls.downloadtype = dl_single; cls.downloadtype = dl_single;
@ -1413,10 +1411,9 @@ Host_WriteConfiguration (void)
QFile *f; QFile *f;
if (host_initialized && cl_writecfg->int_val) { if (host_initialized && cl_writecfg->int_val) {
char *path = va ("%s/config.cfg", qfs_gamedir_path); char *path = va ("%s/config.cfg", qfs_gamedir->dir.def);
QFS_CreatePath (path); f = QFS_WOpen (path, 0);
f = Qopen (path, "w");
if (!f) { if (!f) {
Con_Printf ("Couldn't write config.cfg.\n"); Con_Printf ("Couldn't write config.cfg.\n");
return; return;

View file

@ -324,7 +324,7 @@ Model_NextDownload (void)
"downloaded.\n\n", cl.model_name[i]); "downloaded.\n\n", cl.model_name[i]);
Con_Printf ("You may need to download or purchase a %s client " Con_Printf ("You may need to download or purchase a %s client "
"pack in order to play on this server.\n\n", "pack in order to play on this server.\n\n",
qfs_gamedir_file); qfs_gamedir->gamedir);
CL_Disconnect (); CL_Disconnect ();
return; return;
} }
@ -489,18 +489,14 @@ CL_ParseDownload (void)
} }
// open the file if not opened yet // open the file if not opened yet
if (!cls.download) { if (!cls.download) {
if (!qfs_gamedir->skinpath if (strncmp (cls.downloadtempname, "skins/", 6))
|| !*qfs_gamedir->skinpath snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.def,
|| strncmp (cls.downloadtempname, "skins/", 6))
snprintf (name, sizeof (name), "%s/%s", qfs_gamedir_path,
cls.downloadtempname); cls.downloadtempname);
else else
snprintf (name, sizeof (name), "%s/%s/%s", fs_userpath->string, snprintf (name, sizeof (name), "%s/%s", qfs_gamedir->dir.skins,
qfs_gamedir->skinpath, cls.downloadtempname); cls.downloadtempname + 6);
QFS_CreatePath (name); cls.download = QFS_WOpen (name, 0);
cls.download = Qopen (name, "wb");
if (!cls.download) { if (!cls.download) {
cls.downloadname[0] = 0; cls.downloadname[0] = 0;
net_message->readcount += size; net_message->readcount += size;
@ -532,20 +528,18 @@ CL_ParseDownload (void)
// rename the temp file to it's final name // rename the temp file to it's final name
if (strcmp (cls.downloadtempname, cls.downloadname)) { if (strcmp (cls.downloadtempname, cls.downloadname)) {
if (!qfs_gamedir->skinpath if (strncmp (cls.downloadtempname, "skins/", 6)) {
|| !*qfs_gamedir->skinpath snprintf (oldn, sizeof (oldn), "%s/%s", qfs_gamedir->dir.def,
|| strncmp (cls.downloadtempname, "skins/", 6)) {
snprintf (oldn, sizeof (oldn), "%s/%s", qfs_gamedir_path,
cls.downloadtempname); cls.downloadtempname);
snprintf (newn, sizeof (newn), "%s/%s", qfs_gamedir_path, snprintf (newn, sizeof (newn), "%s/%s", qfs_gamedir->dir.def,
cls.downloadname); cls.downloadname);
} else { } else {
snprintf (oldn, sizeof (oldn), "%s/%s/%s", fs_userpath->string, snprintf (oldn, sizeof (oldn), "%s/%s", qfs_gamedir->dir.skins,
qfs_gamedir->skinpath, cls.downloadtempname); cls.downloadtempname + 6);
snprintf (newn, sizeof (newn), "%s/%s/%s", fs_userpath->string, snprintf (newn, sizeof (newn), "%s/%s", qfs_gamedir->dir.skins,
qfs_gamedir->skinpath, cls.downloadname); cls.downloadname + 6);
} }
r = Qrename (oldn, newn); r = QFS_Rename (oldn, newn);
if (r) if (r)
Con_Printf ("failed to rename, %s.\n", strerror (errno)); Con_Printf ("failed to rename, %s.\n", strerror (errno));
} }
@ -679,7 +673,7 @@ CL_ParseServerData (void)
// game directory // game directory
str = MSG_ReadString (net_message); str = MSG_ReadString (net_message);
if (!strequal (qfs_gamedir_file, str)) { if (!strequal (qfs_gamedir->gamedir, str)) {
// save current config // save current config
Host_WriteConfiguration (); Host_WriteConfiguration ();
cflag = true; cflag = true;

View file

@ -46,9 +46,11 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <sys/stat.h> #include <sys/stat.h>
#include "QF/console.h" #include "QF/console.h"
#include "QF/dstring.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/quakefs.h" #include "QF/quakefs.h"
#include "QF/va.h"
#include "QF/zone.h" #include "QF/zone.h"
#include "compat.h" #include "compat.h"
@ -136,30 +138,22 @@ CF_GetFileSize (const char *path)
static void static void
CF_BuildQuota (void) CF_BuildQuota (void)
{ {
char *file, *path; static dstring_t *path;
struct dirent *i; struct dirent *i;
DIR *dir; DIR *dir;
path = Hunk_TempAlloc (strlen (qfs_gamedir_path) + 1 + strlen (CF_DIR) + 256 +
1);
if (!path) if (!path)
return; path = dstring_new ();
dsprintf (path, "%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, CF_DIR);
strcpy(path, qfs_gamedir_path); dir = opendir (path->str);
strcpy(path + strlen(path), "/");
strcpy(path + strlen(path), CF_DIR);
dir = opendir (path);
if (!dir) if (!dir)
return; return;
file = path + strlen(path);
cf_cursize = 0; cf_cursize = 0;
while ((i = readdir(dir))) { while ((i = readdir(dir))) {
strcpy (file, i->d_name); cf_cursize += CF_GetFileSize (va ("%s/%s", path->str, i->d_name));
cf_cursize += CF_GetFileSize (path);
} }
closedir (dir); closedir (dir);
} }
@ -207,7 +201,8 @@ CF_CloseAllFiles ()
int int
CF_Open (const char *path, const char *mode) CF_Open (const char *path, const char *mode)
{ {
char *fullpath, *j; char *j;
dstring_t *fullpath = dstring_new ();
int desc, oldsize, i; int desc, oldsize, i;
QFile *file; QFile *file;
@ -232,31 +227,25 @@ CF_Open (const char *path, const char *mode)
return -1; return -1;
} }
fullpath = malloc(strlen(qfs_gamedir_path) + 1 + strlen(CF_DIR) dsprintf (fullpath, "%s/%s/%s/%s", fs_userpath->string,
+ strlen(path) + 1); qfs_gamedir->dir.def, CF_DIR, path);
if (!fullpath) {
return -1;
}
strcpy(fullpath, qfs_gamedir_path); j = fullpath->str + strlen(fullpath->str) - strlen (path);
strcpy(fullpath + strlen(fullpath), "/");
strcpy(fullpath + strlen(fullpath), CF_DIR);
j = fullpath + strlen(fullpath);
for (i = 0; path[i]; i++, j++) // strcpy, but force lowercase for (i = 0; path[i]; i++, j++) // strcpy, but force lowercase
*j = tolower(path[i]); *j = tolower(path[i]);
*j = '\0'; *j = '\0';
if (CF_AlreadyOpen(fullpath, mode[0])) { if (CF_AlreadyOpen(fullpath->str, mode[0])) {
free (fullpath); dstring_delete (fullpath);
return -1; return -1;
} }
if (mode[0] == 'w') if (mode[0] == 'w')
oldsize = CF_GetFileSize (fullpath); oldsize = CF_GetFileSize (fullpath->str);
else else
oldsize = 0; oldsize = 0;
file = Qopen (fullpath, mode); file = Qopen (fullpath->str, mode);
if (file) { if (file) {
if (cf_openfiles >= cf_filepcount) { if (cf_openfiles >= cf_filepcount) {
cf_filepcount++; cf_filepcount++;
@ -269,7 +258,7 @@ CF_Open (const char *path, const char *mode)
for (desc = 0; cf_filep[desc].file; desc++) for (desc = 0; cf_filep[desc].file; desc++)
; ;
cf_filep[desc].path = fullpath; cf_filep[desc].path = fullpath->str;
cf_filep[desc].file = file; cf_filep[desc].file = file;
cf_filep[desc].buf = 0; cf_filep[desc].buf = 0;
cf_filep[desc].size = 0; cf_filep[desc].size = 0;

View file

@ -59,7 +59,7 @@ SV_Gamedir_f (void)
const char *dir; const char *dir;
if (Cmd_Argc () == 1) { if (Cmd_Argc () == 1) {
Con_Printf ("Current gamedir: %s\n", qfs_gamedir_file); Con_Printf ("Current gamedir: %s\n", qfs_gamedir->gamedir);
return; return;
} }

View file

@ -200,7 +200,6 @@ static void
SV_Fraglogfile_f (void) SV_Fraglogfile_f (void)
{ {
char name[MAX_OSPATH]; char name[MAX_OSPATH];
int i;
if (sv_fraglogfile) { if (sv_fraglogfile) {
SV_Printf ("Frag file logging off.\n"); SV_Printf ("Frag file logging off.\n");
@ -208,19 +207,7 @@ SV_Fraglogfile_f (void)
sv_fraglogfile = NULL; sv_fraglogfile = NULL;
return; return;
} }
// find an unused name if (!QFS_NextFilename (name, "frag_", ".log")) {
for (i = 0; i < 1000; i++) {
snprintf (name, sizeof (name), "%s/frag_%i.log", qfs_gamedir_path, i);
sv_fraglogfile = Qopen (name, "r");
if (!sv_fraglogfile) { // can't read it, so create this one
sv_fraglogfile = Qopen (name, "w");
if (!sv_fraglogfile)
i = 1000; // give error
break;
}
Qclose (sv_fraglogfile);
}
if (i == 1000) {
SV_Printf ("Can't open any logfiles.\n"); SV_Printf ("Can't open any logfiles.\n");
sv_fraglogfile = NULL; sv_fraglogfile = NULL;
return; return;
@ -1070,14 +1057,15 @@ SV_Snap (int uid)
snprintf (pcxname, sizeof (pcxname), "%d-00.pcx", uid); snprintf (pcxname, sizeof (pcxname), "%d-00.pcx", uid);
snprintf (checkname, sizeof (checkname), "%s/snap", qfs_gamedir_path); snprintf (checkname, sizeof (checkname), "%s/%s/snap", fs_userpath->string,
qfs_gamedir->dir.def);
QFS_CreatePath (va ("%s/dummy", checkname)); QFS_CreatePath (va ("%s/dummy", checkname));
for (i = 0; i <= 99; i++) { for (i = 0; i <= 99; i++) {
pcxname[strlen (pcxname) - 6] = i / 10 + '0'; pcxname[strlen (pcxname) - 6] = i / 10 + '0';
pcxname[strlen (pcxname) - 5] = i % 10 + '0'; pcxname[strlen (pcxname) - 5] = i % 10 + '0';
snprintf (checkname, sizeof (checkname), "%s/snap/%s", snprintf (checkname, sizeof (checkname), "%s/%s/snap/%s",
qfs_gamedir_path, pcxname); fs_userpath->string, qfs_gamedir->dir.def, pcxname);
if (Sys_FileTime (checkname) == -1) if (Sys_FileTime (checkname) == -1)
break; // file doesn't exist break; // file doesn't exist
} }

View file

@ -593,7 +593,7 @@ SV_Stop (int reason)
if (demo.disk) if (demo.disk)
Qclose (demo.file); Qclose (demo.file);
sprintf (path, "%s/%s/%s", qfs_gamedir_path, demo.path->str, demo.name->str); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, demo.path->str, demo.name->str);
unlink (path); unlink (path);
strcpy (path + strlen (path) - 3, "txt"); strcpy (path + strlen (path) - 3, "txt");
@ -1102,7 +1102,7 @@ SV_Record_f (void)
if (sv.demorecording) if (sv.demorecording)
SV_Stop_f (); SV_Stop_f ();
dsprintf (name, "%s/%s/%s%s%s", qfs_gamedir_path, sv_demoDir->string, dsprintf (name, "%s/%s/%s/%s%s%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string,
sv_demoPrefix->string, SV_CleanName (Cmd_Argv (1)), sv_demoPrefix->string, SV_CleanName (Cmd_Argv (1)),
sv_demoSuffix->string); sv_demoSuffix->string);
@ -1223,7 +1223,7 @@ SV_EasyRecord_f (void)
} }
// Make sure the filename doesn't contain illegal characters // Make sure the filename doesn't contain illegal characters
dsprintf (name2, "%s/%s/%s%s%s", qfs_gamedir_path, sv_demoDir->string, dsprintf (name2, "%s/%s/%s/%s%s%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string,
sv_demoPrefix->string, SV_CleanName (name->str), sv_demoPrefix->string, SV_CleanName (name->str),
sv_demoSuffix->string); sv_demoSuffix->string);
QFS_CreatePath (name2->str); QFS_CreatePath (name2->str);
@ -1266,8 +1266,8 @@ SV_DemoList_f (void)
dir_t dir; dir_t dir;
file_t *list; file_t *list;
Con_Printf ("content of %s/%s/ *.mvd\n", qfs_gamedir_path, sv_demoDir->string); Con_Printf ("content of %s/%s/%s/ *.mvd\n", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string);
dir = Sys_listdir (va ("%s/%s", qfs_gamedir_path, sv_demoDir->string), ".mvd"); dir = Sys_listdir (va ("%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string), ".mvd");
list = dir.files; list = dir.files;
if (!list->name[0]) { if (!list->name[0]) {
Con_Printf ("no demos\n"); Con_Printf ("no demos\n");
@ -1307,7 +1307,7 @@ SV_DemoNum (int num)
file_t *list; file_t *list;
dir_t dir; dir_t dir;
dir = Sys_listdir (va ("%s/%s", qfs_gamedir_path, sv_demoDir->string), ".mvd"); dir = Sys_listdir (va ("%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string), ".mvd");
list = dir.files; list = dir.files;
if (num <= 0) if (num <= 0)
@ -1376,7 +1376,7 @@ SV_DemoRemove_f (void)
ptr++; ptr++;
dir = dir =
Sys_listdir (va ("%s/%s", qfs_gamedir_path, sv_demoDir->string), ".mvd"); Sys_listdir (va ("%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string), ".mvd");
list = dir.files; list = dir.files;
for (i = 0; list->name[0]; list++) { for (i = 0; list->name[0]; list++) {
if (strstr (list->name, ptr)) { if (strstr (list->name, ptr)) {
@ -1384,7 +1384,7 @@ SV_DemoRemove_f (void)
SV_Stop_f (); SV_Stop_f ();
// stop recording first; // stop recording first;
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string,
list->name); list->name);
if (!unlink (path)) { if (!unlink (path)) {
Con_Printf ("removing %s...\n", list->name); Con_Printf ("removing %s...\n", list->name);
@ -1407,7 +1407,7 @@ SV_DemoRemove_f (void)
dsprintf (name, "%s", Cmd_Argv (1)); dsprintf (name, "%s", Cmd_Argv (1));
QFS_DefaultExtension (name->str, ".mvd"); QFS_DefaultExtension (name->str, ".mvd");
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, name->str); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string, name->str);
if (sv.demorecording && !strcmp (name->str, demo.name->str)) if (sv.demorecording && !strcmp (name->str, demo.name->str))
SV_Stop_f (); SV_Stop_f ();
@ -1459,7 +1459,7 @@ SV_DemoRemoveNum_f (void)
if (sv.demorecording && !strcmp (name, demo.name->str)) if (sv.demorecording && !strcmp (name, demo.name->str))
SV_Stop_f (); SV_Stop_f ();
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, name); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string, name);
if (!unlink (path)) { if (!unlink (path)) {
Con_Printf ("demo %s succesfully removed\n", name); Con_Printf ("demo %s succesfully removed\n", name);
/* /*
@ -1504,7 +1504,7 @@ SV_DemoInfoAdd_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, demo.path->str, sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, demo.path->str,
SV_DemoName2Txt (demo.name->str)); SV_DemoName2Txt (demo.name->str));
} else { } else {
name = SV_DemoTxTNum (atoi (Cmd_Argv (1))); name = SV_DemoTxTNum (atoi (Cmd_Argv (1)));
@ -1514,7 +1514,7 @@ SV_DemoInfoAdd_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, name); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string, name);
} }
if ((f = Qopen (path, "a+t")) == NULL) { if ((f = Qopen (path, "a+t")) == NULL) {
@ -1551,7 +1551,7 @@ SV_DemoInfoRemove_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, demo.path->str, sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, demo.path->str,
SV_DemoName2Txt (demo.name->str)); SV_DemoName2Txt (demo.name->str));
} else { } else {
name = SV_DemoTxTNum (atoi (Cmd_Argv (1))); name = SV_DemoTxTNum (atoi (Cmd_Argv (1)));
@ -1561,7 +1561,7 @@ SV_DemoInfoRemove_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, name); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string, name);
} }
if (unlink (path)) if (unlink (path))
@ -1589,7 +1589,7 @@ SV_DemoInfo_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, demo.path->str, sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, demo.path->str,
SV_DemoName2Txt (demo.name->str)); SV_DemoName2Txt (demo.name->str));
} else { } else {
name = SV_DemoTxTNum (atoi (Cmd_Argv (1))); name = SV_DemoTxTNum (atoi (Cmd_Argv (1)));
@ -1599,7 +1599,7 @@ SV_DemoInfo_f (void)
return; return;
} }
sprintf (path, "%s/%s/%s", qfs_gamedir_path, sv_demoDir->string, name); sprintf (path, "%s/%s/%s/%s", fs_userpath->string, qfs_gamedir->dir.def, sv_demoDir->string, name);
} }
if ((f = Qopen (path, "rt")) == NULL) { if ((f = Qopen (path, "rt")) == NULL) {

View file

@ -1536,7 +1536,8 @@ SV_WriteIP_f (void)
QFile *f; QFile *f;
const char *type; const char *type;
snprintf (name, sizeof (name), "%s/listip.cfg", qfs_gamedir_path); snprintf (name, sizeof (name), "%s/%s/listip.cfg", fs_userpath->string,
qfs_gamedir->dir.def);
SV_Printf ("Writing IP Filters to %s.\n", name); SV_Printf ("Writing IP Filters to %s.\n", name);

View file

@ -353,7 +353,8 @@ locs_loc (void)
if (!mapname) if (!mapname)
Sys_Error ("Can't duplicate mapname!"); Sys_Error ("Can't duplicate mapname!");
map_to_loc (cl.worldmodel->name,mapname); map_to_loc (cl.worldmodel->name,mapname);
snprintf (locfile, sizeof (locfile), "%s/%s", qfs_gamedir_path, mapname); snprintf (locfile, sizeof (locfile), "%s/%s/%s", fs_userpath->string,
qfs_gamedir->dir.def, mapname);
free(mapname); free(mapname);
if (strcasecmp (Cmd_Argv(1),"save") == 0) { if (strcasecmp (Cmd_Argv(1),"save") == 0) {