예제 #1
0
static void
pkg_disappear(struct pkginfo *pkg, struct pkginfo *infavour)
{
  printf(_("(Noting disappearance of %s, which has been completely replaced.)\n"),
         pkg_name(pkg, pnaw_nonambig));
  log_action("disappear", pkg, &pkg->installed);
  debug(dbg_general, "pkg_disappear disappearing %s",
        pkg_name(pkg, pnaw_nonambig));

  trig_activate_packageprocessing(pkg);
  maintainer_script_installed(pkg, POSTRMFILE,
                              "post-removal script (for disappearance)",
                              "disappear",
                              infavour->set->name,
                              versiondescribe(&infavour->available.version,
                                              vdew_nonambig),
                              NULL);

  /* OK, now we delete all the stuff in the ‘info’ directory .. */
  debug(dbg_general, "pkg_disappear cleaning info directory");
  pkg_infodb_foreach(pkg, &pkg->installed, pkg_infodb_remove_file);
  dir_sync_path(pkgadmindir());

  pkg_set_status(pkg, stat_notinstalled);
  pkg_set_want(pkg, want_unknown);
  pkg_reset_eflags(pkg);

  blankversion(&pkg->configversion);
  pkgbin_blank(&pkg->installed);

  pkg->clientdata->fileslistvalid = false;

  modstatdb_note(pkg);
}
예제 #2
0
파일: help.c 프로젝트: CharizTeam/dpkg
/*
 * 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;
}
예제 #3
0
파일: trigproc.c 프로젝트: nisc-code/dpkg
/*
 * Does cycle checking. Doesn't mind if pkg has no triggers pending - in
 * that case does nothing but fix up any stale awaiters.
 */
void
trigproc(struct pkginfo *pkg)
{
	static struct varbuf namesarg;

	struct trigpend *tp;
	struct pkginfo *gaveup;

	debug(dbg_triggers, "trigproc %s", pkg_name(pkg, pnaw_always));

	if (pkg->clientdata->trigprocdeferred)
		pkg->clientdata->trigprocdeferred->pkg = NULL;
	pkg->clientdata->trigprocdeferred = NULL;

	if (pkg->trigpend_head) {
		assert(pkg->status == stat_triggerspending ||
		       pkg->status == stat_triggersawaited);

		gaveup = check_trigger_cycle(pkg);
		if (gaveup == pkg)
			return;

		printf(_("Processing triggers for %s (%s) ...\n"),
		       pkg_name(pkg, pnaw_nonambig),
		       versiondescribe(&pkg->installed.version, vdew_nonambig));
		log_action("trigproc", pkg, &pkg->installed);

		varbuf_reset(&namesarg);
		for (tp = pkg->trigpend_head; tp; tp = tp->next) {
			varbuf_add_char(&namesarg, ' ');
			varbuf_add_str(&namesarg, tp->name);
		}
		varbuf_end_str(&namesarg);

		/* Setting the status to half-configured
		 * causes modstatdb_note to clear pending triggers. */
		pkg_set_status(pkg, stat_halfconfigured);
		modstatdb_note(pkg);

		if (!f_noact) {
			sincenothing = 0;
			maintscript_postinst(pkg, "triggered",
			                     namesarg.buf + 1, NULL);
		}

		post_postinst_tasks(pkg, stat_installed);
	} else {
		/* In other branch is done by modstatdb_note(), from inside
		 * post_postinst_tasks(). */
		trig_clear_awaiters(pkg);
	}
}
예제 #4
0
파일: errors.c 프로젝트: smcv/dpkg
bool
skip_due_to_hold(struct pkginfo *pkg)
{
  if (pkg->want != PKG_WANT_HOLD)
    return false;
  if (fc_hold) {
    notice(_("package %s was on hold, processing it anyway as you requested"),
           pkg_name(pkg, pnaw_nonambig));
    return false;
  }
  printf(_("Package %s is on hold, not touching it.  Use --force-hold to override.\n"),
         pkg_name(pkg, pnaw_nonambig));
  return true;
}
예제 #5
0
파일: packages.c 프로젝트: guillemj/dpkg
static void
breaks_check_one(struct varbuf *aemsgs, enum dep_check *ok,
                 struct deppossi *breaks, struct pkginfo *broken,
                 struct pkginfo *breaker, struct deppossi *virtbroken)
{
  struct varbuf depmsg = VARBUF_INIT;

  debug(dbg_depcondetail, "      checking breaker %s virtbroken %s",
        pkg_name(breaker, pnaw_always),
        virtbroken ? virtbroken->ed->name : "<none>");

  if (breaker->status == PKG_STAT_NOTINSTALLED ||
      breaker->status == PKG_STAT_CONFIGFILES)
    return;
  if (broken == breaker) return;
  if (!versionsatisfied(&broken->installed, breaks)) return;
  /* The test below can only trigger if dep_breaks start having
   * arch qualifiers different from “any”. */
  if (!archsatisfied(&broken->installed, breaks))
    return;
  if (ignore_depends(breaker)) return;
  if (virtbroken && ignore_depends(&virtbroken->ed->pkg))
    return;
  if (virtbroken && !pkg_virtual_deppossi_satisfied(breaks, virtbroken))
    return;

  varbufdependency(&depmsg, breaks->up);
  varbuf_end_str(&depmsg);
  varbuf_printf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"),
                pkg_name(breaker, pnaw_nonambig),
                versiondescribe(&breaker->installed.version, vdew_nonambig),
                depmsg.buf, gettext(statusstrings[breaker->status]));
  varbuf_destroy(&depmsg);

  if (virtbroken) {
    varbuf_printf(aemsgs, _("  %s (%s) provides %s.\n"),
                  pkg_name(broken, pnaw_nonambig),
                  versiondescribe(&broken->installed.version, vdew_nonambig),
                  virtbroken->ed->name);
  } else if (breaks->verrel != DPKG_RELATION_NONE) {
    varbuf_printf(aemsgs, _("  Version of %s to be configured is %s.\n"),
                  pkg_name(broken, pnaw_nonambig),
                  versiondescribe(&broken->installed.version, vdew_nonambig));
    if (in_force(FORCE_DEPENDS_VERSION))
      return;
  }
  if (force_breaks(breaks)) return;
  *ok = DEP_CHECK_HALT;
}
예제 #6
0
파일: triglib.c 프로젝트: guillemj/dpkg
void
trig_clear_awaiters(struct pkginfo *notpend)
{
	struct trigaw *ta;
	struct pkginfo *aw;

	if (notpend->trigpend_head)
		internerr("package %s has pending triggers",
		          pkg_name(notpend, pnaw_always));

	ta = notpend->othertrigaw_head;
	notpend->othertrigaw_head = NULL;
	for (; ta; ta = ta->samepend_next) {
		aw = ta->aw;
		if (!aw)
			continue;
		LIST_UNLINK_PART(aw->trigaw, ta, sameaw);
		if (!aw->trigaw.head && aw->status == PKG_STAT_TRIGGERSAWAITED) {
			if (aw->trigpend_head)
				pkg_set_status(aw, PKG_STAT_TRIGGERSPENDING);
			else
				pkg_set_status(aw, PKG_STAT_INSTALLED);
			modstatdb_note(aw);
		}
	}
}
예제 #7
0
/*
 * conflictor may be NULL.
 */
void cu_prermdeconfigure(int argc, void **argv) {
  struct pkginfo *deconf= (struct pkginfo*)argv[0];
  struct pkginfo *conflictor = (struct pkginfo *)argv[1];
  struct pkginfo *infavour= (struct pkginfo*)argv[2];

  if (conflictor) {
    maintainer_script_postinst(deconf, "abort-deconfigure",
                               "in-favour",
                               pkgbin_name(infavour, &infavour->available,
                                           pnaw_nonambig),
                               versiondescribe(&infavour->available.version,
                                               vdew_nonambig),
                               "removing",
                               pkg_name(conflictor, pnaw_nonambig),
                               versiondescribe(&conflictor->installed.version,
                                               vdew_nonambig),
                               NULL);
  } else {
    maintainer_script_postinst(deconf, "abort-deconfigure",
                               "in-favour",
                               pkgbin_name(infavour, &infavour->available,
                                           pnaw_nonambig),
                               versiondescribe(&infavour->available.version,
                                               vdew_nonambig),
                               NULL);
  }

  post_postinst_tasks(deconf, stat_installed);
}
예제 #8
0
파일: help.c 프로젝트: CharizTeam/dpkg
/*
 * 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;
}
예제 #9
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
void
trigproc_run_deferred(void)
{
	jmp_buf ejbuf;

	debug(dbg_triggers, "trigproc_run_deferred");
	while (!pkg_queue_is_empty(&deferred)) {
		struct pkginfo *pkg;

		pkg  = pkg_queue_pop(&deferred);
		if (!pkg)
			continue;

		if (setjmp(ejbuf)) {
			pop_error_context(ehflag_bombout);
			continue;
		}
		push_error_context_jump(&ejbuf, print_error_perpackage,
		                        pkg_name(pkg, pnaw_nonambig));

		pkg->clientdata->trigprocdeferred = NULL;
		trigproc(pkg, TRIGPROC_TRY);

		pop_error_context(ehflag_normaltidy);
	}
}
예제 #10
0
파일: trigcmd.c 프로젝트: smcv/dpkg
static const char *
parse_awaiter_package(void)
{
	struct dpkg_error err = DPKG_ERROR_INIT;
	struct pkginfo *pkg;

	if (!f_await)
		bypackage = "-";

	if (bypackage == NULL) {
		const char *pkgname, *archname;

		pkgname = getenv("DPKG_MAINTSCRIPT_PACKAGE");
		archname = getenv("DPKG_MAINTSCRIPT_ARCH");
		if (pkgname == NULL || archname == NULL)
			ohshit(_("must be called from a maintainer script"
			         " (or with a --by-package option)"));

		pkg = pkg_spec_find_pkg(pkgname, archname, &err);
	} else if (strcmp(bypackage, "-") == 0) {
		pkg = NULL;
	} else {
		pkg = pkg_spec_parse_pkg(bypackage, &err);
	}

	/* Normalize the bypackage name if there was no error. */
	if (pkg)
		bypackage = pkg_name(pkg, pnaw_nonambig);

	return err.str;
}
예제 #11
0
파일: packages.c 프로젝트: nisc-code/dpkg
static void
breaks_check_one(struct varbuf *aemsgs, enum dep_check *ok,
                 struct deppossi *breaks, struct pkginfo *broken,
                 struct pkginfo *breaker, struct pkgset *virtbroken)
{
  struct varbuf depmsg = VARBUF_INIT;

  debug(dbg_depcondetail, "      checking breaker %s virtbroken %s",
        pkg_name(breaker, pnaw_always),
        virtbroken ? virtbroken->name : "<none>");

  if (breaker->status == stat_notinstalled ||
      breaker->status == stat_configfiles) return;
  if (broken == breaker) return;
  if (!versionsatisfied(&broken->installed, breaks)) return;
  /* The test below can only trigger if dep_breaks start having
   * arch qualifiers different from “any”. */
  if (!archsatisfied(&broken->installed, breaks))
    return;
  if (ignore_depends(breaker)) return;
  if (virtbroken && ignore_depends(&virtbroken->pkg))
    return;

  varbufdependency(&depmsg, breaks->up);
  varbuf_end_str(&depmsg);
  varbuf_printf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"),
                pkg_name(breaker, pnaw_nonambig),
                versiondescribe(&breaker->installed.version, vdew_nonambig),
                depmsg.buf, gettext(statusstrings[breaker->status]));
  varbuf_destroy(&depmsg);

  if (virtbroken) {
    varbuf_printf(aemsgs, _("  %s (%s) provides %s.\n"),
                  pkg_name(broken, pnaw_nonambig),
                  versiondescribe(&broken->installed.version, vdew_nonambig),
                  virtbroken->name);
  } else if (breaks->verrel != dpkg_relation_none) {
    varbuf_printf(aemsgs, _("  Version of %s to be configured is %s.\n"),
                  pkg_name(broken, pnaw_nonambig),
                  versiondescribe(&broken->installed.version, vdew_nonambig));
    if (fc_dependsversion) return;
  }
  if (force_breaks(breaks)) return;
  *ok = dep_check_halt;
}
예제 #12
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
/*
 * Called by modstatdb_note.
 */
void
trig_activate_packageprocessing(struct pkginfo *pkg)
{
	debug(dbg_triggersdetail, "trigproc_activate_packageprocessing pkg=%s",
	      pkg_name(pkg, pnaw_always));

	trig_parse_ci(pkg_infodb_get_file(pkg, &pkg->installed, TRIGGERSCIFILE),
	              NULL, trig_cicb_statuschange_activate,
	              pkg, &pkg->installed);
}
예제 #13
0
static struct pkginfo *
pkg_array_mapper(const char *name)
{
  struct pkginfo *pkg;

  pkg = dpkg_options_parse_pkgname(cipaction, name);
  if (pkg->status == PKG_STAT_NOTINSTALLED)
    notice(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));

  return pkg;
}
예제 #14
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
static bool
tortoise_not_in_hare(struct pkginfo *processing_now,
                     struct trigcycleperpkg *tortoise_pkg)
{
	const char *processing_now_name, *tortoise_name;
	struct trigpend *hare_trig, *tortoise_trig;

	processing_now_name = pkg_name(processing_now, pnaw_nonambig);
	tortoise_name = pkg_name(tortoise_pkg->pkg, pnaw_nonambig);

	debug(dbg_triggersdetail, "%s pnow=%s tortoise=%s", __func__,
	      processing_now_name, tortoise_name);
	for (tortoise_trig = tortoise_pkg->then_trigs;
	     tortoise_trig;
	     tortoise_trig = tortoise_trig->next) {
		debug(dbg_triggersdetail,
		      "%s pnow=%s tortoise=%s tortoisetrig=%s", __func__,
		      processing_now_name, tortoise_name, tortoise_trig->name);

		/* hare is now so we can just look up in the actual data. */
		for (hare_trig = tortoise_pkg->pkg->trigpend_head;
		     hare_trig;
		     hare_trig = hare_trig->next) {
			debug(dbg_triggersstupid, "%s pnow=%s tortoise=%s"
			      " tortoisetrig=%s haretrig=%s", __func__,
			      processing_now_name, tortoise_name,
			      tortoise_trig->name, hare_trig->name);
			if (strcmp(hare_trig->name, tortoise_trig->name) == 0)
				break;
		}

		if (hare_trig == NULL) {
			/* Not found in hare, yay! */
			debug(dbg_triggersdetail, "%s pnow=%s tortoise=%s OK",
			      __func__, processing_now_name, tortoise_name);
			return true;
		}
	}

	return false;
}
예제 #15
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
static void
trigproc_enqueue_deferred(struct pkginfo *pend)
{
	if (f_triggers < 0)
		return;
	ensure_package_clientdata(pend);
	if (pend->clientdata->trigprocdeferred)
		return;
	pend->clientdata->trigprocdeferred = pkg_queue_push(&deferred, pend);
	debug(dbg_triggers, "trigproc_enqueue_deferred pend=%s",
	      pkg_name(pend, pnaw_always));
}
예제 #16
0
static void describebriefly(struct pkginfo *pkg) {
  int maxl, l;
  const char *pdesc;

  maxl= 57;
  l= strlen(pkg->set->name);
  if (l>20) maxl -= (l-20);

  pdesc = pkgbin_summary(pkg, &pkg->installed, &l);
  l = min(l, maxl);

  printf(" %-20s %.*s\n", pkg_name(pkg, pnaw_nonambig), l, pdesc);
}
예제 #17
0
파일: select.c 프로젝트: nisc-code/dpkg
static void getsel1package(struct pkginfo *pkg) {
  const char *pkgname;
  int l;

  if (pkg->want == want_unknown) return;
  pkgname = pkg_name(pkg, pnaw_nonambig);
  l = strlen(pkgname);
  l >>= 3;
  l = 6 - l;
  if (l < 1)
    l = 1;
  printf("%s%.*s%s\n", pkgname, l, "\t\t\t\t\t\t", wantinfos[pkg->want].name);
}
예제 #18
0
파일: help.c 프로젝트: CharizTeam/dpkg
/*
 * 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;
}
예제 #19
0
/*
 * Note: If anyone wants to set some triggers-pending, they must also
 * set status appropriately, or we will undo it. That is, it is legal
 * to call this when pkg->status and pkg->trigpend_head disagree and
 * in that case pkg->status takes precedence and pkg->trigpend_head
 * will be adjusted.
 */
void modstatdb_note(struct pkginfo *pkg) {
    struct trigaw *ta;

    onerr_abort++;

    /* Clear pending triggers here so that only code that sets the status
     * to interesting (for triggers) values has to care about triggers. */
    if (pkg->status != stat_triggerspending &&
            pkg->status != stat_triggersawaited)
        pkg->trigpend_head = NULL;

    if (pkg->status <= stat_configfiles) {
        for (ta = pkg->trigaw.head; ta; ta = ta->sameaw.next)
            ta->aw = NULL;
        pkg->trigaw.head = pkg->trigaw.tail = NULL;
    }

    log_message("status %s %s %s", statusinfos[pkg->status].name,
                pkg_name(pkg, pnaw_always),
                versiondescribe(&pkg->installed.version, vdew_nonambig));
    statusfd_send("status: %s: %s", pkg_name(pkg, pnaw_nonambig),
                  statusinfos[pkg->status].name);

    if (cstatus >= msdbrw_write)
        modstatdb_note_core(pkg);

    if (!pkg->trigpend_head && pkg->othertrigaw_head) {
        /* Automatically remove us from other packages' Triggers-Awaited.
         * We do this last because we want to maximize our chances of
         * successfully recording the status of the package we were
         * pointed at by our caller, although there is some risk of
         * leaving us in a slightly odd situation which is cleared up
         * by the trigger handling logic in deppossi_ok_found. */
        trig_clear_awaiters(pkg);
    }

    onerr_abort--;
}
예제 #20
0
파일: select.c 프로젝트: smcv/dpkg
static void getsel1package(struct pkginfo *pkg) {
  const char *pkgname;
  int l;

  if (pkg->want == PKG_WANT_UNKNOWN)
    return;
  pkgname = pkg_name(pkg, pnaw_nonambig);
  l = strlen(pkgname);
  l >>= 3;
  l = 6 - l;
  if (l < 1)
    l = 1;
  printf("%s%.*s%s\n", pkgname, l, "\t\t\t\t\t\t", pkg_want_name(pkg));
}
예제 #21
0
파일: help.c 프로젝트: CharizTeam/dpkg
/**
 * 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;
    }
  }
}
예제 #22
0
파일: depcon.c 프로젝트: CharizTeam/dpkg
static bool
foundcyclebroken(struct cyclesofarlink *thislink, struct cyclesofarlink *sofar,
                 struct pkginfo *dependedon, struct deppossi *possi)
{
  struct cyclesofarlink *sol;

  if(!possi)
    return false;

  /* We're investigating the dependency ‘possi’ to see if it
   * is part of a loop. To this end we look to see whether the
   * depended-on package is already one of the packages whose
   * dependencies we're searching. */
  for (sol = sofar; sol && sol->pkg != dependedon; sol = sol->prev);

  /* If not, we do a recursive search on it to see what we find. */
  if (!sol)
    return findbreakcyclerecursive(dependedon, thislink);

  debug(dbg_depcon,"found cycle");
  /* Right, we now break one of the links. We prefer to break
   * a dependency of a package without a postinst script, as
   * this is a null operation. If this is not possible we break
   * the other link in the recursive calling tree which mentions
   * this package (this being the first package involved in the
   * cycle). It doesn't particularly matter which we pick, but if
   * we break the earliest dependency we came across we may be
   * able to do something straight away when findbreakcycle returns. */
  sofar= thislink;
  for (sol = sofar; !(sol != sofar && sol->pkg == dependedon); sol = sol->prev) {
    if (!pkg_infodb_has_file(sol->pkg, &sol->pkg->installed, POSTINSTFILE))
      break;
  }

  /* Now we have either a package with no postinst, or the other
   * occurrence of the current package in the list. */
  sol->possi->cyclebreak = true;

  debug(dbg_depcon, "cycle broken at %s -> %s",
        pkg_name(sol->possi->up->up, pnaw_always), sol->possi->ed->name);

  return true;
}
예제 #23
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
/*
 * cstatus might be msdbrw_readonly if we're in --no-act mode, in which
 * case we don't write out all of the interest files etc. but we do
 * invent all of the activations for our own benefit.
 */
static void
trig_transitional_activate(enum modstatdb_rw cstatus)
{
	struct pkgiterator *iter;
	struct pkginfo *pkg;

	iter = pkg_db_iter_new();
	while ((pkg = pkg_db_iter_next_pkg(iter))) {
		if (pkg->status <= PKG_STAT_HALFINSTALLED)
			continue;
		debug(dbg_triggersdetail, "trig_transitional_activate %s %s",
		      pkg_name(pkg, pnaw_always),
		      pkg_status_name(pkg));
		pkg->trigpend_head = NULL;
		trig_parse_ci(pkg_infodb_get_file(pkg, &pkg->installed,
		                                  TRIGGERSCIFILE),
		              cstatus >= msdbrw_write ?
		              transitional_interest_callback :
		              transitional_interest_callback_ro, NULL,
		              pkg, &pkg->installed);
		/* Ensure we're not creating incoherent data that can't
		 * be written down. This should never happen in theory but
		 * can happen if you restore an old status file that is
		 * not in sync with the infodb files. */
		if (pkg->status < PKG_STAT_TRIGGERSAWAITED)
			continue;

		if (pkg->trigaw.head)
			pkg_set_status(pkg, PKG_STAT_TRIGGERSAWAITED);
		else if (pkg->trigpend_head)
			pkg_set_status(pkg, PKG_STAT_TRIGGERSPENDING);
		else
			pkg_set_status(pkg, PKG_STAT_INSTALLED);
	}
	pkg_db_iter_free(iter);

	if (cstatus >= msdbrw_write) {
		modstatdb_checkpoint();
		trig_file_interests_save();
	}
}
예제 #24
0
파일: pkg_elf.c 프로젝트: varju/pkgng
/* ARGSUSED */
static int
add_shlibs_to_pkg(__unused void *actdata, struct pkg *pkg, const char *fpath,
		  const char *name, bool is_shlib)
{
	switch(filter_system_shlibs(name, NULL, 0)) {
	case EPKG_OK:		/* A non-system library */
		pkg_addshlib_required(pkg, name);
		return (EPKG_OK);
	case EPKG_END:		/* A system library */
		return (EPKG_OK);
	default:
		/* Ignore link resolution errors if we're analysing a
		   shared library. */
		if (is_shlib)
			return (EPKG_OK);

		warnx("(%s-%s) %s - shared library %s not found",
		      pkg_name(pkg), pkg_version(pkg), fpath, name);
		return (EPKG_FATAL);
	}
}
예제 #25
0
파일: verify.c 프로젝트: mwhudson/dpkg
int
verify(const char *const *argv)
{
	struct pkginfo *pkg;
	int rc = 0;

	modstatdb_open(msdbrw_readonly);
	ensure_diversions();

	if (!*argv) {
		struct pkgiterator *it;

		it = pkg_db_iter_new();
		while ((pkg = pkg_db_iter_next_pkg(it)))
			verify_package(pkg);
		pkg_db_iter_free(it);
	} else {
		const char *thisarg;

		while ((thisarg = *argv++)) {
			pkg = dpkg_options_parse_pkgname(cipaction, thisarg);
			if (pkg->status == PKG_STAT_NOTINSTALLED) {
				notice(_("package '%s' is not installed"),
				       pkg_name(pkg, pnaw_nonambig));
				rc = 1;
				continue;
			}

			verify_package(pkg);
		}
	}

	modstatdb_shutdown();

	m_output(stdout, _("<standard output>"));

	return rc;
}
예제 #26
0
파일: depcon.c 프로젝트: CharizTeam/dpkg
void describedepcon(struct varbuf *addto, struct dependency *dep) {
  const char *fmt;
  struct varbuf depstr = VARBUF_INIT;

  switch (dep->type) {
  case dep_depends:
    fmt = _("%s depends on %s");
    break;
  case dep_predepends:
    fmt = _("%s pre-depends on %s");
    break;
  case dep_recommends:
    fmt = _("%s recommends %s");
    break;
  case dep_suggests:
    fmt = _("%s suggests %s");
    break;
  case dep_breaks:
    fmt = _("%s breaks %s");
    break;
  case dep_conflicts:
    fmt = _("%s conflicts with %s");
    break;
  case dep_enhances:
    fmt = _("%s enhances %s");
    break;
  default:
    internerr("unknown deptype '%d'", dep->type);
  }

  varbufdependency(&depstr, dep);
  varbuf_end_str(&depstr);

  varbuf_printf(addto, fmt, pkg_name(dep->up, pnaw_nonambig), depstr.buf);
  varbuf_destroy(&depstr);
}
예제 #27
0
static void
modstatdb_note_core(struct pkginfo *pkg)
{
    assert(cstatus >= msdbrw_write);

    varbuf_reset(&uvb);
    varbufrecord(&uvb, pkg, &pkg->installed);

    if (fwrite(uvb.buf, 1, uvb.used, importanttmp) != uvb.used)
        ohshite(_("unable to write updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));
    if (fflush(importanttmp))
        ohshite(_("unable to flush updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));
    if (ftruncate(fileno(importanttmp), uvb.used))
        ohshite(_("unable to truncate for updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));
    if (fsync(fileno(importanttmp)))
        ohshite(_("unable to fsync updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));
    if (fclose(importanttmp))
        ohshite(_("unable to close updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));
    sprintf(updatefnrest, IMPORTANTFMT, nextupdate);
    if (rename(importanttmpfile, updatefnbuf))
        ohshite(_("unable to install updated status of `%.250s'"),
                pkg_name(pkg, pnaw_nonambig));

    dir_sync_path(updatesdir);

    /* Have we made a real mess? */
    assert(strlen(updatefnrest) <= IMPORTANTMAXLEN);

    nextupdate++;

    if (nextupdate > MAXUPDATES) {
        modstatdb_checkpoint();
        nextupdate = 0;
    }

    createimptmp();
}
예제 #28
0
파일: trigproc.c 프로젝트: CharizTeam/dpkg
/*
 * Does cycle checking. Doesn't mind if pkg has no triggers pending - in
 * that case does nothing but fix up any stale awaiters.
 */
void
trigproc(struct pkginfo *pkg, enum trigproc_type type)
{
	static struct varbuf namesarg;

	struct varbuf depwhynot = VARBUF_INIT;
	struct trigpend *tp;
	struct pkginfo *gaveup;

	debug(dbg_triggers, "trigproc %s", pkg_name(pkg, pnaw_always));

	if (pkg->clientdata->trigprocdeferred)
		pkg->clientdata->trigprocdeferred->pkg = NULL;
	pkg->clientdata->trigprocdeferred = NULL;

	if (pkg->trigpend_head) {
		enum dep_check ok;

		assert(pkg->status == PKG_STAT_TRIGGERSPENDING ||
		       pkg->status == PKG_STAT_TRIGGERSAWAITED);

		if (dependtry > 1) {
			gaveup = check_trigger_cycle(pkg);
			if (gaveup == pkg)
				return;

			if (findbreakcycle(pkg))
				sincenothing = 0;
		}

		ok = dependencies_ok(pkg, NULL, &depwhynot);
		if (ok == DEP_CHECK_DEFER) {
			varbuf_destroy(&depwhynot);
			enqueue_package(pkg);
			return;
		} else if (ok == DEP_CHECK_HALT) {
			/* We cannot process this package on this dpkg run,
			 * and we can get here repeatedly if this package is
			 * required to make progress for other packages. So
			 * reset the trigger cycles tracking to avoid bogus
			 * cycle detections. */
			trigproc_reset_cycle();

			/* When doing opportunistic trigger processig, nothing
			 * requires us to be able to make progress; skip the
			 * package and silently ignore the error due to
			 * unsatisfiable dependencies. */
			if (type == TRIGPROC_TRY) {
				varbuf_destroy(&depwhynot);
				return;
			}

			sincenothing = 0;
			varbuf_end_str(&depwhynot);
			notice(_("dependency problems prevent processing "
			         "triggers for %s:\n%s"),
			       pkg_name(pkg, pnaw_nonambig), depwhynot.buf);
			varbuf_destroy(&depwhynot);
			ohshit(_("dependency problems - leaving triggers unprocessed"));
		} else if (depwhynot.used) {
			varbuf_end_str(&depwhynot);
			notice(_("%s: dependency problems, but processing "
			         "triggers anyway as you requested:\n%s"),
			       pkg_name(pkg, pnaw_nonambig), depwhynot.buf);
			varbuf_destroy(&depwhynot);
		}

		if (dependtry <= 1) {
			gaveup = check_trigger_cycle(pkg);
			if (gaveup == pkg)
				return;
		}

		printf(_("Processing triggers for %s (%s) ...\n"),
		       pkg_name(pkg, pnaw_nonambig),
		       versiondescribe(&pkg->installed.version, vdew_nonambig));
		log_action("trigproc", pkg, &pkg->installed);

		varbuf_reset(&namesarg);
		for (tp = pkg->trigpend_head; tp; tp = tp->next) {
			varbuf_add_char(&namesarg, ' ');
			varbuf_add_str(&namesarg, tp->name);
		}
		varbuf_end_str(&namesarg);

		/* Setting the status to half-configured
		 * causes modstatdb_note to clear pending triggers. */
		pkg_set_status(pkg, PKG_STAT_HALFCONFIGURED);
		modstatdb_note(pkg);

		if (!f_noact) {
			sincenothing = 0;
			maintscript_postinst(pkg, "triggered",
			                     namesarg.buf + 1, NULL);
		}

		post_postinst_tasks(pkg, PKG_STAT_INSTALLED);
	} else {
		/* In other branch is done by modstatdb_note(), from inside
		 * post_postinst_tasks(). */
		trig_clear_awaiters(pkg);
	}
}
예제 #29
0
파일: depcon.c 프로젝트: CharizTeam/dpkg
/*
 * *whynot must already have been initialized; it need not be
 * empty though - it will be reset before use.
 *
 * If depisok returns false for ‘not OK’ it will contain a description,
 * newline-terminated BUT NOT NUL-TERMINATED, of the reason.
 *
 * If depisok returns true it will contain garbage.
 * allowunconfigd should be non-zero during the ‘Pre-Depends’ checking
 * before a package is unpacked, when it is sufficient for the package
 * to be unpacked provided that both the unpacked and previously-configured
 * versions are acceptable.
 *
 * On false return (‘not OK’), *canfixbyremove refers to a package which
 * if removed (dep_conflicts) or deconfigured (dep_breaks) will fix
 * the problem. Caller may pass NULL for canfixbyremove and need not
 * initialize *canfixbyremove.
 *
 * On false return (‘not OK’), *canfixbytrigaw refers to a package which
 * can fix the problem if all the packages listed in Triggers-Awaited have
 * their triggers processed. Caller may pass NULL for canfixbytrigaw and
 * need not initialize *canfixbytrigaw.
 */
bool
depisok(struct dependency *dep, struct varbuf *whynot,
        struct pkginfo **canfixbyremove, struct pkginfo **canfixbytrigaw,
        bool allowunconfigd)
{
  struct deppossi *possi;
  struct deppossi *provider;
  struct pkginfo *pkg_pos;
  int nconflicts;

  /* Use this buffer so that when internationalisation comes along we
   * don't have to rewrite the code completely, only redo the sprintf strings
   * (assuming we have the fancy argument-number-specifiers).
   * Allow 250x3 for package names, versions, &c, + 250 for ourselves. */
  char linebuf[1024];

  assert(dep->type == dep_depends || dep->type == dep_predepends ||
	 dep->type == dep_breaks || dep->type == dep_conflicts ||
	 dep->type == dep_recommends || dep->type == dep_suggests ||
	 dep->type == dep_enhances);

  if (canfixbyremove)
    *canfixbyremove = NULL;
  if (canfixbytrigaw)
    *canfixbytrigaw = NULL;

  /* The dependency is always OK if we're trying to remove the depend*ing*
   * package. */
  switch (dep->up->clientdata->istobe) {
  case PKG_ISTOBE_REMOVE:
  case PKG_ISTOBE_DECONFIGURE:
    return true;
  case PKG_ISTOBE_NORMAL:
    /* Only installed packages can be make dependency problems. */
    switch (dep->up->status) {
    case PKG_STAT_INSTALLED:
    case PKG_STAT_TRIGGERSPENDING:
    case PKG_STAT_TRIGGERSAWAITED:
      break;
    case PKG_STAT_HALFCONFIGURED:
    case PKG_STAT_UNPACKED:
    case PKG_STAT_HALFINSTALLED:
      if (dep->type == dep_predepends ||
          dep->type == dep_conflicts ||
          dep->type == dep_breaks)
        break;
      /* Fall through. */
    case PKG_STAT_CONFIGFILES:
    case PKG_STAT_NOTINSTALLED:
      return true;
    default:
      internerr("unknown status depending '%d'", dep->up->status);
    }
    break;
  case PKG_ISTOBE_INSTALLNEW:
  case PKG_ISTOBE_PREINSTALL:
    break;
  default:
    internerr("unknown istobe depending '%d'", dep->up->clientdata->istobe);
  }

  /* Describe the dependency, in case we have to moan about it. */
  varbuf_reset(whynot);
  varbuf_add_char(whynot, ' ');
  describedepcon(whynot, dep);
  varbuf_add_char(whynot, '\n');

  /* TODO: Check dep_enhances as well. */
  if (dep->type == dep_depends || dep->type == dep_predepends ||
      dep->type == dep_recommends || dep->type == dep_suggests ) {
    /* Go through the alternatives. As soon as we find one that
     * we like, we return ‘true’ straight away. Otherwise, when we get to
     * the end we'll have accumulated all the reasons in whynot and
     * can return ‘false’. */

    for (possi= dep->list; possi; possi= possi->next) {
      struct deppossi_pkg_iterator *possi_iter;

      possi_iter = deppossi_pkg_iter_new(possi, wpb_by_istobe);
      while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) {
        switch (pkg_pos->clientdata->istobe) {
        case PKG_ISTOBE_REMOVE:
          sprintf(linebuf, _("  %.250s is to be removed.\n"),
                  pkg_name(pkg_pos, pnaw_nonambig));
          break;
        case PKG_ISTOBE_DECONFIGURE:
          sprintf(linebuf, _("  %.250s is to be deconfigured.\n"),
                  pkg_name(pkg_pos, pnaw_nonambig));
          break;
        case PKG_ISTOBE_INSTALLNEW:
          if (versionsatisfied(&pkg_pos->available, possi)) {
            deppossi_pkg_iter_free(possi_iter);
            return true;
          }
          sprintf(linebuf, _("  %.250s is to be installed, but is version "
                             "%.250s.\n"),
                  pkgbin_name(pkg_pos, &pkg_pos->available, pnaw_nonambig),
                  versiondescribe(&pkg_pos->available.version, vdew_nonambig));
          break;
        case PKG_ISTOBE_NORMAL:
        case PKG_ISTOBE_PREINSTALL:
          switch (pkg_pos->status) {
          case PKG_STAT_INSTALLED:
          case PKG_STAT_TRIGGERSPENDING:
            if (versionsatisfied(&pkg_pos->installed, possi)) {
              deppossi_pkg_iter_free(possi_iter);
              return true;
            }
            sprintf(linebuf, _("  %.250s is installed, but is version "
                               "%.250s.\n"),
                    pkg_name(pkg_pos, pnaw_nonambig),
                    versiondescribe(&pkg_pos->installed.version, vdew_nonambig));
            break;
          case PKG_STAT_NOTINSTALLED:
            /* Don't say anything about this yet - it might be a virtual package.
             * Later on, if nothing has put anything in linebuf, we know that it
             * isn't and issue a diagnostic then. */
            *linebuf = '\0';
            break;
          case PKG_STAT_TRIGGERSAWAITED:
              if (canfixbytrigaw && versionsatisfied(&pkg_pos->installed, possi))
                *canfixbytrigaw = pkg_pos;
              /* Fall through to have a chance to return OK due to
               * allowunconfigd and to fill the explanation */
          case PKG_STAT_UNPACKED:
          case PKG_STAT_HALFCONFIGURED:
            if (allowunconfigd) {
              if (!dpkg_version_is_informative(&pkg_pos->configversion)) {
                sprintf(linebuf, _("  %.250s is unpacked, but has never been "
                                   "configured.\n"),
                        pkg_name(pkg_pos, pnaw_nonambig));
                break;
              } else if (!versionsatisfied(&pkg_pos->installed, possi)) {
                sprintf(linebuf, _("  %.250s is unpacked, but is version "
                                   "%.250s.\n"),
                        pkg_name(pkg_pos, pnaw_nonambig),
                        versiondescribe(&pkg_pos->installed.version,
                                        vdew_nonambig));
                break;
              } else if (!dpkg_version_relate(&pkg_pos->configversion,
                                              possi->verrel,
                                              &possi->version)) {
                sprintf(linebuf, _("  %.250s latest configured version is "
                                   "%.250s.\n"),
                        pkg_name(pkg_pos, pnaw_nonambig),
                        versiondescribe(&pkg_pos->configversion, vdew_nonambig));
                break;
              } else {
                deppossi_pkg_iter_free(possi_iter);
                return true;
              }
            }
            /* Fall through. */
          default:
            sprintf(linebuf, _("  %.250s is %s.\n"),
                    pkg_name(pkg_pos, pnaw_nonambig),
                    gettext(statusstrings[pkg_pos->status]));
            break;
          }
          break;
        default:
          internerr("unknown istobe depended '%d'", pkg_pos->clientdata->istobe);
        }
        varbuf_add_str(whynot, linebuf);
      }
      deppossi_pkg_iter_free(possi_iter);

        /* See if the package we're about to install Provides it. */
        for (provider = possi->ed->depended.available;
             provider;
             provider = provider->rev_next) {
          if (provider->up->type != dep_provides) continue;
          if (!pkg_virtual_deppossi_satisfied(possi, provider))
            continue;
          if (provider->up->up->clientdata->istobe == PKG_ISTOBE_INSTALLNEW)
            return true;
        }

        /* Now look at the packages already on the system. */
        for (provider = possi->ed->depended.installed;
             provider;
             provider = provider->rev_next) {
          if (provider->up->type != dep_provides) continue;
          if (!pkg_virtual_deppossi_satisfied(possi, provider))
            continue;

          switch (provider->up->up->clientdata->istobe) {
          case PKG_ISTOBE_INSTALLNEW:
            /* Don't pay any attention to the Provides field of the
             * currently-installed version of the package we're trying
             * to install. We dealt with that by using the available
             * information above. */
            continue;
          case PKG_ISTOBE_REMOVE:
            sprintf(linebuf, _("  %.250s provides %.250s but is to be removed.\n"),
                    pkg_name(provider->up->up, pnaw_nonambig),
                    possi->ed->name);
            break;
          case PKG_ISTOBE_DECONFIGURE:
            sprintf(linebuf, _("  %.250s provides %.250s but is to be deconfigured.\n"),
                    pkg_name(provider->up->up, pnaw_nonambig),
                    possi->ed->name);
            break;
          case PKG_ISTOBE_NORMAL:
          case PKG_ISTOBE_PREINSTALL:
            if (provider->up->up->status == PKG_STAT_INSTALLED ||
                provider->up->up->status == PKG_STAT_TRIGGERSPENDING)
              return true;
            if (provider->up->up->status == PKG_STAT_TRIGGERSAWAITED)
              *canfixbytrigaw = provider->up->up;
            sprintf(linebuf, _("  %.250s provides %.250s but is %s.\n"),
                    pkg_name(provider->up->up, pnaw_nonambig),
                    possi->ed->name,
                    gettext(statusstrings[provider->up->up->status]));
            break;
          default:
            internerr("unknown istobe provider '%d'",
                      provider->up->up->clientdata->istobe);
          }
          varbuf_add_str(whynot, linebuf);
        }

        if (!*linebuf) {
          /* If the package wasn't installed at all, and we haven't said
           * yet why this isn't satisfied, we should say so now. */
          sprintf(linebuf, _("  %.250s is not installed.\n"), possi->ed->name);
          varbuf_add_str(whynot, linebuf);
        }
    }

    return false;
  } else {
    /* It's conflicts or breaks. There's only one main alternative,
     * but we also have to consider Providers. We return ‘false’ as soon
     * as we find something that matches the conflict, and only describe
     * it then. If we get to the end without finding anything we return
     * ‘true’. */

    possi= dep->list;
    nconflicts= 0;

    if (possi->ed != possi->up->up->set) {
      struct deppossi_pkg_iterator *possi_iter;

      /* If the package conflicts with or breaks itself it must mean
       * other packages which provide the same virtual name. We
       * therefore don't look at the real package and go on to the
       * virtual ones. */

      possi_iter = deppossi_pkg_iter_new(possi, wpb_by_istobe);
      while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) {
        switch (pkg_pos->clientdata->istobe) {
        case PKG_ISTOBE_REMOVE:
          break;
        case PKG_ISTOBE_INSTALLNEW:
          if (!versionsatisfied(&pkg_pos->available, possi))
            break;
          sprintf(linebuf, _("  %.250s (version %.250s) is to be installed.\n"),
                  pkgbin_name(pkg_pos, &pkg_pos->available, pnaw_nonambig),
                  versiondescribe(&pkg_pos->available.version, vdew_nonambig));
          varbuf_add_str(whynot, linebuf);
          if (!canfixbyremove) {
            deppossi_pkg_iter_free(possi_iter);
            return false;
          }
          nconflicts++;
          *canfixbyremove = pkg_pos;
          break;
        case PKG_ISTOBE_DECONFIGURE:
          if (dep->type == dep_breaks)
            break; /* Already deconfiguring this. */
          /* Fall through. */
        case PKG_ISTOBE_NORMAL:
        case PKG_ISTOBE_PREINSTALL:
          switch (pkg_pos->status) {
          case PKG_STAT_NOTINSTALLED:
          case PKG_STAT_CONFIGFILES:
            break;
          case PKG_STAT_HALFINSTALLED:
          case PKG_STAT_UNPACKED:
          case PKG_STAT_HALFCONFIGURED:
            if (dep->type == dep_breaks)
              break; /* No problem. */
          case PKG_STAT_INSTALLED:
          case PKG_STAT_TRIGGERSPENDING:
          case PKG_STAT_TRIGGERSAWAITED:
            if (!versionsatisfied(&pkg_pos->installed, possi))
              break;
            sprintf(linebuf, _("  %.250s (version %.250s) is present and %s.\n"),
                    pkg_name(pkg_pos, pnaw_nonambig),
                    versiondescribe(&pkg_pos->installed.version, vdew_nonambig),
                    gettext(statusstrings[pkg_pos->status]));
            varbuf_add_str(whynot, linebuf);
            if (!canfixbyremove) {
              deppossi_pkg_iter_free(possi_iter);
              return false;
            }
            nconflicts++;
            *canfixbyremove = pkg_pos;
          }
          break;
        default:
          internerr("unknown istobe conflict '%d'", pkg_pos->clientdata->istobe);
        }
      }
      deppossi_pkg_iter_free(possi_iter);
    }

      /* See if the package we're about to install Provides it. */
      for (provider = possi->ed->depended.available;
           provider;
           provider = provider->rev_next) {
        if (provider->up->type != dep_provides) continue;
        if (provider->up->up->clientdata->istobe != PKG_ISTOBE_INSTALLNEW)
          continue;
        if (provider->up->up->set == dep->up->set)
          continue; /* Conflicts and provides the same. */
        if (!pkg_virtual_deppossi_satisfied(possi, provider))
          continue;
        sprintf(linebuf, _("  %.250s provides %.250s and is to be installed.\n"),
                pkgbin_name(provider->up->up, &provider->up->up->available,
                            pnaw_nonambig), possi->ed->name);
        varbuf_add_str(whynot, linebuf);
        /* We can't remove the one we're about to install: */
        if (canfixbyremove)
          *canfixbyremove = NULL;
        return false;
      }

      /* Now look at the packages already on the system. */
      for (provider = possi->ed->depended.installed;
           provider;
           provider = provider->rev_next) {
        if (provider->up->type != dep_provides) continue;

        if (provider->up->up->set == dep->up->set)
          continue; /* Conflicts and provides the same. */

        if (!pkg_virtual_deppossi_satisfied(possi, provider))
          continue;

        switch (provider->up->up->clientdata->istobe) {
        case PKG_ISTOBE_INSTALLNEW:
          /* Don't pay any attention to the Provides field of the
           * currently-installed version of the package we're trying
           * to install. We dealt with that package by using the
           * available information above. */
          continue;
        case PKG_ISTOBE_REMOVE:
          continue;
        case PKG_ISTOBE_DECONFIGURE:
          if (dep->type == dep_breaks)
            continue; /* Already deconfiguring. */
        case PKG_ISTOBE_NORMAL:
        case PKG_ISTOBE_PREINSTALL:
          switch (provider->up->up->status) {
          case PKG_STAT_NOTINSTALLED:
          case PKG_STAT_CONFIGFILES:
            continue;
          case PKG_STAT_HALFINSTALLED:
          case PKG_STAT_UNPACKED:
          case PKG_STAT_HALFCONFIGURED:
            if (dep->type == dep_breaks)
              break; /* No problem. */
          case PKG_STAT_INSTALLED:
          case PKG_STAT_TRIGGERSPENDING:
          case PKG_STAT_TRIGGERSAWAITED:
            sprintf(linebuf,
                    _("  %.250s provides %.250s and is present and %s.\n"),
                    pkg_name(provider->up->up, pnaw_nonambig), possi->ed->name,
                    gettext(statusstrings[provider->up->up->status]));
            varbuf_add_str(whynot, linebuf);
            if (!canfixbyremove)
              return false;
            nconflicts++;
            *canfixbyremove= provider->up->up;
            break;
          }
          break;
        default:
          internerr("unknown istobe conflict provider '%d'",
                    provider->up->up->clientdata->istobe);
        }
      }

    if (!nconflicts)
      return true;
    if (nconflicts > 1)
      *canfixbyremove = NULL;
    return false;

  } /* if (dependency) {...} else {...} */
}
예제 #30
0
파일: depcon.c 프로젝트: CharizTeam/dpkg
/**
 * Cycle breaking works recursively down the package dependency tree.
 *
 * ‘sofar’ is the list of packages we've descended down already - if we
 * encounter any of its packages again in a dependency we have found a cycle.
 */
static bool
findbreakcyclerecursive(struct pkginfo *pkg, struct cyclesofarlink *sofar)
{
  struct cyclesofarlink thislink, *sol;
  struct dependency *dep;
  struct deppossi *possi, *providelink;
  struct pkginfo *provider, *pkg_pos;

  if (pkg->clientdata->color == PKG_CYCLE_BLACK)
    return false;
  pkg->clientdata->color = PKG_CYCLE_GRAY;

  if (debug_has_flag(dbg_depcondetail)) {
    struct varbuf str_pkgs = VARBUF_INIT;

    for (sol = sofar; sol; sol = sol->prev) {
      varbuf_add_str(&str_pkgs, " <- ");
      varbuf_add_pkgbin_name(&str_pkgs, sol->pkg, &sol->pkg->installed, pnaw_nonambig);
    }
    varbuf_end_str(&str_pkgs);
    debug(dbg_depcondetail, "findbreakcyclerecursive %s %s",
          pkg_name(pkg, pnaw_always), str_pkgs.buf);
    varbuf_destroy(&str_pkgs);
  }
  thislink.pkg= pkg;
  thislink.prev = sofar;
  thislink.possi = NULL;
  for (dep= pkg->installed.depends; dep; dep= dep->next) {
    if (dep->type != dep_depends && dep->type != dep_predepends) continue;
    for (possi= dep->list; possi; possi= possi->next) {
      struct deppossi_pkg_iterator *possi_iter;

      /* Don't find the same cycles again. */
      if (possi->cyclebreak) continue;
      thislink.possi= possi;

      possi_iter = deppossi_pkg_iter_new(possi, wpb_installed);
      while ((pkg_pos = deppossi_pkg_iter_next(possi_iter)))
        if (foundcyclebroken(&thislink, sofar, pkg_pos, possi)) {
          deppossi_pkg_iter_free(possi_iter);
          return true;
        }
      deppossi_pkg_iter_free(possi_iter);

      /* Right, now we try all the providers ... */
      for (providelink = possi->ed->depended.installed;
           providelink;
           providelink = providelink->rev_next) {
        if (providelink->up->type != dep_provides) continue;
        provider= providelink->up->up;
        if (provider->clientdata->istobe == PKG_ISTOBE_NORMAL)
          continue;
        /* We don't break things at ‘provides’ links, so ‘possi’ is
         * still the one we use. */
        if (foundcyclebroken(&thislink, sofar, provider, possi))
          return true;
      }
    }
  }
  /* Nope, we didn't find a cycle to break. */
  pkg->clientdata->color = PKG_CYCLE_BLACK;
  return false;
}