* - The listed thing does not exist. We ignore it.
* - The listed thing is a directory or a symlink to a directory.
* We delete it only if it isn't listed in any other package.
+ * - The listed thing is not a directory, but was part of the package
+ * that was upgraded, we check to make sure the files aren't the
+ * same ones from the old package by checking dev/inode
* - The listed thing is not a directory or a symlink to one (ie,
* it's a plain file, device, pipe, &c, or a symlink to one, or a
* dangling symlink). We delete it.
if (!rmdir(fnamevb.buf)) continue;
if (errno == ENOENT || errno == ELOOP) continue;
if (errno == ENOTDIR) {
+ /* Ok, it's an old file, but is it really not in the new package?
+ * We need to check to make sure, so we stat the file, then compare
+ * it to the new list. If we find a dev/inode match, we assume they
+ * are the same file, and leave it alone. NOTE: we don't check in
+ * other packages for sanity reasons (we don't want to stat _all_
+ * the files on the system).
+ *
+ * We run down the list of _new_ files in this package. This keeps
+ * the process a little leaner. We are only worried about new ones
+ * since ones that stayed the same don't really apply here.
+ */
+ struct stat oldfs, *newfs;
+ int donotrm = 0;
+ /* If we can't stat the old or new file, or it's a directory,
+ * we leave it up to the normal code
+ */
+ debug(dbg_eachfile, "process_archive: checking %s for same files on
+ upgrade/downgrade", fnamevb.buf);
+ if (!lstat(fnamevb.buf, &oldfs) && !S_ISDIR(oldfs.st_mode)) {
+ for (cfile = newfileslist; cfile; cfile = cfile->next) {
+ if(!cfile->namenode->stat) {
+ newfs = nfmalloc(sizeof(struct stat));
+ if (lstat(cfile->namenode->name, newfs)) continue;
+ cfile->namenode->stat = newfs;
+ } else newfs = cfile->namenode->stat;
+ if (!S_ISDIR(newfs->st_mode) && oldfs.st_dev == newfs->st_dev &&
+ oldfs.st_ino == newfs->st_ino) {
+ donotrm = 1;
+ debug(dbg_eachfile, "process_archive: not removing %s, since it matches %s",
+ fnamevb.buf, cfile->namenode->name);
+ }
+ }
+ } else
+ debug(dbg_eachfile, "process_archive: could not stat %s, skipping", fnamevb.buf);
+ if (donotrm) continue;
if (!unlink(fnamevb.buf)) continue;
if (errno == ENOTDIR) continue;
}