2 * dpkg - main program for package management
3 * remove.c - functionality for removing packages
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
8 * This 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 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/>.
25 #include <sys/types.h>
36 #include <dpkg/i18n.h>
37 #include <dpkg/c-ctype.h>
38 #include <dpkg/dpkg.h>
39 #include <dpkg/dpkg-db.h>
41 #include <dpkg/path.h>
43 #include <dpkg/options.h>
44 #include <dpkg/triglib.h>
45 #include <dpkg/db-ctrl.h>
46 #include <dpkg/db-fsys.h>
51 * pkgdepcheck may be a virtual pkg.
53 static void checkforremoval(struct pkginfo
*pkgtoremove
,
54 struct pkgset
*pkgdepcheck
,
55 enum dep_check
*rokp
, struct varbuf
*raemsgs
)
57 struct deppossi
*possi
;
58 struct pkginfo
*depender
;
60 struct varbuf_state raemsgs_state
;
62 for (possi
= pkgdepcheck
->depended
.installed
; possi
; possi
= possi
->rev_next
) {
63 if (possi
->up
->type
!= dep_depends
&& possi
->up
->type
!= dep_predepends
) continue;
64 depender
= possi
->up
->up
;
65 debug(dbg_depcon
, "checking depending package '%s'",
66 pkg_name(depender
, pnaw_always
));
67 if (depender
->status
< PKG_STAT_UNPACKED
)
69 if (ignore_depends(depender
)) {
70 debug(dbg_depcon
, "ignoring depending package '%s'",
71 pkg_name(depender
, pnaw_always
));
74 if (dependtry
>= DEPEND_TRY_CYCLES
) {
75 if (findbreakcycle(pkgtoremove
))
78 varbuf_snapshot(raemsgs
, &raemsgs_state
);
79 ok
= dependencies_ok(depender
,pkgtoremove
,raemsgs
);
80 if (ok
== DEP_CHECK_HALT
&&
81 depender
->clientdata
&&
82 depender
->clientdata
->istobe
== PKG_ISTOBE_REMOVE
)
84 if (ok
== DEP_CHECK_DEFER
)
85 /* Don't burble about reasons for deferral. */
86 varbuf_rollback(&raemsgs_state
);
87 if (ok
< *rokp
) *rokp
= ok
;
91 void deferred_remove(struct pkginfo
*pkg
) {
92 struct varbuf raemsgs
= VARBUF_INIT
;
93 struct dependency
*dep
;
96 debug(dbg_general
, "deferred_remove package %s",
97 pkg_name(pkg
, pnaw_always
));
99 if (!f_pending
&& pkg
->want
!= PKG_WANT_UNKNOWN
) {
100 if (cipaction
->arg_int
== act_purge
)
101 pkg_set_want(pkg
, PKG_WANT_PURGE
);
103 pkg_set_want(pkg
, PKG_WANT_DEINSTALL
);
109 ensure_package_clientdata(pkg
);
111 if (pkg
->status
== PKG_STAT_NOTINSTALLED
) {
113 warning(_("ignoring request to remove %.250s which isn't installed"),
114 pkg_name(pkg
, pnaw_nonambig
));
115 pkg
->clientdata
->istobe
= PKG_ISTOBE_NORMAL
;
117 } else if (!f_pending
&&
118 pkg
->status
== PKG_STAT_CONFIGFILES
&&
119 cipaction
->arg_int
!= act_purge
) {
121 warning(_("ignoring request to remove %.250s, only the config\n"
122 " files of which are on the system; use --purge to remove them too"),
123 pkg_name(pkg
, pnaw_nonambig
));
124 pkg
->clientdata
->istobe
= PKG_ISTOBE_NORMAL
;
128 if (pkg
->status
!= PKG_STAT_CONFIGFILES
) {
129 if (pkg
->installed
.essential
)
130 forcibleerr(FORCE_REMOVE_ESSENTIAL
,
131 _("this is an essential package; it should not be removed"));
132 if (pkg
->installed
.is_protected
)
133 forcibleerr(FORCE_REMOVE_PROTECTED
,
134 _("this is a protected package; it should not be removed"));
137 debug(dbg_general
, "checking dependencies for remove '%s'",
138 pkg_name(pkg
, pnaw_always
));
140 checkforremoval(pkg
, pkg
->set
, &rok
, &raemsgs
);
141 for (dep
= pkg
->installed
.depends
; dep
; dep
= dep
->next
) {
142 if (dep
->type
!= dep_provides
) continue;
143 debug(dbg_depcon
, "checking virtual package '%s'", dep
->list
->ed
->name
);
144 checkforremoval(pkg
, dep
->list
->ed
, &rok
, &raemsgs
);
147 if (rok
== DEP_CHECK_DEFER
) {
148 varbuf_destroy(&raemsgs
);
149 pkg
->clientdata
->istobe
= PKG_ISTOBE_REMOVE
;
150 enqueue_package(pkg
);
152 } else if (rok
== DEP_CHECK_HALT
) {
154 varbuf_end_str(&raemsgs
);
155 notice(_("dependency problems prevent removal of %s:\n%s"),
156 pkg_name(pkg
, pnaw_nonambig
), raemsgs
.buf
);
157 ohshit(_("dependency problems - not removing"));
158 } else if (raemsgs
.used
) {
159 varbuf_end_str(&raemsgs
);
160 notice(_("%s: dependency problems, but removing anyway as you requested:\n%s"),
161 pkg_name(pkg
, pnaw_nonambig
), raemsgs
.buf
);
163 varbuf_destroy(&raemsgs
);
166 if (pkg
->eflag
& PKG_EFLAG_REINSTREQ
)
167 forcibleerr(FORCE_REMOVE_REINSTREQ
,
168 _("package is in a very bad inconsistent state; you should\n"
169 " reinstall it before attempting a removal"));
171 ensure_allinstfiles_available();
175 printf(_("Would remove or purge %s (%s) ...\n"),
176 pkg_name(pkg
, pnaw_nonambig
),
177 versiondescribe(&pkg
->installed
.version
, vdew_nonambig
));
178 pkg_set_status(pkg
, PKG_STAT_NOTINSTALLED
);
179 pkg
->clientdata
->istobe
= PKG_ISTOBE_NORMAL
;
183 pkg_conffiles_mark_old(pkg
);
185 /* Only print and log removal action once. This avoids duplication when
186 * using --remove and --purge in sequence. */
187 if (pkg
->status
> PKG_STAT_CONFIGFILES
) {
188 printf(_("Removing %s (%s) ...\n"), pkg_name(pkg
, pnaw_nonambig
),
189 versiondescribe(&pkg
->installed
.version
, vdew_nonambig
));
190 log_action("remove", pkg
, &pkg
->installed
);
193 trig_activate_packageprocessing(pkg
);
194 if (pkg
->status
>= PKG_STAT_HALFCONFIGURED
) {
195 static enum pkgstatus oldpkgstatus
;
197 oldpkgstatus
= pkg
->status
;
198 pkg_set_status(pkg
, PKG_STAT_HALFCONFIGURED
);
200 push_cleanup(cu_prermremove
, ~ehflag_normaltidy
, 2,
201 (void *)pkg
, (void *)&oldpkgstatus
);
202 maintscript_installed(pkg
, PRERMFILE
, "pre-removal", "remove", NULL
);
204 /* Will turn into ‘half-installed’ soon ... */
205 pkg_set_status(pkg
, PKG_STAT_UNPACKED
);
212 push_leftover(struct fsys_namenode_list
**leftoverp
,
213 struct fsys_namenode
*namenode
)
215 struct fsys_namenode_list
*newentry
;
217 newentry
= nfmalloc(sizeof(*newentry
));
218 newentry
->next
= *leftoverp
;
219 newentry
->namenode
= namenode
;
220 *leftoverp
= newentry
;
224 removal_bulk_remove_file(const char *filename
, const char *filetype
)
226 /* We need the postrm and list files for --purge. */
227 if (strcmp(filetype
, LISTFILE
) == 0 ||
228 strcmp(filetype
, POSTRMFILE
) == 0)
231 debug(dbg_stupidlyverbose
, "removal_bulk info not postrm or list");
233 if (unlink(filename
))
234 ohshite(_("unable to delete control info file '%.250s'"), filename
);
236 debug(dbg_scripts
, "removal_bulk info unlinked %s", filename
);
240 removal_bulk_file_is_shared(struct pkginfo
*pkg
, struct fsys_namenode
*namenode
)
242 struct fsys_node_pkgs_iter
*iter
;
243 struct pkginfo
*otherpkg
;
246 if (pkgset_installed_instances(pkg
->set
) <= 1)
249 iter
= fsys_node_pkgs_iter_new(namenode
);
250 while ((otherpkg
= fsys_node_pkgs_iter_next(iter
))) {
253 if (otherpkg
->set
!= pkg
->set
)
256 debug(dbg_eachfiledetail
, "removal_bulk file shared with %s, skipping",
257 pkg_name(otherpkg
, pnaw_always
));
261 fsys_node_pkgs_iter_free(iter
);
267 removal_bulk_remove_files(struct pkginfo
*pkg
)
269 struct fsys_hash_rev_iter rev_iter
;
270 struct fsys_namenode_list
*leftover
;
271 struct fsys_namenode
*namenode
;
272 static struct varbuf fnvb
;
273 struct varbuf_state fnvb_state
;
276 pkg_set_status(pkg
, PKG_STAT_HALFINSTALLED
);
278 push_checkpoint(~ehflag_bombout
, ehflag_normaltidy
);
280 fsys_hash_rev_iter_init(&rev_iter
, pkg
->files
);
282 while ((namenode
= fsys_hash_rev_iter_next(&rev_iter
))) {
283 struct fsys_namenode
*usenode
;
286 debug(dbg_eachfile
, "removal_bulk '%s' flags=%o",
287 namenode
->name
, namenode
->flags
);
289 usenode
= namenodetouse(namenode
, pkg
, &pkg
->installed
);
291 varbuf_set_str(&fnvb
, dpkg_fsys_get_dir());
292 varbuf_add_str(&fnvb
, usenode
->name
);
293 varbuf_end_str(&fnvb
);
294 varbuf_snapshot(&fnvb
, &fnvb_state
);
296 is_dir
= stat(fnvb
.buf
, &stab
) == 0 && S_ISDIR(stab
.st_mode
);
298 /* A pkgset can share files between its instances that we
299 * don't want to remove, we just want to forget them. This
300 * applies to shared conffiles too. */
301 if (!is_dir
&& removal_bulk_file_is_shared(pkg
, namenode
))
304 /* Non-shared conffiles are kept. */
305 if (namenode
->flags
& FNNF_OLD_CONFF
) {
306 push_leftover(&leftover
, namenode
);
311 debug(dbg_eachfiledetail
, "removal_bulk is a directory");
312 /* Only delete a directory or a link to one if we're the only
313 * package which uses it. Other files should only be listed
314 * in this package (but we don't check). */
315 if (dir_has_conffiles(namenode
, pkg
)) {
316 push_leftover(&leftover
,namenode
);
319 if (dir_is_used_by_pkg(namenode
, pkg
, leftover
)) {
320 push_leftover(&leftover
, namenode
);
323 if (dir_is_used_by_others(namenode
, pkg
))
326 if (strcmp(usenode
->name
, "/.") == 0) {
327 debug(dbg_eachfiledetail
,
328 "removal_bulk '%s' root directory, cannot remove", fnvb
.buf
);
329 push_leftover(&leftover
, namenode
);
334 trig_path_activate(usenode
, pkg
);
336 varbuf_rollback(&fnvb_state
);
337 varbuf_add_str(&fnvb
, DPKGTEMPEXT
);
338 varbuf_end_str(&fnvb
);
339 debug(dbg_eachfiledetail
, "removal_bulk cleaning temp '%s'", fnvb
.buf
);
340 path_remove_tree(fnvb
.buf
);
342 varbuf_rollback(&fnvb_state
);
343 varbuf_add_str(&fnvb
, DPKGNEWEXT
);
344 varbuf_end_str(&fnvb
);
345 debug(dbg_eachfiledetail
, "removal_bulk cleaning new '%s'", fnvb
.buf
);
346 path_remove_tree(fnvb
.buf
);
348 varbuf_rollback(&fnvb_state
);
349 varbuf_end_str(&fnvb
);
351 debug(dbg_eachfiledetail
, "removal_bulk removing '%s'", fnvb
.buf
);
352 if (!rmdir(fnvb
.buf
) || errno
== ENOENT
|| errno
== ELOOP
) continue;
353 if (errno
== ENOTEMPTY
|| errno
== EEXIST
) {
354 debug(dbg_eachfiledetail
,
355 "removal_bulk '%s' was not empty, will try again later",
357 push_leftover(&leftover
,namenode
);
359 } else if (errno
== EBUSY
|| errno
== EPERM
) {
360 warning(_("while removing %.250s, unable to remove directory '%.250s': "
361 "%s - directory may be a mount point?"),
362 pkg_name(pkg
, pnaw_nonambig
), namenode
->name
, strerror(errno
));
363 push_leftover(&leftover
,namenode
);
366 if (errno
!= ENOTDIR
)
367 ohshite(_("cannot remove '%.250s'"), fnvb
.buf
);
368 debug(dbg_eachfiledetail
, "removal_bulk unlinking '%s'", fnvb
.buf
);
369 if (secure_unlink(fnvb
.buf
))
370 ohshite(_("unable to securely remove '%.250s'"), fnvb
.buf
);
372 write_filelist_except(pkg
, &pkg
->installed
, leftover
, 0);
373 maintscript_installed(pkg
, POSTRMFILE
, "post-removal", "remove", NULL
);
375 trig_parse_ci(pkg_infodb_get_file(pkg
, &pkg
->installed
, TRIGGERSCIFILE
),
376 trig_cicb_interest_delete
, NULL
, pkg
, &pkg
->installed
);
377 trig_file_interests_save();
379 debug(dbg_general
, "removal_bulk cleaning info directory");
380 pkg_infodb_foreach(pkg
, &pkg
->installed
, removal_bulk_remove_file
);
381 dir_sync_path(pkg_infodb_get_dir());
383 pkg_set_status(pkg
, PKG_STAT_CONFIGFILES
);
384 pkg
->installed
.essential
= false;
385 pkg
->installed
.is_protected
= false;
387 push_checkpoint(~ehflag_bombout
, ehflag_normaltidy
);
390 static void removal_bulk_remove_leftover_dirs(struct pkginfo
*pkg
) {
391 struct fsys_hash_rev_iter rev_iter
;
392 struct fsys_namenode_list
*leftover
;
393 struct fsys_namenode
*namenode
;
394 static struct varbuf fnvb
;
397 /* We may have modified this previously. */
398 ensure_packagefiles_available(pkg
);
401 push_checkpoint(~ehflag_bombout
, ehflag_normaltidy
);
403 fsys_hash_rev_iter_init(&rev_iter
, pkg
->files
);
405 while ((namenode
= fsys_hash_rev_iter_next(&rev_iter
))) {
406 struct fsys_namenode
*usenode
;
408 debug(dbg_eachfile
, "removal_bulk '%s' flags=%o",
409 namenode
->name
, namenode
->flags
);
410 if (namenode
->flags
& FNNF_OLD_CONFF
) {
411 /* This can only happen if removal_bulk_remove_configfiles() got
412 * interrupted half way. */
413 debug(dbg_eachfiledetail
, "removal_bulk expecting only left over dirs, "
414 "ignoring conffile '%s'", namenode
->name
);
418 usenode
= namenodetouse(namenode
, pkg
, &pkg
->installed
);
420 varbuf_set_str(&fnvb
, dpkg_fsys_get_dir());
421 varbuf_add_str(&fnvb
, usenode
->name
);
422 varbuf_end_str(&fnvb
);
424 if (!stat(fnvb
.buf
,&stab
) && S_ISDIR(stab
.st_mode
)) {
425 debug(dbg_eachfiledetail
, "removal_bulk is a directory");
426 /* Only delete a directory or a link to one if we're the only
427 * package which uses it. Other files should only be listed
428 * in this package (but we don't check). */
429 if (dir_is_used_by_pkg(namenode
, pkg
, leftover
)) {
430 push_leftover(&leftover
, namenode
);
433 if (dir_is_used_by_others(namenode
, pkg
))
436 if (strcmp(usenode
->name
, "/.") == 0) {
437 debug(dbg_eachfiledetail
,
438 "removal_bulk '%s' root directory, cannot remove", fnvb
.buf
);
439 push_leftover(&leftover
, namenode
);
444 trig_path_activate(usenode
, pkg
);
446 debug(dbg_eachfiledetail
, "removal_bulk removing '%s'", fnvb
.buf
);
447 if (!rmdir(fnvb
.buf
) || errno
== ENOENT
|| errno
== ELOOP
) continue;
448 if (errno
== ENOTEMPTY
|| errno
== EEXIST
) {
449 warning(_("while removing %.250s, directory '%.250s' not empty so not removed"),
450 pkg_name(pkg
, pnaw_nonambig
), namenode
->name
);
451 push_leftover(&leftover
,namenode
);
453 } else if (errno
== EBUSY
|| errno
== EPERM
) {
454 warning(_("while removing %.250s, unable to remove directory '%.250s': "
455 "%s - directory may be a mount point?"),
456 pkg_name(pkg
, pnaw_nonambig
), namenode
->name
, strerror(errno
));
457 push_leftover(&leftover
,namenode
);
460 if (errno
!= ENOTDIR
)
461 ohshite(_("cannot remove '%.250s'"), fnvb
.buf
);
463 if (lstat(fnvb
.buf
, &stab
) == 0 && S_ISLNK(stab
.st_mode
)) {
464 debug(dbg_eachfiledetail
, "removal_bulk is a symlink to a directory");
466 if (unlink(fnvb
.buf
))
467 ohshite(_("cannot remove '%.250s'"), fnvb
.buf
);
472 push_leftover(&leftover
,namenode
);
474 write_filelist_except(pkg
, &pkg
->installed
, leftover
, 0);
477 push_checkpoint(~ehflag_bombout
, ehflag_normaltidy
);
480 static void removal_bulk_remove_configfiles(struct pkginfo
*pkg
) {
481 static const char *const removeconffexts
[] = { REMOVECONFFEXTS
, NULL
};
483 int conffnameused
, conffbasenamelen
;
485 struct conffile
*conff
, **lconffp
;
486 struct fsys_namenode_list
*searchfile
;
490 const char *const *ext
;
492 printf(_("Purging configuration files for %s (%s) ...\n"),
493 pkg_name(pkg
, pnaw_nonambig
),
494 versiondescribe(&pkg
->installed
.version
, vdew_nonambig
));
495 log_action("purge", pkg
, &pkg
->installed
);
496 trig_activate_packageprocessing(pkg
);
498 /* We may have modified this above. */
499 ensure_packagefiles_available(pkg
);
501 /* We're about to remove the configuration, so remove the note
502 * about which version it was ... */
503 dpkg_version_blank(&pkg
->configversion
);
506 /* Remove from our list any conffiles that aren't ours any more or
507 * are involved in diversions, except if we are the package doing the
509 for (lconffp
= &pkg
->installed
.conffiles
; (conff
= *lconffp
) != NULL
; ) {
510 for (searchfile
= pkg
->files
;
511 searchfile
&& strcmp(searchfile
->namenode
->name
,conff
->name
);
512 searchfile
= searchfile
->next
);
514 debug(dbg_conff
, "removal_bulk conffile not ours any more '%s'",
516 *lconffp
= conff
->next
;
517 } else if (searchfile
->namenode
->divert
&&
518 (searchfile
->namenode
->divert
->camefrom
||
519 (searchfile
->namenode
->divert
->useinstead
&&
520 searchfile
->namenode
->divert
->pkgset
!= pkg
->set
))) {
521 debug(dbg_conff
, "removal_bulk conffile '%s' ignored due to diversion",
523 *lconffp
= conff
->next
;
525 debug(dbg_conffdetail
, "removal_bulk set to new conffile '%s'",
527 conff
->hash
= NEWCONFFILEFLAG
;
528 lconffp
= &conff
->next
;
533 for (conff
= pkg
->installed
.conffiles
; conff
; conff
= conff
->next
) {
534 struct fsys_namenode
*namenode
, *usenode
;
535 static struct varbuf fnvb
, removevb
;
536 struct varbuf_state removevb_state
;
538 if (conff
->obsolete
) {
539 debug(dbg_conffdetail
, "removal_bulk conffile obsolete %s",
543 rc
= conffderef(pkg
, &fnvb
, conff
->name
);
544 debug(dbg_conffdetail
, "removal_bulk conffile '%s' (= '%s')",
545 conff
->name
, rc
== -1 ? "<rc == -1>" : fnvb
.buf
);
549 namenode
= fsys_hash_find_node(conff
->name
, FHFF_NONE
);
550 usenode
= namenodetouse(namenode
, pkg
, &pkg
->installed
);
552 trig_path_activate(usenode
, pkg
);
554 conffnameused
= fnvb
.used
;
555 if (unlink(fnvb
.buf
) && errno
!= ENOENT
&& errno
!= ENOTDIR
)
556 ohshite(_("cannot remove old config file '%.250s' (= '%.250s')"),
557 conff
->name
, fnvb
.buf
);
558 p
= strrchr(fnvb
.buf
,'/'); if (!p
) continue;
560 varbuf_reset(&removevb
);
561 varbuf_add_dir(&removevb
, fnvb
.buf
);
562 varbuf_end_str(&removevb
);
563 varbuf_snapshot(&removevb
, &removevb_state
);
565 dsd
= opendir(removevb
.buf
);
568 debug(dbg_conffdetail
, "removal_bulk conffile no dsd %s %s",
569 fnvb
.buf
, strerror(e
)); errno
= e
;
570 if (errno
== ENOENT
|| errno
== ENOTDIR
) continue;
571 ohshite(_("cannot read config file directory '%.250s' (from '%.250s')"),
572 fnvb
.buf
, conff
->name
);
574 debug(dbg_conffdetail
, "removal_bulk conffile cleaning dsd %s", fnvb
.buf
);
575 push_cleanup(cu_closedir
, ~0, 1, (void *)dsd
);
577 conffbasenamelen
= strlen(++p
);
578 conffbasename
= fnvb
.buf
+conffnameused
-conffbasenamelen
;
579 while ((de
= readdir(dsd
)) != NULL
) {
580 debug(dbg_stupidlyverbose
, "removal_bulk conffile dsd entry='%s'"
581 " conffbasename='%s' conffnameused=%d conffbasenamelen=%d",
582 de
->d_name
, conffbasename
, conffnameused
, conffbasenamelen
);
583 if (strncmp(de
->d_name
, conffbasename
, conffbasenamelen
) == 0) {
584 debug(dbg_stupidlyverbose
, "removal_bulk conffile dsd entry starts right");
585 for (ext
= removeconffexts
; *ext
; ext
++)
586 if (strcmp(*ext
, de
->d_name
+ conffbasenamelen
) == 0)
588 p
= de
->d_name
+conffbasenamelen
;
590 while (*p
&& c_isdigit(*p
))
592 if (*p
== '~' && !*++p
) goto yes_remove
;
595 debug(dbg_stupidlyverbose
, "removal_bulk conffile dsd entry starts wrong");
596 if (de
->d_name
[0] == '#' &&
597 strncmp(de
->d_name
+ 1, conffbasename
, conffbasenamelen
) == 0 &&
598 strcmp(de
->d_name
+ 1 + conffbasenamelen
, "#") == 0)
600 debug(dbg_stupidlyverbose
, "removal_bulk conffile dsd entry not it");
603 varbuf_rollback(&removevb_state
);
604 varbuf_add_str(&removevb
, de
->d_name
);
605 varbuf_end_str(&removevb
);
606 debug(dbg_conffdetail
, "removal_bulk conffile dsd entry removing '%s'",
608 if (unlink(removevb
.buf
) && errno
!= ENOENT
&& errno
!= ENOTDIR
)
609 ohshite(_("cannot remove old backup config file '%.250s' (of '%.250s')"),
610 removevb
.buf
, conff
->name
);
612 pop_cleanup(ehflag_normaltidy
); /* closedir */
615 /* Remove the conffiles from the file list file. */
616 write_filelist_except(pkg
, &pkg
->installed
, pkg
->files
,
619 pkg
->installed
.conffiles
= NULL
;
622 maintscript_installed(pkg
, POSTRMFILE
, "post-removal", "purge", NULL
);
626 * This is used both by deferred_remove() in this file, and at the end of
627 * process_archive() in archives.c if it needs to finish removing a
628 * conflicting package.
630 void removal_bulk(struct pkginfo
*pkg
) {
633 debug(dbg_general
, "removal_bulk package %s", pkg_name(pkg
, pnaw_always
));
635 if (pkg
->status
== PKG_STAT_HALFINSTALLED
||
636 pkg
->status
== PKG_STAT_UNPACKED
) {
637 removal_bulk_remove_files(pkg
);
640 foundpostrm
= pkg_infodb_has_file(pkg
, &pkg
->installed
, POSTRMFILE
);
642 debug(dbg_general
, "removal_bulk purging? foundpostrm=%d",foundpostrm
);
644 if (!foundpostrm
&& !pkg
->installed
.conffiles
) {
645 /* If there are no config files and no postrm script then we
646 * go straight into ‘purge’. */
647 debug(dbg_general
, "removal_bulk no postrm, no conffiles, purging");
649 pkg_set_want(pkg
, PKG_WANT_PURGE
);
650 dpkg_version_blank(&pkg
->configversion
);
651 } else if (pkg
->want
== PKG_WANT_PURGE
) {
652 removal_bulk_remove_configfiles(pkg
);
655 /* I.e., either of the two branches above. */
656 if (pkg
->want
== PKG_WANT_PURGE
) {
657 const char *filename
;
659 /* Retry empty directories, and warn on any leftovers that aren't. */
660 removal_bulk_remove_leftover_dirs(pkg
);
662 filename
= pkg_infodb_get_file(pkg
, &pkg
->installed
, LISTFILE
);
663 debug(dbg_general
, "removal_bulk purge done, removing list '%s'",
665 if (unlink(filename
) && errno
!= ENOENT
)
666 ohshite(_("cannot remove old files list"));
668 filename
= pkg_infodb_get_file(pkg
, &pkg
->installed
, POSTRMFILE
);
669 debug(dbg_general
, "removal_bulk purge done, removing postrm '%s'",
671 if (unlink(filename
) && errno
!= ENOENT
)
672 ohshite(_("can't remove old postrm script"));
674 pkg_set_status(pkg
, PKG_STAT_NOTINSTALLED
);
675 pkg_set_want(pkg
, PKG_WANT_UNKNOWN
);
677 /* This will mess up reverse links, but if we follow them
678 * we won't go back because pkg->status is PKG_STAT_NOTINSTALLED. */
679 pkgbin_blank(&pkg
->installed
);
682 pkg_reset_eflags(pkg
);
685 debug(dbg_general
, "removal done");