Dpkg::Source::Package: Document method additions with an object
[dpkg.git] / src / dpkg-maintscript-helper.sh
blobd799aa8fe3d66645708b41970043921b41ce643a
1 #!/bin/sh
3 # Copyright © 2007, 2011-2015 Guillem Jover <guillem@debian.org>
4 # Copyright © 2010 Raphaël Hertzog <hertzog@debian.org>
5 # Copyright © 2008 Joey Hess <joeyh@debian.org>
6 # Copyright © 2005 Scott James Remnant (original implementation on www.dpkg.org)
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 # The conffile related functions are inspired by
22 # https://wiki.debian.org/DpkgConffileHandling
24 # This script is documented in dpkg-maintscript-helper(1)
27 ## Functions to remove an obsolete conffile during upgrade
29 rm_conffile() {
30 local CONFFILE="$1"
31 local LASTVERSION="$2"
32 local PACKAGE="$3"
34 if [ "$LASTVERSION" = "--" ]; then
35 LASTVERSION=""
36 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
38 if [ "$PACKAGE" = "--" -o -z "$PACKAGE" ]; then
39 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
41 # Skip remaining parameters up to --
42 while [ "$1" != "--" -a $# -gt 0 ]; do
43 shift
44 done
45 [ $# -gt 0 ] || badusage "missing arguments after --"
46 shift
48 [ -n "$PACKAGE" ] || error "couldn't identify the package"
49 [ -n "$1" ] || error "maintainer script parameters are missing"
50 [ -n "$DPKG_MAINTSCRIPT_NAME" ] || \
51 error "environment variable DPKG_MAINTSCRIPT_NAME is required"
52 [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] || \
53 error "environment variable DPKG_MAINTSCRIPT_PACKAGE is required"
54 [ "${CONFFILE}" != "${CONFFILE#/}" ] || \
55 error "conffile '$CONFFILE' is not an absolute path"
56 validate_optional_version "$LASTVERSION"
58 debug "Executing $0 rm_conffile in $DPKG_MAINTSCRIPT_NAME" \
59 "of $DPKG_MAINTSCRIPT_PACKAGE"
60 debug "CONFFILE=$CONFFILE PACKAGE=$PACKAGE" \
61 "LASTVERSION=$LASTVERSION ACTION=$1 PARAM=$2"
62 case "$DPKG_MAINTSCRIPT_NAME" in
63 preinst)
64 if [ "$1" = "install" -o "$1" = "upgrade" ] && [ -n "$2" ] &&
65 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
66 prepare_rm_conffile "$CONFFILE" "$PACKAGE"
69 postinst)
70 if [ "$1" = "configure" ] && [ -n "$2" ] &&
71 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
72 finish_rm_conffile "$CONFFILE"
75 postrm)
76 if [ "$1" = "purge" ]; then
77 rm -f "$DPKG_ROOT$CONFFILE.dpkg-bak" \
78 "$DPKG_ROOT$CONFFILE.dpkg-remove" \
79 "$DPKG_ROOT$CONFFILE.dpkg-backup"
81 if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] &&
82 [ -n "$2" ] &&
83 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
84 abort_rm_conffile "$CONFFILE" "$PACKAGE"
88 debug "$0 rm_conffile not required in $DPKG_MAINTSCRIPT_NAME"
90 esac
93 prepare_rm_conffile() {
94 local CONFFILE="$1"
95 local PACKAGE="$2"
97 [ -e "$DPKG_ROOT$CONFFILE" ] || return 0
98 ensure_package_owns_file "$PACKAGE" "$CONFFILE" || return 0
100 local md5sum old_md5sum
101 md5sum="$(md5sum "$DPKG_ROOT$CONFFILE" | sed -e 's/ .*//')"
102 old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$PACKAGE" | \
103 sed -n -e "\\'^ $CONFFILE ' { s/ obsolete$//; s/.* //; p }")"
104 if [ "$md5sum" != "$old_md5sum" ]; then
105 mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-backup"
106 else
107 mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-remove"
111 finish_rm_conffile() {
112 local CONFFILE="$1"
114 if [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then
115 echo "Obsolete conffile $DPKG_ROOT$CONFFILE has been modified by you."
116 echo "Saving as $DPKG_ROOT$CONFFILE.dpkg-bak ..."
117 mv -f "$DPKG_ROOT$CONFFILE.dpkg-backup" "$DPKG_ROOT$CONFFILE.dpkg-bak"
119 if [ -e "$DPKG_ROOT$CONFFILE.dpkg-remove" ]; then
120 echo "Removing obsolete conffile $DPKG_ROOT$CONFFILE ..."
121 rm -f "$DPKG_ROOT$CONFFILE.dpkg-remove"
125 abort_rm_conffile() {
126 local CONFFILE="$1"
127 local PACKAGE="$2"
129 ensure_package_owns_file "$PACKAGE" "$CONFFILE" || return 0
131 if [ -e "$DPKG_ROOT$CONFFILE.dpkg-remove" ]; then
132 echo "Reinstalling $DPKG_ROOT$CONFFILE that was moved away"
133 mv "$DPKG_ROOT$CONFFILE.dpkg-remove" "$DPKG_ROOT$CONFFILE"
135 if [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then
136 echo "Reinstalling $DPKG_ROOT$CONFFILE that was backed-up"
137 mv "$DPKG_ROOT$CONFFILE.dpkg-backup" "$DPKG_ROOT$CONFFILE"
142 ## Functions to rename a conffile during upgrade
144 mv_conffile() {
145 local OLDCONFFILE="$1"
146 local NEWCONFFILE="$2"
147 local LASTVERSION="$3"
148 local PACKAGE="$4"
150 if [ "$LASTVERSION" = "--" ]; then
151 LASTVERSION=""
152 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
154 if [ "$PACKAGE" = "--" -o -z "$PACKAGE" ]; then
155 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
157 # Skip remaining parameters up to --
158 while [ "$1" != "--" -a $# -gt 0 ]; do
159 shift
160 done
161 [ $# -gt 0 ] || badusage "missing arguments after --"
162 shift
164 [ -n "$PACKAGE" ] || error "couldn't identify the package"
165 [ -n "$1" ] || error "maintainer script parameters are missing"
166 [ -n "$DPKG_MAINTSCRIPT_NAME" ] || \
167 error "environment variable DPKG_MAINTSCRIPT_NAME is required"
168 [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] || \
169 error "environment variable DPKG_MAINTSCRIPT_PACKAGE is required"
170 [ "${OLDCONFFILE}" != "${OLDCONFFILE#/}" ] || \
171 error "old-conffile '$OLDCONFFILE' is not an absolute path"
172 [ "${NEWCONFFILE}" != "${NEWCONFFILE#/}" ] || \
173 error "new-conffile '$NEWCONFFILE' is not an absolute path"
174 validate_optional_version "$LASTVERSION"
176 debug "Executing $0 mv_conffile in $DPKG_MAINTSCRIPT_NAME" \
177 "of $DPKG_MAINTSCRIPT_PACKAGE"
178 debug "CONFFILE=$OLDCONFFILE -> $NEWCONFFILE PACKAGE=$PACKAGE" \
179 "LASTVERSION=$LASTVERSION ACTION=$1 PARAM=$2"
180 case "$DPKG_MAINTSCRIPT_NAME" in
181 preinst)
182 if [ "$1" = "install" -o "$1" = "upgrade" ] && [ -n "$2" ] &&
183 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
184 prepare_mv_conffile "$OLDCONFFILE" "$PACKAGE"
187 postinst)
188 if [ "$1" = "configure" ] && [ -n "$2" ] &&
189 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
190 finish_mv_conffile "$OLDCONFFILE" "$NEWCONFFILE" "$PACKAGE"
193 postrm)
194 if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] &&
195 [ -n "$2" ] &&
196 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
197 abort_mv_conffile "$OLDCONFFILE" "$PACKAGE"
201 debug "$0 mv_conffile not required in $DPKG_MAINTSCRIPT_NAME"
203 esac
206 prepare_mv_conffile() {
207 local CONFFILE="$1"
208 local PACKAGE="$2"
210 [ -e "$DPKG_ROOT$CONFFILE" ] || return 0
212 ensure_package_owns_file "$PACKAGE" "$CONFFILE" || return 0
214 local md5sum old_md5sum
215 md5sum="$(md5sum "$DPKG_ROOT$CONFFILE" | sed -e 's/ .*//')"
216 old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$PACKAGE" | \
217 sed -n -e "\\'^ $CONFFILE ' { s/ obsolete$//; s/.* //; p }")"
218 if [ "$md5sum" = "$old_md5sum" ]; then
219 mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-remove"
223 finish_mv_conffile() {
224 local OLDCONFFILE="$1"
225 local NEWCONFFILE="$2"
226 local PACKAGE="$3"
228 rm -f "$DPKG_ROOT$OLDCONFFILE.dpkg-remove"
230 [ -e "$DPKG_ROOT$OLDCONFFILE" ] || return 0
231 ensure_package_owns_file "$PACKAGE" "$OLDCONFFILE" || return 0
233 echo "Preserving user changes to $DPKG_ROOT$NEWCONFFILE (renamed from $DPKG_ROOT$OLDCONFFILE)..."
234 if [ -e "$DPKG_ROOT$NEWCONFFILE" ]; then
235 mv -f "$DPKG_ROOT$NEWCONFFILE" "$DPKG_ROOT$NEWCONFFILE.dpkg-new"
237 mv -f "$DPKG_ROOT$OLDCONFFILE" "$DPKG_ROOT$NEWCONFFILE"
240 abort_mv_conffile() {
241 local CONFFILE="$1"
242 local PACKAGE="$2"
244 ensure_package_owns_file "$PACKAGE" "$CONFFILE" || return 0
246 if [ -e "$DPKG_ROOT$CONFFILE.dpkg-remove" ]; then
247 echo "Reinstalling $DPKG_ROOT$CONFFILE that was moved away"
248 mv "$DPKG_ROOT$CONFFILE.dpkg-remove" "$DPKG_ROOT$CONFFILE"
253 ## Functions to replace a symlink with a directory
255 symlink_to_dir() {
256 local SYMLINK="$1"
257 local SYMLINK_TARGET="$2"
258 local LASTVERSION="$3"
259 local PACKAGE="$4"
261 if [ "$LASTVERSION" = "--" ]; then
262 LASTVERSION=""
263 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
265 if [ "$PACKAGE" = "--" -o -z "$PACKAGE" ]; then
266 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
269 # Skip remaining parameters up to --
270 while [ "$1" != "--" -a $# -gt 0 ]; do
271 shift
272 done
273 [ $# -gt 0 ] || badusage "missing arguments after --"
274 shift
276 [ -n "$DPKG_MAINTSCRIPT_NAME" ] || \
277 error "environment variable DPKG_MAINTSCRIPT_NAME is required"
278 [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] || \
279 error "environment variable DPKG_MAINTSCRIPT_PACKAGE is required"
280 [ -n "$PACKAGE" ] || error "cannot identify the package"
281 [ -n "$SYMLINK" ] || error "symlink parameter is missing"
282 [ "${SYMLINK#/}" = "$SYMLINK" ] && \
283 error "symlink pathname is not an absolute path"
284 [ "${SYMLINK%/}" = "$SYMLINK" ] || \
285 error "symlink pathname ends with a slash"
286 [ -n "$SYMLINK_TARGET" ] || error "original symlink target is missing"
287 [ -n "$1" ] || error "maintainer script parameters are missing"
288 validate_optional_version "$LASTVERSION"
290 debug "Executing $0 symlink_to_dir in $DPKG_MAINTSCRIPT_NAME" \
291 "of $DPKG_MAINTSCRIPT_PACKAGE"
292 debug "SYMLINK=$SYMLINK -> $SYMLINK_TARGET PACKAGE=$PACKAGE" \
293 "LASTVERSION=$LASTVERSION ACTION=$1 PARAM=$2"
295 case "$DPKG_MAINTSCRIPT_NAME" in
296 preinst)
297 if [ "$1" = "install" -o "$1" = "upgrade" ] &&
298 [ -n "$2" ] && [ -h "$DPKG_ROOT$SYMLINK" ] &&
299 symlink_match "$SYMLINK" "$SYMLINK_TARGET" &&
300 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
301 mv -f "$DPKG_ROOT$SYMLINK" "$DPKG_ROOT${SYMLINK}.dpkg-backup"
304 postinst)
305 # We cannot bail depending on the version, as here we only
306 # know what was the last configured version, and we might
307 # have been unpacked, then upgraded with an unpack and thus
308 # never been configured before.
309 if [ "$1" = "configure" ] &&
310 [ -h "$DPKG_ROOT${SYMLINK}.dpkg-backup" ] &&
311 symlink_match "${SYMLINK}.dpkg-backup" "$SYMLINK_TARGET"
312 then
313 rm -f "$DPKG_ROOT${SYMLINK}.dpkg-backup"
316 postrm)
317 if [ "$1" = "purge" ] && [ -h "$DPKG_ROOT${SYMLINK}.dpkg-backup" ]; then
318 rm -f "$DPKG_ROOT${SYMLINK}.dpkg-backup"
320 if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] &&
321 [ -n "$2" ] &&
322 [ ! -e "$DPKG_ROOT$SYMLINK" ] &&
323 [ -h "$DPKG_ROOT${SYMLINK}.dpkg-backup" ] &&
324 symlink_match "${SYMLINK}.dpkg-backup" "$SYMLINK_TARGET" &&
325 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
326 echo "Restoring backup of $DPKG_ROOT$SYMLINK ..."
327 mv "$DPKG_ROOT${SYMLINK}.dpkg-backup" "$DPKG_ROOT$SYMLINK"
331 debug "$0 symlink_to_dir not required in $DPKG_MAINTSCRIPT_NAME"
333 esac
337 ## Functions to replace a directory with a symlink
339 dir_to_symlink() {
340 local PATHNAME="${1%/}"
341 local SYMLINK_TARGET="$2"
342 local LASTVERSION="$3"
343 local PACKAGE="$4"
345 if [ "$LASTVERSION" = "--" ]; then
346 LASTVERSION=""
347 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
349 if [ "$PACKAGE" = "--" -o -z "$PACKAGE" ]; then
350 PACKAGE="$DPKG_MAINTSCRIPT_PACKAGE${DPKG_MAINTSCRIPT_ARCH:+:$DPKG_MAINTSCRIPT_ARCH}"
353 # Skip remaining parameters up to --
354 while [ "$1" != "--" -a $# -gt 0 ]; do
355 shift
356 done
357 [ $# -gt 0 ] || badusage "missing arguments after --"
358 shift
360 [ -n "$DPKG_MAINTSCRIPT_NAME" ] || \
361 error "environment variable DPKG_MAINTSCRIPT_NAME is required"
362 [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] || \
363 error "environment variable DPKG_MAINTSCRIPT_PACKAGE is required"
364 [ -n "$PACKAGE" ] || error "cannot identify the package"
365 [ -n "$PATHNAME" ] || error "directory parameter is missing"
366 [ "${PATHNAME#/}" = "$PATHNAME" ] && \
367 error "directory parameter is not an absolute path"
368 [ -n "$SYMLINK_TARGET" ] || error "new symlink target is missing"
369 [ -n "$1" ] || error "maintainer script parameters are missing"
370 validate_optional_version "$LASTVERSION"
372 debug "Executing $0 dir_to_symlink in $DPKG_MAINTSCRIPT_NAME" \
373 "of $DPKG_MAINTSCRIPT_PACKAGE"
374 debug "PATHNAME=$PATHNAME SYMLINK_TARGET=$SYMLINK_TARGET" \
375 "PACKAGE=$PACKAGE LASTVERSION=$LASTVERSION ACTION=$1 PARAM=$2"
377 case "$DPKG_MAINTSCRIPT_NAME" in
378 preinst)
379 if [ "$1" = "install" -o "$1" = "upgrade" ] &&
380 [ -n "$2" ] &&
381 [ ! -h "$DPKG_ROOT$PATHNAME" ] &&
382 [ -d "$DPKG_ROOT$PATHNAME" ] &&
383 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
384 prepare_dir_to_symlink "$PACKAGE" "$PATHNAME"
387 postinst)
388 # We cannot bail depending on the version, as here we only
389 # know what was the last configured version, and we might
390 # have been unpacked, then upgraded with an unpack and thus
391 # never been configured before.
392 if [ "$1" = "configure" ] &&
393 [ -d "$DPKG_ROOT${PATHNAME}.dpkg-backup" ] &&
394 [ ! -h "$DPKG_ROOT$PATHNAME" ] &&
395 [ -d "$DPKG_ROOT$PATHNAME" ] &&
396 [ -f "$DPKG_ROOT$PATHNAME/.dpkg-staging-dir" ]; then
397 finish_dir_to_symlink "$PATHNAME" "$SYMLINK_TARGET"
400 postrm)
401 if [ "$1" = "purge" ] &&
402 [ -d "$DPKG_ROOT${PATHNAME}.dpkg-backup" ]; then
403 rm -rf "$DPKG_ROOT${PATHNAME}.dpkg-backup"
405 if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] &&
406 [ -n "$2" ] &&
407 [ -d "$DPKG_ROOT${PATHNAME}.dpkg-backup" ] &&
408 [ \( ! -h "$DPKG_ROOT$PATHNAME" -a \
409 -d "$DPKG_ROOT$PATHNAME" -a \
410 -f "$DPKG_ROOT$PATHNAME/.dpkg-staging-dir" \) -o \
411 \( -h "$DPKG_ROOT$PATHNAME" -a \
412 \( "$(readlink "$DPKG_ROOT$PATHNAME")" = "$SYMLINK_TARGET" -o \
413 "$(dpkg-realpath "$PATHNAME")" = "$SYMLINK_TARGET" \) \) ] &&
414 dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then
415 abort_dir_to_symlink "$PATHNAME"
419 debug "$0 dir_to_symlink not required in $DPKG_MAINTSCRIPT_NAME"
421 esac
424 prepare_dir_to_symlink()
426 local PACKAGE="$1"
427 local PATHNAME="$2"
429 local LINE
430 # If there are conffiles we should not perform the switch.
431 dpkg-query -W -f='${Conffiles}\n' "$PACKAGE" | while read -r LINE; do
432 case "$LINE" in
433 "$PATHNAME"/*)
434 error "directory '$PATHNAME' contains conffiles," \
435 "cannot switch to symlink"
437 esac
438 done
440 # If there are locally created files or files owned by another package
441 # we should not perform the switch.
442 export DPKG_MAINTSCRIPT_HELPER_INTERNAL_API="$version"
443 find "$DPKG_ROOT$PATHNAME" -print0 | \
444 xargs -0 -n1 "$0" _internal_pkg_must_own_file "$PACKAGE" || \
445 error "directory '$PATHNAME' contains files not owned by" \
446 "package $PACKAGE, cannot switch to symlink"
447 unset DPKG_MAINTSCRIPT_HELPER_INTERNAL_API
449 # At this point, we know that the directory either contains no files,
450 # or only non-conffiles owned by the package.
452 # To do the switch we cannot simply replace it with the final symlink
453 # just yet, because dpkg needs to remove any file present in the old
454 # package that have disappeared in the new one, and we do not want to
455 # lose files resolving to the same pathname in the symlink target.
457 # We cannot replace the directory with a staging symlink either,
458 # because dpkg will update symlinks to their new target.
460 # So we need to create a staging directory, to avoid removing files
461 # from other packages, and to trap any new files in the directory
462 # to move them to their correct place later on.
463 mv -f "$DPKG_ROOT$PATHNAME" "$DPKG_ROOT${PATHNAME}.dpkg-backup"
464 mkdir "$DPKG_ROOT$PATHNAME"
466 # Mark it as a staging directory, so that we can track things.
467 touch "$DPKG_ROOT$PATHNAME/.dpkg-staging-dir"
470 finish_dir_to_symlink()
472 local PATHNAME="$1"
473 local SYMLINK_TARGET="$2"
475 # Move the contents of the staging directory to the symlink target,
476 # as those are all new files installed between this package being
477 # unpacked and configured.
478 local ABS_SYMLINK_TARGET
479 if [ "${SYMLINK_TARGET#/}" = "$SYMLINK_TARGET" ]; then
480 ABS_SYMLINK_TARGET="$(dirname "$PATHNAME")/$SYMLINK_TARGET"
481 else
482 ABS_SYMLINK_TARGET="$SYMLINK_TARGET"
484 rm "$DPKG_ROOT$PATHNAME/.dpkg-staging-dir"
485 find "$DPKG_ROOT$PATHNAME" -mindepth 1 -maxdepth 1 -print0 | \
486 xargs -0 -I% mv -f "%" "$DPKG_ROOT$ABS_SYMLINK_TARGET/"
488 # Remove the staging directory.
489 rmdir "$DPKG_ROOT$PATHNAME"
491 # Do the actual switch.
492 ln -s "$SYMLINK_TARGET" "$DPKG_ROOT$PATHNAME"
494 # We are left behind the old files owned by this package in the backup
495 # directory, just remove it.
496 rm -rf "$DPKG_ROOT${PATHNAME}.dpkg-backup"
499 abort_dir_to_symlink()
501 local PATHNAME="$1"
503 echo "Restoring backup of $DPKG_ROOT$PATHNAME ..."
504 if [ -h "$DPKG_ROOT$PATHNAME" ]; then
505 rm -f "$DPKG_ROOT$PATHNAME"
506 else
507 # The staging directory must be empty, as no other package
508 # should have been unpacked in between.
509 rm -f "$DPKG_ROOT$PATHNAME/.dpkg-staging-dir"
510 rmdir "$DPKG_ROOT$PATHNAME"
513 mv "$DPKG_ROOT${PATHNAME}.dpkg-backup" "$DPKG_ROOT$PATHNAME"
516 # Common functions
517 validate_optional_version() {
518 local VERSION="$1"
520 if [ -z "$VERSION" ]; then
521 return
524 if ! VERSIONCHECK=$(dpkg --validate-version -- "$VERSION" 2>&1); then
525 error "$VERSIONCHECK"
529 ensure_package_owns_file() {
530 local PACKAGE="$1"
531 local FILE="$2"
533 if ! dpkg-query -L "$PACKAGE" | grep -F -q -x "$FILE"; then
534 debug "File '$FILE' not owned by package " \
535 "'$PACKAGE', skipping $command"
536 return 1
538 return 0
541 internal_pkg_must_own_file()
543 local PACKAGE="$1"
544 local FILE="${2##"$DPKG_ROOT"}"
546 if [ "$DPKG_MAINTSCRIPT_HELPER_INTERNAL_API" != "$version" ]; then
547 error "internal API used by external command"
550 if ! ensure_package_owns_file "$PACKAGE" "$FILE"; then
551 error "file '$FILE' not owned by package '$PACKAGE'"
553 return 0
556 symlink_match()
558 local SYMLINK="$1"
559 local SYMLINK_TARGET="$2"
561 [ "$(readlink "$DPKG_ROOT$SYMLINK")" = "$SYMLINK_TARGET" ] || \
562 [ "$(dpkg-realpath "$SYMLINK")" = "$SYMLINK_TARGET" ]
565 usage() {
566 cat <<END
567 Usage: $PROGNAME <command> <parameter>... -- <maintainer-script-parameter>...
569 Commands:
570 supports <command>
571 Returns 0 (success) if the given command is supported, 1 otherwise.
572 rm_conffile <conffile> [<last-version> [<package>]]
573 Remove obsolete conffile. Must be called in preinst, postinst and
574 postrm.
575 mv_conffile <old-conf> <new-conf> [<last-version> [<package>]]
576 Rename a conffile. Must be called in preinst, postinst and postrm.
577 symlink_to_dir <pathname> <old-symlink-target> [<last-version> [<package>]]
578 Replace a symlink with a directory. Must be called in preinst,
579 postinst and postrm.
580 dir_to_symlink <pathname> <new-symlink-target> [<last-version> [<package>]]
581 Replace a directory with a symlink. Must be called in preinst,
582 postinst and postrm.
583 help
584 -?, --help
585 Show this help message.
586 --version
587 Show the version.
591 # Main code
592 set -e
594 PROGNAME=$(basename "$0")
595 version="unknown"
596 DPKG_ROOT=${DPKG_ROOT:+$(realpath "$DPKG_ROOT")}
597 # Remove default root dir.
598 if [ "$DPKG_ROOT" = "/" ]; then
599 DPKG_ROOT=""
601 export DPKG_ROOT
603 PKGDATADIR_DEFAULT=src
604 PKGDATADIR="${DPKG_DATADIR:-$PKGDATADIR_DEFAULT}"
606 # shellcheck source=src/sh/dpkg-error.sh
607 . "$PKGDATADIR/sh/dpkg-error.sh"
609 setup_colors
611 command="$1"
612 [ $# -gt 0 ] || badusage "missing command"
613 shift
615 case "$command" in
616 supports)
617 case "$1" in
618 rm_conffile|mv_conffile|symlink_to_dir|dir_to_symlink)
619 code=0
622 code=1
624 esac
625 if [ -z "$DPKG_MAINTSCRIPT_NAME" ]; then
626 warning "environment variable DPKG_MAINTSCRIPT_NAME missing"
627 code=1
629 if [ -z "$DPKG_MAINTSCRIPT_PACKAGE" ]; then
630 warning "environment variable DPKG_MAINTSCRIPT_PACKAGE missing"
631 code=1
633 exit $code
635 rm_conffile)
636 rm_conffile "$@"
638 mv_conffile)
639 mv_conffile "$@"
641 symlink_to_dir)
642 symlink_to_dir "$@"
644 dir_to_symlink)
645 dir_to_symlink "$@"
647 _internal_pkg_must_own_file)
648 # This is an internal command, must not be used outside this program.
649 internal_pkg_must_own_file "$@"
651 --help|help|-?)
652 usage
654 --version)
655 cat <<END
656 Debian $PROGNAME version $version.
658 This is free software; see the GNU General Public License version 2 or
659 later for copying conditions. There is NO warranty.
663 badusage "command $command is unknown
664 Hint: upgrading dpkg to a newer version might help."
665 esac
667 exit 0