Avoid ext4 auto_da_alloc flush on close (v2).
[pxzcat.git] / pxzcat.c
index 7e036d0..1285ed1 100644 (file)
--- a/pxzcat.c
+++ b/pxzcat.c
@@ -166,16 +166,21 @@ xzfile_uncompress (const char *filename, const char *outputfile,
   debug ("uncompressed size = %" PRIu64 " bytes", size);
 
   /* Avoid annoying ext4 auto_da_alloc which causes a flush on close
-   * unless we are very careful about not truncating the file when it
-   * has zero size.  (Thanks Eric Sandeen)
+   * unless we are very careful about not truncating a regular file
+   * from non-zero size to zero size.  (Thanks Eric Sandeen)
    */
-  unlink (outputfile);
-
-  ofd = open (outputfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0644);
+  ofd = open (outputfile, O_WRONLY|O_CREAT|O_NOCTTY, 0644);
   if (ofd == -1)
     error (EXIT_FAILURE, errno, "open: %s", outputfile);
-  /* See above about auto_da_alloc. */
-  write (ofd, "\0", 1);
+
+  if (ftruncate (ofd, 1) == -1)
+    error (EXIT_FAILURE, errno, "ftruncate (1 byte): %s", outputfile);
+
+  if (lseek (ofd, 0, SEEK_SET) == -1)
+    error (EXIT_FAILURE, errno, "lseek: %s", outputfile);
+
+  if (write (ofd, "\0", 1) == -1)
+    error (EXIT_FAILURE, errno, "write: %s", outputfile);
 
   if (ftruncate (ofd, size) == -1)
     error (EXIT_FAILURE, errno, "ftruncate: %s", outputfile);