]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Re-Use `stat_t` in `FIO_compressFilename_srcFile()`
authorW. Felix Handte <w@felixhandte.com>
Tue, 17 Jan 2023 22:50:31 +0000 (14:50 -0800)
committerW. Felix Handte <w@felixhandte.com>
Wed, 18 Jan 2023 19:33:07 +0000 (11:33 -0800)
programs/fileio.c
programs/util.c
programs/util.h
tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact
tests/cli-tests/file-stat/compress-file-to-stdout.sh.stderr.exact
tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.exact
tests/cli-tests/file-stat/compress-stdin-to-stdout.sh.stderr.exact
tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact
tests/cli-tests/file-stat/decompress-file-to-stdout.sh.stderr.exact

index 2067cfcda17ea4c99d459a2896ce290b4269c5d2..0e1345596b43bd3d4e92822db8e7bb48c594489f 100644 (file)
@@ -662,23 +662,23 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
  * @return : loaded size
  *  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;
     U64 fileSize;
-    stat_t statbuf;
 
     assert(bufferPtr != NULL);
+    assert(dictFileStat != NULL);
     *bufferPtr = NULL;
     if (fileName == NULL) return 0;
 
     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));
     }
 
-    if (!UTIL_isRegularFileStat(&statbuf)) {
+    if (!UTIL_isRegularFileStat(dictFileStat)) {
         EXM_THROW(32, "Dictionary %s must be a regular file.", fileName);
     }
 
@@ -688,7 +688,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));
     }
 
-    fileSize = UTIL_getFileSizeStat(&statbuf);
+    fileSize = UTIL_getFileSizeStat(dictFileStat);
     {
         size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
         if (fileSize >  dictSizeMax) {
@@ -869,6 +869,7 @@ typedef struct {
     void* dictBuffer;
     size_t dictBufferSize;
     const char* dictFileName;
+    stat_t dictFileStat;
     ZSTD_CStream* cctx;
     WritePoolCtx_t *writeCtx;
     ReadPoolCtx_t *readCtx;
@@ -927,7 +928,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
         unsigned long long const ssSize = (unsigned long long)prefs->streamSrcSize;
         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.readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize());
@@ -1712,16 +1713,22 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
     stat_t srcFileStat;
     DISPLAYLEVEL(6, "FIO_compressFilename_srcFile: %s \n", srcFileName);
 
-    /* ensure src is not a directory */
-    if (UTIL_isDirectory(srcFileName)) {
-        DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
-        return 1;
-    }
+    if (strcmp(srcFileName, stdinmark)) {
+        if (UTIL_stat(srcFileName, &srcFileStat)) {
+            /* failure to stat at all is handled during opening */
 
-    /* ensure src is not the same as dict (if present) */
-    if (ress.dictFileName != NULL && UTIL_isSameFile(srcFileName, ress.dictFileName)) {
-        DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
-        return 1;
+            /* ensure src is not a directory */
+            if (UTIL_isDirectoryStat(&srcFileStat)) {
+                DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
+                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
@@ -1998,7 +2005,8 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi
 
     /* dictionary */
     {   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_loadDictionary(ress.dctx, dictBuffer, dictBufferSize) );
         free(dictBuffer);
index 21d7d3b469d32b84eef8b0916fc7be8ea5d2b2c4..7402b75d2a24c3512352702d2ccebc2259f90411 100644 (file)
@@ -272,11 +272,15 @@ int UTIL_isDirectory(const char* infilename)
 
 int UTIL_isDirectoryStat(const stat_t* statbuf)
 {
+    int ret;
+    UTIL_TRACE_CALL("UTIL_isDirectoryStat()");
 #if defined(_MSC_VER)
-    return (statbuf->st_mode & _S_IFDIR) != 0;
+    ret = (statbuf->st_mode & _S_IFDIR) != 0;
 #else
-    return S_ISDIR(statbuf->st_mode) != 0;
+    ret = S_ISDIR(statbuf->st_mode) != 0;
 #endif
+    UTIL_TRACE_RET(ret);
+    return ret;
 }
 
 int UTIL_compareStr(const void *p1, const void *p2) {
@@ -299,8 +303,32 @@ int UTIL_isSameFile(const char* fName1, const char* fName2)
         stat_t file2Stat;
         ret =  UTIL_stat(fName1, &file1Stat)
             && UTIL_stat(fName2, &file2Stat)
-            && (file1Stat.st_dev == file2Stat.st_dev)
-            && (file1Stat.st_ino == file2Stat.st_ino);
+            && UTIL_isSameFileStat(fName1, fName2, &file1Stat, &file2Stat);
+    }
+#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
     UTIL_TRACE_RET(ret);
index 88ee1bad12af3333a4e00f4d65f9ee4950a6d006..4ec54137dd3c3554dcdab8bf3f7dd070f72de68b 100644 (file)
@@ -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_isDirectory(const char* infilename);
 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_isLink(const char* infilename);
 int UTIL_isFIFO(const char* infilename);
index 7297894c712671378fce184b78785999e47b35e5..8732336330dad234a120b041d10e01b03900dee8 100644 (file)
@@ -6,9 +6,9 @@ Trace:FileStat: > UTIL_getFileSize(file)
 Trace:FileStat:  > UTIL_stat(file)
 Trace:FileStat:  < 1
 Trace:FileStat: < 65537
-Trace:FileStat: > UTIL_isDirectory(file)
-Trace:FileStat:  > UTIL_stat(file)
-Trace:FileStat:  < 1
+Trace:FileStat: > UTIL_stat(file)
+Trace:FileStat: < 1
+Trace:FileStat: > UTIL_isDirectoryStat()
 Trace:FileStat: < 0
 Trace:FileStat: > UTIL_stat(file)
 Trace:FileStat: < 1
index e01922f84f27fcf53d39e3b7364a85cd894ae513..e86c4eae348993bd464eda795d53d049ff9c38ac 100644 (file)
@@ -6,9 +6,9 @@ Trace:FileStat: > UTIL_getFileSize(file)
 Trace:FileStat:  > UTIL_stat(file)
 Trace:FileStat:  < 1
 Trace:FileStat: < 65537
-Trace:FileStat: > UTIL_isDirectory(file)
-Trace:FileStat:  > UTIL_stat(file)
-Trace:FileStat:  < 1
+Trace:FileStat: > UTIL_stat(file)
+Trace:FileStat: < 1
+Trace:FileStat: > UTIL_isDirectoryStat()
 Trace:FileStat: < 0
 Trace:FileStat: > UTIL_stat(file)
 Trace:FileStat: < 1
index dce9005f4d53e4616336f13b1f8e11308d9ba5c1..00afd97c365833121848d791be203ae8a2f31694 100644 (file)
@@ -6,10 +6,6 @@ Trace:FileStat: > UTIL_getFileSize(/*stdin*\)
 Trace:FileStat:  > UTIL_stat(/*stdin*\)
 Trace:FileStat:  < 0
 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_stat(/*stdin*\)
 Trace:FileStat:  < 0
index d47bdcf09f8e55ad11704f24c7563598af25498a..2e44511d8a8b845116e6dd8433219235cfbdb5d7 100644 (file)
@@ -6,10 +6,6 @@ Trace:FileStat: > UTIL_getFileSize(/*stdin*\)
 Trace:FileStat:  > UTIL_stat(/*stdin*\)
 Trace:FileStat:  < 0
 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_stat(/*stdout*\)
 Trace:FileStat:  < 0
index 2af60eb4336dea4f9365c95c304ce615c8132c43..53c3333eb123af7b23e177f0e181a395ec50f100 100644 (file)
@@ -7,6 +7,8 @@ Trace:FileStat: < 0
 Trace:FileStat: > UTIL_isDirectory(file.zst)
 Trace:FileStat:  > UTIL_stat(file.zst)
 Trace:FileStat:  < 1
+Trace:FileStat:  > UTIL_isDirectoryStat()
+Trace:FileStat:  < 0
 Trace:FileStat: < 0
 Trace:FileStat: > UTIL_stat(file.zst)
 Trace:FileStat: < 1
index 87fc5e97cbce0492924c32f33c716cc153b4dddc..bbf66506b10934c254172151e10df4644436d6f4 100644 (file)
@@ -5,6 +5,8 @@ Trace:FileStat: < 0
 Trace:FileStat: > UTIL_isDirectory(file.zst)
 Trace:FileStat:  > UTIL_stat(file.zst)
 Trace:FileStat:  < 1
+Trace:FileStat:  > UTIL_isDirectoryStat()
+Trace:FileStat:  < 0
 Trace:FileStat: < 0
 Trace:FileStat: > UTIL_stat(file.zst)
 Trace:FileStat: < 1