Пример #1
0
static int
repo_find_best_pkg_cb(struct xbps_handle *xhp,
		      struct xbps_rpool_index *rpi,
		      void *arg,
		      bool *done)
{
	struct repo_pool_fpkg *rpf = arg;
	const char *repopkgver;
	prop_dictionary_t pkgd;

	(void)done;
	(void)xhp;

	if (rpf->bypattern) {
		pkgd = xbps_find_pkg_in_array_by_pattern(xhp, rpi->repo,
		    rpf->pattern, NULL);
	} else {
		pkgd = xbps_find_pkg_in_array_by_name(xhp, rpi->repo,
		    rpf->pattern, NULL);
	}
	if (pkgd == NULL) {
		if (errno && errno != ENOENT)
			return errno;

		xbps_dbg_printf(xhp,
		    "[rpool] Package '%s' not found in repository "
		    "'%s'.\n", rpf->pattern, rpi->uri);
		return 0;
	}
	prop_dictionary_get_cstring_nocopy(pkgd,
	    "pkgver", &repopkgver);
	if (rpf->bestpkgver == NULL) {
		xbps_dbg_printf(xhp,
		    "[rpool] Found best match '%s' (%s).\n",
		    repopkgver, rpi->uri);
		rpf->pkgd = pkgd;
		prop_dictionary_set_cstring_nocopy(rpf->pkgd,
		    "repository", rpi->uri);
		rpf->bestpkgver = repopkgver;
		return 0;
	}
	/*
	 * Compare current stored version against new
	 * version from current package in repository.
	 */
	if (xbps_cmpver(repopkgver, rpf->bestpkgver) == 1) {
		xbps_dbg_printf(xhp,
		    "[rpool] Found best match '%s' (%s).\n",
		    repopkgver, rpi->uri);
		rpf->pkgd = pkgd;
		prop_dictionary_set_cstring_nocopy(rpf->pkgd,
		    "repository", rpi->uri);
		rpf->bestpkgver = repopkgver;
	}
	return 0;
}
Пример #2
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);
}
Пример #3
0
int
index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force)
{
	xbps_dictionary_t idx, idxmeta, idxstage, binpkgd, curpkgd;
	struct xbps_repo *repo = NULL;
	struct stat st;
	char *tmprepodir = NULL, *repodir = NULL, *rlockfname = NULL;
	int rv = 0, ret = 0, rlockfd = -1;

	assert(argv);
	/*
	 * Read the repository data or create index dictionaries otherwise.
	 */
	if ((tmprepodir = strdup(argv[args])) == NULL)
		return ENOMEM;

	repodir = dirname(tmprepodir);
	if (!xbps_repo_lock(xhp, repodir, &rlockfd, &rlockfname)) {
		fprintf(stderr, "xbps-rindex: cannot lock repository "
		    "%s: %s\n", repodir, strerror(errno));
		rv = -1;
		goto out;
	}
	repo = xbps_repo_public_open(xhp, repodir);
	if (repo == NULL && errno != ENOENT) {
		fprintf(stderr, "xbps-rindex: cannot open/lock repository "
		    "%s: %s\n", repodir, strerror(errno));
		rv = -1;
		goto out;
	}
	if (repo) {
		idx = xbps_dictionary_copy_mutable(repo->idx);
		idxmeta = xbps_dictionary_copy_mutable(repo->idxmeta);
	} else {
		idx = xbps_dictionary_create();
		idxmeta = NULL;
	}
	// TODO: load data from stage repository
	idxstage = xbps_dictionary_create();
	/*
	 * Process all packages specified in argv.
	 */
	for (int i = args; i < argmax; i++) {
		const char *arch = NULL, *pkg = argv[i];
		char *sha256 = NULL, *pkgver = NULL, *pkgname = NULL;

		assert(pkg);
		/*
		 * Read metadata props plist dictionary from binary package.
		 */
		binpkgd = xbps_archive_fetch_plist(pkg, "/props.plist");
		if (binpkgd == NULL) {
			fprintf(stderr, "index: failed to read %s metadata for "
			    "`%s', skipping!\n", XBPS_PKGPROPS, pkg);
			continue;
		}
		xbps_dictionary_get_cstring_nocopy(binpkgd, "architecture", &arch);
		xbps_dictionary_get_cstring(binpkgd, "pkgver", &pkgver);
		if (!xbps_pkg_arch_match(xhp, arch, NULL)) {
			fprintf(stderr, "index: ignoring %s, unmatched arch (%s)\n", pkgver, arch);
			xbps_object_release(binpkgd);
			free(pkgver);
			continue;
		}
		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		/*
		 * Check if this package exists already in the index, but first
		 * checking the version. If current package version is greater
		 * than current registered package, update the index; otherwise
		 * pass to the next one.
		 */
		curpkgd = xbps_dictionary_get(idxstage, pkgname);
		if(curpkgd == NULL)
			curpkgd = xbps_dictionary_get(idx, pkgname);
		if (curpkgd == NULL) {
			if (errno && errno != ENOENT) {
				rv = errno;
				free(pkgver);
				free(pkgname);
				goto out;
			}
		} else if (!force) {
			char *opkgver = NULL, *oarch = NULL;

			/* Only check version if !force */
			xbps_dictionary_get_cstring(curpkgd, "pkgver", &opkgver);
			xbps_dictionary_get_cstring(curpkgd, "architecture", &oarch);
			ret = xbps_cmpver(pkgver, opkgver);

			/*
			 * If the considered package reverts the package in the index,
			 * consider the current package as the newer one.
			 */
			if (ret < 0 && xbps_pkg_reverts(binpkgd, opkgver)) {
				ret = 1;
			/*
			 * If package in the index reverts considered package, consider the
			 * package in the index as the newer one.
			 */
			} else if (ret > 0 && xbps_pkg_reverts(curpkgd, pkgver)) {
				ret = -1;
			}

			if (ret <= 0) {
				/* Same version or index version greater */
				fprintf(stderr, "index: skipping `%s' (%s), already registered.\n", pkgver, arch);
				xbps_object_release(binpkgd);
				free(opkgver);
				free(oarch);
				free(pkgver);
				free(pkgname);
				continue;
			}
			/*
			 * Current package version is greater than
			 * index version.
			 */
			printf("index: removed obsolete entry `%s' (%s).\n", opkgver, oarch);
			xbps_dictionary_remove(idx, pkgname);
			free(opkgver);
			free(oarch);
		}
		/*
		 * Add additional objects for repository ops:
		 * 	- filename-size
		 * 	- filename-sha256
		 */
		if ((sha256 = xbps_file_hash(pkg)) == NULL) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (!xbps_dictionary_set_cstring(binpkgd, "filename-sha256", sha256)) {
			free(sha256);
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		free(sha256);
		if (stat(pkg, &st) == -1) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (!xbps_dictionary_set_uint64(binpkgd, "filename-size", (uint64_t)st.st_size)) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (set_build_date(binpkgd, st.st_mtime) < 0) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		/* Remove unneeded objects */
		xbps_dictionary_remove(binpkgd, "pkgname");
		xbps_dictionary_remove(binpkgd, "version");
		xbps_dictionary_remove(binpkgd, "packaged-with");

		/*
		 * Add new pkg dictionary into the index.
		 */
		if (!xbps_dictionary_set(idxstage, pkgname, binpkgd)) {
			free(pkgname);
			free(pkgver);
			rv = EINVAL;
			goto out;
		}
		printf("index: added `%s' (%s).\n", pkgver, arch);
		xbps_object_release(binpkgd);
		free(pkgname);
		free(pkgver);
	}
	/*
	 * Generate repository data files.
	 */
	if (!repodata_commit(xhp, repodir, idx, idxmeta, idxstage)) {
		fprintf(stderr, "%s: failed to write repodata: %s\n",
				_XBPS_RINDEX, strerror(errno));
		goto out;
	}
	printf("index: %u packages registered.\n", xbps_dictionary_count(idx));

out:
	if (repo)
		xbps_repo_close(repo);

	xbps_repo_unlock(rlockfd, rlockfname);

	if (tmprepodir)
		free(tmprepodir);

	return rv;
}
Пример #4
0
static int
add_missing_reqdep(struct xbps_handle *xhp, const char *reqpkg)
{
	xbps_array_t mdeps;
	xbps_object_iterator_t iter = NULL;
	xbps_object_t obj;
	unsigned int idx = 0;
	bool add_pkgdep, pkgfound, update_pkgdep;
	int rv = 0;

	assert(reqpkg != NULL);

	add_pkgdep = update_pkgdep = pkgfound = false;
	mdeps = xbps_dictionary_get(xhp->transd, "missing_deps");

	iter = xbps_array_iterator(mdeps);
	if (iter == NULL)
		goto out;

	while ((obj = xbps_object_iterator_next(iter)) != NULL) {
		const char *curdep, *curver, *pkgver;
		char *curpkgnamedep = NULL, *pkgnamedep = NULL;

		assert(xbps_object_type(obj) == XBPS_TYPE_STRING);
		curdep = xbps_string_cstring_nocopy(obj);
		curver = xbps_pkgpattern_version(curdep);
		pkgver = xbps_pkgpattern_version(reqpkg);
		if (curver == NULL || pkgver == NULL)
			goto out;
		curpkgnamedep = xbps_pkgpattern_name(curdep);
		if (curpkgnamedep == NULL)
			goto out;
		pkgnamedep = xbps_pkgpattern_name(reqpkg);
		if (pkgnamedep == NULL) {
			free(curpkgnamedep);
			goto out;
		}
		if (strcmp(pkgnamedep, curpkgnamedep) == 0) {
			pkgfound = true;
			if (strcmp(curver, pkgver) == 0) {
				free(curpkgnamedep);
				free(pkgnamedep);
				rv = EEXIST;
				goto out;
			}
			/*
			 * if new dependency version is greater than current
			 * one, store it.
			 */
			xbps_dbg_printf(xhp, "Missing pkgdep name matched, curver: %s newver: %s\n", curver, pkgver);
			if (xbps_cmpver(curver, pkgver) <= 0) {
				add_pkgdep = false;
				free(curpkgnamedep);
				free(pkgnamedep);
				rv = EEXIST;
				goto out;
			}
			update_pkgdep = true;
		}
		free(curpkgnamedep);
		free(pkgnamedep);
		if (pkgfound)
			break;

		idx++;
	}
	add_pkgdep = true;
out:
	if (iter)
		xbps_object_iterator_release(iter);
	if (update_pkgdep)
		xbps_array_remove(mdeps, idx);
	if (add_pkgdep) {
		char *str;

		str = xbps_xasprintf("MISSING: %s", reqpkg);
		xbps_array_add_cstring(mdeps, str);
		free(str);
	}

	return rv;
}