2017-08-18 16:52:05 -07:00
/*
2017-08-21 11:24:32 -07:00
* Copyright ( c ) 2016 - present , Przemyslaw Skibinski , Yann Collet , Facebook , Inc .
2016-12-21 06:08:44 -08:00
* All rights reserved .
*
2017-08-18 16:52:05 -07:00
* This source code is licensed under both the BSD - style license ( found in the
* LICENSE file in the root directory of this source tree ) and the GPLv2 ( found
* in the COPYING file in the root directory of this source tree ) .
2017-09-08 00:09:23 -07:00
* You may select , at your option , one of the above - listed licenses .
2016-12-21 06:08:44 -08:00
*/
2016-05-09 07:19:25 -07:00
2016-04-28 03:23:33 -07:00
# ifndef UTIL_H_MODULE
# define UTIL_H_MODULE
# if defined (__cplusplus)
extern " C " {
# endif
2016-05-05 02:53:42 -07:00
2016-12-21 04:23:34 -08:00
2016-04-28 03:23:33 -07:00
/*-****************************************
* Dependencies
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-21 04:23:34 -08:00
# include "platform.h" /* PLATFORM_POSIX_VERSION */
# include <stdlib.h> /* malloc */
# include <stddef.h> /* size_t, ptrdiff_t */
# include <stdio.h> /* fprintf */
2017-04-13 12:28:28 -07:00
# include <string.h> /* strncmp */
2016-12-21 04:23:34 -08:00
# include <sys/types.h> /* stat, utime */
# include <sys/stat.h> /* stat */
2016-11-03 01:54:53 -07:00
# if defined(_MSC_VER)
2016-12-21 04:23:34 -08:00
# include <sys / utime.h> /* utime */
# include <io.h> /* _chmod */
2016-11-03 01:54:53 -07:00
# else
2016-12-11 16:03:23 -08:00
# include <unistd.h> /* chown, stat */
# include <utime.h> /* utime */
2016-11-03 01:54:53 -07:00
# endif
2016-12-21 04:23:34 -08:00
# include <time.h> /* time */
2016-11-03 01:54:53 -07:00
# include <errno.h>
2016-12-21 04:23:34 -08:00
# include "mem.h" /* U32, U64 */
2016-04-28 03:23:33 -07:00
2016-05-04 15:25:38 -07:00
2017-02-15 08:03:16 -08:00
/* ************************************************************
* Avoid fseek ( ) ' s 2 GiB barrier with MSVC , MacOS , * BSD , MinGW
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(_MSC_VER) && (_MSC_VER >= 1400)
# define UTIL_fseek _fseeki64
# elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */
# define UTIL_fseek fseeko
# elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)
# define UTIL_fseek fseeko64
# else
# define UTIL_fseek fseek
# endif
2016-05-05 02:53:42 -07:00
/*-****************************************
* Sleep functions : Windows - Posix - others
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-04 15:25:38 -07:00
# if defined(_WIN32)
2016-04-28 04:16:01 -07:00
# include <windows.h>
2017-02-07 07:36:19 -08:00
# define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
2016-04-28 04:16:01 -07:00
# define UTIL_sleep(s) Sleep(1000*s)
# define UTIL_sleepMilli(milli) Sleep(milli)
2016-12-16 06:41:18 -08:00
# elif PLATFORM_POSIX_VERSION >= 0 /* Unix-like operating system */
2016-05-04 15:25:38 -07:00
# include <unistd.h>
# include <sys / resource.h> /* setpriority */
# include <time.h> /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */
2016-05-21 04:15:48 -07:00
# if defined(PRIO_PROCESS)
2017-02-07 07:36:19 -08:00
# define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
2016-05-21 04:15:48 -07:00
# else
2017-02-07 07:36:19 -08:00
# define SET_REALTIME_PRIORITY /* disabled */
2016-05-21 04:15:48 -07:00
# endif
2016-05-04 15:25:38 -07:00
# define UTIL_sleep(s) sleep(s)
2016-12-16 06:41:18 -08:00
# if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) || (PLATFORM_POSIX_VERSION >= 200112L) /* nanosleep requires POSIX.1-2001 */
2016-05-05 02:53:42 -07:00
# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }
# else
# define UTIL_sleepMilli(milli) /* disabled */
# endif
2016-04-28 04:16:01 -07:00
# else
2017-02-07 07:36:19 -08:00
# define SET_REALTIME_PRIORITY /* disabled */
2016-05-04 15:25:38 -07:00
# define UTIL_sleep(s) /* disabled */
2016-04-28 04:16:01 -07:00
# define UTIL_sleepMilli(milli) /* disabled */
# endif
2016-05-04 15:25:38 -07:00
2016-12-21 00:04:59 -08:00
/* *************************************
* Constants
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define LIST_SIZE_INCREASE (8*1024)
/*-****************************************
* Compiler specifics
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-21 04:23:34 -08:00
# if defined(__INTEL_COMPILER)
# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */
# endif
2016-12-21 00:04:59 -08:00
# if defined(__GNUC__)
# define UTIL_STATIC static __attribute__((unused))
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ )
# define UTIL_STATIC static inline
# elif defined(_MSC_VER)
# define UTIL_STATIC static __inline
# else
# define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
# endif
2017-08-31 16:58:47 -07:00
/*-****************************************
* Console log
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int g_utilDisplayLevel ;
# define UTIL_DISPLAY(...) fprintf(stderr, __VA_ARGS__)
# define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }
2016-05-04 15:25:38 -07:00
/*-****************************************
* Time functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-02-20 02:11:50 -08:00
# if defined(_WIN32) /* Windows */
2017-02-20 02:27:11 -08:00
typedef LARGE_INTEGER UTIL_freq_t ;
2016-04-28 04:16:01 -07:00
typedef LARGE_INTEGER UTIL_time_t ;
2017-08-31 16:58:47 -07:00
UTIL_STATIC void UTIL_initTimer ( UTIL_freq_t * ticksPerSecond ) { if ( ! QueryPerformanceFrequency ( ticksPerSecond ) ) UTIL_DISPLAYLEVEL ( 1 , " ERROR: QueryPerformance not present \n " ) ; }
2016-05-09 07:19:25 -07:00
UTIL_STATIC void UTIL_getTime ( UTIL_time_t * x ) { QueryPerformanceCounter ( x ) ; }
2017-02-20 02:27:11 -08:00
UTIL_STATIC U64 UTIL_getSpanTimeMicro ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return 1000000ULL * ( clockEnd . QuadPart - clockStart . QuadPart ) / ticksPerSecond . QuadPart ; }
UTIL_STATIC U64 UTIL_getSpanTimeNano ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return 1000000000ULL * ( clockEnd . QuadPart - clockStart . QuadPart ) / ticksPerSecond . QuadPart ; }
2017-02-20 03:18:15 -08:00
# elif defined(__APPLE__) && defined(__MACH__)
# include <mach/mach_time.h>
typedef mach_timebase_info_data_t UTIL_freq_t ;
typedef U64 UTIL_time_t ;
2017-02-21 03:22:05 -08:00
UTIL_STATIC void UTIL_initTimer ( UTIL_freq_t * rate ) { mach_timebase_info ( rate ) ; }
2017-02-20 03:18:15 -08:00
UTIL_STATIC void UTIL_getTime ( UTIL_time_t * x ) { * x = mach_absolute_time ( ) ; }
UTIL_STATIC U64 UTIL_getSpanTimeMicro ( UTIL_freq_t rate , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return ( ( ( clockEnd - clockStart ) * ( U64 ) rate . numer ) / ( ( U64 ) rate . denom ) ) / 1000ULL ; }
UTIL_STATIC U64 UTIL_getSpanTimeNano ( UTIL_freq_t rate , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return ( ( clockEnd - clockStart ) * ( U64 ) rate . numer ) / ( ( U64 ) rate . denom ) ; }
2017-02-20 22:33:45 -08:00
# elif (PLATFORM_POSIX_VERSION >= 200112L)
# include <sys/times.h> /* times */
typedef U64 UTIL_freq_t ;
typedef U64 UTIL_time_t ;
UTIL_STATIC void UTIL_initTimer ( UTIL_freq_t * ticksPerSecond ) { * ticksPerSecond = sysconf ( _SC_CLK_TCK ) ; }
UTIL_STATIC void UTIL_getTime ( UTIL_time_t * x ) { struct tms junk ; clock_t newTicks = ( clock_t ) times ( & junk ) ; ( void ) junk ; * x = ( UTIL_time_t ) newTicks ; }
UTIL_STATIC U64 UTIL_getSpanTimeMicro ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return 1000000ULL * ( clockEnd - clockStart ) / ticksPerSecond ; }
UTIL_STATIC U64 UTIL_getSpanTimeNano ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { return 1000000000ULL * ( clockEnd - clockStart ) / ticksPerSecond ; }
2017-01-20 12:23:30 -08:00
# else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
2017-02-20 02:27:11 -08:00
typedef clock_t UTIL_freq_t ;
2017-01-20 12:23:30 -08:00
typedef clock_t UTIL_time_t ;
2017-02-20 02:27:11 -08:00
UTIL_STATIC void UTIL_initTimer ( UTIL_freq_t * ticksPerSecond ) { * ticksPerSecond = 0 ; }
2017-01-20 12:23:30 -08:00
UTIL_STATIC void UTIL_getTime ( UTIL_time_t * x ) { * x = clock ( ) ; }
2017-02-20 02:27:11 -08:00
UTIL_STATIC U64 UTIL_getSpanTimeMicro ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { ( void ) ticksPerSecond ; return 1000000ULL * ( clockEnd - clockStart ) / CLOCKS_PER_SEC ; }
UTIL_STATIC U64 UTIL_getSpanTimeNano ( UTIL_freq_t ticksPerSecond , UTIL_time_t clockStart , UTIL_time_t clockEnd ) { ( void ) ticksPerSecond ; return 1000000000ULL * ( clockEnd - clockStart ) / CLOCKS_PER_SEC ; }
2016-04-28 04:16:01 -07:00
# endif
/* returns time span in microseconds */
2017-02-20 02:27:11 -08:00
UTIL_STATIC U64 UTIL_clockSpanMicro ( UTIL_time_t clockStart , UTIL_freq_t ticksPerSecond )
2016-04-28 04:16:01 -07:00
{
UTIL_time_t clockEnd ;
2016-05-09 07:19:25 -07:00
UTIL_getTime ( & clockEnd ) ;
2016-04-28 04:16:01 -07:00
return UTIL_getSpanTimeMicro ( ticksPerSecond , clockStart , clockEnd ) ;
}
2017-02-20 02:27:11 -08:00
UTIL_STATIC void UTIL_waitForNextTick ( UTIL_freq_t ticksPerSecond )
2016-04-28 04:16:01 -07:00
{
UTIL_time_t clockStart , clockEnd ;
2016-05-09 07:19:25 -07:00
UTIL_getTime ( & clockStart ) ;
2016-05-20 02:24:35 -07:00
do {
UTIL_getTime ( & clockEnd ) ;
2016-04-28 05:40:45 -07:00
} while ( UTIL_getSpanTimeNano ( ticksPerSecond , clockStart , clockEnd ) = = 0 ) ;
2016-04-28 04:16:01 -07:00
}
2016-05-04 15:25:38 -07:00
/*-****************************************
* File functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-11-02 06:08:07 -07:00
# if defined(_MSC_VER)
2017-03-29 18:51:58 -07:00
# define chmod _chmod
typedef struct __stat64 stat_t ;
2016-11-02 06:08:07 -07:00
# else
typedef struct stat stat_t ;
# endif
UTIL_STATIC int UTIL_setFileStat ( const char * filename , stat_t * statbuf )
2016-11-02 04:52:20 -07:00
{
2016-11-02 06:08:07 -07:00
int res = 0 ;
struct utimbuf timebuf ;
2017-03-29 18:51:58 -07:00
timebuf . actime = time ( NULL ) ;
timebuf . modtime = statbuf - > st_mtime ;
res + = utime ( filename , & timebuf ) ; /* set access and modification times */
2016-11-03 01:54:53 -07:00
2016-11-02 06:08:07 -07:00
# if !defined(_WIN32)
res + = chown ( filename , statbuf - > st_uid , statbuf - > st_gid ) ; /* Copy ownership */
# endif
2016-11-02 04:52:20 -07:00
2016-11-02 06:08:07 -07:00
res + = chmod ( filename , statbuf - > st_mode & 07777 ) ; /* Copy file permissions */
2016-11-02 04:52:20 -07:00
2016-11-02 06:08:07 -07:00
errno = 0 ;
return - res ; /* number of errors is returned */
2016-11-02 04:52:20 -07:00
}
2016-11-02 06:08:07 -07:00
UTIL_STATIC int UTIL_getFileStat ( const char * infilename , stat_t * statbuf )
2016-11-02 04:52:20 -07:00
{
int r ;
# if defined(_MSC_VER)
2016-11-02 06:08:07 -07:00
r = _stat64 ( infilename , statbuf ) ;
if ( r | | ! ( statbuf - > st_mode & S_IFREG ) ) return 0 ; /* No good... */
2016-11-02 04:52:20 -07:00
# else
2016-11-02 06:08:07 -07:00
r = stat ( infilename , statbuf ) ;
if ( r | | ! S_ISREG ( statbuf - > st_mode ) ) return 0 ; /* No good... */
2016-11-02 04:52:20 -07:00
# endif
2016-11-02 06:08:07 -07:00
return 1 ;
2016-11-02 04:52:20 -07:00
}
2017-02-14 00:38:51 -08:00
2017-05-17 18:36:15 -07:00
UTIL_STATIC int UTIL_isRegularFile ( const char * infilename )
2017-02-07 16:33:48 -08:00
{
stat_t statbuf ;
return UTIL_getFileStat ( infilename , & statbuf ) ; /* Only need to know whether it is a regular file */
}
2016-11-02 04:52:20 -07:00
2017-02-14 00:38:51 -08:00
UTIL_STATIC U32 UTIL_isDirectory ( const char * infilename )
{
int r ;
stat_t statbuf ;
# if defined(_MSC_VER)
r = _stat64 ( infilename , & statbuf ) ;
if ( ! r & & ( statbuf . st_mode & _S_IFDIR ) ) return 1 ;
# else
r = stat ( infilename , & statbuf ) ;
if ( ! r & & S_ISDIR ( statbuf . st_mode ) ) return 1 ;
# endif
return 0 ;
}
2017-03-23 11:52:09 -07:00
UTIL_STATIC U32 UTIL_isLink ( const char * infilename )
{
# if defined(_WIN32)
/* no symlinks on windows */
( void ) infilename ;
# else
int r ;
stat_t statbuf ;
r = lstat ( infilename , & statbuf ) ;
if ( ! r & & S_ISLNK ( statbuf . st_mode ) ) return 1 ;
# endif
return 0 ;
}
2017-02-14 00:38:51 -08:00
2016-04-28 03:23:33 -07:00
UTIL_STATIC U64 UTIL_getFileSize ( const char * infilename )
{
int r ;
# if defined(_MSC_VER)
2017-02-13 04:57:29 -08:00
struct __stat64 statbuf ;
2016-04-28 03:23:33 -07:00
r = _stat64 ( infilename , & statbuf ) ;
if ( r | | ! ( statbuf . st_mode & S_IFREG ) ) return 0 ; /* No good... */
2017-02-10 09:37:57 -08:00
# elif defined(__MINGW32__) && defined (__MSVCRT__)
struct _stati64 statbuf ;
r = _stati64 ( infilename , & statbuf ) ;
if ( r | | ! ( statbuf . st_mode & S_IFREG ) ) return 0 ; /* No good... */
2016-04-28 03:23:33 -07:00
# else
struct stat statbuf ;
r = stat ( infilename , & statbuf ) ;
if ( r | | ! S_ISREG ( statbuf . st_mode ) ) return 0 ; /* No good... */
# endif
return ( U64 ) statbuf . st_size ;
}
2016-04-28 07:50:13 -07:00
UTIL_STATIC U64 UTIL_getTotalFileSize ( const char * * fileNamesTable , unsigned nbFiles )
{
U64 total = 0 ;
unsigned n ;
for ( n = 0 ; n < nbFiles ; n + + )
total + = UTIL_getFileSize ( fileNamesTable [ n ] ) ;
return total ;
}
2016-09-15 09:58:18 -07:00
/*
* A modified version of realloc ( ) .
* If UTIL_realloc ( ) fails the original block is freed .
*/
UTIL_STATIC void * UTIL_realloc ( void * ptr , size_t size )
{
void * newptr = realloc ( ptr , size ) ;
if ( newptr ) return newptr ;
free ( ptr ) ;
return NULL ;
}
2016-05-04 15:25:38 -07:00
# ifdef _WIN32
2016-05-05 02:53:42 -07:00
# define UTIL_HAS_CREATEFILELIST
2016-05-04 15:25:38 -07:00
2017-03-23 11:52:09 -07:00
UTIL_STATIC int UTIL_prepareFileList ( const char * dirName , char * * bufStart , size_t * pos , char * * bufEnd , int followLinks )
2016-05-04 15:25:38 -07:00
{
2016-09-13 04:13:10 -07:00
char * path ;
int dirLength , fnameLength , pathLength , nbFiles = 0 ;
2017-02-15 08:13:35 -08:00
WIN32_FIND_DATAA cFile ;
2016-05-04 15:25:38 -07:00
HANDLE hFile ;
2016-09-13 07:38:54 -07:00
dirLength = ( int ) strlen ( dirName ) ;
2016-09-13 04:13:10 -07:00
path = ( char * ) malloc ( dirLength + 3 ) ;
if ( ! path ) return 0 ;
memcpy ( path , dirName , dirLength ) ;
path [ dirLength ] = ' \\ ' ;
path [ dirLength + 1 ] = ' * ' ;
path [ dirLength + 2 ] = 0 ;
2016-05-04 15:25:38 -07:00
2017-02-15 08:13:35 -08:00
hFile = FindFirstFileA ( path , & cFile ) ;
2016-05-04 15:25:38 -07:00
if ( hFile = = INVALID_HANDLE_VALUE ) {
2017-08-31 16:58:47 -07:00
UTIL_DISPLAYLEVEL ( 1 , " Cannot open directory '%s' \n " , dirName ) ;
2016-05-04 15:25:38 -07:00
return 0 ;
}
2016-09-13 04:13:10 -07:00
free ( path ) ;
2016-05-04 15:25:38 -07:00
2016-05-11 05:11:00 -07:00
do {
2016-09-13 07:38:54 -07:00
fnameLength = ( int ) strlen ( cFile . cFileName ) ;
2016-09-13 04:13:10 -07:00
path = ( char * ) malloc ( dirLength + fnameLength + 2 ) ;
if ( ! path ) { FindClose ( hFile ) ; return 0 ; }
memcpy ( path , dirName , dirLength ) ;
path [ dirLength ] = ' \\ ' ;
memcpy ( path + dirLength + 1 , cFile . cFileName , fnameLength ) ;
pathLength = dirLength + 1 + fnameLength ;
path [ pathLength ] = 0 ;
2016-05-04 15:25:38 -07:00
if ( cFile . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
if ( strcmp ( cFile . cFileName , " .. " ) = = 0 | |
2016-05-11 05:11:00 -07:00
strcmp ( cFile . cFileName , " . " ) = = 0 ) continue ;
2016-08-24 08:32:09 -07:00
2017-03-23 11:52:09 -07:00
nbFiles + = UTIL_prepareFileList ( path , bufStart , pos , bufEnd , followLinks ) ; /* Recursively call "UTIL_prepareFileList" with the new path. */
2016-09-13 04:13:10 -07:00
if ( * bufStart = = NULL ) { free ( path ) ; FindClose ( hFile ) ; return 0 ; }
2016-05-04 15:25:38 -07:00
}
else if ( ( cFile . dwFileAttributes & FILE_ATTRIBUTE_NORMAL ) | | ( cFile . dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ) | | ( cFile . dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ) ) {
2016-05-11 05:11:00 -07:00
if ( * bufStart + * pos + pathLength > = * bufEnd ) {
ptrdiff_t newListSize = ( * bufEnd - * bufStart ) + LIST_SIZE_INCREASE ;
2016-09-15 09:58:18 -07:00
* bufStart = ( char * ) UTIL_realloc ( * bufStart , newListSize ) ;
2016-05-11 05:11:00 -07:00
* bufEnd = * bufStart + newListSize ;
2016-09-13 04:13:10 -07:00
if ( * bufStart = = NULL ) { free ( path ) ; FindClose ( hFile ) ; return 0 ; }
2016-05-11 05:11:00 -07:00
}
if ( * bufStart + * pos + pathLength < * bufEnd ) {
strncpy ( * bufStart + * pos , path , * bufEnd - ( * bufStart + * pos ) ) ;
* pos + = pathLength + 1 ;
nbFiles + + ;
}
2016-05-04 15:25:38 -07:00
}
2016-09-13 04:13:10 -07:00
free ( path ) ;
2017-02-15 08:13:35 -08:00
} while ( FindNextFileA ( hFile , & cFile ) ) ;
2016-05-04 15:25:38 -07:00
FindClose ( hFile ) ;
return nbFiles ;
}
2016-12-16 08:12:23 -08:00
# elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
2016-05-05 02:53:42 -07:00
# define UTIL_HAS_CREATEFILELIST
2016-05-04 15:25:38 -07:00
# include <dirent.h> /* opendir, readdir */
2016-12-21 00:04:59 -08:00
# include <string.h> /* strerror, memcpy */
2016-05-04 15:25:38 -07:00
2017-03-23 11:52:09 -07:00
UTIL_STATIC int UTIL_prepareFileList ( const char * dirName , char * * bufStart , size_t * pos , char * * bufEnd , int followLinks )
2016-05-04 15:25:38 -07:00
{
DIR * dir ;
struct dirent * entry ;
2016-09-13 04:13:10 -07:00
char * path ;
int dirLength , fnameLength , pathLength , nbFiles = 0 ;
2016-05-04 15:25:38 -07:00
if ( ! ( dir = opendir ( dirName ) ) ) {
2017-08-31 16:58:47 -07:00
UTIL_DISPLAYLEVEL ( 1 , " Cannot open directory '%s': %s \n " , dirName , strerror ( errno ) ) ;
2016-05-04 15:25:38 -07:00
return 0 ;
}
2016-05-20 02:24:35 -07:00
2016-09-13 07:38:54 -07:00
dirLength = ( int ) strlen ( dirName ) ;
2016-07-26 02:07:37 -07:00
errno = 0 ;
2016-05-12 08:15:41 -07:00
while ( ( entry = readdir ( dir ) ) ! = NULL ) {
2016-05-05 04:10:57 -07:00
if ( strcmp ( entry - > d_name , " .. " ) = = 0 | |
strcmp ( entry - > d_name , " . " ) = = 0 ) continue ;
2016-09-13 07:38:54 -07:00
fnameLength = ( int ) strlen ( entry - > d_name ) ;
2016-09-13 04:13:10 -07:00
path = ( char * ) malloc ( dirLength + fnameLength + 2 ) ;
if ( ! path ) { closedir ( dir ) ; return 0 ; }
memcpy ( path , dirName , dirLength ) ;
2017-03-23 11:52:09 -07:00
2016-09-13 04:13:10 -07:00
path [ dirLength ] = ' / ' ;
memcpy ( path + dirLength + 1 , entry - > d_name , fnameLength ) ;
pathLength = dirLength + 1 + fnameLength ;
path [ pathLength ] = 0 ;
2017-03-23 11:52:09 -07:00
if ( ! followLinks & & UTIL_isLink ( path ) ) {
UTIL_DISPLAYLEVEL ( 2 , " Warning : %s is a symbolic link, ignoring \n " , path ) ;
continue ;
}
2016-05-05 04:10:57 -07:00
if ( UTIL_isDirectory ( path ) ) {
2017-03-23 11:52:09 -07:00
nbFiles + = UTIL_prepareFileList ( path , bufStart , pos , bufEnd , followLinks ) ; /* Recursively call "UTIL_prepareFileList" with the new path. */
2016-09-13 04:13:10 -07:00
if ( * bufStart = = NULL ) { free ( path ) ; closedir ( dir ) ; return 0 ; }
2016-05-04 15:25:38 -07:00
} else {
2016-05-11 05:11:00 -07:00
if ( * bufStart + * pos + pathLength > = * bufEnd ) {
ptrdiff_t newListSize = ( * bufEnd - * bufStart ) + LIST_SIZE_INCREASE ;
2016-09-15 09:58:18 -07:00
* bufStart = ( char * ) UTIL_realloc ( * bufStart , newListSize ) ;
2016-05-11 05:11:00 -07:00
* bufEnd = * bufStart + newListSize ;
2016-09-13 04:13:10 -07:00
if ( * bufStart = = NULL ) { free ( path ) ; closedir ( dir ) ; return 0 ; }
2016-05-11 05:11:00 -07:00
}
if ( * bufStart + * pos + pathLength < * bufEnd ) {
strncpy ( * bufStart + * pos , path , * bufEnd - ( * bufStart + * pos ) ) ;
* pos + = pathLength + 1 ;
nbFiles + + ;
}
2016-05-04 15:25:38 -07:00
}
2016-09-13 04:13:10 -07:00
free ( path ) ;
2016-08-24 08:32:09 -07:00
errno = 0 ; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
2016-05-04 15:25:38 -07:00
}
2016-07-26 02:07:37 -07:00
if ( errno ! = 0 ) {
2017-08-31 16:58:47 -07:00
UTIL_DISPLAYLEVEL ( 1 , " readdir(%s) error: %s \n " , dirName , strerror ( errno ) ) ;
2016-07-26 02:07:37 -07:00
free ( * bufStart ) ;
* bufStart = NULL ;
}
2016-05-04 15:25:38 -07:00
closedir ( dir ) ;
return nbFiles ;
}
# else
2017-03-23 11:52:09 -07:00
UTIL_STATIC int UTIL_prepareFileList ( const char * dirName , char * * bufStart , size_t * pos , char * * bufEnd , int followLinks )
2016-05-04 15:25:38 -07:00
{
2016-05-11 05:11:00 -07:00
( void ) bufStart ; ( void ) bufEnd ; ( void ) pos ;
2017-08-31 16:58:47 -07:00
UTIL_DISPLAYLEVEL ( 1 , " Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE) \n " , dirName ) ;
2016-05-04 15:25:38 -07:00
return 0 ;
}
2016-08-24 08:32:09 -07:00
# endif /* #ifdef _WIN32 */
2016-05-04 15:25:38 -07:00
2016-05-20 02:24:35 -07:00
/*
* UTIL_createFileList - takes a list of files and directories ( params : inputNames , inputNamesNb ) , scans directories ,
2016-05-13 01:52:02 -07:00
* and returns a new list of files ( params : return value , allocatedBuffer , allocatedNamesNb ) .
* After finishing usage of the list the structures should be freed with UTIL_freeFileList ( params : return value , allocatedBuffer )
* In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called .
*/
2017-03-23 11:52:09 -07:00
UTIL_STATIC const char * * UTIL_createFileList ( const char * * inputNames , unsigned inputNamesNb , char * * allocatedBuffer , unsigned * allocatedNamesNb , int followLinks )
2016-05-04 15:25:38 -07:00
{
2016-05-11 05:11:00 -07:00
size_t pos ;
2016-05-13 01:52:02 -07:00
unsigned i , nbFiles ;
2016-12-11 16:03:23 -08:00
char * buf = ( char * ) malloc ( LIST_SIZE_INCREASE ) ;
char * bufend = buf + LIST_SIZE_INCREASE ;
2016-05-13 01:52:02 -07:00
const char * * fileTable ;
2016-05-04 15:25:38 -07:00
2016-05-13 01:52:02 -07:00
if ( ! buf ) return NULL ;
2016-05-05 02:53:42 -07:00
2016-05-13 01:52:02 -07:00
for ( i = 0 , pos = 0 , nbFiles = 0 ; i < inputNamesNb ; i + + ) {
2016-05-25 06:30:55 -07:00
if ( ! UTIL_isDirectory ( inputNames [ i ] ) ) {
2016-12-11 16:03:23 -08:00
size_t const len = strlen ( inputNames [ i ] ) ;
2016-05-11 05:11:00 -07:00
if ( buf + pos + len > = bufend ) {
ptrdiff_t newListSize = ( bufend - buf ) + LIST_SIZE_INCREASE ;
2016-09-15 09:58:18 -07:00
buf = ( char * ) UTIL_realloc ( buf , newListSize ) ;
2016-05-11 05:11:00 -07:00
bufend = buf + newListSize ;
2016-05-13 01:52:02 -07:00
if ( ! buf ) return NULL ;
2016-05-11 05:11:00 -07:00
}
if ( buf + pos + len < bufend ) {
strncpy ( buf + pos , inputNames [ i ] , bufend - ( buf + pos ) ) ;
pos + = len + 1 ;
nbFiles + + ;
}
2016-08-01 05:26:49 -07:00
} else {
2017-03-23 11:52:09 -07:00
nbFiles + = UTIL_prepareFileList ( inputNames [ i ] , & buf , & pos , & bufend , followLinks ) ;
2016-05-13 01:52:02 -07:00
if ( buf = = NULL ) return NULL ;
2016-08-01 05:26:49 -07:00
} }
2016-05-04 15:25:38 -07:00
2016-05-13 01:52:02 -07:00
if ( nbFiles = = 0 ) { free ( buf ) ; return NULL ; }
2016-05-04 15:25:38 -07:00
2016-05-13 01:52:02 -07:00
fileTable = ( const char * * ) malloc ( ( nbFiles + 1 ) * sizeof ( const char * ) ) ;
if ( ! fileTable ) { free ( buf ) ; return NULL ; }
2016-05-04 15:25:38 -07:00
2016-12-11 16:03:23 -08:00
for ( i = 0 , pos = 0 ; i < nbFiles ; i + + ) {
2016-05-13 01:52:02 -07:00
fileTable [ i ] = buf + pos ;
pos + = strlen ( fileTable [ i ] ) + 1 ;
2016-05-04 15:25:38 -07:00
}
2016-05-13 01:52:02 -07:00
if ( buf + pos > bufend ) { free ( buf ) ; free ( ( void * ) fileTable ) ; return NULL ; }
* allocatedBuffer = buf ;
* allocatedNamesNb = nbFiles ;
return fileTable ;
2016-05-04 15:25:38 -07:00
}
2016-05-13 01:52:02 -07:00
UTIL_STATIC void UTIL_freeFileList ( const char * * filenameTable , char * allocatedBuffer )
2016-05-04 15:25:38 -07:00
{
2016-05-13 01:52:02 -07:00
if ( allocatedBuffer ) free ( allocatedBuffer ) ;
if ( filenameTable ) free ( ( void * ) filenameTable ) ;
2016-05-04 15:25:38 -07:00
}
2017-04-13 12:28:28 -07:00
/* count the number of physical cores */
# if defined(_WIN32) || defined(WIN32)
# include <windows.h>
typedef BOOL ( WINAPI * LPFN_GLPI ) ( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION , PDWORD ) ;
UTIL_STATIC int UTIL_countPhysicalCores ( void )
{
2017-04-13 16:34:28 -07:00
static int numPhysicalCores = 0 ;
2017-04-13 12:28:28 -07:00
if ( numPhysicalCores ! = 0 ) return numPhysicalCores ;
{ LPFN_GLPI glpi ;
BOOL done = FALSE ;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL ;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL ;
DWORD returnLength = 0 ;
size_t byteOffset = 0 ;
glpi = ( LPFN_GLPI ) GetProcAddress ( GetModuleHandle ( TEXT ( " kernel32 " ) ) ,
" GetLogicalProcessorInformation " ) ;
if ( glpi = = NULL ) {
goto failed ;
}
while ( ! done ) {
DWORD rc = glpi ( buffer , & returnLength ) ;
if ( FALSE = = rc ) {
if ( GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER ) {
if ( buffer )
free ( buffer ) ;
buffer = ( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ) malloc ( returnLength ) ;
if ( buffer = = NULL ) {
perror ( " zstd " ) ;
exit ( 1 ) ;
}
} else {
/* some other error */
goto failed ;
}
} else {
done = TRUE ;
}
}
2017-04-13 14:03:56 -07:00
ptr = buffer ;
2017-04-13 12:28:28 -07:00
while ( byteOffset + sizeof ( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) < = returnLength ) {
2017-04-13 14:03:56 -07:00
if ( ptr - > Relationship = = RelationProcessorCore ) {
2017-04-13 12:28:28 -07:00
numPhysicalCores + + ;
}
2017-04-13 14:03:56 -07:00
ptr + + ;
byteOffset + = sizeof ( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) ;
2017-04-13 12:28:28 -07:00
}
free ( buffer ) ;
return numPhysicalCores ;
}
failed :
/* try to fall back on GetSystemInfo */
2017-04-13 14:03:56 -07:00
{ SYSTEM_INFO sysinfo ;
GetSystemInfo ( & sysinfo ) ;
numPhysicalCores = sysinfo . dwNumberOfProcessors ;
if ( numPhysicalCores = = 0 ) numPhysicalCores = 1 ; /* just in case */
}
2017-04-13 12:28:28 -07:00
return numPhysicalCores ;
}
# elif defined(__APPLE__)
# include <sys/sysctl.h>
/* Use apple-provided syscall
* see : man 3 sysctl */
UTIL_STATIC int UTIL_countPhysicalCores ( void )
{
2017-04-13 16:34:28 -07:00
static S32 numPhysicalCores = 0 ; /* apple specifies int32_t */
2017-04-13 12:28:28 -07:00
if ( numPhysicalCores ! = 0 ) return numPhysicalCores ;
2017-04-13 12:33:45 -07:00
{ size_t size = sizeof ( S32 ) ;
int const ret = sysctlbyname ( " hw.physicalcpu " , & numPhysicalCores , & size , NULL , 0 ) ;
2017-04-13 12:28:28 -07:00
if ( ret ! = 0 ) {
if ( errno = = ENOENT ) {
/* entry not present, fall back on 1 */
numPhysicalCores = 1 ;
} else {
perror ( " zstd: can't get number of physical cpus " ) ;
exit ( 1 ) ;
}
}
return numPhysicalCores ;
}
}
# elif defined(__linux__)
/* parse /proc/cpuinfo
* siblings / cpu cores should give hyperthreading ratio
* otherwise fall back on sysconf */
UTIL_STATIC int UTIL_countPhysicalCores ( void )
{
2017-04-13 16:34:28 -07:00
static int numPhysicalCores = 0 ;
2017-04-13 12:28:28 -07:00
if ( numPhysicalCores ! = 0 ) return numPhysicalCores ;
2017-04-13 14:06:40 -07:00
numPhysicalCores = ( int ) sysconf ( _SC_NPROCESSORS_ONLN ) ;
2017-04-13 12:28:28 -07:00
if ( numPhysicalCores = = - 1 ) {
/* value not queryable, fall back on 1 */
return numPhysicalCores = 1 ;
}
/* try to determine if there's hyperthreading */
{ FILE * const cpuinfo = fopen ( " /proc/cpuinfo " , " r " ) ;
2017-05-15 18:15:08 -07:00
# define BUF_SIZE 80
2017-04-13 12:28:28 -07:00
char buff [ BUF_SIZE ] ;
int siblings = 0 ;
int cpu_cores = 0 ;
int ratio = 1 ;
if ( cpuinfo = = NULL ) {
/* fall back on the sysconf value */
return numPhysicalCores ;
}
/* assume the cpu cores/siblings values will be constant across all
* present processors */
while ( ! feof ( cpuinfo ) ) {
if ( fgets ( buff , BUF_SIZE , cpuinfo ) ! = NULL ) {
if ( strncmp ( buff , " siblings " , 8 ) = = 0 ) {
const char * const sep = strchr ( buff , ' : ' ) ;
if ( * sep = = ' \0 ' ) {
/* formatting was broken? */
goto failed ;
}
siblings = atoi ( sep + 1 ) ;
}
if ( strncmp ( buff , " cpu cores " , 9 ) = = 0 ) {
const char * const sep = strchr ( buff , ' : ' ) ;
if ( * sep = = ' \0 ' ) {
/* formatting was broken? */
goto failed ;
}
cpu_cores = atoi ( sep + 1 ) ;
}
} else if ( ferror ( cpuinfo ) ) {
/* fall back on the sysconf value */
goto failed ;
}
}
if ( siblings & & cpu_cores ) {
ratio = siblings / cpu_cores ;
}
failed :
fclose ( cpuinfo ) ;
return numPhysicalCores = numPhysicalCores / ratio ;
}
}
2017-04-15 07:25:08 -07:00
# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
/* Use apple-provided syscall
* see : man 3 sysctl */
UTIL_STATIC int UTIL_countPhysicalCores ( void )
{
static int numPhysicalCores = 0 ;
if ( numPhysicalCores ! = 0 ) return numPhysicalCores ;
numPhysicalCores = ( int ) sysconf ( _SC_NPROCESSORS_ONLN ) ;
if ( numPhysicalCores = = - 1 ) {
/* value not queryable, fall back on 1 */
return numPhysicalCores = 1 ;
}
return numPhysicalCores ;
}
2017-04-13 12:28:28 -07:00
# else
UTIL_STATIC int UTIL_countPhysicalCores ( void )
{
/* assume 1 */
return 1 ;
}
# endif
2016-05-04 15:25:38 -07:00
2016-04-28 03:23:33 -07:00
# if defined (__cplusplus)
}
# endif
# endif /* UTIL_H_MODULE */