Просмотр исходного кода

Check if a file isn't also in the new package when upgrading

Wichert Akkerman лет назад: 27
Родитель
Сommit
5b1362c1c0
4 измененных файлов с 45 добавлено и 1 удалено
  1. 4 1
      ChangeLog
  2. 2 0
      main/filesdb.c
  3. 1 0
      main/filesdb.h
  4. 38 0
      main/processarc.c

+ 4 - 1
ChangeLog

@@ -1,6 +1,9 @@
 Wed Oct 13 17:51:17 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
 
-  * Merge patch from Ben Collins to fix windowresizing in dselect
+  * Merge patches from Ben Collins <bcollins@debian.org>:
+    + fix windowresizing in dselect
+    + when upgrading check if a file is not also in the new package before removing
+	  it, so we don't remove new files due to symlinks confusing us
 
 Tue Oct 12 17:15:08 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
 

+ 2 - 0
main/filesdb.c

@@ -515,6 +515,7 @@ void filesdbinit(void) {
       for (fnn= bins[i]; fnn; fnn= fnn->next) {
         fnn->flags= 0;
         fnn->oldhash= 0;
+	fnn->stat= 0;
       }
     break;
   case -1:
@@ -523,6 +524,7 @@ void filesdbinit(void) {
          fnn= fnn->next) {
       fnn->flags= 0;
       fnn->oldhash= 0;
+      fnn->stat= 0;
     }
     break;
   default:

+ 1 - 0
main/filesdb.h

@@ -62,6 +62,7 @@ struct filenamenode {
     fnnf_no_atomic_overwrite= 000020, /* >=1 instance is a dir, cannot rename over */
   } flags; /* Set to zero when a new node is created. */
   const char *oldhash; /* valid iff this namenode is in the newconffiles list */
+  struct stat *stat;
 };
  
 struct fileinlist {

+ 38 - 0
main/processarc.c

@@ -490,6 +490,9 @@ void process_archive(const char *filename) {
    *  - 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.
@@ -586,6 +589,41 @@ void process_archive(const char *filename) {
     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;
     }