static xbps_dictionary_t get_pkg_in_array(xbps_array_t array, const char *str, bool virtual) { xbps_object_t obj = NULL; xbps_object_iterator_t iter; const char *pkgver; char *dpkgn; bool found = false; iter = xbps_array_iterator(array); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { if (virtual) { /* * Check if package pattern matches * any virtual package version in dictionary. */ if (xbps_pkgpattern_version(str)) found = xbps_match_virtual_pkg_in_dict(obj, str, true); else found = xbps_match_virtual_pkg_in_dict(obj, str, false); if (found) break; } else if (xbps_pkgpattern_version(str)) { /* match by pattern against pkgver */ if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) continue; if (xbps_pkgpattern_match(pkgver, str)) { found = true; break; } } else if (xbps_pkg_version(str)) { /* match by exact pkgver */ if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) continue; if (strcmp(str, pkgver) == 0) { found = true; break; } } else { /* match by pkgname */ if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) continue; dpkgn = xbps_pkg_name(pkgver); assert(dpkgn); if (strcmp(dpkgn, str) == 0) { free(dpkgn); found = true; break; } free(dpkgn); } }
prop_dictionary_t xbps_rpool_dictionary_metadata_plist(struct xbps_handle *xhp, const char *pattern, const char *plistf) { prop_dictionary_t pkgd = NULL, plistd = NULL; const char *repoloc; char *url; assert(pattern != NULL); assert(plistf != NULL); /* * Iterate over the the repository pool and search for a plist file * in the binary package matching `pattern'. The plist file will be * internalized to a proplib dictionary. * * The first repository that has it wins and the loop is stopped. * This will work locally and remotely, thanks to libarchive and * libfetch! */ if (xbps_pkgpattern_version(pattern)) pkgd = xbps_rpool_find_pkg(xhp, pattern, true, false); else pkgd = xbps_rpool_find_pkg(xhp, pattern, false, true); if (pkgd == NULL) goto out; prop_dictionary_get_cstring_nocopy(pkgd, "repository", &repoloc); url = xbps_path_from_repository_uri(xhp, pkgd, repoloc); if (url == NULL) { errno = EINVAL; goto out; } plistd = xbps_dictionary_metadata_plist_by_url(url, plistf); free(url); out: if (plistd == NULL) errno = ENOENT; return plistd; }
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); }
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; }