Package: gzip
Version: 1.3.5-13
Severity: critical
Tags: patch
Justification: causes serious data loss

gzip must check that closing the output file succeeds before removing
the input file, since on an NFS filesystem write failures may only be
reported at close time (see the close(2) man page).

Indeed in our environment we are seeing this problem with NFS and disk
quotas.  This results in loss of the input file, despite the fact that
gzip reports an error and the output file is truncated.

I've attached a proposed patch.  In the original code, copy_stat() has
the side-effect of removing the input file.  Here I have moved the
unlink out of that function and to below the close of the output file.

Matt


-- System Information:
Debian Release: testing/unstable
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.16.4-general
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8)

Versions of packages gzip depends on:
hi  debianutils                   2.15.2     Miscellaneous utilities specific t
hi  libc6                         2.3.5-8    GNU C Library: Shared libraries an

gzip recommends no packages.

-- no debconf information
--- gzip.c.orig	2006-05-10 15:12:34.000000000 +1000
+++ gzip.c	2006-05-10 15:45:35.000000000 +1000
@@ -882,10 +882,21 @@
 
     close(ifd);
     if (!to_stdout) {
-         /* Copy modes, times, ownership, and remove the input file */
-         copy_stat(&istat);
-         if (close(ofd))
-            write_error();
+	 /* Copy modes, times, and ownership */
+	 copy_stat(&istat);
+	 if (close(ofd))
+	   write_error();
+	 remove_ofname = 0;
+
+	 /* It's now safe to remove the input file: */
+	 if (xunlink (ifname)) {
+	   int e = errno;
+	   WARN((stderr, "%s: ", progname));
+	   if (!quiet) {
+	     errno = e;
+	     perror(ifname);
+	   }
+	}
     }
     if (method == -1) {
 	if (!to_stdout) xunlink (ofname);
@@ -1745,16 +1756,6 @@
 #ifndef NO_CHOWN
     fchown(ofd, ifstat->st_uid, ifstat->st_gid);  /* Copy ownership */
 #endif
-    remove_ofname = 0;
-    /* It's now safe to remove the input file: */
-    if (xunlink (ifname)) {
-	int e = errno;
-	WARN((stderr, "%s: ", progname));
-	if (!quiet) {
-	    errno = e;
-	    perror(ifname);
-	}
-    }
 }
 
 #if ! NO_DIR

Reply via email to