1 //////////////////////////////////////////////////////////////////////
2 //
3 //                             Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 //	This library is free software; you can redistribute it and/or
10 //	modify it under the terms of the GNU Lesser General Public
11 //	License as published by the Free Software Foundation; either
12 //	version 2.1 of the License, or (at your option) any later version.
13 //
14 //	This library is distributed in the hope that it will be useful,
15 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //	Lesser General Public License for more details.
18 //
19 //	You should have received a copy of the GNU Lesser General Public
20 //	License along with this library; if not, write to the Free Software
21 //	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 //  File				:	os.cpp
27 //  Classes				:	-
28 //  Description			:	OS dependent functions
29 //
30 ////////////////////////////////////////////////////////////////////////
31 
32 // Needs to be first, or clashes with other definitions
33 #if defined(__APPLE__) || defined(__APPLE_CC__)    	// guard against __APPLE__ being undef from ftlk
34 #include <CoreServices/CoreServices.h>         		// For FSRef, FSRefMakePath, FSFindFolder
35 #endif
36 
37 #include "os.h"
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <time.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 
46 // Needed for OSX 10.2.x fix
47 #if defined(__APPLE__) || defined(__APPLE_CC__)	// guard against __APPLE__ being undef from ftlk
48 #include <stdio.h>
49 #endif
50 
51 // Environment seperators
52 #ifdef _WINDOWS
53 // >> Windoze
54 #include <io.h>
55 #include <direct.h>
56 #include <errno.h>
57 
58 
59 // << Windows
60 #else
61 // >> Unix
62 #include <sys/param.h>
63 #include <sys/sysctl.h>
64 #include <dlfcn.h>
65 #include <glob.h>
66 
67 // << Unix
68 #endif
69 
70 #ifdef HAVE_SYS_TIME_H
71 #ifdef TIME_WITH_SYS_TIME
72 #include <sys/time.h>
73 #endif
74 #endif
75 
76 #ifndef HAVE_GETTIMEOFDAY
77 #include <sys/timeb.h>
78 
gettimeofday(struct timeval * tv,void * time_zone)79 static void gettimeofday(struct timeval *tv,void* time_zone) {
80 	timeb cur;
81 
82 	ftime(&cur);
83 
84 	tv->tv_sec	= (long) cur.time;
85 	tv->tv_usec = cur.millitm * 1000;
86 }
87 #endif
88 
89 
90 ///////////////////////////////////////////////////////////////////////
91 // These two hold the operating start time
92 static	time_t	osStartTimeSec;
93 static	time_t	osStartTimeMsec;
94 
95 
96 
97 
98 
99 
100 
101 
102 ///////////////////////////////////////////////////////////////////////
103 // Funvtion				:	osInit
104 // Description			:	Initialize the operating system
105 // Return Value			:	-
106 // Comments				:
osInit()107 void	osInit() {
108 	struct timeval	ti;
109 
110 	gettimeofday(&ti, NULL);
111 
112 	osStartTimeSec	=	ti.tv_sec;
113 	osStartTimeMsec	=	ti.tv_usec;
114 }
115 
116 ///////////////////////////////////////////////////////////////////////
117 // Funvtion				:	osShutdown
118 // Description			:	Shutdown the operating system
119 // Return Value			:	-
120 // Comments				:
osShutdown()121 void	osShutdown() {
122 }
123 
124 
125 ///////////////////////////////////////////////////////////////////////
126 // Funvtion				:	osLoadModule
127 // Description			:	Load / attach a dll/so file
128 // Return Value			:	The module handle
129 // Comments				:
osLoadModule(const char * name)130 void	*osLoadModule(const char *name) {
131 	void	*cModule	=	NULL;
132 
133 #ifdef _WINDOWS
134 	// Windows stuff here
135 	cModule	=	LoadLibrary(name);
136 #else
137 	// Unix stuff here
138 	cModule =	dlopen(name,RTLD_NOW);
139 
140 	// Unix dlopen expects an absolute path or the shared object to be in LD_LIBRARY_PATH
141 	// Convert the name to an absolute file name
142 	if (cModule == NULL) {
143 		char	absoluteName[MAXPATHLEN];
144 		char	*absolute	=	realpath(name,absoluteName);
145 
146 		if (absolute != NULL) {
147 			cModule =	dlopen(absolute,RTLD_NOW);
148 		}
149 	}
150 #endif
151 
152 	return cModule;
153 }
154 
155 ///////////////////////////////////////////////////////////////////////
156 // Funvtion				:	osModuleError
157 // Description			:	Get the latest error
158 // Return Value			:	The error string
159 // Comments				:
osModuleError()160 const char *osModuleError() {
161 #ifdef _WINDOWS
162 	return NULL;
163 #else
164 	return dlerror();
165 #endif
166 }
167 
168 ///////////////////////////////////////////////////////////////////////
169 // Function				:	osUnloadModule
170 // Description			:	Unload / detach a dll/so file
171 // Return Value			:	The module handle
172 // Comments				:
osUnloadModule(void * cModule)173 void	osUnloadModule(void *cModule) {
174 #ifdef _WINDOWS
175 	if (cModule != NULL) FreeLibrary((HMODULE) cModule);
176 #else
177 	if (cModule != NULL) dlclose((void *) cModule);
178 #endif
179 }
180 
181 
182 ///////////////////////////////////////////////////////////////////////
183 // Function				:	osResolve
184 // Description			:	Resolve a symbol in a dll/so file
185 // Return Value			:	The module handle
186 // Comments				:
osResolve(void * cModule,const char * name)187 void	*osResolve(void *cModule,const char *name) {
188 	void	*result	=	NULL;
189 
190 	if (cModule != NULL) {
191 #ifdef _WINDOWS
192 		result	=	GetProcAddress((HMODULE) cModule,name);
193 #else
194 		result	=	dlsym((void *) cModule,name);
195 
196 // OSX 10.2.x fix
197 #if defined(__APPLE__) || defined(__APPLE_CC__)	// guard against __APPLE__ being undef from ftlk
198 		if(result == NULL){
199 			char new_name[strlen(name)+2];
200 			sprintf(new_name,"_%s",name);
201 			result	=	dlsym((void *) cModule,new_name);
202 		}
203 #endif
204 
205 #endif
206 	}
207 
208 	return result;
209 }
210 
211 ///////////////////////////////////////////////////////////////////////
212 // Function				:	osEnvironment
213 // Description			:	Get an environment variable
214 // Return Value			:	The variable value if found
215 // Comments				:
osEnvironment(const char * name)216 char			*osEnvironment(const char *name) {
217 	return getenv(name);
218 }
219 
220 ///////////////////////////////////////////////////////////////////////
221 // Function				:	osFileExists
222 // Description			:	Check if a file exists
223 // Return Value			:	TRUE if it does
224 // Comments				:
osFileExists(const char * name)225 int		osFileExists(const char *name) {
226 #ifdef _WINDOWS
227 	if (_access(name,0) == 0) return TRUE;
228 #else
229 	if (access(name,0) == 0) return TRUE;
230 #endif
231 	return FALSE;
232 }
233 
234 
235 
236 ///////////////////////////////////////////////////////////////////////
237 // Function				:	osFixSlashes
238 // Description			:	Make sure the slashes are right
239 // Return Value			:	-
240 // Comments				:
osFixSlashes(char * st)241 void	osFixSlashes(char *st) {
242 	for (;*st!='\0';st++) {
243 		if ((*st == '\\') || (*st == '/')) *st	=	OS_DIR_SEPERATOR;
244 	}
245 }
246 
247 
248 ///////////////////////////////////////////////////////////////////////
249 // Function            :   osTempdir
250 // Description         :   Create a path to a directory suitable
251 //                     :   for storing temporary files.
252 // Return Value        :   -
253 // Comments            :   The directory will end with / or \
254 //                     :   Does not create the directory.
255 //                     :   Path is only unique within this process.
osTempdir(char * result,size_t resultsize)256 void   osTempdir(char *result, size_t resultsize) {
257 
258 #ifdef _WINDOWS
259 	sprintf(result,"PixieTemp_%d\\",GetCurrentProcessId());
260 #elif defined(__APPLE__) || defined(__APPLE_CC__)  // guard against __APPLE__ being undef from ftlk
261 	FSRef tempRef;
262 	char tempDirPath[OS_MAX_PATH_LENGTH];
263 	OSErr err = FSFindFolder(kLocalDomain,kTemporaryFolderType,true,&tempRef);
264 	if (!err)
265 		err = FSRefMakePath(&tempRef,(UInt8*)tempDirPath,sizeof(tempDirPath));
266 	if (!err)
267 		snprintf(result,resultsize,"%s/PixieTemp_%d/",tempDirPath,getpid());
268 	else
269 		snprintf(result,resultsize,"/tmp/PixieTemp_%d/",getpid());
270 
271 #else
272 	// Unix-y
273 	const char *tempDirEnv = osEnvironment("TMPDIR");
274 	if (!tempDirEnv)
275 		tempDirEnv = osEnvironment("TMP");
276 	if (tempDirEnv != NULL)
277 		snprintf(result,resultsize,"%s/PixieTemp_%d/",tempDirEnv,getpid());
278 	else
279 		snprintf(result,resultsize,"PixieTemp_%d/",getpid());
280 #endif
281 
282 	osFixSlashes(result);
283 }
284 
285 
286 ///////////////////////////////////////////////////////////////////////
287 // Function				:	osTempname
288 // Description			:	Create a temporary file
289 // Return Value			:	-
290 // Comments				:	The directory must end with / (or \)
osTempname(const char * directory,const char * prefix,char * result)291 void	osTempname(const char *directory,const char *prefix,char *result) {
292 	#ifdef _WINDOWS
293 		// avoid some windows shortcomings by extending count when we
294 		// start to get clashes
295 		static int i = 0;
296 		sprintf(result,"%s%s-%4xXXXXXXXX",directory,prefix,i);
297 		while(_mktemp(result) == NULL) {
298 			sprintf(result,"%s%s-%4xXXXXXXXX",directory,prefix,i++);
299 		}
300 	#else
301 		sprintf(result,"%s%s-XXXXXXXX",directory,prefix);
302 		mktemp(result);
303 	#endif
304 }
305 
306 
307 
308 
309 ///////////////////////////////////////////////////////////////////////
310 // Function				:	osCreateDir
311 // Description			:	Create a directory
312 // Return Value			:	-
313 // Comments				:
osCreateDir(const char * n)314 void	osCreateDir(const char *n) {
315 #ifdef _WINDOWS
316 		_mkdir(n);
317 #else
318 		mkdir(n,S_IRWXU);
319 #endif
320 }
321 
322 ///////////////////////////////////////////////////////////////////////
323 // Function				:	osDeleteDir
324 // Description			:	Remove a directory
325 // Return Value			:	-
326 // Comments				:
osDeleteDir(const char * n)327 void	osDeleteDir(const char *n)	{
328 #ifdef _WINDOWS
329 	_rmdir(n);
330 #else
331 	rmdir(n);
332 #endif
333 }
334 
335 ///////////////////////////////////////////////////////////////////////
336 // Function				:	osDeleteFile
337 // Description			:	Delete a file
338 // Return Value			:	-
339 // Comments				:
osDeleteFile(const char * n)340 void	osDeleteFile(const char *n)	{
341 #ifdef _WINDOWS
342 	_unlink(n);
343 #else
344 	unlink(n);
345 #endif
346 }
347 
348 
349 ///////////////////////////////////////////////////////////////////////
350 // Function				:	enumerate
351 // Description			:	Enumerate the files matching a criteria
352 // Return Value			:
353 // Comments				:
osEnumerate(const char * name,int (* callback)(const char *,void *),void * userData)354 void	osEnumerate(const char *name,int (*callback)(const char *,void *),void *userData) {
355 #ifdef _WINDOWS
356 	_finddata_t	c_file;
357 	intptr_t	hFile;
358 	char		tmp[OS_MAX_PATH_LENGTH];
359 	char		*tmpp;
360 
361 	strcpy(tmp,name);
362 	osFixSlashes(tmp);
363 
364 	tmpp	=	strrchr(tmp,OS_DIR_SEPERATOR);
365 	if (tmpp == NULL) {
366 		tmpp	=	tmp;
367 	} else {
368 		tmpp++;
369 	}
370 
371 	if( (hFile = _findfirst(name, &c_file )) == -1L ) {
372 	} else {
373 		strcpy(tmpp,c_file.name);
374 		if (callback(tmp,userData) == TRUE) {
375 			while( _findnext( hFile, &c_file ) == 0 ) {
376 				strcpy(tmpp,c_file.name);
377 				if (callback(tmp,userData) == FALSE)	break;
378 			}
379 		}
380 
381 		_findclose( hFile );
382 	}
383 #else
384 	glob_t	globbuf;
385 	int		i;
386 
387 	globbuf.gl_offs =       0;
388 	glob(name,GLOB_DOOFFS,NULL,&globbuf);
389 
390 
391 	for (i=0;i<globbuf.gl_pathc;i++) {
392 		if (callback(globbuf.gl_pathv[i],userData) == FALSE)	break;
393 	}
394 
395 	globfree(&globbuf);
396 #endif
397 }
398 
399 ///////////////////////////////////////////////////////////////////////
400 // Function				:	osTime
401 // Description			:	Get the time
402 // Return Value			:
403 // Comments				:
osTime()404 float	osTime() {
405 	struct timeval	ti;
406 
407 	gettimeofday(&ti, NULL);
408 
409 	return (float) (ti.tv_sec - osStartTimeSec) + (ti.tv_usec - osStartTimeMsec) / 1000000.0f;
410 }
411 
412 ///////////////////////////////////////////////////////////////////////
413 // Function				:	osTime
414 // Description			:	Get the time
415 // Return Value			:
416 // Comments				:
osCPUTime()417 float	osCPUTime() {
418 	return	clock() / (float) CLOCKS_PER_SEC;
419 }
420 
421 ///////////////////////////////////////////////////////////////////////
422 // Function				:	osCreateThread
423 // Description			:	Start a thread
424 // Return Value			:
425 // Comments				:
osCreateThread(TFun entry,void * d)426 TThread	osCreateThread(TFun entry,void *d) {
427 	TThread	cThread;
428 
429 #ifdef _WINDOWS
430 	DWORD		id;
431 
432 	cThread				=	CreateThread(NULL,80000000,entry,d,0,&id);
433 #else
434 	pthread_attr_t attr;
435 	pthread_attr_init(&attr);
436 	pthread_attr_setstacksize(&attr,1024*1024*8);//8MB stack
437 	pthread_create(&cThread,&attr,entry,d);
438 	pthread_attr_destroy(&attr);
439 	//pthread_create(&cThread,NULL,entry,d);
440 #endif
441 
442 	return	cThread;
443 }
444 
445 ///////////////////////////////////////////////////////////////////////
446 // Function				:	osWaitThread
447 // Description			:	Wait for the termination of a thread
448 // Return Value			:
449 // Comments				:
osWaitThread(TThread thread)450 int		osWaitThread(TThread	thread) {
451 #ifdef _WINDOWS
452 	WaitForSingleObject(thread,INFINITE);
453 #else
454 	return pthread_join(thread,NULL);
455 #endif
456 
457 	return 0;
458 }
459 
460 ///////////////////////////////////////////////////////////////////////
461 // Function				:	osCreateMutex
462 // Description			:	Create a mutex
463 // Return Value			:
464 // Comments				:
osCreateMutex(TMutex & mutex)465 void	osCreateMutex(TMutex &mutex) {
466 #ifdef _WINDOWS
467 	InitializeCriticalSection(&mutex);
468 #else
469 	pthread_mutex_init(&mutex,NULL);
470 #endif
471 }
472 
473 ///////////////////////////////////////////////////////////////////////
474 // Function				:	osDeleteMutex
475 // Description			:	Delete a mutex
476 // Return Value			:
477 // Comments				:
osDeleteMutex(TMutex & mutex)478 void	osDeleteMutex(TMutex &mutex) {
479 #ifdef _WINDOWS
480 	DeleteCriticalSection(&mutex);
481 #else
482 	pthread_mutex_destroy(&mutex);
483 #endif
484 }
485 
486 ///////////////////////////////////////////////////////////////////////
487 // Function				:	osCreateSemaphore
488 // Description			:	Create a semaphere
489 // Return Value			:
490 // Comments				:
osCreateSemaphore(TSemaphore & sem,int count)491 void	osCreateSemaphore(TSemaphore &sem,int count) {
492 #ifdef _WINDOWS
493 	sem	=	CreateSemaphore(NULL,0,count,NULL);
494 #else
495 	sem_init(&sem,PTHREAD_PROCESS_PRIVATE,count);
496 #endif
497 }
498 
499 ///////////////////////////////////////////////////////////////////////
500 // Function				:	osDeleteMutex
501 // Description			:	Delete a mutex
502 // Return Value			:
503 // Comments				:
osDeleteSemaphore(TSemaphore & sem)504 void	osDeleteSemaphore(TSemaphore &sem) {
505 #ifdef _WINDOWS
506 	CloseHandle(sem);
507 #else
508 	sem_destroy(&sem);
509 #endif
510 }
511 
512 
513 ///////////////////////////////////////////////////////////////////////
514 // Function				:	osProcessEscapes
515 // Description			:	Process the escape characters in a string
516 // Return Value			:
517 // Comments				:
osProcessEscapes(char * str)518 void	osProcessEscapes(char *str) {
519 	int		i,n,j;
520 
521 	n	=	(int) strlen(str);
522 	for (i=0;i<n;i++) {
523 		if (str[i] == '\\') {
524 			switch(str[i+1]) {
525 			case 'n':
526 				str[i]	=	'\n';
527 				break;
528 			case 't':
529 				str[i]	=	'\t';
530 				break;
531 			case 'r':
532 				str[i]	=	'\r';
533 				break;
534 			case '\\':
535 				str[i]	=	'\\';
536 				break;
537 			default:
538 				break;
539 			}
540 
541 			j	=	i+2;
542 			do {
543 				str[j-1]	=	str[j];
544 				j++;
545 			} while(str[j] != '\0');
546 			n--;
547 			i++;
548 		}
549 	}
550 	str[i]	=	'\0';
551 }
552 
553 ///////////////////////////////////////////////////////////////////////
554 // Function            :   osAvailableCPUs
555 // Description         :   Get number of CPUs available
556 // Return Value        :   Number of available CPUs or -1 if unknown
557 // Comments            :   See <http://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine>
osAvailableCPUs()558 int    osAvailableCPUs() {
559 
560 #if defined(WIN32)
561 	SYSTEM_INFO sys_info;
562     GetSystemInfo(&sys_info);
563     return sys_info.dwNumberOfProcessors;
564 
565 #elif defined(CTL_HW)
566 	// BSD, Mac OS X
567 	int ncpu = 0;
568 	int mib[2];
569 	size_t sz = sizeof(ncpu);
570 	mib[0] = CTL_HW;
571 #ifdef HW_AVAILCPU
572 	mib[1] = HW_AVAILCPU;
573 #else
574 	mib[1] = HW_NCPU;
575 #endif
576 	if(sysctl(mib, 2, &ncpu, &sz, NULL, 0) == -1)
577 		return ncpu;
578 
579 #elif defined(_SC_NPROCESSORS_ONLN)
580 	// Linux, AIX, Solaris
581 	return sysconf( _SC_NPROCESSORS_ONLN );
582 
583 #elif defined(MPC_GETNUMSPUS)
584 	// HP-UX
585 	return mpctl(MPC_GETNUMSPUS, NULL, NULL);
586 
587 #elif defined(_SC_NPROC_ONLN)
588 	// IRIX
589 	return sysconf( _SC_NPROC_ONLN );
590 #endif
591 
592 	return -1;
593 }
594 
595 
596