diff options
Diffstat (limited to 'src/unix/unix_shared.c')
-rw-r--r-- | src/unix/unix_shared.c | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/src/unix/unix_shared.c b/src/unix/unix_shared.c new file mode 100644 index 0000000..2c238ca --- /dev/null +++ b/src/unix/unix_shared.c @@ -0,0 +1,452 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Tremulous is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#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 <pwd.h> + +#include "../qcommon/q_shared.h" +#include "../qcommon/qcommon.h" + +//============================================================================= + +// Used to determine CD Path +static char cdPath[MAX_OSPATH]; + +// Used to determine local installation path +static char installPath[MAX_OSPATH]; + +// Used to determine where to store user-specific files +static char homePath[MAX_OSPATH]; + +/* +================ +Sys_Milliseconds +================ +*/ +/* base time in seconds, that's our origin + timeval:tv_sec is an int: + assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038 + using unsigned long data type to work right with Sys_XTimeToSysTime */ +unsigned long sys_timeBase = 0; +/* current time in ms, using sys_timeBase as origin + NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch + 0x7fffffff ms - ~24 days + although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int + (which would affect the wrap period) */ +int curtime; +int Sys_Milliseconds (void) +{ + struct timeval tp; + + gettimeofday(&tp, NULL); + + 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; +} + +#if (defined(__linux__) || defined(__FreeBSD__) || defined(__sun)) && !defined(DEDICATED) +/* +================ +Sys_XTimeToSysTime +sub-frame timing of events returned by X +X uses the Time typedef - unsigned long +disable with in_subframe 0 + + sys_timeBase*1000 is the number of ms since the Epoch of our origin + xtime is in ms and uses the Epoch as origin + Time data type is an unsigned long: 0xffffffff ms - ~49 days period + I didn't find much info in the XWindow documentation about the wrapping + we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime + the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase + +================ +*/ +extern cvar_t *in_subframe; +int Sys_XTimeToSysTime (unsigned long xtime) +{ + int ret, time, test; + + if (!in_subframe->value) + { + // if you don't want to do any event times corrections + return Sys_Milliseconds(); + } + + // test the wrap issue +#if 0 + // reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run) + // xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec) + // NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c + // use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f + // after around 5s, xtime would have wrapped around + // we get 7132, the formula handles the wrap safely + unsigned long xtime_aux,base_aux; + int test; +// Com_Printf("sys_timeBase: %p\n", sys_timeBase); +// Com_Printf("xtime: %p\n", xtime); + xtime_aux = 500; // 500 ms after wrap + base_aux = 0x3df3b63f; // the base a few seconds before wrap + test = xtime_aux - (unsigned long)(base_aux*1000); + Com_Printf("xtime wrap test: %d\n", test); +#endif + + // some X servers (like suse 8.1's) report weird event times + // if the game is loading, resolving DNS, etc. we are also getting old events + // so we only deal with subframe corrections that look 'normal' + ret = xtime - (unsigned long)(sys_timeBase*1000); + time = Sys_Milliseconds(); + test = time - ret; + //printf("delta: %d\n", test); + if (test < 0 || test > 30) // in normal conditions I've never seen this go above + { + return time; + } + + return ret; +} +#endif + +//#if 0 // bk001215 - see snapvector.nasm for replacement +#if !id386 // rcg010206 - using this for PPC builds... +long fastftol( float f ) { // bk001213 - from win32/win_shared.c + //static int tmp; + // __asm fld f + //__asm fistp tmp + //__asm mov eax, tmp + return (long)f; +} + +void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c + // bk001213 - old linux + v[0] = rint(v[0]); + v[1] = rint(v[1]); + v[2] = rint(v[2]); +} +#endif + + +void Sys_Mkdir( const char *path ) +{ + mkdir (path, 0777); +} + +char *strlwr (char *s) { + if ( s==NULL ) { // bk001204 - paranoia + assert(0); + return s; + } + while (*s) { + *s = tolower(*s); + s++; + } + return s; // bk001204 - duh +} + +qboolean Sys_RandomBytes( byte *string, int len ) +{ + FILE *fp; + + fp = fopen( "/dev/urandom", "r" ); + if( !fp ) + return qfalse; + + if( !fread( string, sizeof( byte ), len, fp ) ) { + fclose( fp ); + return qfalse; + } + fclose( fp ); + return qtrue; +} + +//============================================ + +#define MAX_FOUND_FILES 0x1000 + +// bk001129 - new in 1.26 +void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) { + char search[MAX_OSPATH], newsubdirs[MAX_OSPATH]; + char filename[MAX_OSPATH]; + DIR *fdir; + struct dirent *d; + struct stat st; + + if ( *numfiles >= MAX_FOUND_FILES - 1 ) { + return; + } + + if (strlen(subdirs)) { + Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs ); + } + else { + Com_sprintf( search, sizeof(search), "%s", basedir ); + } + + if ((fdir = opendir(search)) == NULL) { + return; + } + + while ((d = readdir(fdir)) != NULL) { + Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name); + if (stat(filename, &st) == -1) + continue; + + if (st.st_mode & S_IFDIR) { + if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) { + if (strlen(subdirs)) { + Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name); + } + else { + Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name); + } + Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles ); + } + } + if ( *numfiles >= MAX_FOUND_FILES - 1 ) { + break; + } + Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name ); + if (!Com_FilterPath( filter, filename, qfalse )) + continue; + list[ *numfiles ] = CopyString( filename ); + (*numfiles)++; + } + + closedir(fdir); +} + +// bk001129 - in 1.17 this used to be +// char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs ) +char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs ) +{ + struct dirent *d; + // char *p; // bk001204 - unused + DIR *fdir; + qboolean dironly = wantsubs; + char search[MAX_OSPATH]; + int nfiles; + char **listCopy; + char *list[MAX_FOUND_FILES]; + //int flag; // bk001204 - unused + int i; + struct stat st; + + int extLen; + + if (filter) { + + nfiles = 0; + Sys_ListFilteredFiles( directory, "", filter, list, &nfiles ); + + list[ nfiles ] = NULL; + *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; + } + + 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 ] = NULL; + + 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 Sys_SetDefaultCDPath(const char *path) +{ + Q_strncpyz(cdPath, path, sizeof(cdPath)); +} + +char *Sys_DefaultCDPath(void) +{ + return cdPath; +} + +void Sys_SetDefaultInstallPath(const char *path) +{ + Q_strncpyz(installPath, path, sizeof(installPath)); +} + +char *Sys_DefaultInstallPath(void) +{ + if (*installPath) + return installPath; + else + return Sys_Cwd(); +} + +void Sys_SetDefaultHomePath(const char *path) +{ + Q_strncpyz(homePath, path, sizeof(homePath)); +} + +char *Sys_DefaultHomePath(void) +{ + char *p; + + if (*homePath) + return homePath; + + if ((p = getenv("HOME")) != NULL) { + Q_strncpyz(homePath, p, sizeof(homePath)); +#ifdef MACOS_X + Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Tremulous"); +#else + Q_strcat(homePath, sizeof(homePath), "/.tremulous"); +#endif + if (mkdir(homePath, 0777)) { + if (errno != EEXIST) + Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno); + } + return homePath; + } + return ""; // assume current dir +} + +//============================================ + +int Sys_GetProcessorId( void ) +{ + return CPUID_GENERIC; +} + +void Sys_ShowConsole( int visLevel, qboolean quitOnClose ) +{ +} + +char *Sys_GetCurrentUser( void ) +{ + struct passwd *p; + + if ( (p = getpwuid( getuid() )) == NULL ) { + return "player"; + } + return p->pw_name; +} + +#if defined(__linux__) || defined(__FreeBSD__) +// TTimo +// sysconf() in libc, POSIX.1 compliant +unsigned int Sys_ProcessorCount(void) +{ + return sysconf(_SC_NPROCESSORS_ONLN); +} +#endif |