/*1* Copyright (c) Przemyslaw Skibinski, Yann Collet, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/910#ifndef UTIL_H_MODULE11#define UTIL_H_MODULE1213#if defined (__cplusplus)14extern "C" {15#endif161718/*-****************************************19* Dependencies20******************************************/21#include "platform.h" /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */22#include <stddef.h> /* size_t, ptrdiff_t */23#include <sys/types.h> /* stat, utime */24#include <sys/stat.h> /* stat, chmod */25#include "../lib/common/mem.h" /* U64 */262728/*-************************************************************29* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW30***************************************************************/31#if defined(_MSC_VER) && (_MSC_VER >= 1400)32# define UTIL_fseek _fseeki6433#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */34# define UTIL_fseek fseeko35#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)36# define UTIL_fseek fseeko6437#else38# define UTIL_fseek fseek39#endif404142/*-*************************************************43* Sleep & priority functions: Windows - Posix - others44***************************************************/45#if defined(_WIN32)46# include <windows.h>47# define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)48# define UTIL_sleep(s) Sleep(1000*s)49# define UTIL_sleepMilli(milli) Sleep(milli)5051#elif PLATFORM_POSIX_VERSION > 0 /* Unix-like operating system */52# include <unistd.h> /* sleep */53# define UTIL_sleep(s) sleep(s)54# if ZSTD_NANOSLEEP_SUPPORT /* necessarily defined in platform.h */55# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }56# else57# define UTIL_sleepMilli(milli) /* disabled */58# endif59# if ZSTD_SETPRIORITY_SUPPORT60# include <sys/resource.h> /* setpriority */61# define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)62# else63# define SET_REALTIME_PRIORITY /* disabled */64# endif6566#else /* unknown non-unix operating system */67# define UTIL_sleep(s) /* disabled */68# define UTIL_sleepMilli(milli) /* disabled */69# define SET_REALTIME_PRIORITY /* disabled */70#endif717273/*-****************************************74* Compiler specifics75******************************************/76#if defined(__INTEL_COMPILER)77# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */78#endif79#if defined(__GNUC__)80# define UTIL_STATIC static __attribute__((unused))81#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)82# define UTIL_STATIC static inline83#elif defined(_MSC_VER)84# define UTIL_STATIC static __inline85#else86# define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */87#endif888990/*-****************************************91* Console log92******************************************/93extern int g_utilDisplayLevel;9495/**96* Displays a message prompt and returns success (0) if first character from stdin97* matches any from acceptableLetters. Otherwise, returns failure (1) and displays abortMsg.98* If any of the inputs are stdin itself, then automatically return failure (1).99*/100int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg, const char* acceptableLetters, int hasStdinInput);101102103/*-****************************************104* File functions105******************************************/106#if defined(_MSC_VER)107typedef struct __stat64 stat_t;108typedef int mode_t;109#elif defined(__MINGW32__) && defined (__MSVCRT__)110typedef struct _stati64 stat_t;111#else112typedef struct stat stat_t;113#endif114115#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */116#define PATH_SEP '\\'117#define STRDUP(s) _strdup(s)118#else119#define PATH_SEP '/'120#include <libgen.h>121#define STRDUP(s) strdup(s)122#endif123124125/**126* Calls platform's equivalent of stat() on filename and writes info to statbuf.127* Returns success (1) or failure (0).128*/129int UTIL_stat(const char* filename, stat_t* statbuf);130131/**132* Instead of getting a file's stats, this updates them with the info in the133* provided stat_t. Currently sets owner, group, atime, and mtime. Will only134* update this info for regular files.135*/136int UTIL_setFileStat(const char* filename, const stat_t* statbuf);137138/**139* Set atime to now and mtime to the st_mtim in statbuf.140*141* Directly wraps utime() or utimensat(). Returns -1 on error.142* Does not validate filename is valid.143*/144int UTIL_utime(const char* filename, const stat_t *statbuf);145146/*147* These helpers operate on a pre-populated stat_t, i.e., the result of148* calling one of the above functions.149*/150151int UTIL_isRegularFileStat(const stat_t* statbuf);152int UTIL_isDirectoryStat(const stat_t* statbuf);153int UTIL_isFIFOStat(const stat_t* statbuf);154int UTIL_isBlockDevStat(const stat_t* statbuf);155U64 UTIL_getFileSizeStat(const stat_t* statbuf);156157/**158* Like chmod(), but only modifies regular files. Provided statbuf may be NULL,159* in which case this function will stat() the file internally, in order to160* check whether it should be modified.161*/162int UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions);163164/*165* In the absence of a pre-existing stat result on the file in question, these166* functions will do a stat() call internally and then use that result to167* compute the needed information.168*/169170int UTIL_isRegularFile(const char* infilename);171int UTIL_isDirectory(const char* infilename);172int UTIL_isSameFile(const char* file1, const char* file2);173int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]);174int UTIL_isLink(const char* infilename);175int UTIL_isFIFO(const char* infilename);176177#define UTIL_FILESIZE_UNKNOWN ((U64)(-1))178U64 UTIL_getFileSize(const char* infilename);179U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles);180181/**182* Take @size in bytes,183* prepare the components to pretty-print it in a scaled way.184* The components in the returned struct should be passed in185* precision, value, suffix order to a "%.*f%s" format string.186* Output policy is sensible to @g_utilDisplayLevel,187* for verbose mode (@g_utilDisplayLevel >= 4),188* does not scale down.189*/190typedef struct {191double value;192int precision;193const char* suffix;194} UTIL_HumanReadableSize_t;195196UTIL_HumanReadableSize_t UTIL_makeHumanReadableSize(U64 size);197198int UTIL_compareStr(const void *p1, const void *p2);199const char* UTIL_getFileExtension(const char* infilename);200void UTIL_mirrorSourceFilesDirectories(const char** fileNamesTable, unsigned int nbFiles, const char *outDirName);201char* UTIL_createMirroredDestDirName(const char* srcFileName, const char* outDirRootName);202203204205/*-****************************************206* Lists of Filenames207******************************************/208209typedef struct210{ const char** fileNames;211char* buf; /* fileNames are stored in this buffer (or are read-only) */212size_t tableSize; /* nb of fileNames */213size_t tableCapacity;214} FileNamesTable;215216/*! UTIL_createFileNamesTable_fromFileName() :217* read filenames from @inputFileName, and store them into returned object.218* @return : a FileNamesTable*, or NULL in case of error (ex: @inputFileName doesn't exist).219* Note: inputFileSize must be less than 50MB220*/221FileNamesTable*222UTIL_createFileNamesTable_fromFileName(const char* inputFileName);223224/*! UTIL_assembleFileNamesTable() :225* This function takes ownership of its arguments, @filenames and @buf,226* and store them inside the created object.227* note : this function never fails,228* it will rather exit() the program if internal allocation fails.229* @return : resulting FileNamesTable* object.230*/231FileNamesTable*232UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf);233234/*! UTIL_freeFileNamesTable() :235* This function is compatible with NULL argument and never fails.236*/237void UTIL_freeFileNamesTable(FileNamesTable* table);238239/*! UTIL_mergeFileNamesTable():240* @return : FileNamesTable*, concatenation of @table1 and @table2241* note: @table1 and @table2 are consumed (freed) by this operation242*/243FileNamesTable*244UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2);245246247/*! UTIL_expandFNT() :248* read names from @fnt, and expand those corresponding to directories249* update @fnt, now containing only file names,250* @return : 0 in case of success, 1 if error251* note : in case of error, @fnt[0] is NULL252*/253void UTIL_expandFNT(FileNamesTable** fnt, int followLinks);254255/*! UTIL_createFNT_fromROTable() :256* copy the @filenames pointer table inside the returned object.257* The names themselves are still stored in their original buffer, which must outlive the object.258* @return : a FileNamesTable* object,259* or NULL in case of error260*/261FileNamesTable*262UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames);263264/*! UTIL_allocateFileNamesTable() :265* Allocates a table of const char*, to insert read-only names later on.266* The created FileNamesTable* doesn't hold a buffer.267* @return : FileNamesTable*, or NULL, if allocation fails.268*/269FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize);270271272/*! UTIL_refFilename() :273* Add a reference to read-only name into @fnt table.274* As @filename is only referenced, its lifetime must outlive @fnt.275* Internal table must be large enough to reference a new member,276* otherwise its UB (protected by an `assert()`).277*/278void UTIL_refFilename(FileNamesTable* fnt, const char* filename);279280281/* UTIL_createExpandedFNT() is only active if UTIL_HAS_CREATEFILELIST is defined.282* Otherwise, UTIL_createExpandedFNT() is a shell function which does nothing283* apart from displaying a warning message.284*/285#ifdef _WIN32286# define UTIL_HAS_CREATEFILELIST287#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */288# define UTIL_HAS_CREATEFILELIST289# define UTIL_HAS_MIRRORFILELIST290#else291/* do not define UTIL_HAS_CREATEFILELIST */292#endif293294/*! UTIL_createExpandedFNT() :295* read names from @filenames, and expand those corresponding to directories.296* links are followed or not depending on @followLinks directive.297* @return : an expanded FileNamesTable*, where each name is a file298* or NULL in case of error299*/300FileNamesTable*301UTIL_createExpandedFNT(const char* const* filenames, size_t nbFilenames, int followLinks);302303#if defined(_WIN32) || defined(WIN32)304DWORD CountSetBits(ULONG_PTR bitMask);305#endif306307/*-****************************************308* System309******************************************/310311int UTIL_countCores(int logical);312313int UTIL_countPhysicalCores(void);314315int UTIL_countLogicalCores(void);316317#if defined (__cplusplus)318}319#endif320321#endif /* UTIL_H_MODULE */322323324