From 161985a220fdca1bc5328b359a4db128f4205756 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 11 Aug 2007 06:53:55 +0300 Subject: [PATCH] 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. --- ChangeLog | 6 ++++++ debian/changelog | 4 ++++ src/archives.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/ChangeLog b/ChangeLog index 53fccaeb..4282bbff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-08-11 Ian Jackson + + * 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 * scripts/update-alternatives.pl: In the case where the slave is diff --git a/debian/changelog b/debian/changelog index 0febdea7..090c2e52 100644 --- a/debian/changelog +++ b/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). diff --git a/src/archives.c b/src/archives.c index b907d926..796c65a7 100644 --- a/src/archives.c +++ b/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: -- 2.39.5