Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

unix_shared.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <errno.h>
00025 #include <stdio.h>
00026 #include <dirent.h>
00027 #include <unistd.h>
00028 #include <sys/mman.h>
00029 #include <sys/time.h>
00030 #include <pwd.h>
00031 
00032 #include "../game/q_shared.h"
00033 #include "../qcommon/qcommon.h"
00034 
00035 //=============================================================================
00036 
00037 // Used to determine CD Path
00038 static char cdPath[MAX_OSPATH];
00039 
00040 // Used to determine local installation path
00041 static char installPath[MAX_OSPATH];
00042 
00043 // Used to determine where to store user-specific files
00044 static char homePath[MAX_OSPATH];
00045 
00046 /*
00047 ================
00048 Sys_Milliseconds
00049 ================
00050 */
00051 /* base time in seconds, that's our origin
00052    timeval:tv_sec is an int: 
00053    assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038
00054    using unsigned long data type to work right with Sys_XTimeToSysTime */
00055 unsigned long sys_timeBase = 0;
00056 /* current time in ms, using sys_timeBase as origin
00057    NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
00058      0x7fffffff ms - ~24 days
00059    although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
00060      (which would affect the wrap period) */
00061 int curtime;
00062 int Sys_Milliseconds (void)
00063 {
00064     struct timeval tp;
00065 
00066     gettimeofday(&tp, NULL);
00067     
00068     if (!sys_timeBase)
00069     {
00070         sys_timeBase = tp.tv_sec;
00071         return tp.tv_usec/1000;
00072     }
00073 
00074     curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
00075     
00076     return curtime;
00077 }
00078 
00079 #if defined(__linux__) && !defined(DEDICATED)
00080 /*
00081 ================
00082 Sys_XTimeToSysTime
00083 sub-frame timing of events returned by X
00084 X uses the Time typedef - unsigned long
00085 disable with in_subframe 0
00086 
00087  sys_timeBase*1000 is the number of ms since the Epoch of our origin
00088  xtime is in ms and uses the Epoch as origin
00089    Time data type is an unsigned long: 0xffffffff ms - ~49 days period
00090  I didn't find much info in the XWindow documentation about the wrapping
00091    we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime
00092    the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase
00093 
00094 ================
00095 */
00096 extern cvar_t *in_subframe;
00097 int Sys_XTimeToSysTime (unsigned long xtime)
00098 {
00099     int ret, time, test;
00100     
00101     if (!in_subframe->value)
00102     {
00103         // if you don't want to do any event times corrections
00104         return Sys_Milliseconds();
00105     }
00106 
00107     // test the wrap issue
00108 #if 0   
00109     // reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run)
00110     // xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec)
00111     //   NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c
00112     // use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f
00113     // after around 5s, xtime would have wrapped around
00114     // we get 7132, the formula handles the wrap safely
00115     unsigned long xtime_aux,base_aux;
00116     int test;
00117 //  Com_Printf("sys_timeBase: %p\n", sys_timeBase);
00118 //  Com_Printf("xtime: %p\n", xtime);
00119     xtime_aux = 500; // 500 ms after wrap
00120     base_aux = 0x3df3b63f; // the base a few seconds before wrap
00121     test = xtime_aux - (unsigned long)(base_aux*1000);
00122     Com_Printf("xtime wrap test: %d\n", test);
00123 #endif
00124 
00125   // some X servers (like suse 8.1's) report weird event times
00126   // if the game is loading, resolving DNS, etc. we are also getting old events
00127   // so we only deal with subframe corrections that look 'normal'
00128   ret = xtime - (unsigned long)(sys_timeBase*1000);
00129   time = Sys_Milliseconds();
00130   test = time - ret;
00131   //printf("delta: %d\n", test);
00132   if (test < 0 || test > 30) // in normal conditions I've never seen this go above
00133   {
00134     return time;
00135   }
00136 
00137     return ret;
00138 }
00139 #endif
00140 
00141 //#if 0 // bk001215 - see snapvector.nasm for replacement
00142 #if (defined __APPLE__) // rcg010206 - using this for PPC builds...
00143 long fastftol( float f ) { // bk001213 - from win32/win_shared.c
00144   //static int tmp;
00145   //    __asm fld f
00146   //__asm fistp tmp
00147   //__asm mov eax, tmp
00148   return (long)f;
00149 }
00150 
00151 void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c
00152   // bk001213 - old linux
00153   v[0] = rint(v[0]);
00154   v[1] = rint(v[1]);
00155   v[2] = rint(v[2]);
00156 }
00157 #endif
00158 
00159 
00160 void    Sys_Mkdir( const char *path )
00161 {
00162     mkdir (path, 0777);
00163 }
00164 
00165 char *strlwr (char *s) {
00166   if ( s==NULL ) { // bk001204 - paranoia
00167     assert(0);
00168     return s;
00169   }
00170   while (*s) {
00171     *s = tolower(*s);
00172     s++;
00173   }
00174   return s; // bk001204 - duh
00175 }
00176 
00177 //============================================
00178 
00179 #define MAX_FOUND_FILES 0x1000
00180 
00181 // bk001129 - new in 1.26
00182 void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
00183     char        search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
00184     char        filename[MAX_OSPATH];
00185     DIR         *fdir;
00186     struct dirent *d;
00187     struct stat st;
00188 
00189     if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
00190         return;
00191     }
00192 
00193     if (strlen(subdirs)) {
00194         Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
00195     }
00196     else {
00197         Com_sprintf( search, sizeof(search), "%s", basedir );
00198     }
00199 
00200     if ((fdir = opendir(search)) == NULL) {
00201         return;
00202     }
00203 
00204     while ((d = readdir(fdir)) != NULL) {
00205         Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
00206         if (stat(filename, &st) == -1)
00207             continue;
00208 
00209         if (st.st_mode & S_IFDIR) {
00210             if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
00211                 if (strlen(subdirs)) {
00212                     Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
00213                 }
00214                 else {
00215                     Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
00216                 }
00217                 Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
00218             }
00219         }
00220         if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
00221             break;
00222         }
00223         Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
00224         if (!Com_FilterPath( filter, filename, qfalse ))
00225             continue;
00226         list[ *numfiles ] = CopyString( filename );
00227         (*numfiles)++;
00228     }
00229 
00230     closedir(fdir);
00231 }
00232 
00233 // bk001129 - in 1.17 this used to be
00234 // char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
00235 char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
00236 {
00237     struct dirent *d;
00238     // char *p; // bk001204 - unused
00239     DIR     *fdir;
00240     qboolean dironly = wantsubs;
00241     char        search[MAX_OSPATH];
00242     int         nfiles;
00243     char        **listCopy;
00244     char        *list[MAX_FOUND_FILES];
00245     //int           flag; // bk001204 - unused
00246     int         i;
00247     struct stat st;
00248 
00249     int         extLen;
00250 
00251     if (filter) {
00252 
00253         nfiles = 0;
00254         Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
00255 
00256         list[ nfiles ] = 0;
00257         *numfiles = nfiles;
00258 
00259         if (!nfiles)
00260             return NULL;
00261 
00262         listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
00263         for ( i = 0 ; i < nfiles ; i++ ) {
00264             listCopy[i] = list[i];
00265         }
00266         listCopy[i] = NULL;
00267 
00268         return listCopy;
00269     }
00270 
00271     if ( !extension)
00272         extension = "";
00273 
00274     if ( extension[0] == '/' && extension[1] == 0 ) {
00275         extension = "";
00276         dironly = qtrue;
00277     }
00278 
00279     extLen = strlen( extension );
00280     
00281     // search
00282     nfiles = 0;
00283 
00284     if ((fdir = opendir(directory)) == NULL) {
00285         *numfiles = 0;
00286         return NULL;
00287     }
00288 
00289     while ((d = readdir(fdir)) != NULL) {
00290         Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
00291         if (stat(search, &st) == -1)
00292             continue;
00293         if ((dironly && !(st.st_mode & S_IFDIR)) ||
00294             (!dironly && (st.st_mode & S_IFDIR)))
00295             continue;
00296 
00297         if (*extension) {
00298             if ( strlen( d->d_name ) < strlen( extension ) ||
00299                 Q_stricmp( 
00300                     d->d_name + strlen( d->d_name ) - strlen( extension ),
00301                     extension ) ) {
00302                 continue; // didn't match
00303             }
00304         }
00305 
00306         if ( nfiles == MAX_FOUND_FILES - 1 )
00307             break;
00308         list[ nfiles ] = CopyString( d->d_name );
00309         nfiles++;
00310     }
00311 
00312     list[ nfiles ] = 0;
00313 
00314     closedir(fdir);
00315 
00316     // return a copy of the list
00317     *numfiles = nfiles;
00318 
00319     if ( !nfiles ) {
00320         return NULL;
00321     }
00322 
00323     listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
00324     for ( i = 0 ; i < nfiles ; i++ ) {
00325         listCopy[i] = list[i];
00326     }
00327     listCopy[i] = NULL;
00328 
00329     return listCopy;
00330 }
00331 
00332 void    Sys_FreeFileList( char **list ) {
00333     int     i;
00334 
00335     if ( !list ) {
00336         return;
00337     }
00338 
00339     for ( i = 0 ; list[i] ; i++ ) {
00340         Z_Free( list[i] );
00341     }
00342 
00343     Z_Free( list );
00344 }
00345 
00346 char *Sys_Cwd( void ) 
00347 {
00348     static char cwd[MAX_OSPATH];
00349 
00350     getcwd( cwd, sizeof( cwd ) - 1 );
00351     cwd[MAX_OSPATH-1] = 0;
00352 
00353     return cwd;
00354 }
00355 
00356 void Sys_SetDefaultCDPath(const char *path)
00357 {
00358     Q_strncpyz(cdPath, path, sizeof(cdPath));
00359 }
00360 
00361 char *Sys_DefaultCDPath(void)
00362 {
00363         return cdPath;
00364 }
00365 
00366 void Sys_SetDefaultInstallPath(const char *path)
00367 {
00368     Q_strncpyz(installPath, path, sizeof(installPath));
00369 }
00370 
00371 char *Sys_DefaultInstallPath(void)
00372 {
00373     if (*installPath)
00374         return installPath;
00375     else
00376         return Sys_Cwd();
00377 }
00378 
00379 void Sys_SetDefaultHomePath(const char *path)
00380 {
00381     Q_strncpyz(homePath, path, sizeof(homePath));
00382 }
00383 
00384 char *Sys_DefaultHomePath(void)
00385 {
00386     char *p;
00387 
00388         if (*homePath)
00389             return homePath;
00390             
00391     if ((p = getenv("HOME")) != NULL) {
00392         Q_strncpyz(homePath, p, sizeof(homePath));
00393 #ifdef MACOS_X
00394         Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
00395 #else
00396         Q_strcat(homePath, sizeof(homePath), "/.q3a");
00397 #endif
00398         if (mkdir(homePath, 0777)) {
00399             if (errno != EEXIST) 
00400                 Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno);
00401         }
00402         return homePath;
00403     }
00404     return ""; // assume current dir
00405 }
00406 
00407 //============================================
00408 
00409 int Sys_GetProcessorId( void )
00410 {
00411     return CPUID_GENERIC;
00412 }
00413 
00414 void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
00415 {
00416 }
00417 
00418 char *Sys_GetCurrentUser( void )
00419 {
00420     struct passwd *p;
00421 
00422     if ( (p = getpwuid( getuid() )) == NULL ) {
00423         return "player";
00424     }
00425     return p->pw_name;
00426 }
00427 
00428 #if defined(__linux__)
00429 // TTimo 
00430 // sysconf() in libc, POSIX.1 compliant
00431 unsigned int Sys_ProcessorCount()
00432 {
00433   return sysconf(_SC_NPROCESSORS_ONLN);
00434 }
00435 #endif

Generated on Thu Aug 25 12:38:04 2005 for Quake III Arena by  doxygen 1.3.9.1