Pārlūkot izejas kodu

u-a: Update alternative links only if they change

There's no point in changing the links to the same target. This also
helps when systems might have a read-only file system mounted, but a
writable database.

Closes: #636700

Based-on-patch-by: Salvatore Bonaccorso <carnil@debian.org>
Signed-off-by: Guillem Jover <guillem@debian.org>
Guillem Jover 15 gadi atpakaļ
vecāks
revīzija
05ce02f897
2 mainītis faili ar 32 papildinājumiem un 3 dzēšanām
  1. 3 0
      debian/changelog
  2. 29 3
      utils/update-alternatives.c

+ 3 - 0
debian/changelog

@@ -204,6 +204,9 @@ dpkg (1.16.1) UNRELEASED; urgency=low
     Prompted by Timo Juhani Lindfors <timo.lindfors@iki.fi>.
   * Print an actual error or warning message instead of assert()ing on
     readlink()/stat() size discrepancies. Closes: #639229
+  * Update alternative links only if they change. This allows for a
+    read-only file system and a writable database. Closes: #636700
+    Based on a patch by Salvatore Bonaccorso <carnil@debian.org>.
 
   [ Updated dpkg translations ]
   * German (Sven Joachim). Closes: #620312

+ 29 - 3
utils/update-alternatives.c

@@ -1681,6 +1681,34 @@ alternative_can_replace_path(const char *linkname)
 		return true;
 }
 
+static bool
+alternative_path_needs_update(const char *linkname, const char *filename)
+{
+	char *linktarget;
+	bool update;
+
+	if (opt_force)
+		return true;
+
+	switch (alternative_path_classify(linkname)) {
+	case ALT_PATH_SYMLINK:
+		linktarget = xreadlink(linkname);
+		if (strcmp(linktarget, filename) == 0)
+			update = false;
+		else
+			update = true;
+		free(linktarget);
+
+		return update;
+	case ALT_PATH_OTHER:
+		warning(_("not replacing %s with a link."), linkname);
+		return false;
+	case ALT_PATH_MISSING:
+	default:
+		return true;
+	}
+}
+
 static void
 alternative_prepare_install_single(struct alternative *a, const char *name,
 				   const char *linkname, const char *file)
@@ -1695,15 +1723,13 @@ alternative_prepare_install_single(struct alternative *a, const char *name,
 	alternative_add_commit_op(a, opcode_mv, fntmp, fn);
 	free(fntmp);
 
-	if (alternative_can_replace_path(linkname)) {
+	if (alternative_path_needs_update(linkname, fn)) {
 		/* Create alternative link. */
 		xasprintf(&fntmp, "%s" DPKG_TMP_EXT, linkname);
 		checked_rm(fntmp);
 		checked_symlink(fn, fntmp);
 		alternative_add_commit_op(a, opcode_mv, fntmp, linkname);
 		free(fntmp);
-	} else {
-		warning(_("not replacing %s with a link."), linkname);
 	}
 	free(fn);
 }