Преглед изворни кода

dpkg-maintscript-helper: Add new symlink_to_dir command

Closes: #720712

Based-on-patch-by: Bastien ROUCARIÈS <roucaries.bastien@gmail.com>
Guillem Jover пре 13 година
родитељ
комит
bfc1044bee
3 измењених фајлова са 113 додато и 3 уклоњено
  1. 2 0
      debian/changelog
  2. 36 2
      man/dpkg-maintscript-helper.1
  3. 75 1
      scripts/dpkg-maintscript-helper.sh

+ 2 - 0
debian/changelog

@@ -79,6 +79,8 @@ dpkg (1.17.2) UNRELEASED; urgency=low
     cause a segfault in case the function returns 0 entries.
   * Always return from ensure_statoverrides() if file is NULL, otherwise
     we might get us to read garbage from memory or segfault.
+  * Add new symlink_to_dir command to dpkg-maintscript-helper. Closes: #720712
+    Based on a patch by Bastien ROUCARIÈS <roucaries.bastien@gmail.com>.
 
   [ Updated programs translations ]
   * German (Sven Joachim).

+ 36 - 2
man/dpkg-maintscript-helper.1

@@ -28,6 +28,8 @@ dpkg\-maintscript\-helper \- works around known dpkg limitations in maintainer s
 \fBrm_conffile\fP \fIconffile\fP [\fIprior-version\fP [\fIpackage\fP]]
 .P
 \fBmv_conffile\fP \fIold-conffile\fP \fInew-conffile\fP [\fIprior-version\fP [\fIpackage\fP]]
+.P
+\fBsymlink_to_dir\fP \fIpathname\fP \fIold-target\fP [\fIprior-version\fP [\fIpackage\fP]]
 .
 .SH DESCRIPTION
 .P
@@ -138,15 +140,47 @@ to \fInew-conffile\fP if \fIold-conffile\fP is still available. On
 abort\-upgrade/abort\-install, the \fBpostrm\fP renames
 \fIold-conffile\fP\fB.dpkg\-remove\fP back to \fIold-conffile\fP if required.
 .
+.SH SYMLINK AND DIRECTORY SWITCHES
+.
+When upgrading a package, \fBdpkg\fP will not automatically switch a symlink
+to a directory or vice-versa.
+.
+.SS Switching a symlink to directory
+.
+If a symlink is converted to a real directory, you need to make sure
+before unpacking that the symlink is removed. This may seem a simple
+change to the \fBpreinst\fP script at first, however that will result
+in some problems in case of admin local customization of the symlink
+or when downgrading the package.
+.P
+Graceful renaming can be implemented by putting the following shell
+snippet in the \fBpreinst\fP, \fBpostinst\fP and \fBpostrm\fP maintainer
+scripts:
+.P
+    dpkg\-maintscript\-helper symlink_to_dir \\
+        \fIpathname\fP \fIold-target\fP \fIprior-version\fP \fIpackage\fP \-\- "$@"
+.P
+\fIpathname\fP is the name of the old symlink (the path will be a
+directory at the end of the installation) and \fIold-target\fP the
+target of the former symlink at \fIpathname\fP.
+.P
+Current implementation: the \fBpreinst\fP checks if the symlink exists
+and points to \fIold-target\fP, if not then it's left in place, otherwise
+it's renamed to \fIpathname\fP\fB.dpkg\-backup\fP. On configuration,
+the \fBpostinst\fP removes \fIpathname\fP\fB.dpkg\-backup\fP if
+\fIpathname\fP\fB.dpkg\-backup\fP is still a symlink. On
+abort\-upgrade/abort\-install, the \fBpostrm\fP renames
+\fIpathname\fP\fB.dpkg\-backup\fP back to \fIpathname\fP if required.
+.
 .SH INTEGRATION IN PACKAGES
 .P
 Given that \fBdpkg\-maintscript\-helper\fP is used in the \fBpreinst\fP,
 using it unconditionally requires a pre-dependency to ensure that the
 required version of \fBdpkg\fP has been unpacked before. The required version
 depends on the command used, for \fBrm_conffile\fP and \fBmv_conffile\fP
-it is 1.15.7.2:
+it is 1.15.7.2, for \fBsymlink_to_dir\fP it is 1.17.2:
 .P
-    \fBPre\-Depends:\fP dpkg (>= 1.15.7.2)
+    \fBPre\-Depends:\fP dpkg (>= 1.17.2)
 .P
 But in many cases the operation done by the program is not critical for
 the package, and instead of using a pre-dependency we can call the

+ 75 - 1
scripts/dpkg-maintscript-helper.sh

@@ -227,6 +227,74 @@ abort_mv_conffile() {
 	fi
 }
 
+##
+## Functions to replace a symlink with a directory
+##
+symlink_to_dir() {
+	local SYMLINK="$1"
+	local SYMLINK_TARGET="$2"
+	local LASTVERSION="$3"
+	local PACKAGE="$4"
+
+	if [ "$LASTVERSION" = "--" ]; then
+		LASTVERSION=""
+		PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
+	fi
+	if [ "$PACKAGE" = "--" -o -z "$PACKAGE" ]; then
+		PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
+	fi
+
+	# Skip remaining parameters up to --
+	while [ "$1" != "--" -a $# -gt 0 ]; do shift; done
+	[ $# -gt 0 ] || badusage "missing arguments after --"
+	shift
+
+	[ -n "$DPKG_MAINTSCRIPT_NAME" ] || \
+		error "environment variable DPKG_MAINTSCRIPT_NAME is required"
+	[ -n "$PACKAGE" ] || error "cannot identify the package"
+	[ -n "$SYMLINK" ] || error "symlink parameter is missing"
+	[ -n "$SYMLINK_TARGET" ] || error "original symlink target is missing"
+	[ -n "$LASTVERSION" ] || error "last version is missing"
+	[ -n "$1" ] || error "maintainer script parameters are missing"
+
+	debug "Executing $0 symlink_to_dir in $DPKG_MAINTSCRIPT_NAME" \
+	      "of $DPKG_MAINTSCRIPT_PACKAGE"
+	debug "SYMLINK=$SYMLINK -> $SYMLINK_TARGET PACKAGE=$PACKAGE" \
+	      "LASTVERSION=$LASTVERSION ACTION=$1 PARAM=$2"
+
+	case "$DPKG_MAINTSCRIPT_NAME" in
+	preinst)
+		if [ "$1" = "install" -o "$1" = "upgrade" ] &&
+		   [ -n "$2" ] && [ -h "$SYMLINK" ] &&
+		   [ "$(readlink -f $SYMLINK)" = "$SYMLINK_TARGET" ] &&
+		   dpkg --compare-versions "$2" le-nl "$LASTVERSION"; then
+			mv -f "$SYMLINK" "${SYMLINK}.dpkg-backup"
+		fi
+		;;
+	postinst)
+		if [ "$1" = "configure" ] && [ -h "${SYMLINK}.dpkg-backup" ] &&
+		    dpkg --compare-versions "$2" le-nl "$LASTVERSION"; then
+			rm -f "${SYMLINK}.dpkg-backup"
+		fi
+		;;
+	postrm)
+		if [ "$1" = "purge" ] && [ -h "${SYMLINK}.dpkg-backup" ]; then
+		    rm -f "${SYMLINK}.dpkg-backup"
+		fi
+		if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] &&
+		   [ -n "$2" ] &&
+		   [ -h "${SYMLINK}.dpkg-backup" ] && [ ! -e "$SYMLINK" ] &&
+		   dpkg --compare-versions "$2" le-nl "$LASTVERSION"; then
+			echo "Restoring backup of $SYMLINK ..."
+			mv "${SYMLINK}.dpkg-backup" "$SYMLINK"
+		fi
+		;;
+	*)
+		debug "$0 symlink_to_dir not required in $DPKG_MAINTSCRIPT_NAME"
+		;;
+	esac
+}
+
 # Common functions
 ensure_package_owns_file() {
 	local PACKAGE="$1"
@@ -267,6 +335,9 @@ Commands:
 	postrm.
   mv_conffile <old-conf> <new-conf> [<last-version> [<package>]]
 	Rename a conffile. Must be called in preinst, postinst and postrm.
+  symlink_to_dir <pathname> <old-symlink-target> [<last-version> [<package>]]
+	Replace a symlink with a directory. Must be called in preinst,
+	postinst and postrm.
   help
 	Display this usage information.
 END
@@ -291,7 +362,7 @@ shift
 case "$command" in
 supports)
 	case "$1" in
-	rm_conffile|mv_conffile)
+	rm_conffile|mv_conffile|symlink_to_dir)
 		code=0
 		;;
 	*)
@@ -314,6 +385,9 @@ rm_conffile)
 mv_conffile)
 	mv_conffile "$@"
 	;;
+symlink_to_dir)
+	symlink_to_dir "$@"
+	;;
 --help|help|-?)
 	usage
 	;;