mirror of
https://github.com/facebook/zstd.git
synced 2025-08-07 06:23:00 +03:00
Merge pull request #3432 from felixhandte/fix-perms
Fix CLI Handling of Permissions and Ownership (Again)
This commit is contained in:
@@ -114,11 +114,15 @@ char const* FIO_lzmaVersion(void)
|
|||||||
#define FNSPACE 30
|
#define FNSPACE 30
|
||||||
|
|
||||||
/* Default file permissions 0666 (modulated by umask) */
|
/* Default file permissions 0666 (modulated by umask) */
|
||||||
|
/* Temporary restricted file permissions are used when we're going to
|
||||||
|
* chmod/chown at the end of the operation. */
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
/* These macros aren't defined on windows. */
|
/* These macros aren't defined on windows. */
|
||||||
#define DEFAULT_FILE_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
#define DEFAULT_FILE_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||||
|
#define TEMPORARY_FILE_PERMISSIONS (S_IRUSR|S_IWUSR)
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_FILE_PERMISSIONS (0666)
|
#define DEFAULT_FILE_PERMISSIONS (0666)
|
||||||
|
#define TEMPORARY_FILE_PERMISSIONS (0600)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
@@ -531,26 +535,26 @@ static int FIO_removeFile(const char* path)
|
|||||||
/** FIO_openSrcFile() :
|
/** FIO_openSrcFile() :
|
||||||
* condition : `srcFileName` must be non-NULL. `prefs` may be NULL.
|
* condition : `srcFileName` must be non-NULL. `prefs` may be NULL.
|
||||||
* @result : FILE* to `srcFileName`, or NULL if it fails */
|
* @result : FILE* to `srcFileName`, or NULL if it fails */
|
||||||
static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFileName)
|
static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFileName, stat_t* statbuf)
|
||||||
{
|
{
|
||||||
stat_t statbuf;
|
|
||||||
int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
|
int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
|
||||||
assert(srcFileName != NULL);
|
assert(srcFileName != NULL);
|
||||||
|
assert(statbuf != NULL);
|
||||||
if (!strcmp (srcFileName, stdinmark)) {
|
if (!strcmp (srcFileName, stdinmark)) {
|
||||||
DISPLAYLEVEL(4,"Using stdin for input \n");
|
DISPLAYLEVEL(4,"Using stdin for input \n");
|
||||||
SET_BINARY_MODE(stdin);
|
SET_BINARY_MODE(stdin);
|
||||||
return stdin;
|
return stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UTIL_stat(srcFileName, &statbuf)) {
|
if (!UTIL_stat(srcFileName, statbuf)) {
|
||||||
DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
|
DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
|
||||||
srcFileName, strerror(errno));
|
srcFileName, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UTIL_isRegularFileStat(&statbuf)
|
if (!UTIL_isRegularFileStat(statbuf)
|
||||||
&& !UTIL_isFIFOStat(&statbuf)
|
&& !UTIL_isFIFOStat(statbuf)
|
||||||
&& !(allowBlockDevices && UTIL_isBlockDevStat(&statbuf))
|
&& !(allowBlockDevices && UTIL_isBlockDevStat(statbuf))
|
||||||
) {
|
) {
|
||||||
DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n",
|
DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n",
|
||||||
srcFileName);
|
srcFileName);
|
||||||
@@ -662,23 +666,23 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
|
|||||||
* @return : loaded size
|
* @return : loaded size
|
||||||
* if fileName==NULL, returns 0 and a NULL pointer
|
* if fileName==NULL, returns 0 and a NULL pointer
|
||||||
*/
|
*/
|
||||||
static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName, FIO_prefs_t* const prefs)
|
static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)
|
||||||
{
|
{
|
||||||
FILE* fileHandle;
|
FILE* fileHandle;
|
||||||
U64 fileSize;
|
U64 fileSize;
|
||||||
stat_t statbuf;
|
|
||||||
|
|
||||||
assert(bufferPtr != NULL);
|
assert(bufferPtr != NULL);
|
||||||
|
assert(dictFileStat != NULL);
|
||||||
*bufferPtr = NULL;
|
*bufferPtr = NULL;
|
||||||
if (fileName == NULL) return 0;
|
if (fileName == NULL) return 0;
|
||||||
|
|
||||||
DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
|
DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
|
||||||
|
|
||||||
if (!UTIL_stat(fileName, &statbuf)) {
|
if (!UTIL_stat(fileName, dictFileStat)) {
|
||||||
EXM_THROW(31, "Stat failed on dictionary file %s: %s", fileName, strerror(errno));
|
EXM_THROW(31, "Stat failed on dictionary file %s: %s", fileName, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UTIL_isRegularFileStat(&statbuf)) {
|
if (!UTIL_isRegularFileStat(dictFileStat)) {
|
||||||
EXM_THROW(32, "Dictionary %s must be a regular file.", fileName);
|
EXM_THROW(32, "Dictionary %s must be a regular file.", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +692,7 @@ static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName, FIO_p
|
|||||||
EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
|
EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSize = UTIL_getFileSizeStat(&statbuf);
|
fileSize = UTIL_getFileSizeStat(dictFileStat);
|
||||||
{
|
{
|
||||||
size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
|
size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
|
||||||
if (fileSize > dictSizeMax) {
|
if (fileSize > dictSizeMax) {
|
||||||
@@ -887,6 +891,7 @@ typedef struct {
|
|||||||
void* dictBuffer;
|
void* dictBuffer;
|
||||||
size_t dictBufferSize;
|
size_t dictBufferSize;
|
||||||
const char* dictFileName;
|
const char* dictFileName;
|
||||||
|
stat_t dictFileStat;
|
||||||
ZSTD_CStream* cctx;
|
ZSTD_CStream* cctx;
|
||||||
WritePoolCtx_t *writeCtx;
|
WritePoolCtx_t *writeCtx;
|
||||||
ReadPoolCtx_t *readCtx;
|
ReadPoolCtx_t *readCtx;
|
||||||
@@ -945,7 +950,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
|
|||||||
unsigned long long const ssSize = (unsigned long long)prefs->streamSrcSize;
|
unsigned long long const ssSize = (unsigned long long)prefs->streamSrcSize;
|
||||||
FIO_adjustParamsForPatchFromMode(prefs, &comprParams, UTIL_getFileSize(dictFileName), ssSize > 0 ? ssSize : maxSrcFileSize, cLevel);
|
FIO_adjustParamsForPatchFromMode(prefs, &comprParams, UTIL_getFileSize(dictFileName), ssSize > 0 ? ssSize : maxSrcFileSize, cLevel);
|
||||||
}
|
}
|
||||||
ress.dictBufferSize = FIO_createDictBuffer(&ress.dictBuffer, dictFileName, prefs); /* works with dictFileName==NULL */
|
ress.dictBufferSize = FIO_createDictBuffer(&ress.dictBuffer, dictFileName, prefs, &ress.dictFileStat); /* works with dictFileName==NULL */
|
||||||
|
|
||||||
ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_CStreamOutSize());
|
ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_CStreamOutSize());
|
||||||
ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize());
|
ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize());
|
||||||
@@ -1643,27 +1648,27 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
|
|||||||
cRess_t ress,
|
cRess_t ress,
|
||||||
const char* dstFileName,
|
const char* dstFileName,
|
||||||
const char* srcFileName,
|
const char* srcFileName,
|
||||||
|
const stat_t* srcFileStat,
|
||||||
int compressionLevel)
|
int compressionLevel)
|
||||||
{
|
{
|
||||||
int closeDstFile = 0;
|
int closeDstFile = 0;
|
||||||
int result;
|
int result;
|
||||||
stat_t statbuf;
|
int transferStat = 0;
|
||||||
int transferMTime = 0;
|
|
||||||
FILE *dstFile;
|
FILE *dstFile;
|
||||||
|
|
||||||
assert(AIO_ReadPool_getFile(ress.readCtx) != NULL);
|
assert(AIO_ReadPool_getFile(ress.readCtx) != NULL);
|
||||||
if (AIO_WritePool_getFile(ress.writeCtx) == NULL) {
|
if (AIO_WritePool_getFile(ress.writeCtx) == NULL) {
|
||||||
int dstFilePermissions = DEFAULT_FILE_PERMISSIONS;
|
int dstFileInitialPermissions = DEFAULT_FILE_PERMISSIONS;
|
||||||
if ( strcmp (srcFileName, stdinmark)
|
if ( strcmp (srcFileName, stdinmark)
|
||||||
&& strcmp (dstFileName, stdoutmark)
|
&& strcmp (dstFileName, stdoutmark)
|
||||||
&& UTIL_stat(srcFileName, &statbuf)
|
&& UTIL_isRegularFileStat(srcFileStat) ) {
|
||||||
&& UTIL_isRegularFileStat(&statbuf) ) {
|
transferStat = 1;
|
||||||
dstFilePermissions = statbuf.st_mode;
|
dstFileInitialPermissions = TEMPORARY_FILE_PERMISSIONS;
|
||||||
transferMTime = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDstFile = 1;
|
closeDstFile = 1;
|
||||||
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName);
|
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName);
|
||||||
dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFilePermissions);
|
dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
|
||||||
if (dstFile==NULL) return 1; /* could not open dstFileName */
|
if (dstFile==NULL) return 1; /* could not open dstFileName */
|
||||||
AIO_WritePool_setFile(ress.writeCtx, dstFile);
|
AIO_WritePool_setFile(ress.writeCtx, dstFile);
|
||||||
/* Must only be added after FIO_openDstFile() succeeds.
|
/* Must only be added after FIO_openDstFile() succeeds.
|
||||||
@@ -1683,8 +1688,8 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
|
|||||||
DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
|
DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
|
||||||
result=1;
|
result=1;
|
||||||
}
|
}
|
||||||
if (transferMTime) {
|
if (transferStat) {
|
||||||
UTIL_utime(dstFileName, &statbuf);
|
UTIL_setFileStat(dstFileName, srcFileStat);
|
||||||
}
|
}
|
||||||
if ( (result != 0) /* operation failure */
|
if ( (result != 0) /* operation failure */
|
||||||
&& strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */
|
&& strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */
|
||||||
@@ -1726,18 +1731,25 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
|
|||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
FILE* srcFile;
|
FILE* srcFile;
|
||||||
|
stat_t srcFileStat;
|
||||||
DISPLAYLEVEL(6, "FIO_compressFilename_srcFile: %s \n", srcFileName);
|
DISPLAYLEVEL(6, "FIO_compressFilename_srcFile: %s \n", srcFileName);
|
||||||
|
|
||||||
/* ensure src is not a directory */
|
if (strcmp(srcFileName, stdinmark)) {
|
||||||
if (UTIL_isDirectory(srcFileName)) {
|
if (UTIL_stat(srcFileName, &srcFileStat)) {
|
||||||
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
|
/* failure to stat at all is handled during opening */
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ensure src is not the same as dict (if present) */
|
/* ensure src is not a directory */
|
||||||
if (ress.dictFileName != NULL && UTIL_isSameFile(srcFileName, ress.dictFileName)) {
|
if (UTIL_isDirectoryStat(&srcFileStat)) {
|
||||||
DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
|
DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure src is not the same as dict (if present) */
|
||||||
|
if (ress.dictFileName != NULL && UTIL_isSameFileStat(srcFileName, ress.dictFileName, &srcFileStat, &ress.dictFileStat)) {
|
||||||
|
DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if "srcFile" is compressed. Only done if --exclude-compressed flag is used
|
/* Check if "srcFile" is compressed. Only done if --exclude-compressed flag is used
|
||||||
@@ -1749,11 +1761,14 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
srcFile = FIO_openSrcFile(prefs, srcFileName);
|
srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);
|
||||||
if (srcFile == NULL) return 1; /* srcFile could not be opened */
|
if (srcFile == NULL) return 1; /* srcFile could not be opened */
|
||||||
|
|
||||||
AIO_ReadPool_setFile(ress.readCtx, srcFile);
|
AIO_ReadPool_setFile(ress.readCtx, srcFile);
|
||||||
result = FIO_compressFilename_dstFile(fCtx, prefs, ress, dstFileName, srcFileName, compressionLevel);
|
result = FIO_compressFilename_dstFile(
|
||||||
|
fCtx, prefs, ress,
|
||||||
|
dstFileName, srcFileName,
|
||||||
|
&srcFileStat, compressionLevel);
|
||||||
AIO_ReadPool_closeFile(ress.readCtx);
|
AIO_ReadPool_closeFile(ress.readCtx);
|
||||||
|
|
||||||
if ( prefs->removeSrcFile /* --rm */
|
if ( prefs->removeSrcFile /* --rm */
|
||||||
@@ -2011,7 +2026,8 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi
|
|||||||
|
|
||||||
/* dictionary */
|
/* dictionary */
|
||||||
{ void* dictBuffer;
|
{ void* dictBuffer;
|
||||||
size_t const dictBufferSize = FIO_createDictBuffer(&dictBuffer, dictFileName, prefs);
|
stat_t statbuf;
|
||||||
|
size_t const dictBufferSize = FIO_createDictBuffer(&dictBuffer, dictFileName, prefs, &statbuf);
|
||||||
CHECK( ZSTD_DCtx_reset(ress.dctx, ZSTD_reset_session_only) );
|
CHECK( ZSTD_DCtx_reset(ress.dctx, ZSTD_reset_session_only) );
|
||||||
CHECK( ZSTD_DCtx_loadDictionary(ress.dctx, dictBuffer, dictBufferSize) );
|
CHECK( ZSTD_DCtx_loadDictionary(ress.dctx, dictBuffer, dictBufferSize) );
|
||||||
free(dictBuffer);
|
free(dictBuffer);
|
||||||
@@ -2478,22 +2494,22 @@ static int FIO_decompressFrames(FIO_ctx_t* const fCtx,
|
|||||||
static int FIO_decompressDstFile(FIO_ctx_t* const fCtx,
|
static int FIO_decompressDstFile(FIO_ctx_t* const fCtx,
|
||||||
FIO_prefs_t* const prefs,
|
FIO_prefs_t* const prefs,
|
||||||
dRess_t ress,
|
dRess_t ress,
|
||||||
const char* dstFileName, const char* srcFileName)
|
const char* dstFileName,
|
||||||
|
const char* srcFileName,
|
||||||
|
const stat_t* srcFileStat)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
stat_t statbuf;
|
|
||||||
int releaseDstFile = 0;
|
int releaseDstFile = 0;
|
||||||
int transferMTime = 0;
|
int transferStat = 0;
|
||||||
|
|
||||||
if ((AIO_WritePool_getFile(ress.writeCtx) == NULL) && (prefs->testMode == 0)) {
|
if ((AIO_WritePool_getFile(ress.writeCtx) == NULL) && (prefs->testMode == 0)) {
|
||||||
FILE *dstFile;
|
FILE *dstFile;
|
||||||
int dstFilePermissions = DEFAULT_FILE_PERMISSIONS;
|
int dstFilePermissions = DEFAULT_FILE_PERMISSIONS;
|
||||||
if ( strcmp(srcFileName, stdinmark) /* special case : don't transfer permissions from stdin */
|
if ( strcmp(srcFileName, stdinmark) /* special case : don't transfer permissions from stdin */
|
||||||
&& strcmp(dstFileName, stdoutmark)
|
&& strcmp(dstFileName, stdoutmark)
|
||||||
&& UTIL_stat(srcFileName, &statbuf)
|
&& UTIL_isRegularFileStat(srcFileStat) ) {
|
||||||
&& UTIL_isRegularFileStat(&statbuf) ) {
|
transferStat = 1;
|
||||||
dstFilePermissions = statbuf.st_mode;
|
dstFilePermissions = TEMPORARY_FILE_PERMISSIONS;
|
||||||
transferMTime = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseDstFile = 1;
|
releaseDstFile = 1;
|
||||||
@@ -2518,8 +2534,8 @@ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx,
|
|||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transferMTime) {
|
if (transferStat) {
|
||||||
UTIL_utime(dstFileName, &statbuf);
|
UTIL_setFileStat(dstFileName, srcFileStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (result != 0) /* operation failure */
|
if ( (result != 0) /* operation failure */
|
||||||
@@ -2541,6 +2557,7 @@ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx,
|
|||||||
static int FIO_decompressSrcFile(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)
|
static int FIO_decompressSrcFile(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)
|
||||||
{
|
{
|
||||||
FILE* srcFile;
|
FILE* srcFile;
|
||||||
|
stat_t srcFileStat;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (UTIL_isDirectory(srcFileName)) {
|
if (UTIL_isDirectory(srcFileName)) {
|
||||||
@@ -2548,11 +2565,11 @@ static int FIO_decompressSrcFile(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
srcFile = FIO_openSrcFile(prefs, srcFileName);
|
srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);
|
||||||
if (srcFile==NULL) return 1;
|
if (srcFile==NULL) return 1;
|
||||||
AIO_ReadPool_setFile(ress.readCtx, srcFile);
|
AIO_ReadPool_setFile(ress.readCtx, srcFile);
|
||||||
|
|
||||||
result = FIO_decompressDstFile(fCtx, prefs, ress, dstFileName, srcFileName);
|
result = FIO_decompressDstFile(fCtx, prefs, ress, dstFileName, srcFileName, &srcFileStat);
|
||||||
|
|
||||||
AIO_ReadPool_setFile(ress.readCtx, NULL);
|
AIO_ReadPool_setFile(ress.readCtx, NULL);
|
||||||
|
|
||||||
@@ -2917,10 +2934,11 @@ static InfoError
|
|||||||
getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName)
|
getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName)
|
||||||
{
|
{
|
||||||
InfoError status;
|
InfoError status;
|
||||||
FILE* const srcFile = FIO_openSrcFile(NULL, inFileName);
|
stat_t srcFileStat;
|
||||||
|
FILE* const srcFile = FIO_openSrcFile(NULL, inFileName, &srcFileStat);
|
||||||
ERROR_IF(srcFile == NULL, info_file_error, "Error: could not open source file %s", inFileName);
|
ERROR_IF(srcFile == NULL, info_file_error, "Error: could not open source file %s", inFileName);
|
||||||
|
|
||||||
info->compressedSize = UTIL_getFileSize(inFileName);
|
info->compressedSize = UTIL_getFileSizeStat(&srcFileStat);
|
||||||
status = FIO_analyzeFrames(info, srcFile);
|
status = FIO_analyzeFrames(info, srcFile);
|
||||||
|
|
||||||
fclose(srcFile);
|
fclose(srcFile);
|
||||||
|
@@ -185,7 +185,7 @@ int UTIL_isRegularFileStat(const stat_t* statbuf)
|
|||||||
int UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions)
|
int UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions)
|
||||||
{
|
{
|
||||||
stat_t localStatBuf;
|
stat_t localStatBuf;
|
||||||
UTIL_TRACE_CALL("UTIL_chmod(%s, %u)", filename, (unsigned)permissions);
|
UTIL_TRACE_CALL("UTIL_chmod(%s, %#4o)", filename, (unsigned)permissions);
|
||||||
if (statbuf == NULL) {
|
if (statbuf == NULL) {
|
||||||
if (!UTIL_stat(filename, &localStatBuf)) {
|
if (!UTIL_stat(filename, &localStatBuf)) {
|
||||||
UTIL_TRACE_RET(0);
|
UTIL_TRACE_RET(0);
|
||||||
@@ -249,11 +249,23 @@ int UTIL_setFileStat(const char *filename, const stat_t *statbuf)
|
|||||||
/* set access and modification times */
|
/* set access and modification times */
|
||||||
res += UTIL_utime(filename, statbuf);
|
res += UTIL_utime(filename, statbuf);
|
||||||
|
|
||||||
|
/* Mimic gzip's behavior:
|
||||||
|
*
|
||||||
|
* "Change the group first, then the permissions, then the owner.
|
||||||
|
* That way, the permissions will be correct on systems that allow
|
||||||
|
* users to give away files, without introducing a security hole.
|
||||||
|
* Security depends on permissions not containing the setuid or
|
||||||
|
* setgid bits." */
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */
|
res += chown(filename, -1, statbuf->st_gid); /* Apply group ownership */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
res += UTIL_chmod(filename, &curStatBuf, statbuf->st_mode & 07777); /* Copy file permissions */
|
res += UTIL_chmod(filename, &curStatBuf, statbuf->st_mode & 0777); /* Copy file permissions */
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
res += chown(filename, statbuf->st_uid, -1); /* Apply user ownership */
|
||||||
|
#endif
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
UTIL_TRACE_RET(-res);
|
UTIL_TRACE_RET(-res);
|
||||||
@@ -272,11 +284,15 @@ int UTIL_isDirectory(const char* infilename)
|
|||||||
|
|
||||||
int UTIL_isDirectoryStat(const stat_t* statbuf)
|
int UTIL_isDirectoryStat(const stat_t* statbuf)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
UTIL_TRACE_CALL("UTIL_isDirectoryStat()");
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
return (statbuf->st_mode & _S_IFDIR) != 0;
|
ret = (statbuf->st_mode & _S_IFDIR) != 0;
|
||||||
#else
|
#else
|
||||||
return S_ISDIR(statbuf->st_mode) != 0;
|
ret = S_ISDIR(statbuf->st_mode) != 0;
|
||||||
#endif
|
#endif
|
||||||
|
UTIL_TRACE_RET(ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UTIL_compareStr(const void *p1, const void *p2) {
|
int UTIL_compareStr(const void *p1, const void *p2) {
|
||||||
@@ -299,8 +315,32 @@ int UTIL_isSameFile(const char* fName1, const char* fName2)
|
|||||||
stat_t file2Stat;
|
stat_t file2Stat;
|
||||||
ret = UTIL_stat(fName1, &file1Stat)
|
ret = UTIL_stat(fName1, &file1Stat)
|
||||||
&& UTIL_stat(fName2, &file2Stat)
|
&& UTIL_stat(fName2, &file2Stat)
|
||||||
&& (file1Stat.st_dev == file2Stat.st_dev)
|
&& UTIL_isSameFileStat(fName1, fName2, &file1Stat, &file2Stat);
|
||||||
&& (file1Stat.st_ino == file2Stat.st_ino);
|
}
|
||||||
|
#endif
|
||||||
|
UTIL_TRACE_RET(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UTIL_isSameFileStat(
|
||||||
|
const char* fName1, const char* fName2,
|
||||||
|
const stat_t* file1Stat, const stat_t* file2Stat)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
assert(fName1 != NULL); assert(fName2 != NULL);
|
||||||
|
UTIL_TRACE_CALL("UTIL_isSameFileStat(%s, %s)", fName1, fName2);
|
||||||
|
#if defined(_MSC_VER) || defined(_WIN32)
|
||||||
|
/* note : Visual does not support file identification by inode.
|
||||||
|
* inode does not work on Windows, even with a posix layer, like msys2.
|
||||||
|
* The following work-around is limited to detecting exact name repetition only,
|
||||||
|
* aka `filename` is considered different from `subdir/../filename` */
|
||||||
|
(void)file1Stat;
|
||||||
|
(void)file2Stat;
|
||||||
|
ret = !strcmp(fName1, fName2);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
ret = (file1Stat->st_dev == file2Stat->st_dev)
|
||||||
|
&& (file1Stat->st_ino == file2Stat->st_ino);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
UTIL_TRACE_RET(ret);
|
UTIL_TRACE_RET(ret);
|
||||||
|
@@ -171,6 +171,7 @@ int UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions);
|
|||||||
int UTIL_isRegularFile(const char* infilename);
|
int UTIL_isRegularFile(const char* infilename);
|
||||||
int UTIL_isDirectory(const char* infilename);
|
int UTIL_isDirectory(const char* infilename);
|
||||||
int UTIL_isSameFile(const char* file1, const char* file2);
|
int UTIL_isSameFile(const char* file1, const char* file2);
|
||||||
|
int UTIL_isSameFileStat(const char* file1, const char* file2, const stat_t* file1Stat, const stat_t* file2Stat);
|
||||||
int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]);
|
int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]);
|
||||||
int UTIL_isLink(const char* infilename);
|
int UTIL_isLink(const char* infilename);
|
||||||
int UTIL_isFIFO(const char* infilename);
|
int UTIL_isFIFO(const char* infilename);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
datagen > file
|
datagen > file
|
||||||
|
chmod 642 file
|
||||||
|
|
||||||
zstd file -q --trace-file-stat -o file.zst
|
zstd file -q --trace-file-stat -o file.zst
|
||||||
zstd -tq file.zst
|
zstd -tq file.zst
|
||||||
|
@@ -6,12 +6,10 @@ Trace:FileStat: > UTIL_getFileSize(file)
|
|||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: < 65537
|
Trace:FileStat: < 65537
|
||||||
Trace:FileStat: > UTIL_isDirectory(file)
|
|
||||||
Trace:FileStat: > UTIL_stat(file)
|
|
||||||
Trace:FileStat: < 1
|
|
||||||
Trace:FileStat: < 0
|
|
||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
|
Trace:FileStat: > UTIL_isDirectoryStat()
|
||||||
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: > UTIL_isSameFile(file, file.zst)
|
Trace:FileStat: > UTIL_isSameFile(file, file.zst)
|
||||||
@@ -32,5 +30,13 @@ Trace:FileStat: > UTIL_getFileSize(file)
|
|||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: < 65537
|
Trace:FileStat: < 65537
|
||||||
Trace:FileStat: > UTIL_utime(file.zst)
|
Trace:FileStat: > UTIL_setFileStat(file.zst)
|
||||||
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
|
Trace:FileStat: < 1
|
||||||
|
Trace:FileStat: > UTIL_utime(file.zst)
|
||||||
|
Trace:FileStat: < 0
|
||||||
|
Trace:FileStat: > UTIL_chmod(file.zst, 0642)
|
||||||
|
Trace:FileStat: > chmod
|
||||||
|
Trace:FileStat: < 0
|
||||||
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
|
@@ -6,9 +6,9 @@ Trace:FileStat: > UTIL_getFileSize(file)
|
|||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: < 65537
|
Trace:FileStat: < 65537
|
||||||
Trace:FileStat: > UTIL_isDirectory(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: > UTIL_isDirectoryStat()
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
|
@@ -6,10 +6,6 @@ Trace:FileStat: > UTIL_getFileSize(/*stdin*\)
|
|||||||
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < -1
|
Trace:FileStat: < -1
|
||||||
Trace:FileStat: > UTIL_isDirectory(/*stdin*\)
|
|
||||||
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
|
||||||
Trace:FileStat: < 0
|
|
||||||
Trace:FileStat: < 0
|
|
||||||
Trace:FileStat: > UTIL_isSameFile(/*stdin*\, file.zst)
|
Trace:FileStat: > UTIL_isSameFile(/*stdin*\, file.zst)
|
||||||
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
|
@@ -6,10 +6,6 @@ Trace:FileStat: > UTIL_getFileSize(/*stdin*\)
|
|||||||
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < -1
|
Trace:FileStat: < -1
|
||||||
Trace:FileStat: > UTIL_isDirectory(/*stdin*\)
|
|
||||||
Trace:FileStat: > UTIL_stat(/*stdin*\)
|
|
||||||
Trace:FileStat: < 0
|
|
||||||
Trace:FileStat: < 0
|
|
||||||
Trace:FileStat: > UTIL_isRegularFile(/*stdout*\)
|
Trace:FileStat: > UTIL_isRegularFile(/*stdout*\)
|
||||||
Trace:FileStat: > UTIL_stat(/*stdout*\)
|
Trace:FileStat: > UTIL_stat(/*stdout*\)
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
|
@@ -3,5 +3,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
datagen | zstd -q > file.zst
|
datagen | zstd -q > file.zst
|
||||||
|
chmod 642 file.zst
|
||||||
|
|
||||||
zstd -dq --trace-file-stat file.zst
|
zstd -dq --trace-file-stat file.zst
|
||||||
|
@@ -7,11 +7,11 @@ Trace:FileStat: < 0
|
|||||||
Trace:FileStat: > UTIL_isDirectory(file.zst)
|
Trace:FileStat: > UTIL_isDirectory(file.zst)
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
|
Trace:FileStat: > UTIL_isDirectoryStat()
|
||||||
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
|
||||||
Trace:FileStat: < 1
|
|
||||||
Trace:FileStat: > UTIL_isSameFile(file.zst, file)
|
Trace:FileStat: > UTIL_isSameFile(file.zst, file)
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
@@ -26,5 +26,13 @@ Trace:FileStat: > UTIL_isRegularFile(file)
|
|||||||
Trace:FileStat: > UTIL_stat(file)
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
Trace:FileStat: > UTIL_utime(file)
|
Trace:FileStat: > UTIL_setFileStat(file)
|
||||||
|
Trace:FileStat: > UTIL_stat(file)
|
||||||
|
Trace:FileStat: < 1
|
||||||
|
Trace:FileStat: > UTIL_utime(file)
|
||||||
|
Trace:FileStat: < 0
|
||||||
|
Trace:FileStat: > UTIL_chmod(file, 0642)
|
||||||
|
Trace:FileStat: > chmod
|
||||||
|
Trace:FileStat: < 0
|
||||||
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
|
@@ -5,6 +5,8 @@ Trace:FileStat: < 0
|
|||||||
Trace:FileStat: > UTIL_isDirectory(file.zst)
|
Trace:FileStat: > UTIL_isDirectory(file.zst)
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
|
Trace:FileStat: > UTIL_isDirectoryStat()
|
||||||
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: < 0
|
Trace:FileStat: < 0
|
||||||
Trace:FileStat: > UTIL_stat(file.zst)
|
Trace:FileStat: > UTIL_stat(file.zst)
|
||||||
Trace:FileStat: < 1
|
Trace:FileStat: < 1
|
||||||
|
@@ -562,19 +562,9 @@ if [ "$isWindows" = false ] ; then
|
|||||||
zstd -f -d tmp1.zst -o tmp1.out
|
zstd -f -d tmp1.zst -o tmp1.out
|
||||||
assertFilePermissions tmp1.out 400
|
assertFilePermissions tmp1.out 400
|
||||||
|
|
||||||
rm -f tmp1.zst tmp1.out
|
|
||||||
|
|
||||||
umask 0666
|
umask 0666
|
||||||
chmod 0666 tmp1 tmp2
|
chmod 0666 tmp1 tmp2
|
||||||
|
|
||||||
println "test : respect umask when copying permissions in file -> file compression "
|
|
||||||
zstd -f tmp1 -o tmp1.zst
|
|
||||||
assertFilePermissions tmp1.zst 0
|
|
||||||
println "test : respect umask when copying permissions in file -> file decompression "
|
|
||||||
chmod 0666 tmp1.zst
|
|
||||||
zstd -f -d tmp1.zst -o tmp1.out
|
|
||||||
assertFilePermissions tmp1.out 0
|
|
||||||
|
|
||||||
rm -f tmp1.zst tmp1.out
|
rm -f tmp1.zst tmp1.out
|
||||||
|
|
||||||
println "test : respect umask when compressing from stdin input "
|
println "test : respect umask when compressing from stdin input "
|
||||||
|
Reference in New Issue
Block a user