Guillem Jover wrote:

> This is misleading on Linux, but it's not a safe portable assumption
> to make on POSIX in general as that behaviour is not specified and as
> such is implementation specific, some Unix systems do actually fail
> on read-only file descriptors, for example:
>
>   
> <http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/fsync.htm>

Right.

Actually, there's another bug lurking here: files marked as hard links
in the tarfile get installed before the corresponding fsync(), with
corresponding risk of 0-length files and so on.

How about this?  Untested.
---
 debian/changelog |   10 ++++++++++
 src/archives.c   |   37 ++++++++++++++++++++++++++++++-------
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 20c296d5..44dfc9d7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -186,6 +186,16 @@ dpkg (1.16.1~jrn) local; urgency=low
   * Add new --raw-extract option to dpkg-deb combining --control and
     --extract. Closes: #552123
 
+  [ Jonathan Nieder ]
+  * Defer installing hard links with their final name until the file has
+    been fsynced. This avoids a small window in which the content of the
+    file is undefined.
+  * Skip fsync if a file being installed cannot be opened for writing and
+    errno is ETXTBSY, under the assumption that another link must have been
+    fsynced renamed into place already. For example, this happens when
+    upgrading the /usr/bin/perl hard link. Regression introduced in
+    1.15.6.1. Closes: #635683
+
   [ Updated dpkg translations ]
   * German (Sven Joachim). Closes: #620312
   * Swedish (Peter Krefting).
diff --git a/src/archives.c b/src/archives.c
index f060e706..88821c60 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -851,7 +851,8 @@ tarobject(void *ctx, struct tar_entry *ti)
    * in .dpkg-new.
    */
 
-  if (ti->type == tar_filetype_file || ti->type == tar_filetype_symlink) {
+  if (ti->type == tar_filetype_file || ti->type == tar_filetype_symlink ||
+      ti->type == tar_filetype_hardlink) {
     nifd->namenode->flags |= fnnf_deferred_rename;
 
     debug(dbg_eachfiledetail, "tarobject done and installation deferred");
@@ -938,12 +939,34 @@ tar_deferred_extract(struct fileinlist *files, struct 
pkginfo *pkg)
       debug(dbg_eachfiledetail, "deferred extract needs fsync");
 
       fd = open(fnamenewvb.buf, O_WRONLY);
-      if (fd < 0)
-        ohshite(_("unable to open '%.255s'"), fnamenewvb.buf);
-      if (fsync(fd))
-        ohshite(_("unable to sync file '%.255s'"), fnamenewvb.buf);
-      if (close(fd))
-        ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf);
+      if (fd < 0 && errno == ETXTBSY) {
+        /*
+         * The file wasn't renamed yet. Why would someone map its
+         * text so early?
+         *
+         * Most likely, this is a second hard link to a binary
+         * that already _was_ renamed into place. For example, by
+         * the time we prepare to rename /usr/bin/perl5.x.dpkg-new,
+         * the other link /usr/bin/perl can be in use. Luckily,
+         * that means the file was already synchronized to disk
+         * before renaming the first link and it is safe to skip
+         * the fsync this time around.
+         *
+         * The other possibility is that someone executed the
+         * .dpkg-new file directly. The file will not be
+         * synchronized, but that's ok --- no need to error out.
+         */
+
+         debug(dbg_eachfiledetail,
+               "deferred extract skipping fsync (text is busy)");
+      } else {
+        if (fd < 0)
+          ohshite(_("unable to open '%.255s'"), fnamenewvb.buf);
+        if (fsync(fd))
+          ohshite(_("unable to sync file '%.255s'"), fnamenewvb.buf);
+        if (close(fd))
+          ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf);
+      }
 
       cfile->namenode->flags &= ~fnnf_deferred_fsync;
     }
-- 
1.7.6





-- 
To UNSUBSCRIBE, email to debian-dpkg-bugs-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to