chiark / gitweb /
lib/dpkg/tarfn.c: Kludge `tar_header_decode' to handle spurious `errno'.
[dpkg] / src / remove.c
1 /*
2  * dpkg - main program for package management
3  * remove.c - functionality for removing packages
4  *
5  * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include <config.h>
23 #include <compat.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
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>
35
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
46 #include "infodb.h"
47 #include "filesdb.h"
48 #include "main.h"
49
50 /*
51  * pkgdepcheck may be a virtual pkg.
52  */
53 static void checkforremoval(struct pkginfo *pkgtoremove,
54                             struct pkgset *pkgdepcheck,
55                             enum dep_check *rokp, struct varbuf *raemsgs)
56 {
57   struct deppossi *possi;
58   struct pkginfo *depender;
59   enum dep_check ok;
60   struct varbuf_state raemsgs_state;
61
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;
73     }
74     if (dependtry > 1) { if (findbreakcycle(pkgtoremove)) sincenothing= 0; }
75     varbuf_snapshot(raemsgs, &raemsgs_state);
76     ok= dependencies_ok(depender,pkgtoremove,raemsgs);
77     if (ok == DEP_CHECK_HALT &&
78         depender->clientdata->istobe == PKG_ISTOBE_REMOVE)
79       ok = DEP_CHECK_DEFER;
80     if (ok == DEP_CHECK_DEFER)
81       /* Don't burble about reasons for deferral. */
82       varbuf_rollback(raemsgs, &raemsgs_state);
83     if (ok < *rokp) *rokp= ok;
84   }
85 }
86
87 void deferred_remove(struct pkginfo *pkg) {
88   struct varbuf raemsgs = VARBUF_INIT;
89   struct dependency *dep;
90   enum dep_check rok;
91
92   debug(dbg_general, "deferred_remove package %s",
93         pkg_name(pkg, pnaw_always));
94
95   if (!f_pending && pkg->want != PKG_WANT_UNKNOWN) {
96     if (cipaction->arg_int == act_purge)
97       pkg_set_want(pkg, PKG_WANT_PURGE);
98     else
99       pkg_set_want(pkg, PKG_WANT_DEINSTALL);
100
101     if (!f_noact)
102       modstatdb_note(pkg);
103   }
104
105   if (pkg->status == PKG_STAT_NOTINSTALLED) {
106     sincenothing = 0;
107     warning(_("ignoring request to remove %.250s which isn't installed"),
108             pkg_name(pkg, pnaw_nonambig));
109     pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
110     return;
111   } else if (!f_pending &&
112              pkg->status == PKG_STAT_CONFIGFILES &&
113              cipaction->arg_int != act_purge) {
114     sincenothing = 0;
115     warning(_("ignoring request to remove %.250s, only the config\n"
116               " files of which are on the system; use --purge to remove them too"),
117             pkg_name(pkg, pnaw_nonambig));
118     pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
119     return;
120   }
121
122   if (pkg->installed.essential && pkg->status != PKG_STAT_CONFIGFILES)
123     forcibleerr(fc_removeessential,
124                 _("this is an essential package; it should not be removed"));
125
126   debug(dbg_general, "checking dependencies for remove '%s'",
127         pkg_name(pkg, pnaw_always));
128   rok = DEP_CHECK_OK;
129   checkforremoval(pkg, pkg->set, &rok, &raemsgs);
130   for (dep= pkg->installed.depends; dep; dep= dep->next) {
131     if (dep->type != dep_provides) continue;
132     debug(dbg_depcon, "checking virtual package '%s'", dep->list->ed->name);
133     checkforremoval(pkg, dep->list->ed, &rok, &raemsgs);
134   }
135
136   if (rok == DEP_CHECK_DEFER) {
137     varbuf_destroy(&raemsgs);
138     pkg->clientdata->istobe = PKG_ISTOBE_REMOVE;
139     enqueue_package(pkg);
140     return;
141   } else if (rok == DEP_CHECK_HALT) {
142     sincenothing= 0;
143     varbuf_end_str(&raemsgs);
144     notice(_("dependency problems prevent removal of %s:\n%s"),
145             pkg_name(pkg, pnaw_nonambig), raemsgs.buf);
146     ohshit(_("dependency problems - not removing"));
147   } else if (raemsgs.used) {
148     varbuf_end_str(&raemsgs);
149     notice(_("%s: dependency problems, but removing anyway as you requested:\n%s"),
150             pkg_name(pkg, pnaw_nonambig), raemsgs.buf);
151   }
152   varbuf_destroy(&raemsgs);
153   sincenothing= 0;
154
155   if (pkg->eflag & PKG_EFLAG_REINSTREQ)
156     forcibleerr(fc_removereinstreq,
157                 _("package is in a very bad inconsistent state; you should\n"
158                   " reinstall it before attempting a removal"));
159
160   ensure_allinstfiles_available();
161   filesdbinit();
162
163   if (f_noact) {
164     printf(_("Would remove or purge %s (%s) ...\n"),
165            pkg_name(pkg, pnaw_nonambig),
166            versiondescribe(&pkg->installed.version, vdew_nonambig));
167     pkg_set_status(pkg, PKG_STAT_NOTINSTALLED);
168     pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
169     return;
170   }
171
172   pkg_conffiles_mark_old(pkg);
173
174   /* Only print and log removal action once. This avoids duplication when
175    * using --remove and --purge in sequence. */
176   if (pkg->status > PKG_STAT_CONFIGFILES) {
177     printf(_("Removing %s (%s) ...\n"), pkg_name(pkg, pnaw_nonambig),
178            versiondescribe(&pkg->installed.version, vdew_nonambig));
179     log_action("remove", pkg, &pkg->installed);
180   }
181
182   trig_activate_packageprocessing(pkg);
183   if (pkg->status >= PKG_STAT_HALFCONFIGURED) {
184     static enum pkgstatus oldpkgstatus;
185
186     oldpkgstatus= pkg->status;
187     pkg_set_status(pkg, PKG_STAT_HALFCONFIGURED);
188     modstatdb_note(pkg);
189     push_cleanup(cu_prermremove, ~ehflag_normaltidy, NULL, 0, 2,
190                  (void *)pkg, (void *)&oldpkgstatus);
191     maintscript_installed(pkg, PRERMFILE, "pre-removal", "remove", NULL);
192
193     /* Will turn into ‘half-installed’ soon ... */
194     pkg_set_status(pkg, PKG_STAT_UNPACKED);
195   }
196
197   removal_bulk(pkg);
198 }
199
200 static void push_leftover(struct fileinlist **leftoverp,
201                           struct filenamenode *namenode) {
202   struct fileinlist *newentry;
203   newentry= nfmalloc(sizeof(struct fileinlist));
204   newentry->next= *leftoverp;
205   newentry->namenode= namenode;
206   *leftoverp= newentry;
207 }
208
209 static void
210 removal_bulk_remove_file(const char *filename, const char *filetype)
211 {
212   /* We need the postrm and list files for --purge. */
213   if (strcmp(filetype, LISTFILE) == 0 ||
214       strcmp(filetype, POSTRMFILE) == 0)
215     return;
216
217   debug(dbg_stupidlyverbose, "removal_bulk info not postrm or list");
218
219   if (unlink(filename))
220     ohshite(_("unable to delete control info file '%.250s'"), filename);
221
222   debug(dbg_scripts, "removal_bulk info unlinked %s", filename);
223 }
224
225 static bool
226 removal_bulk_file_is_shared(struct pkginfo *pkg, struct filenamenode *namenode)
227 {
228   struct filepackages_iterator *iter;
229   struct pkginfo *otherpkg;
230   bool shared = false;
231
232   if (pkgset_installed_instances(pkg->set) <= 1)
233     return false;
234
235   iter = filepackages_iter_new(namenode);
236   while ((otherpkg = filepackages_iter_next(iter))) {
237     if (otherpkg == pkg)
238       continue;
239     if (otherpkg->set != pkg->set)
240       continue;
241
242     debug(dbg_eachfiledetail, "removal_bulk file shared with %s, skipping",
243           pkg_name(otherpkg, pnaw_always));
244     shared = true;
245     break;
246   }
247   filepackages_iter_free(iter);
248
249   return shared;
250 }
251
252 static void
253 removal_bulk_remove_files(struct pkginfo *pkg)
254 {
255   struct reversefilelistiter rev_iter;
256   struct fileinlist *leftover;
257   struct filenamenode *namenode;
258   static struct varbuf fnvb;
259   struct varbuf_state fnvb_state;
260   struct stat stab;
261
262     pkg_set_status(pkg, PKG_STAT_HALFINSTALLED);
263     modstatdb_note(pkg);
264     push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
265
266     reversefilelist_init(&rev_iter, pkg->clientdata->files);
267     leftover = NULL;
268     while ((namenode = reversefilelist_next(&rev_iter))) {
269       struct filenamenode *usenode;
270       bool is_dir;
271
272       debug(dbg_eachfile, "removal_bulk '%s' flags=%o",
273             namenode->name, namenode->flags);
274
275       usenode = namenodetouse(namenode, pkg, &pkg->installed);
276
277       varbuf_reset(&fnvb);
278       varbuf_add_str(&fnvb, instdir);
279       varbuf_add_str(&fnvb, usenode->name);
280       varbuf_end_str(&fnvb);
281       varbuf_snapshot(&fnvb, &fnvb_state);
282
283       is_dir = stat(fnvb.buf, &stab) == 0 && S_ISDIR(stab.st_mode);
284
285       /* A pkgset can share files between its instances that we
286        * don't want to remove, we just want to forget them. This
287        * applies to shared conffiles too. */
288       if (!is_dir && removal_bulk_file_is_shared(pkg, namenode))
289         continue;
290
291       /* Non-shared conffiles are kept. */
292       if (namenode->flags & fnnf_old_conff) {
293         push_leftover(&leftover, namenode);
294         continue;
295       }
296
297       if (is_dir) {
298         debug(dbg_eachfiledetail, "removal_bulk is a directory");
299         /* Only delete a directory or a link to one if we're the only
300          * package which uses it. Other files should only be listed
301          * in this package (but we don't check). */
302         if (dir_has_conffiles(namenode, pkg)) {
303           push_leftover(&leftover,namenode);
304           continue;
305         }
306         if (dir_is_used_by_pkg(namenode, pkg, leftover)) {
307           push_leftover(&leftover, namenode);
308           continue;
309         }
310         if (dir_is_used_by_others(namenode, pkg))
311           continue;
312
313         if (strcmp(usenode->name, "/.") == 0) {
314           debug(dbg_eachfiledetail,
315                 "removal_bulk '%s' root directory, cannot remove", fnvb.buf);
316           push_leftover(&leftover, namenode);
317           continue;
318         }
319       }
320
321       trig_path_activate(usenode, pkg);
322
323       varbuf_rollback(&fnvb, &fnvb_state);
324       varbuf_add_str(&fnvb, DPKGTEMPEXT);
325       varbuf_end_str(&fnvb);
326       debug(dbg_eachfiledetail, "removal_bulk cleaning temp '%s'", fnvb.buf);
327       path_remove_tree(fnvb.buf);
328
329       varbuf_rollback(&fnvb, &fnvb_state);
330       varbuf_add_str(&fnvb, DPKGNEWEXT);
331       varbuf_end_str(&fnvb);
332       debug(dbg_eachfiledetail, "removal_bulk cleaning new '%s'", fnvb.buf);
333       path_remove_tree(fnvb.buf);
334
335       varbuf_rollback(&fnvb, &fnvb_state);
336       varbuf_end_str(&fnvb);
337
338       debug(dbg_eachfiledetail, "removal_bulk removing '%s'", fnvb.buf);
339       if (!rmdir(fnvb.buf) || errno == ENOENT || errno == ELOOP) continue;
340       if (errno == ENOTEMPTY || errno == EEXIST) {
341         debug(dbg_eachfiledetail,
342               "removal_bulk '%s' was not empty, will try again later",
343               fnvb.buf);
344         push_leftover(&leftover,namenode);
345         continue;
346       } else if (errno == EBUSY || errno == EPERM) {
347         warning(_("while removing %.250s, unable to remove directory '%.250s': "
348                   "%s - directory may be a mount point?"),
349                 pkg_name(pkg, pnaw_nonambig), namenode->name, strerror(errno));
350         push_leftover(&leftover,namenode);
351         continue;
352       }
353       if (errno != ENOTDIR)
354         ohshite(_("cannot remove '%.250s'"), fnvb.buf);
355       debug(dbg_eachfiledetail, "removal_bulk unlinking '%s'", fnvb.buf);
356       if (secure_unlink(fnvb.buf))
357         ohshite(_("unable to securely remove '%.250s'"), fnvb.buf);
358     }
359     write_filelist_except(pkg, &pkg->installed, leftover, 0);
360     maintscript_installed(pkg, POSTRMFILE, "post-removal", "remove", NULL);
361
362     trig_parse_ci(pkg_infodb_get_file(pkg, &pkg->installed, TRIGGERSCIFILE),
363                   trig_cicb_interest_delete, NULL, pkg, &pkg->installed);
364     trig_file_interests_save();
365
366     debug(dbg_general, "removal_bulk cleaning info directory");
367     pkg_infodb_foreach(pkg, &pkg->installed, removal_bulk_remove_file);
368     dir_sync_path(pkg_infodb_get_dir());
369
370     pkg_set_status(pkg, PKG_STAT_CONFIGFILES);
371     pkg->installed.essential = false;
372     modstatdb_note(pkg);
373     push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
374 }
375
376 static void removal_bulk_remove_leftover_dirs(struct pkginfo *pkg) {
377   struct reversefilelistiter rev_iter;
378   struct fileinlist *leftover;
379   struct filenamenode *namenode;
380   static struct varbuf fnvb;
381   struct stat stab;
382
383   /* We may have modified this previously. */
384   ensure_packagefiles_available(pkg);
385
386   modstatdb_note(pkg);
387   push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
388
389   reversefilelist_init(&rev_iter, pkg->clientdata->files);
390   leftover = NULL;
391   while ((namenode = reversefilelist_next(&rev_iter))) {
392     struct filenamenode *usenode;
393
394     debug(dbg_eachfile, "removal_bulk '%s' flags=%o",
395           namenode->name, namenode->flags);
396     if (namenode->flags & fnnf_old_conff) {
397       /* This can only happen if removal_bulk_remove_configfiles() got
398        * interrupted half way. */
399       debug(dbg_eachfiledetail, "removal_bulk expecting only left over dirs, "
400                                 "ignoring conffile '%s'", namenode->name);
401       continue;
402     }
403
404     usenode = namenodetouse(namenode, pkg, &pkg->installed);
405
406     varbuf_reset(&fnvb);
407     varbuf_add_str(&fnvb, instdir);
408     varbuf_add_str(&fnvb, usenode->name);
409     varbuf_end_str(&fnvb);
410
411     if (!stat(fnvb.buf,&stab) && S_ISDIR(stab.st_mode)) {
412       debug(dbg_eachfiledetail, "removal_bulk is a directory");
413       /* Only delete a directory or a link to one if we're the only
414        * package which uses it. Other files should only be listed
415        * in this package (but we don't check). */
416       if (dir_is_used_by_pkg(namenode, pkg, leftover)) {
417         push_leftover(&leftover, namenode);
418         continue;
419       }
420       if (dir_is_used_by_others(namenode, pkg))
421         continue;
422
423       if (strcmp(usenode->name, "/.") == 0) {
424         debug(dbg_eachfiledetail,
425               "removal_bulk '%s' root directory, cannot remove", fnvb.buf);
426         push_leftover(&leftover, namenode);
427         continue;
428       }
429     }
430
431     trig_path_activate(usenode, pkg);
432
433     debug(dbg_eachfiledetail, "removal_bulk removing '%s'", fnvb.buf);
434     if (!rmdir(fnvb.buf) || errno == ENOENT || errno == ELOOP) continue;
435     if (errno == ENOTEMPTY || errno == EEXIST) {
436       warning(_("while removing %.250s, directory '%.250s' not empty so not removed"),
437               pkg_name(pkg, pnaw_nonambig), namenode->name);
438       push_leftover(&leftover,namenode);
439       continue;
440     } else if (errno == EBUSY || errno == EPERM) {
441       warning(_("while removing %.250s, unable to remove directory '%.250s': "
442                 "%s - directory may be a mount point?"),
443               pkg_name(pkg, pnaw_nonambig), namenode->name, strerror(errno));
444       push_leftover(&leftover,namenode);
445       continue;
446     }
447     if (errno != ENOTDIR)
448       ohshite(_("cannot remove '%.250s'"), fnvb.buf);
449
450     if (lstat(fnvb.buf, &stab) == 0 && S_ISLNK(stab.st_mode)) {
451       debug(dbg_eachfiledetail, "removal_bulk is a symlink to a directory");
452
453       if (unlink(fnvb.buf))
454         ohshite(_("cannot remove '%.250s'"), fnvb.buf);
455
456       continue;
457     }
458
459     push_leftover(&leftover,namenode);
460     continue;
461   }
462   write_filelist_except(pkg, &pkg->installed, leftover, 0);
463
464   modstatdb_note(pkg);
465   push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
466 }
467
468 static void removal_bulk_remove_configfiles(struct pkginfo *pkg) {
469   static const char *const removeconffexts[] = { REMOVECONFFEXTS, NULL };
470   int rc;
471   int conffnameused, conffbasenamelen;
472   char *conffbasename;
473   struct conffile *conff, **lconffp;
474   struct fileinlist *searchfile;
475   DIR *dsd;
476   struct dirent *de;
477   char *p;
478   const char *const *ext;
479
480     printf(_("Purging configuration files for %s (%s) ...\n"),
481            pkg_name(pkg, pnaw_nonambig),
482            versiondescribe(&pkg->installed.version, vdew_nonambig));
483     log_action("purge", pkg, &pkg->installed);
484     trig_activate_packageprocessing(pkg);
485
486     /* We may have modified this above. */
487     ensure_packagefiles_available(pkg);
488
489     /* We're about to remove the configuration, so remove the note
490      * about which version it was ... */
491     dpkg_version_blank(&pkg->configversion);
492     modstatdb_note(pkg);
493
494     /* Remove from our list any conffiles that aren't ours any more or
495      * are involved in diversions, except if we are the package doing the
496      * diverting. */
497     for (lconffp = &pkg->installed.conffiles; (conff = *lconffp) != NULL; ) {
498       for (searchfile= pkg->clientdata->files;
499            searchfile && strcmp(searchfile->namenode->name,conff->name);
500            searchfile= searchfile->next);
501       if (!searchfile) {
502         debug(dbg_conff, "removal_bulk conffile not ours any more '%s'",
503               conff->name);
504         *lconffp= conff->next;
505       } else if (searchfile->namenode->divert &&
506                  (searchfile->namenode->divert->camefrom ||
507                   (searchfile->namenode->divert->useinstead &&
508                    searchfile->namenode->divert->pkgset != pkg->set))) {
509         debug(dbg_conff, "removal_bulk conffile '%s' ignored due to diversion",
510               conff->name);
511         *lconffp= conff->next;
512       } else {
513         debug(dbg_conffdetail, "removal_bulk set to new conffile '%s'",
514               conff->name);
515         conff->hash = NEWCONFFILEFLAG;
516         lconffp= &conff->next;
517       }
518     }
519     modstatdb_note(pkg);
520
521     for (conff= pkg->installed.conffiles; conff; conff= conff->next) {
522       struct filenamenode *namenode, *usenode;
523     static struct varbuf fnvb, removevb;
524       struct varbuf_state removevb_state;
525
526       if (conff->obsolete) {
527         debug(dbg_conffdetail, "removal_bulk conffile obsolete %s",
528               conff->name);
529       }
530       varbuf_reset(&fnvb);
531       rc = conffderef(pkg, &fnvb, conff->name);
532       debug(dbg_conffdetail, "removal_bulk conffile '%s' (= '%s')",
533             conff->name, rc == -1 ? "<rc == -1>" : fnvb.buf);
534       if (rc == -1)
535         continue;
536
537       namenode = findnamenode(conff->name, 0);
538       usenode = namenodetouse(namenode, pkg, &pkg->installed);
539
540       trig_path_activate(usenode, pkg);
541
542       conffnameused = fnvb.used;
543       if (unlink(fnvb.buf) && errno != ENOENT && errno != ENOTDIR)
544         ohshite(_("cannot remove old config file '%.250s' (= '%.250s')"),
545                 conff->name, fnvb.buf);
546       p= strrchr(fnvb.buf,'/'); if (!p) continue;
547       *p = '\0';
548       varbuf_reset(&removevb);
549       varbuf_add_str(&removevb, fnvb.buf);
550       varbuf_add_char(&removevb, '/');
551       varbuf_end_str(&removevb);
552       varbuf_snapshot(&removevb, &removevb_state);
553
554       dsd= opendir(removevb.buf);
555       if (!dsd) {
556         int e=errno;
557         debug(dbg_conffdetail, "removal_bulk conffile no dsd %s %s",
558               fnvb.buf, strerror(e)); errno= e;
559         if (errno == ENOENT || errno == ENOTDIR) continue;
560         ohshite(_("cannot read config file directory '%.250s' (from '%.250s')"),
561                 fnvb.buf, conff->name);
562       }
563       debug(dbg_conffdetail, "removal_bulk conffile cleaning dsd %s", fnvb.buf);
564       push_cleanup(cu_closedir, ~0, NULL, 0, 1, (void *)dsd);
565       *p= '/';
566       conffbasenamelen= strlen(++p);
567       conffbasename= fnvb.buf+conffnameused-conffbasenamelen;
568       while ((de = readdir(dsd)) != NULL) {
569         debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry='%s'"
570               " conffbasename='%s' conffnameused=%d conffbasenamelen=%d",
571               de->d_name, conffbasename, conffnameused, conffbasenamelen);
572         if (strncmp(de->d_name, conffbasename, conffbasenamelen) == 0) {
573           debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry starts right");
574           for (ext= removeconffexts; *ext; ext++)
575             if (strcmp(*ext, de->d_name + conffbasenamelen) == 0)
576               goto yes_remove;
577           p= de->d_name+conffbasenamelen;
578           if (*p++ == '~') {
579             while (*p && c_isdigit(*p))
580               p++;
581             if (*p == '~' && !*++p) goto yes_remove;
582           }
583         }
584         debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry starts wrong");
585         if (de->d_name[0] == '#' &&
586             strncmp(de->d_name + 1, conffbasename, conffbasenamelen) == 0 &&
587             strcmp(de->d_name + 1 + conffbasenamelen, "#") == 0)
588           goto yes_remove;
589         debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry not it");
590         continue;
591       yes_remove:
592         varbuf_rollback(&removevb, &removevb_state);
593         varbuf_add_str(&removevb, de->d_name);
594         varbuf_end_str(&removevb);
595         debug(dbg_conffdetail, "removal_bulk conffile dsd entry removing '%s'",
596               removevb.buf);
597         if (unlink(removevb.buf) && errno != ENOENT && errno != ENOTDIR)
598           ohshite(_("cannot remove old backup config file '%.250s' (of '%.250s')"),
599                   removevb.buf, conff->name);
600       }
601       pop_cleanup(ehflag_normaltidy); /* closedir */
602     }
603
604     /* Remove the conffiles from the file list file. */
605     write_filelist_except(pkg, &pkg->installed, pkg->clientdata->files,
606                           fnnf_old_conff);
607
608     pkg->installed.conffiles = NULL;
609     modstatdb_note(pkg);
610
611     maintscript_installed(pkg, POSTRMFILE, "post-removal", "purge", NULL);
612 }
613
614 /*
615  * This is used both by deferred_remove() in this file, and at the end of
616  * process_archive() in archives.c if it needs to finish removing a
617  * conflicting package.
618  */
619 void removal_bulk(struct pkginfo *pkg) {
620   bool foundpostrm;
621
622   debug(dbg_general, "removal_bulk package %s", pkg_name(pkg, pnaw_always));
623
624   if (pkg->status == PKG_STAT_HALFINSTALLED ||
625       pkg->status == PKG_STAT_UNPACKED) {
626     removal_bulk_remove_files(pkg);
627   }
628
629   foundpostrm = pkg_infodb_has_file(pkg, &pkg->installed, POSTRMFILE);
630
631   debug(dbg_general, "removal_bulk purging? foundpostrm=%d",foundpostrm);
632
633   if (!foundpostrm && !pkg->installed.conffiles) {
634     /* If there are no config files and no postrm script then we
635      * go straight into ‘purge’.  */
636     debug(dbg_general, "removal_bulk no postrm, no conffiles, purging");
637
638     pkg_set_want(pkg, PKG_WANT_PURGE);
639     dpkg_version_blank(&pkg->configversion);
640   } else if (pkg->want == PKG_WANT_PURGE) {
641
642     removal_bulk_remove_configfiles(pkg);
643
644   }
645
646   /* I.e., either of the two branches above. */
647   if (pkg->want == PKG_WANT_PURGE) {
648     const char *filename;
649
650     /* Retry empty directories, and warn on any leftovers that aren't. */
651     removal_bulk_remove_leftover_dirs(pkg);
652
653     filename = pkg_infodb_get_file(pkg, &pkg->installed, LISTFILE);
654     debug(dbg_general, "removal_bulk purge done, removing list '%s'",
655           filename);
656     if (unlink(filename) && errno != ENOENT)
657       ohshite(_("cannot remove old files list"));
658
659     filename = pkg_infodb_get_file(pkg, &pkg->installed, POSTRMFILE);
660     debug(dbg_general, "removal_bulk purge done, removing postrm '%s'",
661           filename);
662     if (unlink(filename) && errno != ENOENT)
663       ohshite(_("can't remove old postrm script"));
664
665     pkg_set_status(pkg, PKG_STAT_NOTINSTALLED);
666     pkg_set_want(pkg, PKG_WANT_UNKNOWN);
667
668     /* This will mess up reverse links, but if we follow them
669      * we won't go back because pkg->status is PKG_STAT_NOTINSTALLED. */
670     pkgbin_blank(&pkg->installed);
671   }
672
673   pkg_reset_eflags(pkg);
674   modstatdb_note(pkg);
675
676   debug(dbg_general, "removal done");
677 }