Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu lucid ubuntu-patch

Here is a patch which adds some fsync on files and directories to
prevent delayed allocation and the zero-length file problem on ext4
filesystem.

This patch is build against dpkg 1.15.5.6ubuntu1, I'll try to provide a
version for debian soon.

Don't hesitate to comment this patch and I'll update it if needed.

Thanks.
diff -Nru dpkg-1.15.5.6ubuntu1/debian/changelog 
dpkg-1.15.5.6ubuntu2/debian/changelog
--- dpkg-1.15.5.6ubuntu1/debian/changelog       2010-02-14 02:40:26.000000000 
+0100
+++ dpkg-1.15.5.6ubuntu2/debian/changelog       2010-02-14 12:56:27.000000000 
+0100
@@ -1,3 +1,14 @@
+dpkg (1.15.5.6ubuntu2) lucid; urgency=low
+
+  * Add fsync on files and directories to prevent delayed allocation and the
+    zero-length file problem after a system crash LP: #512096 (Debian #567089) 
+    - dpkg-deb/extract.c: fsync control files
+    - src/archive.c: fsync newly extracted files
+    - lib/dpkg/cleanup.c: fsync directory before closing
+    - lib/dpkg/dump.c: fsync db directory
+
+ -- Jean-Baptiste Lallement <jeanbaptiste.lallem...@gmail.com>  Sun, 14 Feb 
2010 12:44:38 +0100
+
 dpkg (1.15.5.6ubuntu1) lucid; urgency=low
 
   * Resynchronise with Debian.  Remaining changes:
diff -Nru dpkg-1.15.5.6ubuntu1/dpkg-deb/extract.c 
dpkg-1.15.5.6ubuntu2/dpkg-deb/extract.c
--- dpkg-1.15.5.6ubuntu1/dpkg-deb/extract.c     2010-02-14 02:40:26.000000000 
+0100
+++ dpkg-1.15.5.6ubuntu2/dpkg-deb/extract.c     2010-02-14 12:19:16.000000000 
+0100
@@ -36,6 +36,7 @@
 #include <ar.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <fcntl.h>
 #ifdef WITH_ZLIB
 #include <zlib.h>
 #endif
@@ -337,6 +338,30 @@
       movecontrolfiles(OLDDEBDIR);
     }
   }
+
+  /* fsync extracted files to prevent delayed allocation and the zero-length
+   * file problem */
+  if (taroption && directory) {
+    DIR *dsd;
+    struct dirent *de;
+    int fd;
+
+    dsd= opendir(directory); 
+    if (!dsd) ohshite(_("cannot read directory `%.250s'"),directory);
+    if (chdir(directory)) 
+        ohshite(_("failed to chdir to `%.255s'"), directory);
+
+    while ((de = readdir(dsd)) != NULL){
+      if (strchr(de->d_name,'.'))
+        continue;
+
+      if ((fd = open( de->d_name, O_RDONLY )) != -1) {
+        fsync(fd);
+        close(fd);
+      }
+    }
+    closedir( dsd );
+  }
 }
 
 static void controlextractvextract(int admin,
diff -Nru dpkg-1.15.5.6ubuntu1/lib/dpkg/cleanup.c 
dpkg-1.15.5.6ubuntu2/lib/dpkg/cleanup.c
--- dpkg-1.15.5.6ubuntu1/lib/dpkg/cleanup.c     2010-02-14 02:40:26.000000000 
+0100
+++ dpkg-1.15.5.6ubuntu2/lib/dpkg/cleanup.c     2010-02-14 12:30:21.000000000 
+0100
@@ -51,8 +51,10 @@
 {
        DIR *d = (DIR *)(argv[0]);
 
-       if (d)
+       if (d) {
+               fsync(dirfd(d));
                closedir(d);
+       }
 }
 
 void
diff -Nru dpkg-1.15.5.6ubuntu1/lib/dpkg/dump.c 
dpkg-1.15.5.6ubuntu2/lib/dpkg/dump.c
--- dpkg-1.15.5.6ubuntu1/lib/dpkg/dump.c        2010-02-14 02:40:26.000000000 
+0100
+++ dpkg-1.15.5.6ubuntu2/lib/dpkg/dump.c        2010-02-14 12:08:08.000000000 
+0100
@@ -33,6 +33,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <dirent.h>
 
 #include <dpkg/i18n.h>
 #include <dpkg/dpkg.h>
@@ -362,6 +363,8 @@
   FILE *file;
   struct varbuf vb = VARBUF_INIT;
   int old_umask;
+  char *fname, *dname;
+  DIR *dirp;
 
   which= available ? "available" : "status";
   oldfn= m_malloc(strlen(filename)+sizeof(OLDDBEXT));
@@ -409,4 +412,17 @@
             newfn, filename, which);
   free(newfn);
   free(oldfn);
+
+  /* We need to sync the directory */
+  fname = strdup( filename );
+  dname = strrchr( fname, '/' );
+  if ( dname && *dname )
+    *dname = '\0';
+
+  if ( (dirp = opendir(fname))==NULL) 
+    ohshite(_("failed to opendir `%.250s'"), fname );
+  if ( fsync(dirfd(dirp)) == -1 ) 
+    ohshite(_("failed to fsync `%.250s'"), fname );
+  closedir( dirp );
+  free( fname );
 }
diff -Nru dpkg-1.15.5.6ubuntu1/src/archives.c 
dpkg-1.15.5.6ubuntu2/src/archives.c
--- dpkg-1.15.5.6ubuntu1/src/archives.c 2010-02-14 02:40:27.000000000 +0100
+++ dpkg-1.15.5.6ubuntu2/src/archives.c 2010-02-14 12:14:20.000000000 +0100
@@ -655,6 +655,8 @@
     if (fchmod(fd,am))
       ohshite(_("error setting permissions of `%.255s'"),ti->Name);
     pop_cleanup(ehflag_normaltidy); /* fd= open(fnamenewvb.buf) */
+    if (fsync(fd))
+      ohshite(_("unable to fsync new file `%.250s'"), fnamenewvb.buf );
     if (close(fd))
       ohshite(_("error closing/writing `%.255s'"),ti->Name);
     newtarobject_utime(fnamenewvb.buf,ti);

Reply via email to