]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Check regular file for sparse support after opening
authorLi-Yu Yu <aaronyu@google.com>
Fri, 28 Mar 2025 21:16:29 +0000 (21:16 +0000)
committerLi-Yu Yu <aaronyu@google.com>
Fri, 28 Mar 2025 21:23:10 +0000 (21:23 +0000)
A regular file may be created by the open call.
Checking after opening allows sparseFileSupport even
if dstFileName does not already exist.

programs/fileio.c
programs/util.c
programs/util.h

index dc7636949725558aeebd0836886981345a57163e..b1303a2ad140fd60be0a31b8336c770f859f63b4 100644 (file)
@@ -585,8 +585,6 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
                 const char* srcFileName, const char* dstFileName,
                 const int mode)
 {
-    int isDstRegFile;
-
     if (prefs->testMode) return NULL;  /* do not open file in test mode */
 
     assert(dstFileName != NULL);
@@ -606,16 +604,7 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
         return NULL;
     }
 
-    isDstRegFile = UTIL_isRegularFile(dstFileName);  /* invoke once */
-    if (prefs->sparseFileSupport == 1) {
-        prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
-        if (!isDstRegFile) {
-            prefs->sparseFileSupport = 0;
-            DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n");
-        }
-    }
-
-    if (isDstRegFile) {
+    if (UTIL_isRegularFile(dstFileName)) {
         /* Check if destination file already exists */
 #if !defined(_WIN32)
         /* this test does not work on Windows :
@@ -658,6 +647,16 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
             f = fdopen(fd, "wb");
         }
 #endif
+
+        if (prefs->sparseFileSupport == 1) {
+            prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
+            /* Check regular file after opening with O_CREAT */
+            if (!UTIL_isFdRegularFile(fd)) {
+                prefs->sparseFileSupport = 0;
+                DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n");
+            }
+        }
+
         if (f == NULL) {
             if (UTIL_isFileDescriptorPipe(dstFileName)) {
                 DISPLAYLEVEL(1, "zstd: error: no output specified (use -o or -c). \n");
index 94c40cc958b811bd77efe68aaf22a0594a87be25..850bcacd2e9aa4db73d6084d9b2098cac2e42ace 100644 (file)
@@ -197,6 +197,16 @@ int UTIL_stat(const char* filename, stat_t* statbuf)
     return UTIL_fstat(-1, filename, statbuf);
 }
 
+int UTIL_isFdRegularFile(int fd)
+{
+    stat_t statbuf;
+    int ret;
+    UTIL_TRACE_CALL("UTIL_isFdRegularFile(%d)", fd);
+    ret = UTIL_fstat(fd, "", &statbuf) && UTIL_isRegularFileStat(&statbuf);
+    UTIL_TRACE_RET(ret);
+    return ret;
+}
+
 int UTIL_isRegularFile(const char* infilename)
 {
     stat_t statbuf;
index 427bcf441ea6163a2b773f349e4f78a641bd2d10..65e12633a6759cf35ccaa0f1bba1d36f130d6d62 100644 (file)
@@ -184,6 +184,7 @@ int UTIL_fchmod(const int fd, char const* filename, const stat_t* statbuf, mode_
  * compute the needed information.
  */
 
+int UTIL_isFdRegularFile(int fd);
 int UTIL_isRegularFile(const char* infilename);
 int UTIL_isDirectory(const char* infilename);
 int UTIL_isSameFile(const char* file1, const char* file2);