소스 검색

Do not treat two symlinks to the same directory as a file conflict.

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.
Ian Jackson 19 년 전
부모
커밋
161985a220
3개의 변경된 파일53개의 추가작업 그리고 0개의 파일을 삭제
  1. 6 0
      ChangeLog
  2. 4 0
      debian/changelog
  3. 43 0
      src/archives.c

+ 6 - 0
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

+ 4 - 0
debian/changelog

@@ -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).

+ 43 - 0
src/archives.c

@@ -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: