1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos #ifndef UTIL_H_MODULE 12*3117ece4Schristos #define UTIL_H_MODULE 13*3117ece4Schristos 14*3117ece4Schristos #if defined (__cplusplus) 15*3117ece4Schristos extern "C" { 16*3117ece4Schristos #endif 17*3117ece4Schristos 18*3117ece4Schristos 19*3117ece4Schristos /*-**************************************** 20*3117ece4Schristos * Dependencies 21*3117ece4Schristos ******************************************/ 22*3117ece4Schristos #include "platform.h" /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */ 23*3117ece4Schristos #include <stddef.h> /* size_t, ptrdiff_t */ 24*3117ece4Schristos #include <sys/types.h> /* stat, utime */ 25*3117ece4Schristos #include <sys/stat.h> /* stat, chmod */ 26*3117ece4Schristos #include "../lib/common/mem.h" /* U64 */ 27*3117ece4Schristos 28*3117ece4Schristos 29*3117ece4Schristos /*-************************************************************ 30*3117ece4Schristos * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW 31*3117ece4Schristos ***************************************************************/ 32*3117ece4Schristos #if defined(_MSC_VER) && (_MSC_VER >= 1400) 33*3117ece4Schristos # define UTIL_fseek _fseeki64 34*3117ece4Schristos #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ 35*3117ece4Schristos # define UTIL_fseek fseeko 36*3117ece4Schristos #elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) 37*3117ece4Schristos # define UTIL_fseek fseeko64 38*3117ece4Schristos #else 39*3117ece4Schristos # define UTIL_fseek fseek 40*3117ece4Schristos #endif 41*3117ece4Schristos 42*3117ece4Schristos 43*3117ece4Schristos /*-************************************************* 44*3117ece4Schristos * Sleep & priority functions: Windows - Posix - others 45*3117ece4Schristos ***************************************************/ 46*3117ece4Schristos #if defined(_WIN32) 47*3117ece4Schristos # include <windows.h> 48*3117ece4Schristos # define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) 49*3117ece4Schristos # define UTIL_sleep(s) Sleep(1000*s) 50*3117ece4Schristos # define UTIL_sleepMilli(milli) Sleep(milli) 51*3117ece4Schristos 52*3117ece4Schristos #elif PLATFORM_POSIX_VERSION > 0 /* Unix-like operating system */ 53*3117ece4Schristos # include <unistd.h> /* sleep */ 54*3117ece4Schristos # define UTIL_sleep(s) sleep(s) 55*3117ece4Schristos # if ZSTD_NANOSLEEP_SUPPORT /* necessarily defined in platform.h */ 56*3117ece4Schristos # define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); } 57*3117ece4Schristos # else 58*3117ece4Schristos # define UTIL_sleepMilli(milli) /* disabled */ 59*3117ece4Schristos # endif 60*3117ece4Schristos # if ZSTD_SETPRIORITY_SUPPORT 61*3117ece4Schristos # include <sys/resource.h> /* setpriority */ 62*3117ece4Schristos # define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20) 63*3117ece4Schristos # else 64*3117ece4Schristos # define SET_REALTIME_PRIORITY /* disabled */ 65*3117ece4Schristos # endif 66*3117ece4Schristos 67*3117ece4Schristos #else /* unknown non-unix operating system */ 68*3117ece4Schristos # define UTIL_sleep(s) /* disabled */ 69*3117ece4Schristos # define UTIL_sleepMilli(milli) /* disabled */ 70*3117ece4Schristos # define SET_REALTIME_PRIORITY /* disabled */ 71*3117ece4Schristos #endif 72*3117ece4Schristos 73*3117ece4Schristos 74*3117ece4Schristos /*-**************************************** 75*3117ece4Schristos * Compiler specifics 76*3117ece4Schristos ******************************************/ 77*3117ece4Schristos #if defined(__INTEL_COMPILER) 78*3117ece4Schristos # pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */ 79*3117ece4Schristos #endif 80*3117ece4Schristos #if defined(__GNUC__) 81*3117ece4Schristos # define UTIL_STATIC static __attribute__((unused)) 82*3117ece4Schristos #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 83*3117ece4Schristos # define UTIL_STATIC static inline 84*3117ece4Schristos #elif defined(_MSC_VER) 85*3117ece4Schristos # define UTIL_STATIC static __inline 86*3117ece4Schristos #else 87*3117ece4Schristos # define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ 88*3117ece4Schristos #endif 89*3117ece4Schristos 90*3117ece4Schristos 91*3117ece4Schristos /*-**************************************** 92*3117ece4Schristos * Console log 93*3117ece4Schristos ******************************************/ 94*3117ece4Schristos extern int g_utilDisplayLevel; 95*3117ece4Schristos 96*3117ece4Schristos /** 97*3117ece4Schristos * Displays a message prompt and returns success (0) if first character from stdin 98*3117ece4Schristos * matches any from acceptableLetters. Otherwise, returns failure (1) and displays abortMsg. 99*3117ece4Schristos * If any of the inputs are stdin itself, then automatically return failure (1). 100*3117ece4Schristos */ 101*3117ece4Schristos int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg, const char* acceptableLetters, int hasStdinInput); 102*3117ece4Schristos 103*3117ece4Schristos 104*3117ece4Schristos /*-**************************************** 105*3117ece4Schristos * File functions 106*3117ece4Schristos ******************************************/ 107*3117ece4Schristos #if defined(_MSC_VER) 108*3117ece4Schristos typedef struct __stat64 stat_t; 109*3117ece4Schristos typedef int mode_t; 110*3117ece4Schristos #elif defined(__MINGW32__) && defined (__MSVCRT__) 111*3117ece4Schristos typedef struct _stati64 stat_t; 112*3117ece4Schristos #else 113*3117ece4Schristos typedef struct stat stat_t; 114*3117ece4Schristos #endif 115*3117ece4Schristos 116*3117ece4Schristos #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */ 117*3117ece4Schristos #define PATH_SEP '\\' 118*3117ece4Schristos #define STRDUP(s) _strdup(s) 119*3117ece4Schristos #else 120*3117ece4Schristos #define PATH_SEP '/' 121*3117ece4Schristos #include <libgen.h> 122*3117ece4Schristos #define STRDUP(s) strdup(s) 123*3117ece4Schristos #endif 124*3117ece4Schristos 125*3117ece4Schristos 126*3117ece4Schristos /** 127*3117ece4Schristos * Calls platform's equivalent of stat() on filename and writes info to statbuf. 128*3117ece4Schristos * Returns success (1) or failure (0). 129*3117ece4Schristos * 130*3117ece4Schristos * UTIL_fstat() is like UTIL_stat() but takes an optional fd that refers to the 131*3117ece4Schristos * file in question. It turns out that this can be meaningfully faster. If fd is 132*3117ece4Schristos * -1, behaves just like UTIL_stat() (i.e., falls back to using the filename). 133*3117ece4Schristos */ 134*3117ece4Schristos int UTIL_stat(const char* filename, stat_t* statbuf); 135*3117ece4Schristos int UTIL_fstat(const int fd, const char* filename, stat_t* statbuf); 136*3117ece4Schristos 137*3117ece4Schristos /** 138*3117ece4Schristos * Instead of getting a file's stats, this updates them with the info in the 139*3117ece4Schristos * provided stat_t. Currently sets owner, group, atime, and mtime. Will only 140*3117ece4Schristos * update this info for regular files. 141*3117ece4Schristos * 142*3117ece4Schristos * UTIL_setFDStat() also takes an fd, and will preferentially use that to 143*3117ece4Schristos * indicate which file to modify, If fd is -1, it will fall back to using the 144*3117ece4Schristos * filename. 145*3117ece4Schristos */ 146*3117ece4Schristos int UTIL_setFileStat(const char* filename, const stat_t* statbuf); 147*3117ece4Schristos int UTIL_setFDStat(const int fd, const char* filename, const stat_t* statbuf); 148*3117ece4Schristos 149*3117ece4Schristos /** 150*3117ece4Schristos * Set atime to now and mtime to the st_mtim in statbuf. 151*3117ece4Schristos * 152*3117ece4Schristos * Directly wraps utime() or utimensat(). Returns -1 on error. 153*3117ece4Schristos * Does not validate filename is valid. 154*3117ece4Schristos */ 155*3117ece4Schristos int UTIL_utime(const char* filename, const stat_t *statbuf); 156*3117ece4Schristos 157*3117ece4Schristos /* 158*3117ece4Schristos * These helpers operate on a pre-populated stat_t, i.e., the result of 159*3117ece4Schristos * calling one of the above functions. 160*3117ece4Schristos */ 161*3117ece4Schristos 162*3117ece4Schristos int UTIL_isRegularFileStat(const stat_t* statbuf); 163*3117ece4Schristos int UTIL_isDirectoryStat(const stat_t* statbuf); 164*3117ece4Schristos int UTIL_isFIFOStat(const stat_t* statbuf); 165*3117ece4Schristos int UTIL_isBlockDevStat(const stat_t* statbuf); 166*3117ece4Schristos U64 UTIL_getFileSizeStat(const stat_t* statbuf); 167*3117ece4Schristos 168*3117ece4Schristos /** 169*3117ece4Schristos * Like chmod(), but only modifies regular files. Provided statbuf may be NULL, 170*3117ece4Schristos * in which case this function will stat() the file internally, in order to 171*3117ece4Schristos * check whether it should be modified. 172*3117ece4Schristos * 173*3117ece4Schristos * If fd is -1, fd is ignored and the filename is used. 174*3117ece4Schristos */ 175*3117ece4Schristos int UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions); 176*3117ece4Schristos int UTIL_fchmod(const int fd, char const* filename, const stat_t* statbuf, mode_t permissions); 177*3117ece4Schristos 178*3117ece4Schristos /* 179*3117ece4Schristos * In the absence of a pre-existing stat result on the file in question, these 180*3117ece4Schristos * functions will do a stat() call internally and then use that result to 181*3117ece4Schristos * compute the needed information. 182*3117ece4Schristos */ 183*3117ece4Schristos 184*3117ece4Schristos int UTIL_isRegularFile(const char* infilename); 185*3117ece4Schristos int UTIL_isDirectory(const char* infilename); 186*3117ece4Schristos int UTIL_isSameFile(const char* file1, const char* file2); 187*3117ece4Schristos int UTIL_isSameFileStat(const char* file1, const char* file2, const stat_t* file1Stat, const stat_t* file2Stat); 188*3117ece4Schristos int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]); 189*3117ece4Schristos int UTIL_isLink(const char* infilename); 190*3117ece4Schristos int UTIL_isFIFO(const char* infilename); 191*3117ece4Schristos 192*3117ece4Schristos /** 193*3117ece4Schristos * Returns with the given file descriptor is a console. 194*3117ece4Schristos * Allows faking whether stdin/stdout/stderr is a console 195*3117ece4Schristos * using UTIL_fake*IsConsole(). 196*3117ece4Schristos */ 197*3117ece4Schristos int UTIL_isConsole(FILE* file); 198*3117ece4Schristos 199*3117ece4Schristos /** 200*3117ece4Schristos * Pretends that stdin/stdout/stderr is a console for testing. 201*3117ece4Schristos */ 202*3117ece4Schristos void UTIL_fakeStdinIsConsole(void); 203*3117ece4Schristos void UTIL_fakeStdoutIsConsole(void); 204*3117ece4Schristos void UTIL_fakeStderrIsConsole(void); 205*3117ece4Schristos 206*3117ece4Schristos /** 207*3117ece4Schristos * Emit traces for functions that read, or modify file metadata. 208*3117ece4Schristos */ 209*3117ece4Schristos void UTIL_traceFileStat(void); 210*3117ece4Schristos 211*3117ece4Schristos #define UTIL_FILESIZE_UNKNOWN ((U64)(-1)) 212*3117ece4Schristos U64 UTIL_getFileSize(const char* infilename); 213*3117ece4Schristos U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles); 214*3117ece4Schristos 215*3117ece4Schristos /** 216*3117ece4Schristos * Take @size in bytes, 217*3117ece4Schristos * prepare the components to pretty-print it in a scaled way. 218*3117ece4Schristos * The components in the returned struct should be passed in 219*3117ece4Schristos * precision, value, suffix order to a "%.*f%s" format string. 220*3117ece4Schristos * Output policy is sensible to @g_utilDisplayLevel, 221*3117ece4Schristos * for verbose mode (@g_utilDisplayLevel >= 4), 222*3117ece4Schristos * does not scale down. 223*3117ece4Schristos */ 224*3117ece4Schristos typedef struct { 225*3117ece4Schristos double value; 226*3117ece4Schristos int precision; 227*3117ece4Schristos const char* suffix; 228*3117ece4Schristos } UTIL_HumanReadableSize_t; 229*3117ece4Schristos 230*3117ece4Schristos UTIL_HumanReadableSize_t UTIL_makeHumanReadableSize(U64 size); 231*3117ece4Schristos 232*3117ece4Schristos int UTIL_compareStr(const void *p1, const void *p2); 233*3117ece4Schristos const char* UTIL_getFileExtension(const char* infilename); 234*3117ece4Schristos void UTIL_mirrorSourceFilesDirectories(const char** fileNamesTable, unsigned int nbFiles, const char *outDirName); 235*3117ece4Schristos char* UTIL_createMirroredDestDirName(const char* srcFileName, const char* outDirRootName); 236*3117ece4Schristos 237*3117ece4Schristos 238*3117ece4Schristos 239*3117ece4Schristos /*-**************************************** 240*3117ece4Schristos * Lists of Filenames 241*3117ece4Schristos ******************************************/ 242*3117ece4Schristos 243*3117ece4Schristos typedef struct 244*3117ece4Schristos { const char** fileNames; 245*3117ece4Schristos char* buf; /* fileNames are stored in this buffer (or are read-only) */ 246*3117ece4Schristos size_t tableSize; /* nb of fileNames */ 247*3117ece4Schristos size_t tableCapacity; 248*3117ece4Schristos } FileNamesTable; 249*3117ece4Schristos 250*3117ece4Schristos /*! UTIL_createFileNamesTable_fromFileName() : 251*3117ece4Schristos * read filenames from @inputFileName, and store them into returned object. 252*3117ece4Schristos * @return : a FileNamesTable*, or NULL in case of error (ex: @inputFileName doesn't exist). 253*3117ece4Schristos * Note: inputFileSize must be less than 50MB 254*3117ece4Schristos */ 255*3117ece4Schristos FileNamesTable* 256*3117ece4Schristos UTIL_createFileNamesTable_fromFileName(const char* inputFileName); 257*3117ece4Schristos 258*3117ece4Schristos /*! UTIL_assembleFileNamesTable() : 259*3117ece4Schristos * This function takes ownership of its arguments, @filenames and @buf, 260*3117ece4Schristos * and store them inside the created object. 261*3117ece4Schristos * note : this function never fails, 262*3117ece4Schristos * it will rather exit() the program if internal allocation fails. 263*3117ece4Schristos * @return : resulting FileNamesTable* object. 264*3117ece4Schristos */ 265*3117ece4Schristos FileNamesTable* 266*3117ece4Schristos UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf); 267*3117ece4Schristos 268*3117ece4Schristos /*! UTIL_freeFileNamesTable() : 269*3117ece4Schristos * This function is compatible with NULL argument and never fails. 270*3117ece4Schristos */ 271*3117ece4Schristos void UTIL_freeFileNamesTable(FileNamesTable* table); 272*3117ece4Schristos 273*3117ece4Schristos /*! UTIL_mergeFileNamesTable(): 274*3117ece4Schristos * @return : FileNamesTable*, concatenation of @table1 and @table2 275*3117ece4Schristos * note: @table1 and @table2 are consumed (freed) by this operation 276*3117ece4Schristos */ 277*3117ece4Schristos FileNamesTable* 278*3117ece4Schristos UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2); 279*3117ece4Schristos 280*3117ece4Schristos 281*3117ece4Schristos /*! UTIL_expandFNT() : 282*3117ece4Schristos * read names from @fnt, and expand those corresponding to directories 283*3117ece4Schristos * update @fnt, now containing only file names, 284*3117ece4Schristos * note : in case of error, @fnt[0] is NULL 285*3117ece4Schristos */ 286*3117ece4Schristos void UTIL_expandFNT(FileNamesTable** fnt, int followLinks); 287*3117ece4Schristos 288*3117ece4Schristos /*! UTIL_createFNT_fromROTable() : 289*3117ece4Schristos * copy the @filenames pointer table inside the returned object. 290*3117ece4Schristos * The names themselves are still stored in their original buffer, which must outlive the object. 291*3117ece4Schristos * @return : a FileNamesTable* object, 292*3117ece4Schristos * or NULL in case of error 293*3117ece4Schristos */ 294*3117ece4Schristos FileNamesTable* 295*3117ece4Schristos UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames); 296*3117ece4Schristos 297*3117ece4Schristos /*! UTIL_allocateFileNamesTable() : 298*3117ece4Schristos * Allocates a table of const char*, to insert read-only names later on. 299*3117ece4Schristos * The created FileNamesTable* doesn't hold a buffer. 300*3117ece4Schristos * @return : FileNamesTable*, or NULL, if allocation fails. 301*3117ece4Schristos */ 302*3117ece4Schristos FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize); 303*3117ece4Schristos 304*3117ece4Schristos /*! UTIL_searchFileNamesTable() : 305*3117ece4Schristos * Searched through entries in FileNamesTable for a specific name. 306*3117ece4Schristos * @return : index of entry if found or -1 if not found 307*3117ece4Schristos */ 308*3117ece4Schristos int UTIL_searchFileNamesTable(FileNamesTable* table, char const* name); 309*3117ece4Schristos 310*3117ece4Schristos /*! UTIL_refFilename() : 311*3117ece4Schristos * Add a reference to read-only name into @fnt table. 312*3117ece4Schristos * As @filename is only referenced, its lifetime must outlive @fnt. 313*3117ece4Schristos * Internal table must be large enough to reference a new member, 314*3117ece4Schristos * otherwise its UB (protected by an `assert()`). 315*3117ece4Schristos */ 316*3117ece4Schristos void UTIL_refFilename(FileNamesTable* fnt, const char* filename); 317*3117ece4Schristos 318*3117ece4Schristos 319*3117ece4Schristos /* UTIL_createExpandedFNT() is only active if UTIL_HAS_CREATEFILELIST is defined. 320*3117ece4Schristos * Otherwise, UTIL_createExpandedFNT() is a shell function which does nothing 321*3117ece4Schristos * apart from displaying a warning message. 322*3117ece4Schristos */ 323*3117ece4Schristos #ifdef _WIN32 324*3117ece4Schristos # define UTIL_HAS_CREATEFILELIST 325*3117ece4Schristos #elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */ 326*3117ece4Schristos # define UTIL_HAS_CREATEFILELIST 327*3117ece4Schristos # define UTIL_HAS_MIRRORFILELIST 328*3117ece4Schristos #else 329*3117ece4Schristos /* do not define UTIL_HAS_CREATEFILELIST */ 330*3117ece4Schristos #endif 331*3117ece4Schristos 332*3117ece4Schristos /*! UTIL_createExpandedFNT() : 333*3117ece4Schristos * read names from @filenames, and expand those corresponding to directories. 334*3117ece4Schristos * links are followed or not depending on @followLinks directive. 335*3117ece4Schristos * @return : an expanded FileNamesTable*, where each name is a file 336*3117ece4Schristos * or NULL in case of error 337*3117ece4Schristos */ 338*3117ece4Schristos FileNamesTable* 339*3117ece4Schristos UTIL_createExpandedFNT(const char* const* filenames, size_t nbFilenames, int followLinks); 340*3117ece4Schristos 341*3117ece4Schristos #if defined(_WIN32) 342*3117ece4Schristos DWORD CountSetBits(ULONG_PTR bitMask); 343*3117ece4Schristos #endif 344*3117ece4Schristos 345*3117ece4Schristos /*-**************************************** 346*3117ece4Schristos * System 347*3117ece4Schristos ******************************************/ 348*3117ece4Schristos 349*3117ece4Schristos int UTIL_countCores(int logical); 350*3117ece4Schristos 351*3117ece4Schristos int UTIL_countPhysicalCores(void); 352*3117ece4Schristos 353*3117ece4Schristos int UTIL_countLogicalCores(void); 354*3117ece4Schristos 355*3117ece4Schristos #if defined (__cplusplus) 356*3117ece4Schristos } 357*3117ece4Schristos #endif 358*3117ece4Schristos 359*3117ece4Schristos #endif /* UTIL_H_MODULE */ 360