fteqw/engine/common/log.c
Spoike 503eff6421 Reworked the filesystem. We now support a virtual filesystem. Many places accept stream usage, although many formats do not support this.
I'm not sure if this will break anything. It shouldn't do, but it might.

Not everything is ported over yet. Ideally there would be no more use of fopen anywhere else in the engine, and com_gamedir would be made static to fs.c
There are a couple of other changes too.

http/ftp stuff is currently disabled.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1728 fc73d0e0-1445-4013-8a0c-d673dee63da5
2005-12-21 03:07:33 +00:00

243 lines
No EOL
6.1 KiB
C

// log.c: handles console logging functions and cvars
#include "quakedef.h"
// cvars
#define CONLOGGROUP "Console logging"
cvar_t log_name = {"log_name", "", NULL, CVAR_NOTFROMSERVER};
cvar_t log_dir = {"log_dir", "", NULL, CVAR_NOTFROMSERVER};
cvar_t log_readable = {"log_readable", "0", NULL, CVAR_NOTFROMSERVER};
cvar_t log_enable = {"log_enable", "0", NULL, CVAR_NOTFROMSERVER};
cvar_t log_developer = {"log_developer", "0", NULL, CVAR_NOTFROMSERVER};
cvar_t log_rotate_files = {"log_rotate_files", "0", NULL, CVAR_NOTFROMSERVER};
cvar_t log_rotate_size = {"log_rotate_size", "131072", NULL, CVAR_NOTFROMSERVER};
cvar_t log_dosformat = {"log_dosformat", "0", NULL, CVAR_NOTFROMSERVER};
// externals
int COM_FileSize(char *path);
extern char gamedirfile[];
// table of readable characters, same as ezquake
char readable[256] =
{
'.', '_', '_', '_', '_', '.', '_', '_',
'_', '_', '\n', '_', '\n', '>', '.', '.',
'[', ']', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '.', '_', '_', '_',
' ', '!', '\"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '_',
'_', '_', '_', '_', '_', '.', '_', '_',
'_', '_', '_', '_', '_', '>', '.', '.',
'[', ']', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '.', '_', '_', '_',
' ', '!', '\"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '_'
};
// Con_Log: log string to console log
void Con_Log (char *s)
{
char *d; // directory
char *f; // filename
char *t;
char logbuf[1024];
int i;
if (!log_enable.value)
return;
// cvar sanity checks
if (log_dir.modified)
{
t = log_dir.string;
if (strstr(t, "..") || strstr(t, ":") || *t == '/' || *t == '\\')
{
Con_Printf("log_dir forced to default due to invalid characters.\n");
Cvar_ForceSet(&log_dir, log_dir.defaultstr);
}
log_dir.modified = false;
}
if (log_name.modified)
{
t = log_name.string;
if (strstr(t, "..") || strstr(t, ":") || strstr(t, "/") || strstr(t, "\\"))
{
Con_Printf("log_name forced to default due to invalid characters.\n");
Cvar_ForceSet(&log_name, log_name.defaultstr);
}
log_name.modified = false;
}
// get directory/filename
d = gamedirfile;
if (log_dir.string[0])
d = log_dir.string;
f = "qconsole";
if (log_name.string[0])
f = log_name.string;
// readable translation and Q3 code removal, use t for final string to write
t = logbuf;
// max debuglog buf is 1024
for (i = 0; i < 1023; i++, s++)
{
if (*s == 0)
break;
else if (((int)(log_readable.value) & 2) && *s == '^')
{
// log_readable 2 removes Q3 codes as well
char c;
c = *(s+1);
if ((c >= '0' && c < '8') || c == 'a' || c == 'b' || c == 's' || c == 'r')
{
i--;
s++;
}
else
{
*t = '^';
t++;
}
}
else if (log_dosformat.value && *s == '\n')
{
// convert \n to \r\n
*t = '\r';
t++;
i++;
if (i < 1023)
{
*t = '\n';
t++;
}
}
else
{
// use readable table to convert quake chars to reabable text
if ((int)(log_readable.value) & 1)
*t = readable[(unsigned char)(*s)]; // translate
else
*t = *s; // copy
t++;
}
}
*t = 0;
f = va("%s/%s.log",d,f); // temp string in va()
// file rotation
if (log_rotate_size.value >= 4096 && log_rotate_files.value >= 1)
{
int x;
vfsfile_t *fi;
// check file size, use x as temp
if ((fi = FS_OpenVFS(f, "rb", FS_BASE)))
{
x = VFS_GETLEN(fi);
VFS_CLOSE(fi);
}
else
x = 0;
if (x > (int)log_rotate_size.value)
{
char newf[MAX_OSPATH];
char oldf[MAX_OSPATH];
i = log_rotate_files.value;
// unlink file at the top of the chain
_snprintf(oldf, sizeof(oldf)-1, "%s.%i", f, i);
FS_Remove(oldf, FS_BASE);
// rename files through chain
for (x = i-1; x > 0; x--)
{
strcpy(newf, oldf);
_snprintf(oldf, sizeof(oldf)-1, "%s.%i", f, x);
// check if file exists, otherwise skip
if ((fi = FS_OpenVFS(f, "rb", FS_BASE)))
VFS_CLOSE(fi);
else
continue; // skip nonexistant files
if (FS_Rename(oldf, newf, FS_BASE))
{
// rename failed, disable log and bug out
Cvar_ForceSet(&log_enable, "0");
Con_Printf("Unable to rotate log files. Logging disabled.\n");
return;
}
}
// TODO: option to compress file somewhere in here?
// rename our base file, which better exist...
if (rename(f, oldf))
{
// rename failed, disable log and bug out
Cvar_ForceSet(&log_enable, "0");
Con_Printf("Unable to rename base log file. Logging disabled.\n");
return;
}
}
}
// write to log file
if (Sys_DebugLog(f, "%s", logbuf))
{
// write failed, bug out
Cvar_ForceSet(&log_enable, "0");
Con_Printf("Unable to write to log file. Logging disabled.\n");
return;
}
}
void Log_Init(void)
{
// register cvars
Cvar_Register (&log_name, CONLOGGROUP);
Cvar_Register (&log_dir, CONLOGGROUP);
Cvar_Register (&log_readable, CONLOGGROUP);
Cvar_Register (&log_enable, CONLOGGROUP);
Cvar_Register (&log_developer, CONLOGGROUP);
Cvar_Register (&log_rotate_size, CONLOGGROUP);
Cvar_Register (&log_rotate_files, CONLOGGROUP);
Cvar_Register (&log_dosformat, CONLOGGROUP);
// cmd line options, debug options
#ifdef CRAZYDEBUGGING
Cvar_ForceSet(&log_enable, "1");
TRACE(("dbg: Con_Init: log_enable forced\n"));
#endif
if (COM_CheckParm("-condebug"))
Cvar_ForceSet(&log_enable, "1");
}