Beispiel #1
0
int
event_callback(void *data, struct pkg_event *ev)
{
	struct pkg *pkg = NULL, *pkg_new, *pkg_old;
	int *debug = data;
	struct pkg_event_conflict *cur_conflict;
	const char *filename;

	if (msg_buf == NULL) {
		msg_buf = sbuf_new_auto();
	}

	/*
	 * If a progressbar has been interrupted by another event, then
	 * we need to add a newline to prevent bad formatting.
	 */
	if (progress_started && ev->type != PKG_EVENT_PROGRESS_TICK &&
	    !progress_interrupted) {
		putchar('\n');
		progress_interrupted = true;
	}

	switch(ev->type) {
	case PKG_EVENT_ERRNO:
		warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg,
		    strerror(ev->e_errno.no));
		break;
	case PKG_EVENT_ERROR:
		warnx("%s", ev->e_pkg_error.msg);
		break;
	case PKG_EVENT_NOTICE:
		if (!quiet)
			printf("%s\n", ev->e_pkg_notice.msg);
		break;
	case PKG_EVENT_DEVELOPER_MODE:
		warnx("DEVELOPER_MODE: %s", ev->e_pkg_error.msg);
		break;
	case PKG_EVENT_UPDATE_ADD:
		if (quiet || !isatty(STDOUT_FILENO))
			break;
		printf("\rPushing new entries %d/%d", ev->e_upd_add.done, ev->e_upd_add.total);
		if (ev->e_upd_add.total == ev->e_upd_add.done)
			printf("\n");
		break;
	case PKG_EVENT_UPDATE_REMOVE:
		if (quiet || !isatty(STDOUT_FILENO))
			break;
		printf("\rRemoving entries %d/%d", ev->e_upd_remove.done, ev->e_upd_remove.total);
		if (ev->e_upd_remove.total == ev->e_upd_remove.done)
			printf("\n");
		break;
	case PKG_EVENT_FETCH_BEGIN:
		if (quiet)
			break;
		filename = strrchr(ev->e_fetching.url, '/');
		if (filename != NULL) {
			filename++;
		} else {
			/*
			 * We failed at being smart, so display
			 * the entire url.
			 */
			filename = ev->e_fetching.url;
		}
		job_status_begin(msg_buf);
		progress_debit = true;
		sbuf_printf(msg_buf, "Fetching %s", filename);

		break;
	case PKG_EVENT_FETCH_FINISHED:
		progress_debit = false;
		break;
	case PKG_EVENT_INSTALL_BEGIN:
		if (quiet)
			break;
		else {
			nbdone++;
			job_status_begin(msg_buf);

			pkg = ev->e_install_begin.pkg;
			pkg_sbuf_printf(msg_buf, "Installing %n-%v...\n", pkg,
			    pkg);
			sbuf_finish(msg_buf);
			printf("%s", sbuf_data(msg_buf));
		}
		break;
	case PKG_EVENT_INSTALL_FINISHED:
		if (quiet)
			break;
		pkg = ev->e_install_finished.pkg;
		if (pkg_has_message(pkg)) {
			if (messages == NULL)
				messages = sbuf_new_auto();
			pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n",
			    pkg, pkg, pkg);
		}
		break;
	case PKG_EVENT_EXTRACT_BEGIN:
		if (quiet)
			break;
		else {
			job_status_begin(msg_buf);
			pkg = ev->e_install_begin.pkg;
			pkg_sbuf_printf(msg_buf, "Extracting %n-%v", pkg, pkg);
		}
		break;
	case PKG_EVENT_EXTRACT_FINISHED:
		break;
	case PKG_EVENT_ADD_DEPS_BEGIN:
		++add_deps_depth;
		break;
	case PKG_EVENT_ADD_DEPS_FINISHED:
		--add_deps_depth;
		break;
	case PKG_EVENT_INTEGRITYCHECK_BEGIN:
		if (quiet)
			break;
		printf("Checking integrity...");
		break;
	case PKG_EVENT_INTEGRITYCHECK_FINISHED:
		if (quiet)
			break;
		printf(" done (%d conflicting)\n", ev->e_integrity_finished.conflicting);
		break;
	case PKG_EVENT_INTEGRITYCHECK_CONFLICT:
		if (*debug == 0)
			break;
		printf("\nConflict found on path %s between %s and ",
		    ev->e_integrity_conflict.pkg_path,
		    ev->e_integrity_conflict.pkg_uid);
		cur_conflict = ev->e_integrity_conflict.conflicts;
		while (cur_conflict) {
			if (cur_conflict->next)
				printf("%s, ", cur_conflict->uid);
			else
				printf("%s", cur_conflict->uid);

			cur_conflict = cur_conflict->next;
		}
		printf("\n");
		break;
	case PKG_EVENT_DEINSTALL_BEGIN:
		if (quiet)
			break;
		nbdone++;

		job_status_begin(msg_buf);

		pkg = ev->e_install_begin.pkg;
		pkg_sbuf_printf(msg_buf, "Deinstalling %n-%v...\n", pkg, pkg);
		sbuf_finish(msg_buf);
		printf("%s", sbuf_data(msg_buf));
		break;
	case PKG_EVENT_DEINSTALL_FINISHED:
		if (quiet)
			break;
		break;
	case PKG_EVENT_DELETE_FILES_BEGIN:
		if (quiet)
			break;
		else {
			job_status_begin(msg_buf);
			pkg = ev->e_install_begin.pkg;
			pkg_sbuf_printf(msg_buf, "Deleting files for %n-%v",
			    pkg, pkg);
		}
		break;
	case PKG_EVENT_DELETE_FILES_FINISHED:
		break;
	case PKG_EVENT_UPGRADE_BEGIN:
		if (quiet)
			break;
		pkg_new = ev->e_upgrade_begin.n;
		pkg_old = ev->e_upgrade_begin.o;
		nbdone++;

		job_status_begin(msg_buf);

		switch (pkg_version_change_between(pkg_new, pkg_old)) {
		case PKG_DOWNGRADE:
			pkg_sbuf_printf(msg_buf, "Downgrading %n from %v to %v...\n",
			    pkg_new, pkg_old, pkg_new);
			break;
		case PKG_REINSTALL:
			pkg_sbuf_printf(msg_buf, "Reinstalling %n-%v...\n",
		    pkg_old, pkg_old);
			break;
		case PKG_UPGRADE:
			pkg_sbuf_printf(msg_buf, "Upgrading %n from %v to %v...\n",
			    pkg_new, pkg_old, pkg_new);
			break;
		}
		sbuf_finish(msg_buf);
		printf("%s", sbuf_data(msg_buf));
		break;
	case PKG_EVENT_UPGRADE_FINISHED:
		if (quiet)
			break;
		pkg_new = ev->e_upgrade_finished.n;
		if (pkg_has_message(pkg_new)) {
			if (messages == NULL)
				messages = sbuf_new_auto();
			pkg_sbuf_printf(messages, "Message for %n-%v:\n %M\n",
				pkg_new, pkg_new, pkg_new);
		}
		break;
	case PKG_EVENT_LOCKED:
		pkg = ev->e_locked.pkg;
		pkg_printf("\n%n-%v is locked and may not be modified\n", pkg, pkg);
		break;
	case PKG_EVENT_REQUIRED:
		pkg = ev->e_required.pkg;
		pkg_printf("\n%n-%v is required by: %r%{%rn-%rv%| %}", pkg, pkg, pkg);
		if (ev->e_required.force == 1)
			fprintf(stderr, ", deleting anyway\n");
		else
			fprintf(stderr, "\n");
		break;
	case PKG_EVENT_ALREADY_INSTALLED:
		if (quiet)
			break;
		pkg = ev->e_already_installed.pkg;
		pkg_printf("the most recent version of %n-%v is already installed\n",
				pkg, pkg);
		break;
	case PKG_EVENT_NOT_FOUND:
		printf("Package '%s' was not found in "
		    "the repositories\n", ev->e_not_found.pkg_name);
		break;
	case PKG_EVENT_MISSING_DEP:
		warnx("Missing dependency '%s-%s'",
		    pkg_dep_name(ev->e_missing_dep.dep),
		    pkg_dep_version(ev->e_missing_dep.dep));
		break;
	case PKG_EVENT_NOREMOTEDB:
		fprintf(stderr, "Unable to open remote database \"%s\". "
		    "Try running '%s update' first.\n", ev->e_remotedb.repo,
		    getprogname());
		break;
	case PKG_EVENT_NOLOCALDB:
		fprintf(stderr, "Local package database nonexistent!\n");
		break;
	case PKG_EVENT_NEWPKGVERSION:
		newpkgversion = true;
		printf("New version of pkg detected; it needs to be "
		    "installed first.\n");
		break;
	case PKG_EVENT_FILE_MISMATCH:
		pkg = ev->e_file_mismatch.pkg;
		pkg_fprintf(stderr, "%n-%v: checksum mismatch for %Fn\n", pkg,
		    pkg, ev->e_file_mismatch.file);
		break;
	case PKG_EVENT_PLUGIN_ERRNO:
		warnx("%s: %s(%s): %s",
		    pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
		    ev->e_plugin_errno.func, ev->e_plugin_errno.arg,
		    strerror(ev->e_plugin_errno.no));
		break;
	case PKG_EVENT_PLUGIN_ERROR:
		warnx("%s: %s",
		    pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
		    ev->e_plugin_error.msg);
		break;
	case PKG_EVENT_PLUGIN_INFO:
		if (quiet)
			break;
		printf("%s: %s\n",
		    pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
		    ev->e_plugin_info.msg);
		break;
	case PKG_EVENT_INCREMENTAL_UPDATE:
		if (!quiet)
			printf("%s repository update completed. %d packages processed.\n",
			    ev->e_incremental_update.reponame,
			    ev->e_incremental_update.processed);
		break;
	case PKG_EVENT_DEBUG:
		fprintf(stderr, "DBG(%d)[%d]> %s\n", ev->e_debug.level,
			(int)getpid(), ev->e_debug.msg);
		break;
	case PKG_EVENT_QUERY_YESNO:
		return ( ev->e_query_yesno.deft ?
			query_yesno(true, ev->e_query_yesno.msg, "[Y/n]") :
			query_yesno(false, ev->e_query_yesno.msg, "[y/N]") );
		break;
	case PKG_EVENT_QUERY_SELECT:
		return query_select(ev->e_query_select.msg, ev->e_query_select.items,
			ev->e_query_select.ncnt, ev->e_query_select.deft);
		break;
	case PKG_EVENT_SANDBOX_CALL:
		return ( event_sandboxed_call(ev->e_sandbox_call.call,
				ev->e_sandbox_call.fd,
				ev->e_sandbox_call.userdata) );
		break;
	case PKG_EVENT_SANDBOX_GET_STRING:
		return ( event_sandboxed_get_string(ev->e_sandbox_call_str.call,
				ev->e_sandbox_call_str.result,
				ev->e_sandbox_call_str.len,
				ev->e_sandbox_call_str.userdata) );
		break;
	case PKG_EVENT_PROGRESS_START:
		progressbar_start(ev->e_progress_start.msg);
		break;
	case PKG_EVENT_PROGRESS_TICK:
		progressbar_tick(ev->e_progress_tick.current,
		    ev->e_progress_tick.total);
		break;
	case PKG_EVENT_BACKUP:
		sbuf_cat(msg_buf, "Backing up");
		sbuf_finish(msg_buf);
		break;
	case PKG_EVENT_RESTORE:
		sbuf_cat(msg_buf, "Restoring");
		sbuf_finish(msg_buf);
		break;
	default:
		break;
	}

	return 0;
}
Beispiel #2
0
Datei: check.c Projekt: dpl0/pkg
int
exec_check(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it = NULL;
	struct pkgdb *db = NULL;
	struct sbuf *msg = NULL;
	match_t match = MATCH_EXACT;
	int flags = PKG_LOAD_BASIC;
	int ret, rc = EX_OK;
	int ch;
	bool dcheck = false;
	bool checksums = false;
	bool recompute = false;
	bool reanalyse_shlibs = false;
	bool noinstall = false;
	int nbpkgs = 0;
	int i, processed, total = 0;
	int verbose = 0;

	struct option longopts[] = {
		{ "all",		no_argument,	NULL,	'a' },
		{ "shlibs",		no_argument,	NULL,	'B' },
		{ "case-sensitive",	no_argument,	NULL,	'C' },
		{ "dependencies",	no_argument,	NULL,	'd' },
		{ "glob",		no_argument,	NULL,	'g' },
		{ "case-insensitive",	no_argument,	NULL,	'i' },
		{ "dry-run",		no_argument,	NULL,	'n' },
		{ "recompute",		no_argument,	NULL,	'r' },
		{ "checksums",		no_argument,	NULL,	's' },
		{ "verbose",		no_argument,	NULL,	'v' },
		{ "regex",		no_argument,	NULL,	'x' },
		{ "yes",		no_argument,	NULL,	'y' },
		{ NULL,			0,		NULL,	0   },
	};

	struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh);

	processed = 0;

	while ((ch = getopt_long(argc, argv, "+aBCdginrsvxy", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'B':
			reanalyse_shlibs = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 'C':
			pkgdb_set_case_sensitivity(true);
			break;
		case 'd':
			dcheck = true;
			flags |= PKG_LOAD_DEPS;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'n':
			noinstall = true;
			break;
		case 'r':
			recompute = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 's':
			checksums = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_check();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	/* Default to all packages if no pkg provided */
	if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) {
		match = MATCH_ALL;
	} else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) {
		usage_check();
		return (EX_USAGE);
	}

	if (recompute || reanalyse_shlibs)
		ret = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
				   PKGDB_DB_LOCAL);
	else
		ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);

	if (ret == EPKG_ENODB) {
		warnx("No packages installed.  Nothing to do!");
		return (EX_OK);
	} else if (ret == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to access the package database");
		return (EX_NOPERM);
	} else if (ret != EPKG_OK) {
		warnx("Error accessing the package database");
		return (EX_SOFTWARE);
	}

	ret = pkgdb_open(&db, PKGDB_DEFAULT);
	if (ret != EPKG_OK)
		return (EX_IOERR);

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_ADVISORY) != EPKG_OK) {
		pkgdb_close(db);
		warnx("Cannot get an advisory lock on a database, it is locked by another process");
		return (EX_TEMPFAIL);
	}

	i = 0;
	nbdone = 0;
	do {
		/* XXX: This is really quirky, it would be cleaner to pass
		 * in multiple matches and only run this top-loop once. */
		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
			rc = EX_IOERR;
			goto cleanup;
		}

		if (msg == NULL)
			msg = sbuf_new_auto();
		if (!verbose) {
			if (match == MATCH_ALL)
				progressbar_start("Checking all packages");
			else {
				sbuf_printf(msg, "Checking %s", argv[i]);
				sbuf_finish(msg);
				progressbar_start(sbuf_data(msg));
			}
			processed = 0;
			total = pkgdb_it_count(it);
		} else {
			if (match == MATCH_ALL)
				nbactions = pkgdb_it_count(it);
			else
				nbactions = argc;
		}

		while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
			if (!verbose)
				progressbar_tick(processed, total);
			else {
				++nbdone;
				job_status_begin(msg);
				pkg_sbuf_printf(msg, "Checking %n-%v:",
				    pkg, pkg);
				sbuf_flush(msg);
			}

			/* check for missing dependencies */
			if (dcheck) {
				if (verbose)
					printf(" dependencies...");
				nbpkgs += check_deps(db, pkg, &dh, noinstall);
				if (noinstall && nbpkgs > 0) {
					rc = EX_UNAVAILABLE;
				}
			}
			if (checksums) {
				if (verbose)
					printf(" checksums...");
				if (pkg_test_filesum(pkg) != EPKG_OK) {
					rc = EX_DATAERR;
				}
			}
			if (recompute) {
				if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY,
						PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) {
					if (verbose)
						printf(" recomputing...");
					if (pkg_recompute(db, pkg) != EPKG_OK) {
						rc = EX_DATAERR;
					}
					pkgdb_downgrade_lock(db,
					    PKGDB_LOCK_EXCLUSIVE,
					    PKGDB_LOCK_ADVISORY);
				}
				else {
					rc = EX_TEMPFAIL;
				}
			}
			if (reanalyse_shlibs) {
				if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY,
						PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) {
					if (verbose)
						printf(" shared libraries...");
					if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK) {
						pkg_fprintf(stderr, "Failed to "
						    "reanalyse for shlibs: "
						    "%n-%v\n", pkg, pkg);
						rc = EX_UNAVAILABLE;
					}
					pkgdb_downgrade_lock(db,
					    PKGDB_LOCK_EXCLUSIVE,
					    PKGDB_LOCK_ADVISORY);
				}
				else {
					rc = EX_TEMPFAIL;
				}
			}

			if (!verbose)
				++processed;
			else
				printf(" done\n");
		}
		if (!verbose)
			progressbar_tick(processed, total);
		if (msg != NULL) {
			sbuf_delete(msg);
			msg = NULL;
		}

		if (dcheck && nbpkgs > 0 && !noinstall) {
			printf("\n>>> Missing package dependencies were detected.\n");
			printf(">>> Found %d issue(s) in the package database.\n\n", nbpkgs);
			if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY,
					PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) {
				ret = fix_deps(db, &dh, nbpkgs, yes);
				if (ret == EPKG_OK)
					check_summary(db, &dh);
				else if (ret == EPKG_ENODB) {
					db = NULL;
					rc = EX_IOERR;
				}
				pkgdb_downgrade_lock(db, PKGDB_LOCK_EXCLUSIVE,
				    PKGDB_LOCK_ADVISORY);
				if (rc == EX_IOERR)
					goto cleanup;
			}
			else {
				rc = EX_TEMPFAIL;
				goto cleanup;
			}
		}
		pkgdb_it_free(it);
		i++;
	} while (i < argc);

cleanup:
	if (!verbose)
		progressbar_stop();
	if (msg != NULL)
		sbuf_delete(msg);
	deps_free(&dh);
	pkg_free(pkg);
	pkgdb_release_lock(db, PKGDB_LOCK_ADVISORY);
	pkgdb_close(db);

	return (rc);
}