]> err.no Git - dpkg/commitdiff
Do not treat two symlinks to the same directory as a file conflict.
authorIan Jackson <iwj@ubuntu.com>
Sat, 11 Aug 2007 03:53:55 +0000 (06:53 +0300)
committerGuillem Jover <guillem@debian.org>
Sat, 11 Aug 2007 03:53:55 +0000 (06:53 +0300)
If the package contains a symlink to a directory where the existing
symlink on-disk points to the same place, do not consider it a file
conflict.

ChangeLog
debian/changelog
src/archives.c

index 53fccaeb7cb664a9a05a4c7ccd0160b300f1c604..4282bbff8cb54461acfcc549075f27595d5f3d20 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-08-11  Ian Jackson  <iwj@ubuntu.com>
+
+       * src/archives.c (linktosameexistingdir): New function.
+       (tarobject): Call linktosameexistingdir if the tarball and the on-disk
+       files are symlinks and ignore the symlink if it returns true.
+
 2007-08-08  Ian Jackson  <iwj@ubuntu.com>
 
        * scripts/update-alternatives.pl: In the case where the slave is
index 0febdea75032b9c081ccca6b4f63c323821892b4..090c2e522d3a9ad3202b913a199a1378891f3cf3 100644 (file)
@@ -31,6 +31,10 @@ dpkg (1.14.6) UNRELEASED; urgency=low
   * When a slave alternative is inapplicable do not attempt to create the
     slave link before removing it again. Closes: #411699
     Thanks to Ian Jackson.
+  * Do not consider it a file conflict if the package contains a symlink
+    to a directory where the existing symlink on-disk points to the
+    same place. Closes: #377682
+    Thanks to Ian Jackson.
 
   [ Updated scripts translations ]
   * French (Frédéric Bothamy, Christian Perrier).
index b907d92662c8c4b598f616800238a8c42c2f4847..796c65a70d8cdf7f691db3608ef34cbb34c2cfa3 100644 (file)
@@ -326,6 +326,46 @@ struct fileinlist *addfiletolist(struct tarcontext *tc,
   return nifd;
 }
 
+static int linktosameexistingdir(const struct TarInfo *ti,
+                                 const char *fname,
+                                 struct varbuf *symlinkfn) {
+  struct stat oldstab, newstab;
+  int statr;
+  const char *lastslash;
+
+  statr= stat(fname, &oldstab);
+  if (statr) {
+    if (!(errno == ENOENT || errno == ELOOP || errno == ENOTDIR))
+      ohshite("failed to stat (dereference) existing symlink `%.250s'", fname);
+    return 0;
+  }
+  if (!S_ISDIR(oldstab.st_mode)) return 0;
+
+  /* But is it to the same dir ? */
+  varbufreset(symlinkfn);
+  if (ti->LinkName[0] == '/') {
+    varbufaddstr(symlinkfn, instdir);
+  } else {
+    lastslash= strrchr(fname, '/');
+    assert(lastslash);
+    varbufaddbuf(symlinkfn, fname, (lastslash - fname) + 1);
+  }
+  varbufaddstr(symlinkfn, ti->LinkName);
+  varbufaddc(symlinkfn, 0);
+
+  statr= stat(symlinkfn->buf, &newstab);
+  if (statr) {
+    if (!(errno == ENOENT || errno == ELOOP || errno == ENOTDIR))
+      ohshite("failed to stat (dereference) proposed new symlink target"
+              " `%.250s' for symlink `%.250s'", symlinkfn->buf, fname);
+    return 0;
+  }
+  if (!S_ISDIR(newstab.st_mode)) return 0;
+  if (newstab.st_dev != oldstab.st_dev ||
+      newstab.st_ino != oldstab.st_ino) return 0;
+  return 1;
+}
+
 int tarobject(struct TarInfo *ti) {
   static struct varbuf conffderefn, hardlinkfn, symlinkfn;
   const char *usename;
@@ -423,6 +463,9 @@ int tarobject(struct TarInfo *ti) {
     if (!statr && S_ISDIR(stab.st_mode)) {
       debug(dbg_eachfiledetail,"tarobject SymbolicLink exists as directory");
       existingdirectory= 1;
+    } else if (!statr && S_ISLNK(stab.st_mode)) {
+      if (linktosameexistingdir(ti, fnamevb.buf, &symlinkfn))
+        existingdirectory= 1;
     }
     break;
   case Directory: