tags 1006655 + patch thanks I've attached a patch implementing an rm_conffile_if_unmodifed command for dpkg-maintscript-helper, as well as a declarative version for debian/conffiles.
I've included documentation and tests for both. Using this has the same effect as rm_conffile if the file is unmodified. However, if the file is modified, this leaves the file in place under the existing name (treating it as an obsolete conffile so that it still gets removed if purging the package). Thus, unlike rm_conffile, this version is useful for packages that still support reading the configuration file if present, and thus don't want to move existing modified configuration aside with a .dpkg-bak suffix, because that'll prevent the modified configuration from being used. - Josh Triplett
>From f3f04a4288076471b9f963f75d10470ba7e446a6 Mon Sep 17 00:00:00 2001 Message-ID: <f3f04a4288076471b9f963f75d10470ba7e446a6.1716931259.git.j...@joshtriplett.org> From: Josh Triplett <j...@joshtriplett.org> Date: Tue, 28 May 2024 11:11:06 -0700 Subject: [PATCH] Implement rm_conffile_if_unmodified Sometimes, a package wants to no longer install a conffile in new versions; for instance, the conffile might still be supported, but the default version is not needed for new installations. In this case, the existing `rm_conffile` doesn't suffice, because it will rename modified versions with a .dpkg-bak suffix. Add a new `rm_conffile_if_unmodified` (also available as `rm_conffile --if-unmodified`) to handle this case. Provide a declarative version `remove-if-unmodified` as well. Document these, and add tests for them. Closes: #1006655 Signed-off-by: Josh Triplett <j...@joshtriplett.org> --- lib/dpkg/dpkg-db.h | 1 + lib/dpkg/dump.c | 2 + lib/dpkg/fields.c | 10 +++- lib/dpkg/fsys.h | 2 + man/deb-conffiles.pod | 19 ++++++- man/dpkg-maintscript-helper.pod | 43 ++++++++++++++-- src/deb/build.c | 7 ++- src/dpkg-maintscript-helper.sh | 50 +++++++++++++++---- src/main/archives.c | 7 ++- src/main/configure.c | 8 ++- src/main/help.c | 4 +- src/main/unpack.c | 26 ++++++---- tests/t-conffile-declarative-removal/Makefile | 21 +++++++- .../pkg-conffile-v1/DEBIAN/conffiles | 1 + .../test-conffile-to-be-removed-if-unmodified | 0 .../pkg-conffile-v2/DEBIAN/conffiles | 1 + tests/t-conffile-obsolete/Makefile | 18 ++++++- .../pkg-conff-obsolete-0/DEBIAN/conffiles | 1 + .../pkg-conff-obsolete-0/test-conffile-2 | 1 + .../pkg-conff-obsolete-2/DEBIAN/postinst | 3 ++ .../pkg-conff-obsolete-2/DEBIAN/postrm | 3 ++ .../pkg-conff-obsolete-2/DEBIAN/preinst | 3 ++ 22 files changed, 197 insertions(+), 34 deletions(-) create mode 100644 tests/t-conffile-declarative-removal/pkg-conffile-v1/test-dir/test-conffile-to-be-removed-if-unmodified create mode 100644 tests/t-conffile-obsolete/pkg-conff-obsolete-0/test-conffile-2 diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h index 61f220506..072222881 100644 --- a/lib/dpkg/dpkg-db.h +++ b/lib/dpkg/dpkg-db.h @@ -83,6 +83,7 @@ struct conffile { const char *hash; bool obsolete; bool remove_on_upgrade; + bool remove_if_unmodified; }; struct archivedetails { diff --git a/lib/dpkg/dump.c b/lib/dpkg/dump.c index 8a1e30481..db4a823ef 100644 --- a/lib/dpkg/dump.c +++ b/lib/dpkg/dump.c @@ -394,6 +394,8 @@ w_conffiles(struct varbuf *vb, varbuf_add_str(vb, " obsolete"); if (i->remove_on_upgrade) varbuf_add_str(vb, " remove-on-upgrade"); + if (i->remove_if_unmodified) + varbuf_add_str(vb, " remove-if-unmodified"); } if (flags&fw_printheader) varbuf_add_char(vb, '\n'); diff --git a/lib/dpkg/fields.c b/lib/dpkg/fields.c index 525dc0a15..a67f0bc90 100644 --- a/lib/dpkg/fields.c +++ b/lib/dpkg/fields.c @@ -355,6 +355,7 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, { static const char obsolete_str[]= "obsolete"; static const char remove_on_upgrade_str[] = "remove-on-upgrade"; + static const char remove_if_unmodified_str[] = "remove-if-unmodified"; struct conffile **lastp; lastp = &pkgbin->conffiles; @@ -363,7 +364,7 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, const char *endent, *endfn, *hashstart; char *newptr; int c, namelen, hashlen; - bool obsolete, remove_on_upgrade; + bool obsolete, remove_on_upgrade, remove_if_unmodified; c= *value++; if (c == '\n') continue; @@ -381,6 +382,12 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, conffvalue_lastword(value, endfn, endent, &hashstart, &hashlen, &endfn, ps); + remove_if_unmodified = (hashlen == sizeof(remove_if_unmodified_str) - 1 && + memcmp(hashstart, remove_if_unmodified_str, hashlen) == 0); + if (remove_if_unmodified) + conffvalue_lastword(value, endfn, endent, &hashstart, &hashlen, &endfn, + ps); + obsolete= (hashlen == sizeof(obsolete_str)-1 && memcmp(hashstart, obsolete_str, hashlen) == 0); if (obsolete) @@ -405,6 +412,7 @@ f_conffiles(struct pkginfo *pkg, struct pkgbin *pkgbin, newlink->hash= newptr; newlink->obsolete= obsolete; newlink->remove_on_upgrade = remove_on_upgrade; + newlink->remove_if_unmodified = remove_if_unmodified; newlink->next =NULL; *lastp= newlink; lastp= &newlink->next; diff --git a/lib/dpkg/fsys.h b/lib/dpkg/fsys.h index ede5cdff8..63256e10a 100644 --- a/lib/dpkg/fsys.h +++ b/lib/dpkg/fsys.h @@ -85,6 +85,8 @@ enum DPKG_ATTR_ENUM_FLAGS fsys_namenode_flags { FNNF_FILTERED = DPKG_BIT(9), /** Conffile removal requested by upgrade. */ FNNF_RM_CONFF_ON_UPGRADE = DPKG_BIT(10), + /** Conffile removal requested by upgrade if unmodified. */ + FNNF_RM_CONFF_IF_UNMODIFIED = DPKG_BIT(11), }; /** diff --git a/man/deb-conffiles.pod b/man/deb-conffiles.pod index e3a57b189..353c8e9f8 100644 --- a/man/deb-conffiles.pod +++ b/man/deb-conffiles.pod @@ -39,11 +39,25 @@ not accepted. Files without a flag should exist in the binary package, otherwise L<dpkg(1)> will ignore them. -There is currently only one flag supported, B<remove-on-upgrade>, to mark -that a conffile needs to be removed on the next upgrade (since dpkg 1.20.6). +There are currently two flags supported: + +=over + +=item B<remove-on-upgrade> (since dpkg 1.20.6) + +to mark that a conffile needs to be removed on the next upgrade. These files must not exist in the binary package, as both L<dpkg(1)> and L<dpkg-deb(1)> will not accept building nor processing such binary packages. +=item B<remove-if-unmodified> (since dpkg 1.22.7) + +to mark that a conffile needs to be removed on the next upgrade if unmodified, +but left in place if modified. +These files must not exist in the binary package, as both L<dpkg(1)> and +L<dpkg-deb(1)> will not accept building nor processing such binary packages. + +=back + =head1 EXAMPLE %CONFDIR%/alternatives/README @@ -51,6 +65,7 @@ L<dpkg-deb(1)> will not accept building nor processing such binary packages. %PKGCONFDIR%/dpkg.cfg %CONFDIR%/logrotate.d/dpkg remove-on-upgrade /etc/some-old-file.conf + remove-if-unmodified /etc/old-but-still-supported.conf =head1 SEE ALSO diff --git a/man/dpkg-maintscript-helper.pod b/man/dpkg-maintscript-helper.pod index ee938e911..177e76902 100644 --- a/man/dpkg-maintscript-helper.pod +++ b/man/dpkg-maintscript-helper.pod @@ -33,7 +33,9 @@ I<command> [I<parameter>...] B<--> I<maint-script-parameter>... =item B<supports> I<command> -=item B<rm_conffile> I<conffile> [I<prior-version> [I<package>]] +=item B<rm_conffile> [I<--if-unmodified>] I<conffile> [I<prior-version> [I<package>]] + +=item B<rm_conffile_if_unmodified> I<conffile> [I<prior-version> [I<package>]] =item B<mv_conffile> I<old-conffile> I<new-conffile> [I<prior-version> [I<package>]] @@ -130,7 +132,7 @@ it must explicitly do so and B<dpkg-maintscript-helper> can be used to implement graceful deletion and moving of conffiles within maintainer scripts. -=head2 Removing a conffile +=head2 Removing an obsolete conffile B<Note>: This can be replaced in most cases by the C<remove-on-upgrade> flag in F<DEBIAN/conffiles> (since dpkg 1.20.6), see L<deb-conffiles(5)>. @@ -165,6 +167,35 @@ If the package upgrade aborts, the B<postrm> reinstalls the original conffile. During purge, the B<postrm> will also delete the B<.dpkg-bak> file kept up to now. +=head2 Removing a conffile if unmodified + +B<Note>: This can be replaced in most cases by the C<remove-if-unmodified> +flag in F<DEBIAN/conffiles> (since dpkg 1.22.7), see L<deb-conffiles(5)>. + +Sometimes, a package wants to no longer install a conffile in new versions; +for instance, the conffile might still be supported, but the default version +is not needed for new installations. +In this case, the package should remove the conffile from disk, but only if +the user has not modified it. +If there are local modifications, they should be preserved. +If the package upgrade aborts, the conffile should not disappear. + +All of this is implemented by putting the following shell snippet in the +B<preinst>, B<postinst> and B<postrm> maintainer scripts: + +=over + +Z<> + dpkg-maintscript-helper rm_conffile --if-unmodified \ + I<conffile> I<prior-version> I<package> -- "$@" + +=back + +I<conffile> is the filename of the conffile to remove. + +This uses the same implementation as C<rm_conffile>, but leaves modified +versions in place rather than renaming them. + =head2 Renaming a conffile If a conffile is moved from one location to another, you need to make sure @@ -305,11 +336,12 @@ required version of B<dpkg> has been unpacked before. The required version depends on the command used, for B<rm_conffile> and B<mv_conffile> it is 1.15.7.2, for B<symlink_to_dir> and B<dir_to_symlink> -it is 1.17.14: +it is 1.17.14, and for B<rm_conffile_if_unmodified> or the I<--if-unmodified> +option to B<rm_conffile> it is 1.22.7: =over - Pre-Depends: dpkg (>= 1.17.14) + Pre-Depends: dpkg (>= 1.22.7) =back @@ -333,6 +365,9 @@ B<supports> command will check if the environment variables as set by dpkg and required by the script are present, and will consider it a failure in case the environment is not sufficient. +Note that B<supports rm_conffile_if_unmodified> also indicates the +availability of the I<--if-unmodified> option to B<rm_conffile>. + =head1 ENVIRONMENT =over diff --git a/src/deb/build.c b/src/deb/build.c index 5da2e76cd..d146434da 100644 --- a/src/deb/build.c +++ b/src/deb/build.c @@ -272,6 +272,7 @@ check_conffiles(const char *ctrldir, const char *rootdir) char *conffilename = conffilenamebuf; int n; bool remove_on_upgrade = false; + bool remove_if_unmodified = false; n = strlen(conffilename); if (!n) @@ -317,6 +318,8 @@ check_conffiles(const char *ctrldir, const char *rootdir) if (strcmp(flag, "remove-on-upgrade") == 0) remove_on_upgrade = true; + else if (strcmp(flag, "remove-if-unmodified") == 0) + remove_if_unmodified = true; else ohshit(_("unknown flag '%s' for conffile '%s'"), flag, conffilename); } @@ -328,11 +331,11 @@ check_conffiles(const char *ctrldir, const char *rootdir) if ((n > 1) && c_isspace(conffilename[n - 1])) warning(_("conffile filename '%s' contains trailing white spaces"), conffilename); - if (!remove_on_upgrade) + if (!remove_on_upgrade && !remove_if_unmodified) ohshit(_("conffile '%.250s' does not appear in package"), conffilename); } else ohshite(_("conffile '%.250s' is not stattable"), conffilename); - } else if (remove_on_upgrade) { + } else if (remove_on_upgrade || remove_if_unmodified) { ohshit(_("conffile '%s' is present but is requested to be removed"), conffilename); } else if (!S_ISREG(controlstab.st_mode)) { diff --git a/src/dpkg-maintscript-helper.sh b/src/dpkg-maintscript-helper.sh index d799aa8fe..b8b3cb329 100755 --- a/src/dpkg-maintscript-helper.sh +++ b/src/dpkg-maintscript-helper.sh @@ -27,6 +27,12 @@ ## Functions to remove an obsolete conffile during upgrade ## rm_conffile() { + local IF_UNMODIFIED= + if [ "$1" = "--if-unmodified" ]; then + IF_UNMODIFIED="$1" + shift + fi + local CONFFILE="$1" local LASTVERSION="$2" local PACKAGE="$3" @@ -63,13 +69,13 @@ rm_conffile() { preinst) if [ "$1" = "install" -o "$1" = "upgrade" ] && [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then - prepare_rm_conffile "$CONFFILE" "$PACKAGE" + prepare_rm_conffile $IF_UNMODIFIED "$CONFFILE" "$PACKAGE" fi ;; postinst) if [ "$1" = "configure" ] && [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then - finish_rm_conffile "$CONFFILE" + finish_rm_conffile $IF_UNMODIFIED "$CONFFILE" fi ;; postrm) @@ -81,7 +87,7 @@ rm_conffile() { if [ "$1" = "abort-install" -o "$1" = "abort-upgrade" ] && [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "$LASTVERSION"; then - abort_rm_conffile "$CONFFILE" "$PACKAGE" + abort_rm_conffile $IF_UNMODIFIED "$CONFFILE" "$PACKAGE" fi ;; *) @@ -91,6 +97,12 @@ rm_conffile() { } prepare_rm_conffile() { + local IF_UNMODIFIED= + if [ "$1" = "--if-unmodified" ]; then + IF_UNMODIFIED="$1" + shift + fi + local CONFFILE="$1" local PACKAGE="$2" @@ -102,16 +114,24 @@ prepare_rm_conffile() { old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$PACKAGE" | \ sed -n -e "\\'^ $CONFFILE ' { s/ obsolete$//; s/.* //; p }")" if [ "$md5sum" != "$old_md5sum" ]; then - mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-backup" + if [ -z "$IF_UNMODIFIED" ]; then + mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-backup" + fi else mv -f "$DPKG_ROOT$CONFFILE" "$DPKG_ROOT$CONFFILE.dpkg-remove" fi } finish_rm_conffile() { + local IF_UNMODIFIED= + if [ "$1" = "--if-unmodified" ]; then + IF_UNMODIFIED="$1" + shift + fi + local CONFFILE="$1" - if [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then + if [ -z "$IF_UNMODIFIED" ] && [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then echo "Obsolete conffile $DPKG_ROOT$CONFFILE has been modified by you." echo "Saving as $DPKG_ROOT$CONFFILE.dpkg-bak ..." mv -f "$DPKG_ROOT$CONFFILE.dpkg-backup" "$DPKG_ROOT$CONFFILE.dpkg-bak" @@ -123,6 +143,12 @@ finish_rm_conffile() { } abort_rm_conffile() { + local IF_UNMODIFIED= + if [ "$1" = "--if-unmodified" ]; then + IF_UNMODIFIED="$1" + shift + fi + local CONFFILE="$1" local PACKAGE="$2" @@ -132,7 +158,7 @@ abort_rm_conffile() { echo "Reinstalling $DPKG_ROOT$CONFFILE that was moved away" mv "$DPKG_ROOT$CONFFILE.dpkg-remove" "$DPKG_ROOT$CONFFILE" fi - if [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then + if [ -z "$IF_UNMODIFIED" ] && [ -e "$DPKG_ROOT$CONFFILE.dpkg-backup" ]; then echo "Reinstalling $DPKG_ROOT$CONFFILE that was backed-up" mv "$DPKG_ROOT$CONFFILE.dpkg-backup" "$DPKG_ROOT$CONFFILE" fi @@ -569,9 +595,12 @@ Usage: $PROGNAME <command> <parameter>... -- <maintainer-script-parameter>... Commands: supports <command> Returns 0 (success) if the given command is supported, 1 otherwise. - rm_conffile <conffile> [<last-version> [<package>]] + rm_conffile [--if-unmodified] <conffile> [<last-version> [<package>]] Remove obsolete conffile. Must be called in preinst, postinst and - postrm. + postrm. If given --if-unmodified, act as rm_conffile_if_unmodfied. + rm_conffile_if_unmodified <conffile> [<last-version> [<package>]] + Remove still-supported conffile if unmodified. Must be called in + preinst, postinst and 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>]] @@ -615,7 +644,7 @@ shift case "$command" in supports) case "$1" in - rm_conffile|mv_conffile|symlink_to_dir|dir_to_symlink) + rm_conffile|rm_conffile_if_unmodified|mv_conffile|symlink_to_dir|dir_to_symlink) code=0 ;; *) @@ -635,6 +664,9 @@ supports) rm_conffile) rm_conffile "$@" ;; +rm_conffile_if_unmodified) + rm_conffile --if-unmodified "$@" + ;; mv_conffile) mv_conffile "$@" ;; diff --git a/src/main/archives.c b/src/main/archives.c index fa703f048..f33d514ca 100644 --- a/src/main/archives.c +++ b/src/main/archives.c @@ -240,7 +240,9 @@ md5hash_prev_conffile(struct pkginfo *pkg, char *oldhash, const char *oldname, &otherpkg->configversion) != 0) continue; for (conff = otherpkg->installed.conffiles; conff; conff = conff->next) { - if (conff->obsolete || conff->remove_on_upgrade) + if (conff->obsolete || + conff->remove_on_upgrade || + conff->remove_if_unmodified) continue; if (strcmp(conff->name, namenode->name) == 0) break; @@ -682,7 +684,8 @@ tarobject(struct tar_archive *tar, struct tar_entry *ti) namenode = fsys_hash_find_node(ti->name, FHFF_NONE); - if (namenode->flags & FNNF_RM_CONFF_ON_UPGRADE) + if ((namenode->flags & FNNF_RM_CONFF_ON_UPGRADE) || + (namenode->flags & FNNF_RM_CONFF_IF_UNMODIFIED)) ohshit(_("conffile '%s' marked for removal on upgrade, shipped in package"), ti->name); diff --git a/src/main/configure.c b/src/main/configure.c index b12b06808..5831447a3 100644 --- a/src/main/configure.c +++ b/src/main/configure.c @@ -356,7 +356,9 @@ deferred_configure_ghost_conffile(struct pkginfo *pkg, struct conffile *conff) for (otherconff = otherpkg->installed.conffiles; otherconff; otherconff = otherconff->next) { - if (otherconff->obsolete || otherconff->remove_on_upgrade) + if (otherconff->obsolete || + otherconff->remove_on_upgrade || + otherconff->remove_if_unmodified) continue; /* Check if we need to propagate the new hash from @@ -652,7 +654,9 @@ deferred_configure(struct pkginfo *pkg) * ‘*.dpkg-new’ no longer exists we assume that we've * already processed this one. */ for (conff = pkg->installed.conffiles; conff; conff = conff->next) { - if (conff->obsolete || conff->remove_on_upgrade) + if (conff->obsolete || + conff->remove_on_upgrade || + conff->remove_if_unmodified) continue; deferred_configure_conffile(pkg, conff); } diff --git a/src/main/help.c b/src/main/help.c index 59e730e1c..8774dd677 100644 --- a/src/main/help.c +++ b/src/main/help.c @@ -196,7 +196,9 @@ dir_has_conffiles(struct fsys_namenode *file, struct pkginfo *pkg) pkg_name(pkg, pnaw_always)); namelen = strlen(file->name); for (conff= pkg->installed.conffiles; conff; conff= conff->next) { - if (conff->obsolete || conff->remove_on_upgrade) + if (conff->obsolete || + conff->remove_on_upgrade || + conff->remove_if_unmodified) continue; if (strncmp(file->name, conff->name, namelen) == 0 && strlen(conff->name) > namelen && conff->name[namelen] == '/') { diff --git a/src/main/unpack.c b/src/main/unpack.c index 20d30c6c8..0708b437a 100644 --- a/src/main/unpack.c +++ b/src/main/unpack.c @@ -386,6 +386,9 @@ deb_parse_conffiles(const struct pkginfo *pkg, const char *control_conffiles, if (strcmp(flag, "remove-on-upgrade") == 0) { confflags |= FNNF_RM_CONFF_ON_UPGRADE; confflags &= ~FNNF_NEW_CONFF; + } else if (strcmp(flag, "remove-if-unmodified") == 0) { + confflags |= FNNF_RM_CONFF_IF_UNMODIFIED; + confflags &= ~FNNF_NEW_CONFF; } else { if (c_isspace(flag[0])) warning(_("line with conffile filename '%s' has leading white spaces"), @@ -657,15 +660,17 @@ pkg_remove_conffile_on_upgrade(struct pkginfo *pkg, struct fsys_namenode *nameno } /* Otherwise, preserve the modified conffile. */ - varbuf_rollback(&cdrext_state); - varbuf_add_str(&cdrext, DPKGOLDEXT); + if (namenode->flags & FNNF_RM_CONFF_ON_UPGRADE) { + varbuf_rollback(&cdrext_state); + varbuf_add_str(&cdrext, DPKGOLDEXT); - printf(_("Obsolete conffile '%s' has been modified by you.\n"), cdr.buf); - printf(_("Saving as %s ...\n"), cdrext.buf); - if (rename(cdr.buf, cdrext.buf) < 0) - warning(_("%s: cannot rename obsolete conffile '%s' to '%s': %s"), - pkg_name(pkg, pnaw_nonambig), - cdr.buf, cdrext.buf, strerror(errno)); + printf(_("Obsolete conffile '%s' has been modified by you.\n"), cdr.buf); + printf(_("Saving as %s ...\n"), cdrext.buf); + if (rename(cdr.buf, cdrext.buf) < 0) + warning(_("%s: cannot rename obsolete conffile '%s' to '%s': %s"), + pkg_name(pkg, pnaw_nonambig), + cdr.buf, cdrext.buf, strerror(errno)); + } } static void @@ -687,7 +692,8 @@ pkg_remove_old_files(struct pkginfo *pkg, debug(dbg_conffdetail, "%s: removing conffile '%s' for %s?", __func__, cfile->namenode->name, pkg_name(pkg, pnaw_always)); - if (!(cfile->namenode->flags & FNNF_RM_CONFF_ON_UPGRADE)) + if (!(cfile->namenode->flags & FNNF_RM_CONFF_ON_UPGRADE) && + !(cfile->namenode->flags & FNNF_RM_CONFF_IF_UNMODIFIED)) continue; pkg_remove_conffile_on_upgrade(pkg, cfile->namenode); @@ -922,6 +928,8 @@ pkg_update_fields(struct pkginfo *pkg, struct fsys_namenode_queue *newconffiles) newiconff->obsolete = !!(cfile->namenode->flags & FNNF_OBS_CONFF); newiconff->remove_on_upgrade = !!( cfile->namenode->flags & FNNF_RM_CONFF_ON_UPGRADE); + newiconff->remove_if_unmodified = !!( + cfile->namenode->flags & FNNF_RM_CONFF_IF_UNMODIFIED); *iconffileslastp = newiconff; iconffileslastp = &newiconff->next; } diff --git a/tests/t-conffile-declarative-removal/Makefile b/tests/t-conffile-declarative-removal/Makefile index 0d0e77b86..d74adb2ab 100644 --- a/tests/t-conffile-declarative-removal/Makefile +++ b/tests/t-conffile-declarative-removal/Makefile @@ -22,45 +22,64 @@ test-case: $(DPKG_INSTALL) pkg-conffile-v1.deb test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" $(DPKG_INSTALL) pkg-conffile-v2.deb test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" # Reset. $(DPKG_PURGE) pkg-conffile test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" # Unmodified case; but force it to happen via two invocations. $(DPKG_INSTALL) pkg-conffile-v1.deb test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" $(DPKG_UNPACK) pkg-conffile-v2.deb # The old conffile is removed during unpack. test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" # After configure, the file is still removed. $(DPKG_CONFIGURE) pkg-conffile test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" # Reset. $(DPKG_PURGE) pkg-conffile test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" - # Modified; should store .dpkg-old. + # Modified; should store .dpkg-old for remove-on-upgrade, or leave in place for remove-if-unmodified. $(DPKG_INSTALL) pkg-conffile-v1.deb test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" echo "modify this" >"$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" + test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + echo "modify this" >"$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" $(DPKG_INSTALL) pkg-conffile-v2.deb test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified.dpkg-old" # Reset. $(DPKG_PURGE) pkg-conffile test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed" $(RM) "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed.dpkg-old" + test ! -f "$(DPKG_INSTDIR)/test-dir/test-conffile-to-be-removed-if-unmodified" # Queue a remove on upgrade, and move ownership. $(DPKG_INSTALL) pkg-conffile-v1.deb diff --git a/tests/t-conffile-declarative-removal/pkg-conffile-v1/DEBIAN/conffiles b/tests/t-conffile-declarative-removal/pkg-conffile-v1/DEBIAN/conffiles index c4138c4fa..4627abe1a 100644 --- a/tests/t-conffile-declarative-removal/pkg-conffile-v1/DEBIAN/conffiles +++ b/tests/t-conffile-declarative-removal/pkg-conffile-v1/DEBIAN/conffiles @@ -1 +1,2 @@ /test-dir/test-conffile-to-be-removed +/test-dir/test-conffile-to-be-removed-if-unmodified diff --git a/tests/t-conffile-declarative-removal/pkg-conffile-v1/test-dir/test-conffile-to-be-removed-if-unmodified b/tests/t-conffile-declarative-removal/pkg-conffile-v1/test-dir/test-conffile-to-be-removed-if-unmodified new file mode 100644 index 000000000..e69de29bb diff --git a/tests/t-conffile-declarative-removal/pkg-conffile-v2/DEBIAN/conffiles b/tests/t-conffile-declarative-removal/pkg-conffile-v2/DEBIAN/conffiles index 587753be1..58fee74b1 100644 --- a/tests/t-conffile-declarative-removal/pkg-conffile-v2/DEBIAN/conffiles +++ b/tests/t-conffile-declarative-removal/pkg-conffile-v2/DEBIAN/conffiles @@ -1 +1,2 @@ remove-on-upgrade /test-dir/test-conffile-to-be-removed +remove-if-unmodified /test-dir/test-conffile-to-be-removed-if-unmodified diff --git a/tests/t-conffile-obsolete/Makefile b/tests/t-conffile-obsolete/Makefile index 55d9477f5..3ed7d6267 100644 --- a/tests/t-conffile-obsolete/Makefile +++ b/tests/t-conffile-obsolete/Makefile @@ -6,27 +6,39 @@ test-case: $(DPKG_INSTALL) pkg-conff-obsolete-0.deb $(DPKG_INSTALL) pkg-conff-obsolete-1.deb test -f '$(DPKG_INSTDIR)/test-conffile' + test -f '$(DPKG_INSTDIR)/test-conffile-2' $(DPKG_PURGE) pkg-conff-obsolete test ! -f '$(DPKG_INSTDIR)/test-conffile' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2' # Unmodified conffile is autoremoved for the user $(DPKG_INSTALL) pkg-conff-obsolete-0.deb $(DPKG_UNPACK) pkg-conff-obsolete-2.deb test -f '$(DPKG_INSTDIR)/test-conffile.dpkg-remove' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-backup' + test -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-remove' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-backup' $(DPKG_CONFIGURE) pkg-conff-obsolete test ! -f '$(DPKG_INSTDIR)/test-conffile' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-bak' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-backup' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-remove' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-bak' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-backup' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-remove' $(DPKG_PURGE) pkg-conff-obsolete - # Modified conffile is moved away in .dpkg-bak for the user + # Modified conffile 1 is moved away in .dpkg-bak for the user $(DPKG_INSTALL) pkg-conff-obsolete-0.deb $(BEROOT) sh -c "echo foo >>'$(DPKG_INSTDIR)/test-conffile'" + $(BEROOT) sh -c "echo foo >>'$(DPKG_INSTDIR)/test-conffile-2'" $(DPKG_INSTALL) pkg-conff-obsolete-2.deb test ! -f '$(DPKG_INSTDIR)/test-conffile' test -f '$(DPKG_INSTDIR)/test-conffile.dpkg-bak' + test -f '$(DPKG_INSTDIR)/test-conffile-2' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-bak' $(DPKG_PURGE) pkg-conff-obsolete test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-bak' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2' # Abort-upgrade restores the to-be-removed conffile $(DPKG_INSTALL) pkg-conff-obsolete-0.deb $(BEROOT) touch '$(DPKG_INSTDIR)/fail-preinst' @@ -36,6 +48,10 @@ test-case: test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-remove' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-bak' test ! -f '$(DPKG_INSTDIR)/test-conffile.dpkg-backup' + test -f '$(DPKG_INSTDIR)/test-conffile-2' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-remove' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-bak' + test ! -f '$(DPKG_INSTDIR)/test-conffile-2.dpkg-backup' test-clean: $(DPKG_PURGE) pkg-conff-obsolete diff --git a/tests/t-conffile-obsolete/pkg-conff-obsolete-0/DEBIAN/conffiles b/tests/t-conffile-obsolete/pkg-conff-obsolete-0/DEBIAN/conffiles index 4fad7e9dc..fa95b58e0 100644 --- a/tests/t-conffile-obsolete/pkg-conff-obsolete-0/DEBIAN/conffiles +++ b/tests/t-conffile-obsolete/pkg-conff-obsolete-0/DEBIAN/conffiles @@ -1 +1,2 @@ /test-conffile +/test-conffile-2 diff --git a/tests/t-conffile-obsolete/pkg-conff-obsolete-0/test-conffile-2 b/tests/t-conffile-obsolete/pkg-conff-obsolete-0/test-conffile-2 new file mode 100644 index 000000000..6fbc8b586 --- /dev/null +++ b/tests/t-conffile-obsolete/pkg-conff-obsolete-0/test-conffile-2 @@ -0,0 +1 @@ +test init diff --git a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postinst b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postinst index c6b0782d4..54d282e02 100755 --- a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postinst +++ b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postinst @@ -2,3 +2,6 @@ if dpkg-maintscript-helper supports rm_conffile; then dpkg-maintscript-helper rm_conffile /test-conffile 0 -- "$@" fi +if dpkg-maintscript-helper supports rm_conffile_if_unmodified; then + dpkg-maintscript-helper rm_conffile --if-unmodified /test-conffile-2 0 -- "$@" +fi diff --git a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postrm b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postrm index c6b0782d4..54d282e02 100755 --- a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postrm +++ b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/postrm @@ -2,3 +2,6 @@ if dpkg-maintscript-helper supports rm_conffile; then dpkg-maintscript-helper rm_conffile /test-conffile 0 -- "$@" fi +if dpkg-maintscript-helper supports rm_conffile_if_unmodified; then + dpkg-maintscript-helper rm_conffile --if-unmodified /test-conffile-2 0 -- "$@" +fi diff --git a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/preinst b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/preinst index c0e592b0e..0dd3eeb26 100755 --- a/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/preinst +++ b/tests/t-conffile-obsolete/pkg-conff-obsolete-2/DEBIAN/preinst @@ -2,6 +2,9 @@ if dpkg-maintscript-helper supports rm_conffile; then dpkg-maintscript-helper rm_conffile /test-conffile 0 -- "$@" fi +if dpkg-maintscript-helper supports rm_conffile_if_unmodified; then + dpkg-maintscript-helper rm_conffile --if-unmodified /test-conffile-2 0 -- "$@" +fi if [ -e "$DPKG_ROOT/fail-preinst" ]; then exit 1 -- 2.45.1