123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- /*
- * dpkg - main program for package management
- * help.c - various helper routines
- *
- * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
- * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include <config.h>
- #include <compat.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <dpkg/i18n.h>
- #include <dpkg/dpkg.h>
- #include <dpkg/dpkg-db.h>
- #include <dpkg/path.h>
- #include "filesdb.h"
- #include "main.h"
- const char *const statusstrings[]= {
- [PKG_STAT_NOTINSTALLED] = N_("not installed"),
- [PKG_STAT_CONFIGFILES] = N_("not installed but configs remain"),
- [PKG_STAT_HALFINSTALLED] = N_("broken due to failed removal or installation"),
- [PKG_STAT_UNPACKED] = N_("unpacked but not configured"),
- [PKG_STAT_HALFCONFIGURED] = N_("broken due to postinst failure"),
- [PKG_STAT_TRIGGERSAWAITED] = N_("awaiting trigger processing by another package"),
- [PKG_STAT_TRIGGERSPENDING] = N_("triggered"),
- [PKG_STAT_INSTALLED] = N_("installed")
- };
- struct filenamenode *
- namenodetouse(struct filenamenode *namenode, struct pkginfo *pkg,
- struct pkgbin *pkgbin)
- {
- struct filenamenode *r;
- if (!namenode->divert) {
- r = namenode;
- return r;
- }
- debug(dbg_eachfile, "namenodetouse namenode='%s' pkg=%s",
- namenode->name, pkgbin_name(pkg, pkgbin, pnaw_always));
- r=
- (namenode->divert->useinstead && namenode->divert->pkgset != pkg->set)
- ? namenode->divert->useinstead : namenode;
- debug(dbg_eachfile,
- "namenodetouse ... useinstead=%s camefrom=%s pkg=%s return %s",
- namenode->divert->useinstead ? namenode->divert->useinstead->name : "<none>",
- namenode->divert->camefrom ? namenode->divert->camefrom->name : "<none>",
- namenode->divert->pkgset ? namenode->divert->pkgset->name : "<none>",
- r->name);
- return r;
- }
- bool
- find_command(const char *prog)
- {
- struct varbuf filename = VARBUF_INIT;
- struct stat stab;
- const char *path_list;
- const char *path, *path_end;
- size_t path_len;
- path_list = getenv("PATH");
- if (!path_list)
- ohshit(_("PATH is not set"));
- for (path = path_list; path; path = path_end ? path_end + 1 : NULL) {
- path_end = strchr(path, ':');
- path_len = path_end ? (size_t)(path_end - path) : strlen(path);
- varbuf_reset(&filename);
- varbuf_add_buf(&filename, path, path_len);
- if (path_len)
- varbuf_add_char(&filename, '/');
- varbuf_add_str(&filename, prog);
- varbuf_end_str(&filename);
- if (stat(filename.buf, &stab) == 0 && (stab.st_mode & 0111)) {
- varbuf_destroy(&filename);
- return true;
- }
- }
- varbuf_destroy(&filename);
- return false;
- }
- /**
- * Verify that some programs can be found in the PATH.
- */
- void checkpath(void) {
- static const char *const prog_list[] = {
- DEFAULTSHELL,
- RM,
- TAR,
- DIFF,
- BACKEND,
- "launchctl",
- #if BUILD_START_STOP_DAEMON
- "start-stop-daemon",
- #endif
- NULL
- };
- const char *const *prog;
- int warned= 0;
- for (prog = prog_list; *prog; prog++) {
- if (!find_command(*prog)) {
- warning(_("'%s' not found in PATH or not executable"), *prog);
- warned++;
- }
- }
- if (warned)
- forcibleerr(fc_badpath,
- P_("%d expected program not found in PATH or not executable\n%s",
- "%d expected programs not found in PATH or not executable\n%s",
- warned),
- warned, _("Note: root's PATH should usually contain "
- "/usr/local/sbin, /usr/sbin and /sbin"));
- }
- bool
- ignore_depends(struct pkginfo *pkg)
- {
- struct pkg_list *id;
- for (id= ignoredependss; id; id= id->next)
- if (id->pkg == pkg)
- return true;
- return false;
- }
- static bool
- ignore_depends_possi(struct deppossi *possi)
- {
- struct deppossi_pkg_iterator *possi_iter;
- struct pkginfo *pkg;
- possi_iter = deppossi_pkg_iter_new(possi, wpb_installed);
- while ((pkg = deppossi_pkg_iter_next(possi_iter))) {
- if (ignore_depends(pkg)) {
- deppossi_pkg_iter_free(possi_iter);
- return true;
- }
- }
- deppossi_pkg_iter_free(possi_iter);
- return false;
- }
- bool
- force_depends(struct deppossi *possi)
- {
- return fc_depends ||
- ignore_depends_possi(possi) ||
- ignore_depends(possi->up->up);
- }
- bool
- force_breaks(struct deppossi *possi)
- {
- return fc_breaks ||
- ignore_depends_possi(possi) ||
- ignore_depends(possi->up->up);
- }
- bool
- force_conflicts(struct deppossi *possi)
- {
- return fc_conflicts;
- }
- void clear_istobes(void) {
- struct pkgiterator *iter;
- struct pkginfo *pkg;
- iter = pkg_db_iter_new();
- while ((pkg = pkg_db_iter_next_pkg(iter)) != NULL) {
- ensure_package_clientdata(pkg);
- pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
- pkg->clientdata->replacingfilesandsaid= 0;
- }
- pkg_db_iter_free(iter);
- }
- /*
- * Returns true if the directory contains conffiles belonging to pkg,
- * false otherwise.
- */
- bool
- dir_has_conffiles(struct filenamenode *file, struct pkginfo *pkg)
- {
- struct conffile *conff;
- size_t namelen;
- debug(dbg_veryverbose, "dir_has_conffiles '%s' (from %s)", file->name,
- pkg_name(pkg, pnaw_always));
- namelen = strlen(file->name);
- for (conff= pkg->installed.conffiles; conff; conff= conff->next) {
- if (conff->obsolete)
- continue;
- if (strncmp(file->name, conff->name, namelen) == 0 &&
- strlen(conff->name) > namelen && conff->name[namelen] == '/') {
- debug(dbg_veryverbose, "directory %s has conffile %s from %s",
- file->name, conff->name, pkg_name(pkg, pnaw_always));
- return true;
- }
- }
- debug(dbg_veryverbose, "dir_has_conffiles no");
- return false;
- }
- /*
- * Returns true if the file is used by packages other than pkg,
- * false otherwise.
- */
- bool
- dir_is_used_by_others(struct filenamenode *file, struct pkginfo *pkg)
- {
- struct filepackages_iterator *iter;
- struct pkginfo *other_pkg;
- debug(dbg_veryverbose, "dir_is_used_by_others '%s' (except %s)", file->name,
- pkg ? pkg_name(pkg, pnaw_always) : "<none>");
- iter = filepackages_iter_new(file);
- while ((other_pkg = filepackages_iter_next(iter))) {
- debug(dbg_veryverbose, "dir_is_used_by_others considering %s ...",
- pkg_name(other_pkg, pnaw_always));
- if (other_pkg == pkg)
- continue;
- filepackages_iter_free(iter);
- debug(dbg_veryverbose, "dir_is_used_by_others yes");
- return true;
- }
- filepackages_iter_free(iter);
- debug(dbg_veryverbose, "dir_is_used_by_others no");
- return false;
- }
- /*
- * Returns true if the file is used by pkg, false otherwise.
- */
- bool
- dir_is_used_by_pkg(struct filenamenode *file, struct pkginfo *pkg,
- struct fileinlist *list)
- {
- struct fileinlist *node;
- size_t namelen;
- debug(dbg_veryverbose, "dir_is_used_by_pkg '%s' (by %s)",
- file->name, pkg ? pkg_name(pkg, pnaw_always) : "<none>");
- namelen = strlen(file->name);
- for (node = list; node; node = node->next) {
- debug(dbg_veryverbose, "dir_is_used_by_pkg considering %s ...",
- node->namenode->name);
- if (strncmp(file->name, node->namenode->name, namelen) == 0 &&
- strlen(node->namenode->name) > namelen &&
- node->namenode->name[namelen] == '/') {
- debug(dbg_veryverbose, "dir_is_used_by_pkg yes");
- return true;
- }
- }
- debug(dbg_veryverbose, "dir_is_used_by_pkg no");
- return false;
- }
- /**
- * Mark a conffile as obsolete.
- *
- * @param pkg The package owning the conffile.
- * @param namenode The namenode for the obsolete conffile.
- */
- void
- conffile_mark_obsolete(struct pkginfo *pkg, struct filenamenode *namenode)
- {
- struct conffile *conff;
- for (conff = pkg->installed.conffiles; conff; conff = conff->next) {
- if (strcmp(conff->name, namenode->name) == 0) {
- debug(dbg_conff, "marking %s conffile %s as obsolete",
- pkg_name(pkg, pnaw_always), conff->name);
- conff->obsolete = true;
- return;
- }
- }
- }
- /**
- * Mark all package conffiles as old.
- *
- * @param pkg The package owning the conffiles.
- */
- void
- pkg_conffiles_mark_old(struct pkginfo *pkg)
- {
- const struct conffile *conff;
- struct filenamenode *namenode;
- for (conff = pkg->installed.conffiles; conff; conff = conff->next) {
- namenode = findnamenode(conff->name, 0); /* XXX */
- namenode->flags |= fnnf_old_conff;
- if (!namenode->oldhash)
- namenode->oldhash = conff->hash;
- debug(dbg_conffdetail, "%s '%s' namenode '%s' flags %o", __func__,
- conff->name, namenode->name, namenode->flags);
- }
- }
- void
- log_action(const char *action, struct pkginfo *pkg, struct pkgbin *pkgbin)
- {
- log_message("%s %s %s %s", action, pkgbin_name(pkg, pkgbin, pnaw_always),
- versiondescribe(&pkg->installed.version, vdew_nonambig),
- versiondescribe(&pkg->available.version, vdew_nonambig));
- statusfd_send("processing: %s: %s", action,
- pkgbin_name(pkg, pkgbin, pnaw_nonambig));
- }
|