jedioutcast/code/unix/unix_shared.c

370 lines
7 KiB
C
Raw Normal View History

2013-04-04 18:24:26 +00:00
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
//===============================================================================
// Used to determine CD Path
static char programpath[MAX_OSPATH];
/*
================
Sys_Milliseconds
================
*/
int curtime;
int sys_timeBase;
int Sys_Milliseconds (void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
if (!sys_timeBase)
{
sys_timeBase = tp.tv_sec;
return tp.tv_usec/1000;
}
curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
return curtime;
}
void Sys_Mkdir( const char *path )
{
mkdir (path, 0777);
}
char *strlwr (char *s)
{
while (*s) {
*s = tolower(*s);
s++;
}
}
//============================================
/* Like glob_match, but match PATTERN against any final segment of TEXT. */
static int glob_match_after_star(char *pattern, char *text)
{
register char *p = pattern, *t = text;
register char c, c1;
while ((c = *p++) == '?' || c == '*')
if (c == '?' && *t++ == '\0')
return 0;
if (c == '\0')
return 1;
if (c == '\\')
c1 = *p;
else
c1 = c;
while (1) {
if ((c == '[' || *t == c1) && glob_match(p - 1, t))
return 1;
if (*t++ == '\0')
return 0;
}
}
/* Return nonzero if PATTERN has any special globbing chars in it. */
static int glob_pattern_p(char *pattern)
{
register char *p = pattern;
register char c;
int open = 0;
while ((c = *p++) != '\0')
switch (c) {
case '?':
case '*':
return 1;
case '[': /* Only accept an open brace if there is a close */
open++; /* brace to match it. Bracket expressions must be */
continue; /* complete, according to Posix.2 */
case ']':
if (open)
return 1;
continue;
case '\\':
if (*p++ == '\0')
return 0;
}
return 0;
}
/* Match the pattern PATTERN against the string TEXT;
return 1 if it matches, 0 otherwise.
A match means the entire string TEXT is used up in matching.
In the pattern string, `*' matches any sequence of characters,
`?' matches any character, [SET] matches any character in the specified set,
[!SET] matches any character not in the specified set.
A set is composed of characters or ranges; a range looks like
character hyphen character (as in 0-9 or A-Z).
[0-9a-zA-Z_] is the set of characters allowed in C identifiers.
Any other character in the pattern must be matched exactly.
To suppress the special syntactic significance of any of `[]*?!-\',
and match the character exactly, precede it with a `\'.
*/
int glob_match(char *pattern, char *text)
{
register char *p = pattern, *t = text;
register char c;
while ((c = *p++) != '\0')
switch (c) {
case '?':
if (*t == '\0')
return 0;
else
++t;
break;
case '\\':
if (*p++ != *t++)
return 0;
break;
case '*':
return glob_match_after_star(p, t);
case '[':
{
register char c1 = *t++;
int invert;
if (!c1)
return (0);
invert = ((*p == '!') || (*p == '^'));
if (invert)
p++;
c = *p++;
while (1) {
register char cstart = c, cend = c;
if (c == '\\') {
cstart = *p++;
cend = cstart;
}
if (c == '\0')
return 0;
c = *p++;
if (c == '-' && *p != ']') {
cend = *p++;
if (cend == '\\')
cend = *p++;
if (cend == '\0')
return 0;
c = *p++;
}
if (c1 >= cstart && c1 <= cend)
goto match;
if (c == ']')
break;
}
if (!invert)
return 0;
break;
match:
/* Skip the rest of the [...] construct that already matched. */
while (c != ']') {
if (c == '\0')
return 0;
c = *p++;
if (c == '\0')
return 0;
else if (c == '\\')
++p;
}
if (invert)
return 0;
break;
}
default:
if (c != *t++)
return 0;
}
return *t == '\0';
}
//============================================
#define MAX_FOUND_FILES 0x1000
char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
{
struct dirent *d;
char *p;
DIR *fdir;
qboolean dironly = wantsubs;
char search[MAX_OSPATH];
int nfiles;
char **listCopy;
char *list[MAX_FOUND_FILES];
int flag;
int i;
struct stat st;
int extLen;
if ( !extension)
extension = "";
if ( extension[0] == '/' && extension[1] == 0 ) {
extension = "";
dironly = qtrue;
}
extLen = strlen( extension );
// search
nfiles = 0;
if ((fdir = opendir(directory)) == NULL) {
*numfiles = 0;
return NULL;
}
while ((d = readdir(fdir)) != NULL) {
Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
if (stat(search, &st) == -1)
continue;
if ((dironly && !(st.st_mode & S_IFDIR)) ||
(!dironly && (st.st_mode & S_IFDIR)))
continue;
if (*extension) {
if ( strlen( d->d_name ) < strlen( extension ) ||
Q_stricmp(
d->d_name + strlen( d->d_name ) - strlen( extension ),
extension ) ) {
continue; // didn't match
}
}
if ( nfiles == MAX_FOUND_FILES - 1 )
break;
list[ nfiles ] = CopyString( d->d_name );
nfiles++;
}
list[ nfiles ] = 0;
closedir(fdir);
// return a copy of the list
*numfiles = nfiles;
if ( !nfiles ) {
return NULL;
}
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
for ( i = 0 ; i < nfiles ; i++ ) {
listCopy[i] = list[i];
}
listCopy[i] = NULL;
return listCopy;
}
void Sys_FreeFileList( char **list ) {
int i;
if ( !list ) {
return;
}
for ( i = 0 ; list[i] ; i++ ) {
Z_Free( list[i] );
}
Z_Free( list );
}
char *Sys_Cwd( void )
{
static char cwd[MAX_OSPATH];
getcwd( cwd, sizeof( cwd ) - 1 );
cwd[MAX_OSPATH-1] = 0;
return cwd;
}
void SetProgramPath(char *path)
{
char *p;
Q_strncpyz(programpath, path, sizeof(programpath));
if ((p = strrchr(programpath, '/')) != NULL)
*p = 0; // remove program name, leave only path
}
char *Sys_DefaultCDPath(void)
{
if (*programpath)
return programpath;
else
return Sys_Cwd();
}
char *Sys_DefaultBasePath(void)
{
char *p;
static char basepath[MAX_OSPATH];
int e;
if ((p = getenv("HOME")) != NULL) {
Q_strncpyz(basepath, p, sizeof(basepath));
Q_strcat(basepath, sizeof(basepath), "/.q3a");
if (mkdir(basepath, 0777)) {
if (errno != EEXIST)
Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", basepath, strerror(errno), errno);
}
return basepath;
}
return ""; // assume current dir
}
//============================================
int Sys_GetProcessorId( void )
{
return CPUID_GENERIC;
}
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
{
}