libdpkg: Deindent an else clause
[dpkg.git] / src / main / remove.c
blob88c01a22719dfb355f4aacbf7470fed3e52f9969
1 /*
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/>.
22 #include <config.h>
23 #include <compat.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <dirent.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <stdio.h>
36 #include <dpkg/i18n.h>
37 #include <dpkg/c-ctype.h>
38 #include <dpkg/dpkg.h>
39 #include <dpkg/dpkg-db.h>
40 #include <dpkg/pkg.h>
41 #include <dpkg/path.h>
42 #include <dpkg/dir.h>
43 #include <dpkg/options.h>
44 #include <dpkg/triglib.h>
45 #include <dpkg/db-ctrl.h>
46 #include <dpkg/db-fsys.h>
48 #include "main.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;
59 enum dep_check ok;
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)
68 continue;
69 if (ignore_depends(depender)) {
70 debug(dbg_depcon, "ignoring depending package '%s'",
71 pkg_name(depender, pnaw_always));
72 continue;
74 if (dependtry >= DEPEND_TRY_CYCLES) {
75 if (findbreakcycle(pkgtoremove))
76 sincenothing = 0;
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)
83 ok = DEP_CHECK_DEFER;
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;
94 enum dep_check rok;
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);
102 else
103 pkg_set_want(pkg, PKG_WANT_DEINSTALL);
105 if (!f_noact)
106 modstatdb_note(pkg);
109 ensure_package_clientdata(pkg);
111 if (pkg->status == PKG_STAT_NOTINSTALLED) {
112 sincenothing = 0;
113 warning(_("ignoring request to remove %.250s which isn't installed"),
114 pkg_name(pkg, pnaw_nonambig));
115 pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
116 return;
117 } else if (!f_pending &&
118 pkg->status == PKG_STAT_CONFIGFILES &&
119 cipaction->arg_int != act_purge) {
120 sincenothing = 0;
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;
125 return;
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));
139 rok = DEP_CHECK_OK;
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);
151 return;
152 } else if (rok == DEP_CHECK_HALT) {
153 sincenothing= 0;
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);
164 sincenothing= 0;
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();
172 fsys_hash_init();
174 if (f_noact) {
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;
180 return;
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);
199 modstatdb_note(pkg);
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);
208 removal_bulk(pkg);
211 static void
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;
223 static void
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)
229 return;
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);
239 static bool
240 removal_bulk_file_is_shared(struct pkginfo *pkg, struct fsys_namenode *namenode)
242 struct fsys_node_pkgs_iter *iter;
243 struct pkginfo *otherpkg;
244 bool shared = false;
246 if (pkgset_installed_instances(pkg->set) <= 1)
247 return false;
249 iter = fsys_node_pkgs_iter_new(namenode);
250 while ((otherpkg = fsys_node_pkgs_iter_next(iter))) {
251 if (otherpkg == pkg)
252 continue;
253 if (otherpkg->set != pkg->set)
254 continue;
256 debug(dbg_eachfiledetail, "removal_bulk file shared with %s, skipping",
257 pkg_name(otherpkg, pnaw_always));
258 shared = true;
259 break;
261 fsys_node_pkgs_iter_free(iter);
263 return shared;
266 static void
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;
274 struct stat stab;
276 pkg_set_status(pkg, PKG_STAT_HALFINSTALLED);
277 modstatdb_note(pkg);
278 push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
280 fsys_hash_rev_iter_init(&rev_iter, pkg->files);
281 leftover = NULL;
282 while ((namenode = fsys_hash_rev_iter_next(&rev_iter))) {
283 struct fsys_namenode *usenode;
284 bool is_dir;
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))
302 continue;
304 /* Non-shared conffiles are kept. */
305 if (namenode->flags & FNNF_OLD_CONFF) {
306 push_leftover(&leftover, namenode);
307 continue;
310 if (is_dir) {
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);
317 continue;
319 if (dir_is_used_by_pkg(namenode, pkg, leftover)) {
320 push_leftover(&leftover, namenode);
321 continue;
323 if (dir_is_used_by_others(namenode, pkg))
324 continue;
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);
330 continue;
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",
356 fnvb.buf);
357 push_leftover(&leftover,namenode);
358 continue;
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);
364 continue;
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;
386 modstatdb_note(pkg);
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;
395 struct stat stab;
397 /* We may have modified this previously. */
398 ensure_packagefiles_available(pkg);
400 modstatdb_note(pkg);
401 push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
403 fsys_hash_rev_iter_init(&rev_iter, pkg->files);
404 leftover = NULL;
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);
415 continue;
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);
431 continue;
433 if (dir_is_used_by_others(namenode, pkg))
434 continue;
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);
440 continue;
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);
452 continue;
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);
458 continue;
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);
469 continue;
472 push_leftover(&leftover,namenode);
474 write_filelist_except(pkg, &pkg->installed, leftover, 0);
476 modstatdb_note(pkg);
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 };
482 int rc;
483 int conffnameused, conffbasenamelen;
484 char *conffbasename;
485 struct conffile *conff, **lconffp;
486 struct fsys_namenode_list *searchfile;
487 DIR *dsd;
488 struct dirent *de;
489 char *p;
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);
504 modstatdb_note(pkg);
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
508 * diverting. */
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);
513 if (!searchfile) {
514 debug(dbg_conff, "removal_bulk conffile not ours any more '%s'",
515 conff->name);
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",
522 conff->name);
523 *lconffp= conff->next;
524 } else {
525 debug(dbg_conffdetail, "removal_bulk set to new conffile '%s'",
526 conff->name);
527 conff->hash = NEWCONFFILEFLAG;
528 lconffp= &conff->next;
531 modstatdb_note(pkg);
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",
540 conff->name);
542 varbuf_reset(&fnvb);
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);
546 if (rc == -1)
547 continue;
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;
559 *p = '\0';
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);
566 if (!dsd) {
567 int e=errno;
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);
576 *p= '/';
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)
587 goto yes_remove;
588 p= de->d_name+conffbasenamelen;
589 if (*p++ == '~') {
590 while (*p && c_isdigit(*p))
591 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)
599 goto yes_remove;
600 debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry not it");
601 continue;
602 yes_remove:
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'",
607 removevb.buf);
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,
617 FNNF_OLD_CONFF);
619 pkg->installed.conffiles = NULL;
620 modstatdb_note(pkg);
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) {
631 bool foundpostrm;
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'",
664 filename);
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'",
670 filename);
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);
683 modstatdb_note(pkg);
685 debug(dbg_general, "removal done");