Exemple #1
0
/*
===========
FS_FOpenDemoFileWrite

===========
*/
qboolean FS_FOpenDemoFileWrite( const char *filename, fileHandleData_t *fh ) {
	
	char ospath[MAX_OSPATH];

	if ( !FS_Initialized() ) {
		Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
	}

	FS_BuildOSPathForThread( fs_homepath->string, filename, "", ospath, 0 );
	ospath[strlen(ospath)-1] = '\0';

	fh->zipFile = qfalse;

	if ( fs_debug->boolean ) {
		Com_Printf( "FS_SV_FOpenDemoFileWrite: %s\n", ospath );
	}

	if( FS_CreatePath( ospath ) ) {
		return qfalse;
	}

	fh->handleFiles.file.o = fopen( ospath, "wb" );

	Q_strncpyz( fh->name, filename, sizeof( fh->name ) );

	fh->handleSync = qfalse;
	if (!fh->handleFiles.file.o) {
		return qfalse;
	}
	fh->writebuffer = Z_Malloc(FS_DEMOWRITEBUF_SIZE);
	fh->bufferSize = FS_DEMOWRITEBUF_SIZE;
	return qtrue;
}
Exemple #2
0
void Log_AutoLogging_SaveMatch(void) {
	int error, num;
	FILE *f;
	char *dir, *tempname, savedname[2 * MAX_OSPATH], *fullsavedname, *exts[] = {"log", NULL};

	if (!temp_log_ready)
		return;

	temp_log_ready = false;

	dir = Log_LogDirectory();
	tempname = va("%s/%s", MT_TempDirectory(), TEMP_LOG_NAME);

	fullsavedname = va("%s/%s", dir, auto_matchname);
	if ((num = Util_Extend_Filename(fullsavedname, exts)) == -1) {
		Com_Printf("Error: no available filenames\n");
		return;
	}
	snprintf (savedname, sizeof(savedname), "%s_%03i.log", auto_matchname, num);

	fullsavedname = va("%s/%s", dir, savedname);

	
	if (!(f = fopen(tempname, "rb")))
		return;
	fclose(f);

	if ((error = rename(tempname, fullsavedname))) {
		FS_CreatePath(fullsavedname);
		error = rename(tempname, fullsavedname);
	}

	if (!error)
		Com_Printf("Match console log saved to %s\n", savedname);
}
Exemple #3
0
/*
 * Returns file size or -1 on error.
 */
int
FS_FOpenFileAppend(fsHandle_t *handle)
{
	char path[MAX_OSPATH];

	FS_CreatePath(handle->name);

	Com_sprintf(path, sizeof(path), "%s/%s", fs_gamedir, handle->name);

	handle->file = fopen(path, "ab");

	if (handle->file)
	{
		if (fs_debug->value)
		{
			Com_Printf("FS_FOpenFileAppend: '%s'.\n", path);
		}

		return FS_FileLength(handle->file);
	}

	if (fs_debug->value)
	{
		Com_Printf("FS_FOpenFileAppend: couldn't open '%s'.\n", path);
	}

	return -1;
}
Exemple #4
0
/*
 * Use ~/.quake2/dir as fs_gamedir.
 */
void
FS_AddHomeAsGameDirectory(char *dir)
{
	char *home;
	char gdir[MAX_OSPATH];
	size_t len;

	home = Sys_GetHomeDir();

	if (home == NULL)
	{
		return;
	}

    len = snprintf(gdir, sizeof(gdir), "%s%s/", home, dir);
	FS_CreatePath(gdir);

	if ((len > 0) && (len < sizeof(gdir)) && (gdir[len - 1] == '/'))
	{
		gdir[len - 1] = 0;
	}

	Q_strlcpy(fs_gamedir, gdir, sizeof(fs_gamedir));

	FS_AddGameDirectory(gdir);
}
/*
===========
FS_FOpenFileAppend

===========
*/
fileHandle_t FS_FOpenFileAppend( const char *filename ) {
	char			*ospath;
	fileHandle_t	f;

	if ( !fs_searchpaths ) {
		Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
	}

	f = FS_HandleForFile();
	fsh[f].zipFile = qfalse;

	Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) );

	// don't let sound stutter
	S_ClearSoundBuffer();

#ifdef _XBOX
	ospath = FS_BuildOSPath( filename );
#else
	ospath = FS_BuildOSPath( fs_basepath->string, fs_gamedir, filename );
#endif

	if ( fs_debug->integer ) {
		Com_Printf( "FS_FOpenFileAppend: %s\n", ospath );
	}

	FS_CreatePath( ospath );
	fsh[f].handleFiles.file.o = fopen( ospath, "ab" );
	fsh[f].handleSync = qfalse;
	if (!fsh[f].handleFiles.file.o) {
		f = 0;
	}
	return f;
}
Exemple #6
0
/*
 * Always returns 0 or -1 on error.
 */
int
FS_FOpenFileWrite(fsHandle_t *handle)
{
	char path[MAX_OSPATH];

	FS_CreatePath(handle->name);

	Com_sprintf(path, sizeof(path), "%s/%s", fs_gamedir, handle->name);

	if ((handle->file = fopen(path, "wb")) != NULL)
	{
		if (fs_debug->value)
		{
			Com_Printf("FS_FOpenFileWrite: '%s'.\n", path);
		}

		return 0;
	}

	if (fs_debug->value)
	{
		Com_Printf("FS_FOpenFileWrite: couldn't open '%s'.\n", path);
	}

	return -1;
}
Exemple #7
0
void Host_LockSession(void)
{
	if(locksession_run)
		return;
	locksession_run = true;
	if(locksession.integer != 0 && !COM_CheckParm("-readonly"))
	{
		char vabuf[1024];
		char *p = va(vabuf, sizeof(vabuf), "%slock%s", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string);
		FS_CreatePath(p);
		locksession_fh = FS_SysOpen(p, "wl", false);
		// TODO maybe write the pid into the lockfile, while we are at it? may help server management tools
		if(!locksession_fh)
		{
			if(locksession.integer == 2)
			{
				Con_Printf("WARNING: session lock %s could not be acquired. Please run with -sessionid and an unique session name. Continuing anyway.\n", p);
			}
			else
			{
				Sys_Error("session lock %s could not be acquired. Please run with -sessionid and an unique session name.\n", p);
			}
		}
	}
}
Exemple #8
0
/*
===========
FS_FOpenDemoFileWrite

===========
*/
fileHandle_t FS_FOpenDemoFileWrite( const char *filename ) {
	char *ospath;
	fileHandle_t	f;

	if ( !fs_searchpaths ) {
		Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
	}

	ospath = FS_BuildOSPath( fs_homepath->string, filename, "" );
	ospath[strlen(ospath)-1] = '\0';

	f = FS_HandleForDemoFile();
	demofsh[f].zipFile = qfalse;

	if ( fs_debug->boolean ) {
		Com_Printf( "FS_SV_FOpenDemoFileWrite: %s\n", ospath );
	}

	if( FS_CreatePath( ospath ) ) {
		return 0;
	}

	demofsh[f].handleFiles.file.o = fopen( ospath, "wb" );

	Q_strncpyz( demofsh[f].name, filename, sizeof( demofsh[f].name ) );

	demofsh[f].handleSync = qfalse;
	if (!demofsh[f].handleFiles.file.o) {
		f = 0;
	}
	return f;
}
Exemple #9
0
/*
==================
SV_GameMap_f

Saves the state of the map just being exited and goes to a new map.

If the initial character of the map string is '*', the next map is
in a new unit, so the current savegame directory is cleared of
map files.

Example:

*inter.cin+jail

Clears the archived maps, plays the inter.cin cinematic, then
goes to map jail.bsp.
==================
*/
void SV_GameMap_f (void)
{
	char		*map;
	int			i;
	client_t	*cl;
	qboolean	*savedInuse;

	if (Cmd_Argc() != 2)
	{
		Com_Printf ("USAGE: gamemap <map>\n");
		return;
	}

	Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1));

	FS_CreatePath (va("%s/save/current/", FS_Gamedir()));

	// check for clearing the current savegame
	map = Cmd_Argv(1);
	if (map[0] == '*')
	{
		// wipe all the *.sav files
		SV_WipeSavegame ("current");
	}
	else
	{	// save the map just exited
		if (sv.state == ss_game)
		{
			// clear all the client inuse flags before saving so that
			// when the level is re-entered, the clients will spawn
			// at spawn points instead of occupying body shells
			savedInuse = malloc(maxclients->value * sizeof(qboolean));
			for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
			{
				savedInuse[i] = cl->edict->inuse;
				cl->edict->inuse = false;
			}

			SV_WriteLevelFile ();

			// we must restore these for clients to transfer over correctly
			for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
				cl->edict->inuse = savedInuse[i];
			free (savedInuse);
		}
	}

	// start up the next map
	SV_Map (false, Cmd_Argv(1), false );

	// archive server state
	strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1);

	// copy off the level to the autosave slot
	if (!dedicated->value)
	{
		SV_WriteServerFile (true);
		SV_CopySaveGame ("current", "save0");
	}
}
Exemple #10
0
/*
=======================================================================================================================================
DL_BeginDownload

Inspired from http://www.w3.org/Library/Examples/LoadToFile.c, setup the download, return once we have a connection.
=======================================================================================================================================
*/
int DL_BeginDownload(char *localName, const char *remoteName) {
	char referer[MAX_STRING_CHARS + 5 /*"ET://"*/];

	if (dl_request) {
		Com_Printf(S_COLOR_RED "DL_BeginDownload: Error - called with a download request already active\n");
		return 0;
	}

	if (!localName[0] || !remoteName[0]) {
		Com_Printf(S_COLOR_RED "DL_BeginDownload: Error - empty download URL or empty local file name\n");
		return 0;
	}

	if (FS_CreatePath(localName)) {
		Com_Printf(S_COLOR_RED "DL_BeginDownload: Error - unable to create directory(%s).\n", localName);
		return 0;
	}

	dl_file = fopen(localName, "wb + ");

	if (!dl_file) {
		Com_Printf(S_COLOR_RED  "DL_BeginDownload: Error - unable to open '%s' for writing\n", localName);
		return 0;
	}

	DL_InitDownload();
	// ET://ip:port
	strcpy(referer, "ET://");
	Q_strncpyz(referer + 5, Cvar_VariableString("cl_currentServerIP"), MAX_STRING_CHARS);

	dl_request = curl_easy_init();
	curl_easy_setopt(dl_request, CURLOPT_USERAGENT, va("%s %s", APP_NAME "/" APP_VERSION, curl_version()));
	curl_easy_setopt(dl_request, CURLOPT_REFERER, referer);
	curl_easy_setopt(dl_request, CURLOPT_URL, remoteName);
	curl_easy_setopt(dl_request, CURLOPT_WRITEFUNCTION, DL_cb_FWriteFile);
	curl_easy_setopt(dl_request, CURLOPT_WRITEDATA, (void *)dl_file);
	curl_easy_setopt(dl_request, CURLOPT_PROGRESSFUNCTION, DL_cb_Progress);
	curl_easy_setopt(dl_request, CURLOPT_NOPROGRESS, 0);
	curl_easy_setopt(dl_request, CURLOPT_FAILONERROR, 1);
	curl_easy_setopt(dl_request, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(dl_request, CURLOPT_MAXREDIRS, 5);
#ifdef FEATURE_OPENSSL
#if 0
	curl_easy_setopt(dl_request, CURLOPT_CAINFO, "./cert.crt");
#else
	curl_easy_setopt(dl_request, CURLOPT_SSL_VERIFYHOST, 0);
	curl_easy_setopt(dl_request, CURLOPT_SSL_VERIFYPEER, 0);
#endif
#endif
	if (curl_multi_add_handle(dl_multi, dl_request) != CURLM_OK) {
		Com_Printf(S_COLOR_RED "DL_BeginDownload: Error - invalid handle.\n");
	}

	Cvar_Set("cl_downloadName", remoteName);

	return 1;
}
Exemple #11
0
void
FS_InitFilesystem(void)
{
	/* Register FS commands. */
	Cmd_AddCommand("path", FS_Path_f);
	Cmd_AddCommand("link", FS_Link_f);
	Cmd_AddCommand("dir", FS_Dir_f);

	/* basedir <path> Allows the game to run from outside the data tree.  */
	fs_basedir = Cvar_Get("basedir",
#ifdef SYSTEMWIDE
		SYSTEMDIR,
#else
		".",
#endif
		CVAR_NOSET);

	/* cddir <path> Logically concatenates the cddir after the basedir to
	   allow the game to run from outside the data tree. */
	fs_cddir = Cvar_Get("cddir", "", CVAR_NOSET);

	if (fs_cddir->string[0] != '\0')
	{
		FS_AddGameDirectory(va("%s/" BASEDIRNAME, fs_cddir->string));
	}

	/* Debug flag. */
	fs_debug = Cvar_Get("fs_debug", "0", 0);

	/* Game directory. */
	fs_gamedirvar = Cvar_Get("game", "", CVAR_LATCH | CVAR_SERVERINFO);

	/* Current directory. */
	fs_homepath = Cvar_Get("homepath", Sys_GetCurrentDirectory(), CVAR_NOSET);

	/* Add baseq2 to search path. */
	FS_AddGameDirectory(va("%s/" BASEDIRNAME, fs_basedir->string));
	FS_AddBinaryDirAsGameDirectory(BASEDIRNAME);
	FS_AddHomeAsGameDirectory(BASEDIRNAME);

	/* Any set gamedirs will be freed up to here. */
	fs_baseSearchPaths = fs_searchPaths;
	Q_strlcpy(fs_currentGame, BASEDIRNAME, sizeof(fs_currentGame));

	/* Check for game override. */
	if (fs_gamedirvar->string[0] != '\0')
	{
		FS_SetGamedir(fs_gamedirvar->string);
	}

	/* Create directory if it does not exist. */
	FS_CreatePath(fs_gamedir);

	Com_Printf("Using '%s' for writing.\n", fs_gamedir);
}
Exemple #12
0
/*
================
SV_CopySaveGame
================
*/
void SV_CopySaveGame (char *src, char *dst)
{
	char	name[MAX_OSPATH], name2[MAX_OSPATH];
	int		l, len;
	char	*found;

	Com_DPrintf("SV_CopySaveGame(%s, %s)\n", src, dst);

	SV_WipeSavegame (dst);

	// copy the savegame over
	Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), src);
	Com_sprintf (name2, sizeof(name2), "%s/save/%s/server.ssv", FS_Gamedir(), dst);
	FS_CreatePath (name2);
	CopyFile (name, name2);

	Com_sprintf (name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), src);
	Com_sprintf (name2, sizeof(name2), "%s/save/%s/game.ssv", FS_Gamedir(), dst);
	CopyFile (name, name2);

	// Knightmare- copy screenshot
	if (strcmp(dst, "kmq2save0")) // no screenshot for start of level autosaves
	{
		Com_sprintf (name, sizeof(name), "%s/save/%s/shot.jpg", FS_Gamedir(), src);
		Com_sprintf (name2, sizeof(name2), "%s/save/%s/shot.jpg", FS_Gamedir(), dst);
		CopyFile (name, name2);
	}

	Com_sprintf (name, sizeof(name), "%s/save/%s/", FS_Gamedir(), src);
	len = strlen(name);
	Com_sprintf (name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), src);
	found = Sys_FindFirst(name, 0, 0 );
	while (found)
	{
	//	strncpy (name+len, found+len);
		Q_strncpyz (name+len, found+len, sizeof(name)-len);
		Com_sprintf (name2, sizeof(name2), "%s/save/%s/%s", FS_Gamedir(), dst, found+len);
		CopyFile (name, name2);

		// change sav to sv2
		l = strlen(name);
	//	strncpy (name+l-3, "sv2");
		Q_strncpyz (name+l-3, "sv2", sizeof(name)-l+3);
		l = strlen(name2);
	//	strncpy (name2+l-3, "sv2");
		Q_strncpyz (name2+l-3, "sv2", sizeof(name2)-l+3);
		CopyFile (name, name2);

		found = Sys_FindNext( 0, 0 );
	}
	Sys_FindClose ();
}
Exemple #13
0
/*
==============
Sys_ErrorDialog

Display an error message
==============
*/
void Sys_ErrorDialog( const char *error )
{
	char         buffer[ 1024 ];
	unsigned int size;
	int          f;
	const char   *homepath = Cvar_VariableString( "fs_homepath" );
	const char   *gamedir = Cvar_VariableString( "fs_game" );
	const char   *fileName = "crashlog.txt";
	char         *ospath = FS_BuildOSPath( homepath, gamedir, fileName );

	Sys_Print( va( "%s\n", error ) );

#ifndef DEDICATED
	// We may have grabbed input devices. Need to release.
	if ( SDL_WasInit( SDL_INIT_VIDEO ) )
	{
		SDL_WM_GrabInput( SDL_GRAB_OFF );
	}

	Sys_Dialog( DT_ERROR, va( "%s. See \"%s\" for details.", error, ospath ), "Error" );
#endif

	// Make sure the write path for the crashlog exists...
	if ( FS_CreatePath( ospath ) )
	{
		Com_Printf( "ERROR: couldn't create path '%s' for crash log.\n", ospath );
		return;
	}

	// We might be crashing because we maxed out the Quake MAX_FILE_HANDLES,
	// which will come through here, so we don't want to recurse forever by
	// calling FS_FOpenFileWrite()...use the Unix system APIs instead.
	f = open( ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640 );

	if ( f == -1 )
	{
		Com_Printf( "ERROR: couldn't open %s\n", fileName );
		return;
	}

	// We're crashing, so we don't care much if write() or close() fails.
	while ( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 )
	{
		if ( write( f, buffer, size ) != size )
		{
			Com_Printf( "ERROR: couldn't fully write to %s\n", fileName );
			break;
		}
	}

	close( f );
}
Exemple #14
0
void screenshotJPEG(char *filename, qbyte *screendata, int screenwidth, int screenheight)	//input is rgb NOT rgba
{
	qbyte	*buffer;
	vfsfile_t	*outfile;
	jpeg_error_mgr_wrapper jerr;
	struct jpeg_compress_struct cinfo;
	JSAMPROW row_pointer[1];

	if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
	{
		FS_CreatePath (filename, FS_GAME);
		if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
		{
			Con_Printf("Error opening %s\n", filename);
			return;
		}
	}

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = jpeg_error_exit;
	if (setjmp(jerr.setjmp_buffer))
	{
		jpeg_destroy_compress(&cinfo);
		VFS_CLOSE(outfile);
		FS_Remove(filename, FS_GAME);
		Con_Printf("Failed to create jpeg\n");
		return;
	}
	jpeg_create_compress(&cinfo);

	buffer = screendata;
	
	jpeg_mem_dest(&cinfo, outfile);
	cinfo.image_width = screenwidth; 	
	cinfo.image_height = screenheight;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality (&cinfo, 75/*bound(0, (int) gl_image_jpeg_quality_level.value, 100)*/, true);
	jpeg_start_compress(&cinfo, true);

	while (cinfo.next_scanline < cinfo.image_height)
	{
	    *row_pointer = &buffer[(cinfo.image_height - cinfo.next_scanline - 1) * cinfo.image_width * 3];
	    jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	VFS_CLOSE(outfile);
	jpeg_destroy_compress(&cinfo);
}
Exemple #15
0
void Log_AutoLogging_StartMatch(char *logname) {
	char extendedname[MAX_OSPATH * 2], *fullname;
	FILE *templog;
	void *buf;

	temp_log_ready = false;

	if (!match_auto_logconsole.value)
		return;

	if (Log_IsLogging()) {
		if (autologging) {		
			
			autologging = false;
			Log_Stop();
		} else {
			Com_Printf("Auto console logging skipped (already logging)\n");
			return;
		}
	}


	strlcpy(auto_matchname, logname, sizeof(auto_matchname));

	strlcpy (extendedname, TEMP_LOG_NAME, sizeof(extendedname));
	COM_ForceExtensionEx (extendedname, ".log", sizeof (extendedname));
	fullname = va("%s/%s", MT_TempDirectory(), extendedname);


	if (!(templog = fopen (fullname, log_readable.value ? "w" : "wb"))) {
		FS_CreatePath(fullname);
		if (!(templog = fopen (fullname, log_readable.value ? "w" : "wb"))) {
			Com_Printf("Error: Couldn't open %s\n", fullname);
			return;
		}
	}

	buf = Q_calloc(1, LOGFILEBUFFER);
	if (!buf) {
		Com_Printf("Not enough memory to allocate log buffer\n");
		return;
	}
	memlogfile = FSMMAP_OpenVFS(buf, LOGFILEBUFFER);

	Com_Printf ("Auto console logging commenced\n");

	logfile = templog;
	autologging = true;
	auto_starttime = cls.realtime;
}
Exemple #16
0
void
SV_CopySaveGame(char *src, char *dst)
{
	char name[MAX_OSPATH], name2[MAX_OSPATH];
	size_t l, len;
	char *found;

	Com_DPrintf("SV_CopySaveGame(%s, %s)\n", src, dst);

	SV_WipeSavegame(dst);

	/* copy the savegame over */
	Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), src);
	Com_sprintf(name2, sizeof(name2), "%s/save/%s/server.ssv", FS_Gamedir(), dst);
	FS_CreatePath(name2);
	CopyFile(name, name2);

	Com_sprintf(name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), src);
	Com_sprintf(name2, sizeof(name2), "%s/save/%s/game.ssv", FS_Gamedir(), dst);
	CopyFile(name, name2);

	Com_sprintf(name, sizeof(name), "%s/save/%s/", FS_Gamedir(), src);
	len = strlen(name);
	Com_sprintf(name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), src);
	found = Sys_FindFirst(name, 0, 0);

	while (found)
	{
		strcpy(name + len, found + len);

		Com_sprintf(name2, sizeof(name2), "%s/save/%s/%s",
					FS_Gamedir(), dst, found + len);
		CopyFile(name, name2);

		/* change sav to sv2 */
		l = strlen(name);
		strcpy(name + l - 3, "sv2");
		l = strlen(name2);
		strcpy(name2 + l - 3, "sv2");
		CopyFile(name, name2);

		found = Sys_FindNext(0, 0);
	}

	Sys_FindClose();
}
Exemple #17
0
void Log_AutoLogging_SaveMatch(qbool allow_upload) {
	int error, num;
	FILE *f;
	char *dir, *tempname, savedname[2 * MAX_OSPATH], *fullsavedname, *exts[] = {"log", NULL};

	if (!temp_log_ready)
		return;

	if (temp_log_upload_pending) {
		Com_Printf("Error: Can't save the log. Log upload is still pending.\n");
		return;
	}

	temp_log_ready = false;

	dir = Log_LogDirectory();
	tempname = va("%s/%s", MT_TempDirectory(), TEMP_LOG_NAME);

	fullsavedname = va("%s/%s", dir, auto_matchname);
	if ((num = Util_Extend_Filename(fullsavedname, exts)) == -1) {
		Com_Printf("Error: no available filenames\n");
		return;
	}
	snprintf (savedname, sizeof(savedname), "%s_%03i.log", auto_matchname, num);

	fullsavedname = va("%s/%s", dir, savedname);

	
	if (!(f = fopen(tempname, "rb")))
		return;
	fclose(f);

	if ((error = rename(tempname, fullsavedname))) {
		FS_CreatePath(fullsavedname);
		error = rename(tempname, fullsavedname);
	}

	if (!error) {
		Com_Printf("Match console log saved to %s\n", savedname);
		if (allow_upload && Log_IsUploadAllowed()) {
			// note: we allow the client to be a spectator, so that spectators
			// can submit logs for matches they spec in case players don't do it
			Log_AutoLogging_Upload(fullsavedname);
		}
	}
}
Exemple #18
0
bool MakeDir(std::string destdir, std::string basegame)
{
    std::string destpath(destdir);

    if ( basegame != "" )
    {
        destpath += '/';
        destpath += basegame;
    }

    if ( *destpath.rbegin() != '/' )
        destpath += '/'; // XXX FS_CreatePath requires a trailing slash. 
        // Maybe the assumption is that a file listing might be included?

    FS_CreatePath(destpath.c_str());
    return true;
}
Exemple #19
0
static int copy_file(const char *src, const char *dst, const char *name)
{
    char    path[MAX_OSPATH];
    byte    buf[0x10000];
    FILE    *ifp, *ofp;
    size_t  len, res;
    int     ret = -1;

    len = Q_snprintf(path, MAX_OSPATH, "%s/save/%s/%s", fs_gamedir, src, name);
    if (len >= MAX_OSPATH)
        goto fail0;

    ifp = fopen(path, "rb");
    if (!ifp)
        goto fail0;

    len = Q_snprintf(path, MAX_OSPATH, "%s/save/%s/%s", fs_gamedir, dst, name);
    if (len >= MAX_OSPATH)
        goto fail1;

    if (FS_CreatePath(path))
        goto fail1;

    ofp = fopen(path, "wb");
    if (!ofp)
        goto fail1;

    do {
        len = fread(buf, 1, sizeof(buf), ifp);
        res = fwrite(buf, 1, len, ofp);
    } while (len == sizeof(buf) && res == len);

    if (ferror(ifp))
        goto fail2;

    if (ferror(ofp))
        goto fail2;

    ret = 0;
fail2:
    fclose(ofp);
fail1:
    fclose(ifp);
fail0:
    return ret;
}
/*
===============
inspired from http://www.w3.org/Library/Examples/LoadToFile.c
setup the download, return once we have a connection
===============
*/
int DL_BeginDownload( const char *localName, const char *remoteName, int debug )
{
	char referer[ MAX_STRING_CHARS + URI_SCHEME_LENGTH ];

	if ( dl_request )
	{
		Com_Printf( "ERROR: DL_BeginDownload called with a download request already active\n" );
		return 0;
	}

	if ( !localName || !remoteName )
	{
		Com_DPrintf( "Empty download URL or empty local file name\n" );
		return 0;
	}

	FS_CreatePath( localName );
	dl_file = fopen( localName, "wb+" );

	if ( !dl_file )
	{
		Com_Printf( "ERROR: DL_BeginDownload unable to open '%s' for writing\n", localName );
		return 0;
	}

	DL_InitDownload();

	strcpy( referer, URI_SCHEME );
	Q_strncpyz( referer + URI_SCHEME_LENGTH, Cvar_VariableString( "cl_currentServerIP" ), MAX_STRING_CHARS );

	dl_request = curl_easy_init();
	curl_easy_setopt( dl_request, CURLOPT_USERAGENT, va( "%s %s", PRODUCT_NAME "/" PRODUCT_VERSION, curl_version() ) );
	curl_easy_setopt( dl_request, CURLOPT_REFERER, referer );
	curl_easy_setopt( dl_request, CURLOPT_URL, remoteName );
	curl_easy_setopt( dl_request, CURLOPT_WRITEFUNCTION, DL_cb_FWriteFile );
	curl_easy_setopt( dl_request, CURLOPT_WRITEDATA, ( void * ) dl_file );
	curl_easy_setopt( dl_request, CURLOPT_PROGRESSFUNCTION, DL_cb_Progress );
	curl_easy_setopt( dl_request, CURLOPT_NOPROGRESS, 0 );
	curl_easy_setopt( dl_request, CURLOPT_FAILONERROR, 1 );

	curl_multi_add_handle( dl_multi, dl_request );

	Cvar_Set( "cl_downloadName", remoteName );

	return 1;
}
void DumpHUD(const char *name)
{
	// Dumps all variables from CFG_GROUP_HUD into a file
	extern cvar_t scr_newHud;

	FILE *f;
	int max_width = 0, i = 0, j;
	char *outfile, *spaces;
	cvar_t *var;
	cvar_t *sorted[MAX_DUMPED_CVARS];

	outfile = va("%s/ezquake/configs/%s", com_basedir, name);
	if (!(f	= fopen	(outfile, "w"))) {
		FS_CreatePath(outfile);
		if (!(f	= fopen	(outfile, "w"))) {
			Com_Printf ("Couldn't write	%s.\n",	name);
			return;
		}
	}

	fprintf(f, "//\n");
	fprintf(f, "// Head Up Display Configuration Dump\n");
	fprintf(f, "//\n\n");

	for(var = cvar_vars; var; var = var->next)
		if(var->group && !strcmp(var->group->name, CVAR_GROUP_HUD)) {
			max_width = max(max_width, strlen(var->name));
			sorted[i++] = var;
		}

	max_width++;
	qsort(sorted, i, sizeof(cvar_t *), Cvar_CvarCompare);

	spaces = CreateSpaces(max_width - strlen(scr_newHud.name));
	fprintf(f, "%s%s\"%d\"\n", scr_newHud.name, spaces, scr_newHud.integer);

	for(j = 0; j < i; j++) {
		spaces = CreateSpaces(max_width - strlen(sorted[j]->name));
		fprintf(f, "%s%s\"%s\"\n", sorted[j]->name, spaces, sorted[j]->string);
	}

	fprintf(f, "hud_recalculate\n");

	fclose(f);
}
Exemple #22
0
//FIXME: this is bad, loads entire file for just 8 bytes!
qboolean GetWalInfo (const char *name, int *width, int *height)
{
		miptex_t	mt;
		qboolean	closeFile;
		FILE		*h;

		FS_FOpenFile (name, &h, HANDLE_OPEN, &closeFile);
		if (!h)
			return false;

		/*if (fread (&mt, sizeof(mt), 1, h) != 1)
		{
			ri.FS_FCloseFile (h);
			return false;
		}*/
		FS_Read (&mt, sizeof(mt), h);

		if (closeFile)
			FS_FCloseFile (h);
		
		*width = LittleLong(mt.width);
		*height = LittleLong(mt.height);

#if defined(_DEBUG) && !defined(EMSCRIPTEN)
		int		i;
		char	grey = 8;

		FS_CreatePath (va("wals/%s", name));
		h = fopen (va("wals/%s", name), "wb");
		fwrite (&mt, 1, sizeof(mt), h);
		for (i = 0; i < mt.width * mt.height; i++)
			fwrite (&grey, 1, 1, h);
		for (i = 0; i < (mt.width * mt.height) / 2; i++)
			fwrite (&grey, 1, 1, h);
		for (i = 0; i < (mt.width * mt.height) / 4; i++)
			fwrite (&grey, 1, 1, h);
		for (i = 0; i < (mt.width * mt.height) / 8; i++)
			fwrite (&grey, 1, 1, h);
		fclose (h);
#endif

		return true;
}
Exemple #23
0
/*
=================
Sys_WritePIDFile

Return qtrue if there is an existing stale PID file
=================
*/
static qboolean Sys_WritePIDFile( const char *gamedir )
{
	char      *pidFile = Sys_PIDFileName( gamedir );
	FILE      *f;
	qboolean  stale = qfalse;

	if( pidFile == NULL )
		return qfalse;

	// First, check if the pid file is already there
	if( ( f = fopen( pidFile, "r" ) ) != NULL )
	{
		char  pidBuffer[ 64 ] = { 0 };
		int   pid;

		pid = fread( pidBuffer, sizeof( char ), sizeof( pidBuffer ) - 1, f );
		fclose( f );

		if(pid > 0)
		{
			pid = atoi( pidBuffer );
			if( !Sys_PIDIsRunning( pid ) )
				stale = qtrue;
		}
		else
			stale = qtrue;
	}

	if( FS_CreatePath( pidFile ) ) {
		return 0;
	}

	if( ( f = fopen( pidFile, "w" ) ) != NULL )
	{
		fprintf( f, "%d", Sys_PID( ) );
		fclose( f );
	}
	else
		Com_Printf( S_COLOR_YELLOW "Couldn't write %s.\n", pidFile );

	return stale;
}
Exemple #24
0
void SV_Snap (int uid) {
	client_t *cl;
	char pcxname[80], checkname[MAX_OSPATH];
	int i;
	FILE *f;

	for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
		if (cl->state < cs_connected)
			continue;
		if (cl->userid == uid)
			break;
	}
	if (i >= MAX_CLIENTS) {
		Com_Printf ("userid not found\n");
		return;
	}

	FS_CreatePath (va("%s/snap/", com_gamedir));
	snprintf (pcxname, sizeof (pcxname), "%d-00.pcx", uid);
		
	for (i = 0; i <= 99; i++) { 
		pcxname[strlen(pcxname) - 6] = i / 10 + '0'; 
		pcxname[strlen(pcxname) - 5] = i % 10 + '0'; 
		snprintf (checkname, sizeof(checkname), "%s/snap/%s", com_gamedir, pcxname);
		if (!(f = fopen (checkname, "rb")))
			break;  // file doesn't exist
		fclose (f);
	} 
	if (i == 100) {
		Com_Printf ("Snap: Couldn't create a file, clean some out.\n"); 
		return;
	}
	strlcpy (cl->uploadfn, checkname, sizeof (cl->uploadfn));

	memcpy(&cl->snap_from, &net_from, sizeof(net_from));
	cl->remote_snap  =  (sv_redirected != RD_NONE);

	ClientReliableWrite_Begin (cl, svc_stufftext, 24);
	ClientReliableWrite_String (cl, "cmd snap\n");
	Com_Printf ("Requesting snap from user %d...\n", uid);
}
Exemple #25
0
void CL_ParseDownload (qboolean dataIsCompressed)
{
	int		size, percent;
	char	name[MAX_OSPATH];

	// read the data
	size = MSG_ReadShort (&net_message);
	percent = MSG_ReadByte (&net_message);

	if (size < 0)
	{
		if (size == -1)
			Com_Printf ("Server does not have this file.\n", LOG_CLIENT);
		else
			Com_Printf ("Bad download data from server.\n", LOG_CLIENT);

		//r1: nuke the temp filename
		cls.downloadtempname[0] = 0;
		cls.downloadname[0] = 0;
		cls.failed_download = true;

		if (cls.download)
		{
			// if here, we tried to resume a file but the server said no
			fclose (cls.download);
			cls.download = NULL;
		}

		cls.downloadpending = false;
		CL_RequestNextDownload ();
		return;
	}

	// open the file if not opened yet
	if (!cls.download)
	{
		if (!cls.downloadtempname[0])
		{
			Com_Printf ("Received download packet without request. Ignored.\n", LOG_CLIENT);
			net_message.readcount += size;
			return;
		}
		CL_DownloadFileName(name, sizeof(name), cls.downloadtempname);

		FS_CreatePath (name);

		cls.download = fopen (name, "wb");
		if (!cls.download)
		{
			net_message.readcount += size;
			Com_Printf ("Failed to open %s\n", LOG_CLIENT, cls.downloadtempname);
			cls.downloadpending = false;
			CL_RequestNextDownload ();
			return;
		}
	}

	//r1: downloading something, drop to console to show status bar
	SCR_EndLoadingPlaque();

	//r1: if we're stuck with udp, may as well make best use of the bandwidth...
	if (dataIsCompressed)
	{
#ifndef NO_ZLIB
		uint16		uncompressedLen;
		byte		uncompressed[0xFFFF];

		uncompressedLen = (uint16)MSG_ReadShort (&net_message);

		if (!uncompressedLen)
			Com_Error (ERR_DROP, "uncompressedLen == 0");

		ZLibDecompress (net_message_buffer + net_message.readcount, size, uncompressed, uncompressedLen, -15);
		fwrite (uncompressed, 1, uncompressedLen, cls.download);
		Com_DPrintf ("svc_zdownload(%s): %d -> %d\n", cls.downloadname, size, uncompressedLen);
#else
		Com_Error (ERR_DROP, "Received a unrequested compressed download");
#endif
	}
	else
	{
		fwrite (net_message_buffer + net_message.readcount, 1, size, cls.download);
	}

	net_message.readcount += size;

	if (percent != 100)
	{
		cls.downloadpercent = percent;

		MSG_WriteByte (clc_stringcmd);
		MSG_Print ("nextdl");
		MSG_EndWriting (&cls.netchan.message);
		send_packet_now = true;
	}
	else
	{
		CL_FinishDownload ();

		// get another file if needed
		CL_RequestNextDownload ();
	}
}
Exemple #26
0
/*
===============
CL_StartHTTPDownload

Actually starts a download by adding it to the curl multi
handle.
===============
*/
static void CL_StartHTTPDownload (dlqueue_t *entry, dlhandle_t *dl)
{
	size_t		len;
	char		tempFile[MAX_OSPATH];
	char		escapedFilePath[MAX_QPATH*4];
	
	//yet another hack to accomodate filelists, how i wish i could push :(
	//NULL file handle indicates filelist.
	len = strlen (entry->quakePath);
	if (len > 9 && !strcmp (entry->quakePath + len - 9, ".filelist"))
	{
		dl->file = NULL;
		CL_EscapeHTTPPath (entry->quakePath, escapedFilePath);
	}
	else
	{
		CL_HTTP_Reset_KBps_counter ();	// Knightmare- for KB/s counter

		Com_sprintf (dl->filePath, sizeof(dl->filePath), "%s/%s", FS_Gamedir(), entry->quakePath);

		Com_sprintf (tempFile, sizeof(tempFile), "%s/%s", cl.gamedir, entry->quakePath);
		CL_EscapeHTTPPath (dl->filePath, escapedFilePath);

	//	strncat (dl->filePath, ".tmp");
		Q_strncatz (dl->filePath, ".tmp", sizeof(dl->filePath));

		FS_CreatePath (dl->filePath);

		//don't bother with http resume... too annoying if server doesn't support it.
		dl->file = fopen (dl->filePath, "wb");
		if (!dl->file)
		{
			Com_Printf ("CL_StartHTTPDownload: Couldn't open %s for writing.\n", dl->filePath);
			entry->state = DLQ_STATE_DONE;
			//CL_RemoveHTTPDownload (entry->quakePath);
			return;
		}
	}

	dl->tempBuffer = NULL;
	dl->speed = 0;
	dl->fileSize = 0;
	dl->position = 0;
	dl->queueEntry = entry;

	if (!dl->curl)
		dl->curl = curl_easy_init ();

	Com_sprintf (dl->URL, sizeof(dl->URL), "%s%s", cls.downloadServer, escapedFilePath);

	curl_easy_setopt (dl->curl, CURLOPT_ENCODING, "");
	//curl_easy_setopt (dl->curl, CURLOPT_DEBUGFUNCTION, CL_CURL_Debug);
	//curl_easy_setopt (dl->curl, CURLOPT_VERBOSE, 1);
	curl_easy_setopt (dl->curl, CURLOPT_NOPROGRESS, 0);
	if (dl->file)
	{
		curl_easy_setopt (dl->curl, CURLOPT_WRITEDATA, dl->file);
		curl_easy_setopt (dl->curl, CURLOPT_WRITEFUNCTION, NULL);
	}
	else
	{
		curl_easy_setopt (dl->curl, CURLOPT_WRITEDATA, dl);
		curl_easy_setopt (dl->curl, CURLOPT_WRITEFUNCTION, CL_HTTP_Recv);
	}
	curl_easy_setopt (dl->curl, CURLOPT_PROXY, cl_http_proxy->string);
	curl_easy_setopt (dl->curl, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt (dl->curl, CURLOPT_MAXREDIRS, 5);
	curl_easy_setopt (dl->curl, CURLOPT_WRITEHEADER, dl);
	curl_easy_setopt (dl->curl, CURLOPT_HEADERFUNCTION, CL_HTTP_Header);
	curl_easy_setopt (dl->curl, CURLOPT_PROGRESSFUNCTION, CL_HTTP_Progress);
	curl_easy_setopt (dl->curl, CURLOPT_PROGRESSDATA, dl);
	curl_easy_setopt (dl->curl, CURLOPT_USERAGENT, Cvar_VariableString ("version"));
	curl_easy_setopt (dl->curl, CURLOPT_REFERER, cls.downloadReferer);
	curl_easy_setopt (dl->curl, CURLOPT_URL, dl->URL);

	if (curl_multi_add_handle (multi, dl->curl) != CURLM_OK)
	{
		Com_Printf ("curl_multi_add_handle: error\n");
		dl->queueEntry->state = DLQ_STATE_DONE;
		return;
	}

	handleCount++;
	//Com_Printf ("started dl: hc = %d\n", LOG_GENERAL, handleCount);
	Com_DPrintf  ("CL_StartHTTPDownload: Fetching %s...\n", dl->URL);
	dl->queueEntry->state = DLQ_STATE_RUNNING;
}
Exemple #27
0
/*
===============
inspired from http://www.w3.org/Library/Examples/LoadToFile.c
setup the download, return once we have a connection
===============
*/
int DL_BeginDownload( const char *localName, const char *remoteName, int debug )
{
	char *access = NULL;
	char *url = NULL;
	char *login = NULL;
	char *path = NULL;
	char *ptr = NULL;

	if ( dl_running )
	{
		Com_Printf(_( "ERROR: DL_BeginDownload called with a download request already active\n" ));
		return 0;
	}

	terminate_status = HT_UNDEF;

#ifdef HTDEBUG

	if ( debug )
	{
		WWWTRACE = SHOW_ALL_TRACE;
	}

#endif

	if ( !localName || !remoteName )
	{
		Com_DPrintf( "Empty download URL or empty local file name\n" );
		return 0;
	}

	DL_InitDownload();

	/* need access for ftp behaviour and HTTP Basic Auth */
	access = HTParse( remoteName, "", PARSE_ACCESS );

	/*
	   Set the timeout for how long we are going to wait for a response
	   This needs to be set and reset to 0 after dl each time
	   idcvs/2003-January/000449.html
	   http://lists.w3.org/Archives/Public/www-lib/2003AprJun/0033.html
	   In case of ftp download, we leave no timeout during connect phase cause of libwww bugs
	   show_bug.cgi?id=605
	 */
	if ( !Q_stricmp( access, "ftp" ) )
	{
		dl_is_ftp = 1;
		HTHost_setEventTimeout( -1 );
	}
	else
	{
		dl_is_ftp = 0;
		HTHost_setEventTimeout( 30000 );
	}

	dl_request = HTRequest_new();

	/* HTTP Basic Auth */
	if ( !Q_stricmp( access, "http" ) )
	{
		HTBasic *basic;

		login = HTParse( remoteName, "", PARSE_HOST );
		path = HTParse( remoteName, "", PARSE_PATH + PARSE_PUNCTUATION );
		ptr = strchr( login, '@' );

		if ( ptr )
		{
			/* Uid and/or passwd specified */
			char *passwd;

			*ptr = '\0';
			passwd = strchr( login, ':' );

			if ( passwd )
			{
				/* Passwd specified */
				*passwd++ = '\0';
				HTUnEscape( passwd );
			}

			HTUnEscape( login );
			/* proactively set the auth */
			basic = HTBasic_new();
			StrAllocCopy( basic->uid, login );
			StrAllocCopy( basic->pw, passwd );
			basic_credentials( dl_request, basic );
			HTBasic_delete( basic );
			/* correct the HTTP */
			url = HT_MALLOC( 7 + strlen( ptr + 1 ) + strlen( path ) + 1 );
			sprintf( url, "http://%s%s", ptr + 1, path );
			Com_DPrintf( "HTTP Basic Auth – %s %s %s\n", login, passwd, url );
			HT_FREE( login );
			HT_FREE( path );
		}
		else
		{
			StrAllocCopy( url, remoteName );
		}
	}
	else
	{
		StrAllocCopy( url, remoteName );
	}

	HT_FREE( access );

	FS_CreatePath( localName );

	/* Start the load */
	if ( HTLoadToFile( url, dl_request, localName ) != YES )
	{
		Com_DPrintf( "HTLoadToFile failed\n" );
		HT_FREE( url );
		HTProfile_delete();
		return 0;
	}

	HT_FREE( url );

	/* remove possible login/pass part for the ui */
	access = HTParse( remoteName, "", PARSE_ACCESS );
	login = HTParse( remoteName, "", PARSE_HOST );
	path = HTParse( remoteName, "", PARSE_PATH + PARSE_PUNCTUATION );
	ptr = strchr( login, '@' );

	if ( ptr )
	{
		/* Uid and/or passwd specified */
		Cvar_Set( "cl_downloadName", va( "%s://*:*%s%s", access, ptr, path ) );
	}
	else
	{
		Cvar_Set( "cl_downloadName", remoteName );
	}

	HT_FREE( path );
	HT_FREE( login );
	HT_FREE( access );

	if ( dl_is_ftp )
	{
		HTHost_setEventTimeout( 30000 );
	}

	/* Go into the event loop... */
	HTEventList_init( dl_request );

	dl_running = 1;

	return 1;
}
Exemple #28
0
/*
=====================
CL_ParseDownload

A download message has been received from the server
=====================
*/
void CL_ParseDownload(void)
{
    int size, percent;
    char name[MAX_OSPATH];
    int r;

    // read the data
    size = MSG_ReadShort(&net_message);
    percent = MSG_ReadByte(&net_message);
    if (size == -1)
    {
        Com_Printf("Server does not have this file.\n");
        if (cls.download)
        {
            // if here, we tried to resume a file but the server said no
            fclose(cls.download);
            cls.download = NULL;
        }
        CL_RequestNextDownload();
        return;
    }

    // open the file if not opened yet
    if (!cls.download)
    {
        CL_DownloadFileName(name, sizeof(name), cls.downloadtempname);

        FS_CreatePath(name);

        cls.download = fopen(name, "wb");
        if (!cls.download)
        {
            net_message.readcount += size;
            Com_Printf("Failed to open %s\n", cls.downloadtempname);
            CL_RequestNextDownload();
            return;
        }
    }

    fwrite(net_message.data + net_message.readcount, 1, size, cls.download);
    net_message.readcount += size;

    if (percent != 100)
    {
// request next block
// change display routines by zoid
#if 0
		Com_Printf (".");
		if (10*(percent/10) != cls.downloadpercent)
		{
			cls.downloadpercent = 10*(percent/10);
			Com_Printf ("%i%%", cls.downloadpercent);
		}
#endif
        cls.downloadpercent = percent;

        MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
        SZ_Print(&cls.netchan.message, "nextdl");
    }
    else
    {
        char oldn[MAX_OSPATH];
        char newn[MAX_OSPATH];

        //		Com_Printf ("100%%\n");

        fclose(cls.download);

        // rename the temp file to it's final name
        CL_DownloadFileName(oldn, sizeof(oldn), cls.downloadtempname);
        CL_DownloadFileName(newn, sizeof(newn), cls.downloadname);
        r = rename(oldn, newn);
        if (r)
            Com_Printf("failed to rename.\n");

        cls.download = NULL;
        cls.downloadpercent = 0;

        // get another file if needed

        CL_RequestNextDownload();
    }
}
Exemple #29
0
void SV_SaveGame_f (void) {
	char fname[MAX_OSPATH], comment[SAVEGAME_COMMENT_LENGTH+1];
	FILE *f;
	int i;

	if (Cmd_Argc() != 2) {
		Com_Printf ("Usage: %s <savefname> : save a game\n", Cmd_Argv(0));
		return;
	} else if (strstr(Cmd_Argv(1), "..")) {
		Com_Printf ("Relative pathfnames are not allowed.\n");
		return;
	} else if (sv.state != ss_active) {
		Com_Printf ("Not playing a local game.\n");
		return;
	} else if (cl.intermission) {
		Com_Printf ("Can't save in intermission.\n");
		return;
	} else if (deathmatch.value != 0 || coop.value != 0 || maxclients.value != 1) {
		Com_Printf ("Can't save multiplayer games.\n");
		return;
	}

	for (i = 1; i < MAX_CLIENTS; i++) {
		if (svs.clients[i].state == cs_spawned) {
			Com_Printf ("Can't save multiplayer games.\n");
			return;
		}
	}	

	if (svs.clients[0].state != cs_spawned) {
		Com_Printf ("Can't save, client #0 not spawned.\n");
		return;
	} else if (svs.clients[0].edict->v.health <= 0) {
		Com_Printf ("Can't save game with a dead player\n");
		// in fact, we can, but does it make sense?
		return;
	}

	snprintf (fname, sizeof(fname), "%s/save/%s", com_gamedir, Cmd_Argv(1));
	COM_DefaultExtension (fname, ".sav");
	
	Com_Printf ("Saving game to %s...\n", fname);
	if (!(f = fopen (fname, "w"))) {		
		FS_CreatePath (fname);
		if (!(f = fopen (fname, "w"))) {
			Com_Printf ("ERROR: couldn't open.\n");
			return;
		}
	}

	fprintf (f, "%i\n", SAVEGAME_VERSION);
	SV_SavegameComment (comment);
	fprintf (f, "%s\n", comment);
	for (i = 0 ; i < NUM_SPAWN_PARMS; i++)
		fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
	fprintf (f, "%d\n", current_skill);
	fprintf (f, "%s\n", sv.mapname);
	fprintf (f, "%f\n", sv.time);

	// write the light styles
	for (i = 0; i < MAX_LIGHTSTYLES; i++) {
		if (sv.lightstyles[i])
			fprintf (f, "%s\n", sv.lightstyles[i]);
		else
			fprintf (f,"m\n");
	}

	ED_WriteGlobals (f);
	for (i = 0; i < sv.num_edicts; i++) {
		ED_Write (f, EDICT_NUM(i));
		fflush (f);
	}
	fclose (f);
	Com_Printf ("done.\n");
}
void DumpConfig(char *name)
{
	FILE	*f;
	char	*outfile, *newlines = "\n";

	if (cfg_use_home.integer) // homedir
		outfile = va("%s/%s/%s", com_homedir, (strcmp(com_gamedirfile, "qw") == 0 || !cfg_use_gamedir.integer) ? "" : com_gamedirfile, name);
	else // basedir
		outfile = va("%s/%s/configs/%s", com_basedir, (strcmp(com_gamedirfile, "qw") == 0 || !cfg_use_gamedir.integer) ? "ezquake" : com_gamedirfile, name);

	if (!(f	= fopen	(outfile, "w"))) {
		FS_CreatePath(outfile);
		if (!(f	= fopen	(outfile, "w"))) {
			Com_Printf ("Couldn't write	%s.\n",	name);
			return;
		}
	}

	Com_Printf("Saving configuration to %s\n", outfile);

	Config_PrintPreamble(f);

	if (cfg_save_cvars.value) {
		Config_PrintHeading(f, "V A R I A B L E S");
		DumpVariables(f);
		fprintf(f, "%s", newlines);
	}

	if (cfg_save_cmds.value) {
		Config_PrintHeading(f, "S E L E C T E D   S O U R C E S");
		WriteSourcesConfiguration(f);
		fprintf(f, "%s", newlines);
	}

	if (cfg_save_aliases.value) {
		Config_PrintHeading(f, "A L I A S E S");
		DumpAliases(f);
		fprintf(f, "%s", newlines);
	}

	if (cfg_save_cmds.value) {
		Config_PrintHeading(f, "Q W 2 6 2   H U D");
		DumpHUD262(f);
		fprintf(f, "%s", newlines);

		Config_PrintHeading(f, "T E A M P L A Y   C O M M A N D S");
		DumpTeamplay(f);
		fprintf(f, "%s", newlines);

		Config_PrintHeading(f, "M I S C E L L A N E O U S   C O M M A N D S");
		DumpMisc(f);
		fprintf(f, "%s", newlines);

		Config_PrintHeading(f, "P L U S   C O M M A N D S");
		DumpPlusCommands(f);
		fprintf(f, "%s", newlines);
	}

	if (cfg_save_binds.value) {
		Config_PrintHeading(f, "K E Y   B I N D I N G S");
		DumpBindings(f);
	}

	fclose(f);
}