Пример #1
0
/*
 * Checks package integrity of an installed package.
 * The following task is accomplished in this file:
 *
 * 	o Check for target file in symlinks, so that we can check that
 * 	  they have not been modified.
 *
 * returns 0 if test ran successfully, 1 otherwise and -1 on error.
 */
static char *
symlink_target(const char *pkgname, const char *path)
{
	struct stat sb;
	char *lnk;
	ssize_t r;

	if (lstat(path, &sb) == -1) {
		xbps_error_printf("%s: lstat failed for %s\n", pkgname, path);
		return NULL;
	}

	lnk = malloc(sb.st_size + 1);
	assert(lnk);

	r = readlink(path, lnk, sb.st_size + 1);
	if (r < 0 || r > sb.st_size) {
		xbps_error_printf("%s: readlink failed for %s\n", pkgname, path);
		free(lnk);
		return NULL;
	}
	lnk[sb.st_size] = '\0';

	return lnk;
}
Пример #2
0
int
check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg)
{
	xbps_array_t array;
	xbps_object_t obj;
	xbps_dictionary_t filesd = arg;
	int rv = 0;

	array = xbps_dictionary_get(filesd, "links");
	if (array == NULL)
		return 0;

	for (unsigned int i = 0; i < xbps_array_count(array); i++) {
		const char *file = NULL, *tgt = NULL;
		char path[PATH_MAX], *lnk = NULL;

		obj = xbps_array_get(array, i);
		if (!xbps_dictionary_get_cstring_nocopy(obj, "file", &file))
			continue;

		if (!xbps_dictionary_get_cstring_nocopy(obj, "target", &tgt)) {
			xbps_warn_printf("%s: `%s' symlink with "
			    "empty target object!\n", pkgname, file);
			continue;
		}
		if (tgt[0] == '\0') {
			xbps_warn_printf("%s: `%s' symlink with "
			    "empty target object!\n", pkgname, file);
			continue;
		}
		snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file);
		if ((lnk = xbps_symlink_target(xhp, path, tgt)) == NULL) {
			xbps_error_printf("%s: broken symlink %s (target: %s)\n", pkgname, file, tgt);
			rv = -1;
			continue;
		}
		if (strcmp(lnk, tgt)) {
			xbps_warn_printf("%s: modified symlink %s "
			    "points to %s (shall be %s)\n",
			    pkgname, file, lnk, tgt);
			rv = -1;
		}
		free(lnk);
	}
	return rv;
}
Пример #3
0
int
xbps_pkgdb_update(struct xbps_handle *xhp, bool flush, bool update)
{
	xbps_dictionary_t pkgdb_storage;
	static int cached_rv;
	int rv = 0;

	if (cached_rv && !flush)
		return cached_rv;

	if (xhp->pkgdb && update) {
		pkgdb_storage = xbps_dictionary_internalize_from_file(xhp->pkgdb_plist);
		if (pkgdb_storage == NULL ||
		    !xbps_dictionary_equals(xhp->pkgdb, pkgdb_storage)) {
			/* flush dictionary to storage */
			if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, xhp->pkgdb_plist))
				return errno;
		}
		if (pkgdb_storage)
			xbps_object_release(pkgdb_storage);

		xbps_object_release(xhp->pkgdb);
		xhp->pkgdb = NULL;
		cached_rv = 0;
	}
	if (!update)
		return rv;

	/* update copy in memory */
	if ((xhp->pkgdb = xbps_dictionary_internalize_from_file(xhp->pkgdb_plist)) == NULL) {
		rv = errno;
		if (!rv)
			rv = EINVAL;

		if (rv == ENOENT)
			xhp->pkgdb = xbps_dictionary_create();
		else
			xbps_error_printf("cannot access to pkgdb: %s\n", strerror(rv));

		cached_rv = rv = errno;
	}

	return rv;
}
Пример #4
0
int
xbps_pkgdb_update(struct xbps_handle *xhp, bool flush)
{
	xbps_dictionary_t pkgdb_storage;
	char *plist;
	static int cached_rv;
	int rv = 0;

	if (cached_rv && !flush)
		return cached_rv;

	plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);
	if (xhp->pkgdb && flush) {
		pkgdb_storage = xbps_dictionary_internalize_from_file(plist);
		if (pkgdb_storage == NULL ||
		    !xbps_dictionary_equals(xhp->pkgdb, pkgdb_storage)) {
			/* flush dictionary to storage */
			if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, plist)) {
				free(plist);
				return errno;
			}
		}
		if (pkgdb_storage)
			xbps_object_release(pkgdb_storage);

		xbps_object_release(xhp->pkgdb);
		xhp->pkgdb = NULL;
		cached_rv = 0;
	}
	/* update copy in memory */
	if ((xhp->pkgdb = xbps_dictionary_internalize_from_file(plist)) == NULL) {
		if (errno == ENOENT)
			xhp->pkgdb = xbps_dictionary_create();
		else
			xbps_error_printf("cannot access to pkgdb: %s\n", strerror(errno));

		cached_rv = rv = errno;
	}
	free(plist);

	return rv;
}
Пример #5
0
int
main(int argc, char **argv)
{
	xbps_dictionary_t dict;
	struct xbps_handle xh;
	struct xferstat xfer;
	const char *version, *rootdir = NULL, *confdir = NULL;
	char *pkgname, *hash, *filename;
	int flags = 0, c, rv = 0;

	while ((c = getopt(argc, argv, "C:dr:V")) != -1) {
		switch (c) {
		case 'C':
			confdir = optarg;
			break;
		case 'r':
			/* To specify the root directory */
			rootdir = optarg;
			break;
		case 'd':
			flags |= XBPS_FLAG_DEBUG;
			break;
		case 'V':
			printf("%s\n", XBPS_RELVER);
			exit(EXIT_SUCCESS);
		case '?':
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1)
		usage();

	memset(&xh, 0, sizeof(xh));

	if ((strcmp(argv[0], "version") == 0) ||
	    (strcmp(argv[0], "real-version") == 0) ||
	    (strcmp(argv[0], "arch") == 0) ||
	    (strcmp(argv[0], "getsystemdir") == 0) ||
	    (strcmp(argv[0], "fetch") == 0)) {
		/*
		* Initialize libxbps.
		*/
		xh.flags = flags;
		xh.fetch_cb = fetch_file_progress_cb;
		xh.fetch_cb_data = &xfer;
		if (rootdir)
			xbps_strlcpy(xh.rootdir, rootdir, sizeof(xh.rootdir));
		if (confdir)
			xbps_strlcpy(xh.confdir, confdir, sizeof(xh.confdir));
		if ((rv = xbps_init(&xh)) != 0) {
			xbps_error_printf("xbps-uhelper: failed to "
			    "initialize libxbps: %s.\n", strerror(rv));
			exit(EXIT_FAILURE);
		}
	}

	if (strcmp(argv[0], "version") == 0) {
		/* Prints version of an installed package */
		if (argc != 2)
			usage();

		if ((((dict = xbps_pkgdb_get_pkg(&xh, argv[1])) == NULL)) &&
		    (((dict = xbps_pkgdb_get_virtualpkg(&xh, argv[1])) == NULL)))
			exit(EXIT_FAILURE);

		xbps_dictionary_get_cstring_nocopy(dict, "pkgver", &version);
		printf("%s\n", xbps_pkg_version(version));
	} else if (strcmp(argv[0], "real-version") == 0) {
		/* Prints version of an installed real package, not virtual */
		if (argc != 2)
			usage();

		if ((dict = xbps_pkgdb_get_pkg(&xh, argv[1])) == NULL)
			exit(EXIT_FAILURE);

		xbps_dictionary_get_cstring_nocopy(dict, "pkgver", &version);
		printf("%s\n", xbps_pkg_version(version));
	} else if (strcmp(argv[0], "getpkgversion") == 0) {
		/* Returns the version of a pkg string */
		if (argc != 2)
			usage();

		version = xbps_pkg_version(argv[1]);
		if (version == NULL) {
			fprintf(stderr,
			    "Invalid string, expected <string>-<version>_<revision>\n");
			exit(EXIT_FAILURE);
		}
		printf("%s\n", version);
	} else if (strcmp(argv[0], "getpkgname") == 0) {
		/* Returns the name of a pkg string */
		if (argc != 2)
			usage();

		pkgname = xbps_pkg_name(argv[1]);
		if (pkgname == NULL) {
			fprintf(stderr,
			    "Invalid string, expected <string>-<version>_<revision>\n");
			exit(EXIT_FAILURE);
		}
		printf("%s\n", pkgname);
		free(pkgname);
	} else if (strcmp(argv[0], "getpkgrevision") == 0) {
		/* Returns the revision of a pkg string */
		if (argc != 2)
			usage();

		version = xbps_pkg_revision(argv[1]);
		if (version == NULL)
			exit(EXIT_SUCCESS);

		printf("%s\n", version);
	} else if (strcmp(argv[0], "getpkgdepname") == 0) {
		/* Returns the pkgname of a dependency */
		if (argc != 2)
			usage();

		pkgname = xbps_pkgpattern_name(argv[1]);
		if (pkgname == NULL)
			exit(EXIT_FAILURE);

		printf("%s\n", pkgname);
		free(pkgname);
	} else if (strcmp(argv[0], "getpkgdepversion") == 0) {
		/* returns the version of a package pattern dependency */
		if (argc != 2)
			usage();

		version = xbps_pkgpattern_version(argv[1]);
		if (version == NULL)
			exit(EXIT_FAILURE);

		printf("%s\n", version);
	} else if (strcmp(argv[0], "binpkgver") == 0) {
		/* Returns the pkgver of a binpkg string */
		if (argc != 2)
			usage();

		version = xbps_binpkg_pkgver(argv[1]);
		if (version == NULL) {
			fprintf(stderr,
			    "Invalid string, expected <pkgname>-<version>_<revision>.<arch>.xbps\n");
			exit(EXIT_FAILURE);
		}
		printf("%s\n", version);
	} else if (strcmp(argv[0], "binpkgarch") == 0) {
		/* Returns the arch of a binpkg string */
		if (argc != 2)
			usage();

		version = xbps_binpkg_arch(argv[1]);
		if (version == NULL) {
			fprintf(stderr,
			    "Invalid string, expected <pkgname>-<version>_<revision>.<arch>.xbps\n");
			exit(EXIT_FAILURE);
		}
		printf("%s\n", version);
	} else if (strcmp(argv[0], "pkgmatch") == 0) {
		/* Matches a pkg with a pattern */
		if (argc != 3)
			usage();

		exit(xbps_pkgpattern_match(argv[1], argv[2]));
	} else if (strcmp(argv[0], "cmpver") == 0) {
		/* Compare two version strings, installed vs required */
		if (argc != 3)
			usage();

		exit(xbps_cmpver(argv[1], argv[2]));
	} else if (strcmp(argv[0], "arch") == 0) {
		/* returns the xbps native arch */
		if (argc != 1)
			usage();

		printf("%s\n", xh.native_arch);
	} else if (strcmp(argv[0], "getsystemdir") == 0) {
		/* returns the xbps system directory (<sharedir>/xbps.d) */
		if (argc != 1)
			usage();

		printf("%s\n", XBPS_SYSDEFCONF_PATH);
	} else if (strcmp(argv[0], "digest") == 0) {
		/* Prints SHA256 hashes for specified files */
		if (argc < 2)
			usage();

		for (int i = 1; i < argc; i++) {
			hash = xbps_file_hash(argv[i]);
			if (hash == NULL) {
				fprintf(stderr,
				    "E: couldn't get hash for %s (%s)\n",
				    argv[i], strerror(errno));
				exit(EXIT_FAILURE);
			}
			printf("%s\n", hash);
		}
	} else if (strcmp(argv[0], "fetch") == 0) {
		/* Fetch a file from specified URL */
		if (argc < 2)
			usage();

		for (int i = 1; i < argc; i++) {
			filename = fname(argv[i]);
			rv = xbps_fetch_file_dest(&xh, argv[i], filename, "v");

			if (rv == -1) {
				printf("%s: %s\n", argv[i],
				    xbps_fetch_error_string());
			} else if (rv == 0) {
				printf("%s: file is identical with remote.\n",
				    argv[i]);
			} else
				rv = 0;
		}
	} else {
		usage();
	}

	exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
}
Пример #6
0
int
exec_transaction(struct xbps_handle *xhp, int maxcols, bool yes, bool drun)
{
	xbps_array_t array;
	struct transaction *trans;
	uint64_t fsize = 0, isize = 0;
	char freesize[8], instsize[8];
	int rv = 0;

	trans = calloc(1, sizeof(*trans));
	if (trans == NULL)
		return ENOMEM;

	if ((rv = xbps_transaction_prepare(xhp)) != 0) {
		if (rv == ENODEV) {
			array = xbps_dictionary_get(xhp->transd, "missing_deps");
			if (xbps_array_count(array)) {
				/* missing dependencies */
				print_array(array);
				fprintf(stderr, "Transaction aborted due to unresolved dependencies.\n");
			}
		} else if (rv == ENOEXEC) {
			array = xbps_dictionary_get(xhp->transd, "missing_shlibs");
			if (xbps_array_count(array)) {
				/* missing shlibs */
				print_array(array);
				fprintf(stderr, "Transaction aborted due to unresolved shlibs.\n");
			}
		} else if (rv == EAGAIN) {
			/* conflicts */
			array = xbps_dictionary_get(xhp->transd, "conflicts");
			print_array(array);
			fprintf(stderr, "Transaction aborted due to conflicting packages.\n");
		} else if (rv == ENOSPC) {
			/* not enough free space */
			xbps_dictionary_get_uint64(xhp->transd,
			    "total-installed-size", &isize);
			if (xbps_humanize_number(instsize, (int64_t)isize) == -1) {
				xbps_error_printf("humanize_number2 returns "
					"%s\n", strerror(errno));
				return -1;
			}
			xbps_dictionary_get_uint64(xhp->transd,
			    "disk-free-size", &fsize);
			if (xbps_humanize_number(freesize, (int64_t)fsize) == -1) {
				xbps_error_printf("humanize_number2 returns "
					"%s\n", strerror(errno));
				return -1;
			}
			fprintf(stderr, "Transaction aborted due to insufficient disk "
			    "space (need %s, got %s free).\n", instsize, freesize);
		} else {
			xbps_dbg_printf(xhp, "Empty transaction dictionary: %s\n",
			    strerror(errno));
		}
		goto out;
	}
#ifdef FULL_DEBUG
	xbps_dbg_printf(xhp, "Dictionary before transaction happens:\n");
	xbps_dbg_printf_append(xhp, "%s",
	    xbps_dictionary_externalize(xhp->transd));
#endif

	trans->xhp = xhp;
	trans->d = xhp->transd;
	trans->iter = xbps_array_iter_from_dict(xhp->transd, "packages");
	assert(trans->iter);

	/*
	 * dry-run mode, show what would be done but don't run anything.
	 */
	if (drun) {
		show_actions(trans->iter);
		goto out;
	}
	/*
	 * Show download/installed size for the transaction.
	 */
	if ((rv = show_transaction_sizes(trans, maxcols)) != 0)
		goto out;
	/*
	 * Ask interactively (if -y not set).
	 */
	if (!yes && !yesno("Do you want to continue?")) {
		printf("Aborting!\n");
		goto out;
	}
	/*
	 * It's time to run the transaction!
	 */
	if ((rv = xbps_transaction_commit(xhp)) == 0) {
		printf("\n%u downloaded, %u installed, %u updated, "
		    "%u configured, %u removed.\n",
		    trans->dl_pkgcnt, trans->inst_pkgcnt,
		    trans->up_pkgcnt, trans->cf_pkgcnt + trans->inst_pkgcnt,
		    trans->rm_pkgcnt);
	}
out:
	if (trans->iter)
		xbps_object_iterator_release(trans->iter);
	if (trans)
		free(trans);
	return rv;
}
Пример #7
0
static int
show_transaction_sizes(struct transaction *trans, int cols)
{
	uint64_t dlsize = 0, instsize = 0, rmsize = 0, disk_free_size = 0;
	char size[8];

	if (!print_trans_colmode(trans, cols)) {
		/*
		 * Show the list of packages that will be downloaded, installed, updated,
		 * removed or configured.
		 */
		xbps_dictionary_get_uint32(trans->d, "total-download-pkgs",
		    &trans->dl_pkgcnt);
		if (trans->dl_pkgcnt) {
			printf("%u package%s will be downloaded:\n",
			    trans->dl_pkgcnt, trans->dl_pkgcnt == 1 ? "" : "s");
			show_package_list(trans, NULL, cols);
			printf("\n");
		}
		xbps_dictionary_get_uint32(trans->d, "total-install-pkgs",
		    &trans->inst_pkgcnt);
		if (trans->inst_pkgcnt) {
			printf("%u package%s will be installed:\n",
			    trans->inst_pkgcnt, trans->inst_pkgcnt == 1 ? "" : "s");
			show_package_list(trans, "install", cols);
			printf("\n");
		}
		xbps_dictionary_get_uint32(trans->d, "total-update-pkgs",
		    &trans->up_pkgcnt);
		if (trans->up_pkgcnt) {
			printf("%u package%s will be updated:\n",
			    trans->up_pkgcnt, trans->up_pkgcnt == 1 ? "" : "s");
			show_package_list(trans, "update", cols);
			printf("\n");
		}
		xbps_dictionary_get_uint32(trans->d, "total-configure-pkgs",
		    &trans->cf_pkgcnt);
		if (trans->cf_pkgcnt) {
			printf("%u package%s will be configured:\n",
			    trans->cf_pkgcnt, trans->cf_pkgcnt == 1 ? "" : "s");
			show_package_list(trans, "configure", cols);
			printf("\n");
		}
		xbps_dictionary_get_uint32(trans->d, "total-remove-pkgs",
		    &trans->rm_pkgcnt);
		if (trans->rm_pkgcnt) {
			printf("%u package%s will be removed:\n",
			    trans->rm_pkgcnt, trans->rm_pkgcnt == 1 ? "" : "s");
			show_package_list(trans, "remove", cols);
			printf("\n");
		}
	}
	/*
	 * Show total download/installed/removed size for all required packages.
	 */
	xbps_dictionary_get_uint64(trans->d, "total-download-size", &dlsize);
	xbps_dictionary_get_uint64(trans->d, "total-installed-size", &instsize);
	xbps_dictionary_get_uint64(trans->d, "total-removed-size", &rmsize);
	xbps_dictionary_get_uint64(trans->d, "disk-free-size", &disk_free_size);
	if (dlsize || instsize || rmsize || disk_free_size)
		printf("\n");

	if (dlsize) {
		if (xbps_humanize_number(size, (int64_t)dlsize) == -1) {
			xbps_error_printf("humanize_number returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Size to download:             %6s\n", size);
	}
	if (instsize) {
		if (xbps_humanize_number(size, (int64_t)instsize) == -1) {
			xbps_error_printf("humanize_number2 returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Size required on disk:        %6s\n", size);
	}
	if (rmsize) {
		if (xbps_humanize_number(size, (int64_t)rmsize) == -1) {
			xbps_error_printf("humanize_number3 returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Size freed on disk:           %6s\n", size);
	}
	if (disk_free_size) {
		if (xbps_humanize_number(size, (int64_t)disk_free_size) == -1) {
			xbps_error_printf("humanize_number3 returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Free space on disk:           %6s\n", size);
	}
	printf("\n");

	return 0;
}
Пример #8
0
static int
show_transaction_sizes(struct transaction *trans, int cols)
{
	uint64_t dlsize = 0, instsize = 0, rmsize = 0;
	char size[8];

	/*
	 * Show the list of packages that will be installed.
	 */
	if (xbps_dictionary_get_uint32(trans->d, "total-install-pkgs",
	    &trans->inst_pkgcnt)) {
		printf("%u package%s will be installed:\n",
		    trans->inst_pkgcnt, trans->inst_pkgcnt == 1 ? "" : "s");
		show_package_list(trans->iter, "install", cols);
		printf("\n");
	}
	if (xbps_dictionary_get_uint32(trans->d, "total-update-pkgs",
	    &trans->up_pkgcnt)) {
		printf("%u package%s will be updated:\n",
		    trans->up_pkgcnt, trans->up_pkgcnt == 1 ? "" : "s");
		show_package_list(trans->iter, "update", cols);
		printf("\n");
	}
	if (xbps_dictionary_get_uint32(trans->d, "total-configure-pkgs",
	    &trans->cf_pkgcnt)) {
		printf("%u package%s will be configured:\n",
		    trans->cf_pkgcnt, trans->cf_pkgcnt == 1 ? "" : "s");
		show_package_list(trans->iter, "configure", cols);
		printf("\n");
	}
	if (xbps_dictionary_get_uint32(trans->d, "total-remove-pkgs",
	    &trans->rm_pkgcnt)) {
		printf("%u package%s will be removed:\n",
		    trans->rm_pkgcnt, trans->rm_pkgcnt == 1 ? "" : "s");
		show_package_list(trans->iter, "remove", cols);
		printf("\n");
	}
	/*
	 * Show total download/installed/removed size for all required packages.
	 */
	xbps_dictionary_get_uint64(trans->d, "total-download-size", &dlsize);
	xbps_dictionary_get_uint64(trans->d, "total-installed-size",
	    &instsize);
	xbps_dictionary_get_uint64(trans->d, "total-removed-size", &rmsize);
	if (dlsize || instsize || rmsize)
		printf("\n");

	if (dlsize) {
		if (xbps_humanize_number(size, (int64_t)dlsize) == -1) {
			xbps_error_printf("humanize_number returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Total download size:\t%6s\n", size);
	}
	if (instsize) {
		if (xbps_humanize_number(size, (int64_t)instsize) == -1) {
			xbps_error_printf("humanize_number2 returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Total installed size:\t%6s\n", size);
	}
	if (rmsize) {
		if (xbps_humanize_number(size, (int64_t)rmsize) == -1) {
			xbps_error_printf("humanize_number3 returns "
			    "%s\n", strerror(errno));
			return -1;
		}
		printf("Total freed size:\t%6s\n", size);
	}
	printf("\n");

	return 0;
}