I'm not sure if this patch is similar enough against 1.14.4 that the
old one would still apply but since I've done the merge anyway here it
is.  This patch is safe and should be applied to sid's dpkg
immediately.

Ian.

diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/archives.c construct/dpkg-1.14.4/src/archives.c
--- in/debian/dpkg-1.14.4/src/archives.c        2007-03-21 21:20:28.000000000 
+0000
+++ construct/dpkg-1.14.4/src/archives.c        2007-05-30 16:09:39.000000000 
+0100
@@ -326,6 +325,46 @@
   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 +462,9 @@
     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:

Reply via email to