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); }
/* * Returns -1 on error, 0 if transfer was not necessary (local/remote * size and/or mtime match) and 1 if downloaded successfully. */ int HIDDEN xbps_repo_sync(struct xbps_handle *xhp, const char *uri) { const char *arch, *fetchstr = NULL; char *repodata, *lrepodir, *uri_fixedp; int rv = 0; assert(uri != NULL); /* ignore non remote repositories */ if (!xbps_repository_is_remote(uri)) return 0; uri_fixedp = xbps_get_remote_repo_string(uri); if (uri_fixedp == NULL) return -1; if (xhp->target_arch) arch = xhp->target_arch; else arch = xhp->native_arch; /* * Full path to repository directory to store the plist * index file. */ lrepodir = xbps_xasprintf("%s/%s", xhp->metadir, uri_fixedp); free(uri_fixedp); /* * Create repodir in metadir. */ if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) { if (errno != EEXIST) { xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, errno, NULL, "[reposync] failed " "to create repodir `%s': %s", lrepodir, strerror(errno)); free(lrepodir); return rv; } } if (chdir(lrepodir) == -1) { xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, errno, NULL, "[reposync] failed to change dir to repodir `%s': %s", lrepodir, strerror(errno)); free(lrepodir); return -1; } free(lrepodir); /* * Remote repository plist index full URL. */ repodata = xbps_xasprintf("%s/%s-repodata", uri, arch); /* reposync start cb */ xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, repodata, NULL); /* * Download plist index file from repository. */ if ((rv = xbps_fetch_file(xhp, repodata, NULL)) == -1) { /* reposync error cb */ fetchstr = xbps_fetch_error_string(); xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, fetchLastErrCode != 0 ? fetchLastErrCode : errno, NULL, "[reposync] failed to fetch file `%s': %s", repodata, fetchstr ? fetchstr : strerror(errno)); } else if (rv == 1) rv = 0; free(repodata); return rv; }
static int download_binpkgs(struct xbps_handle *xhp, prop_object_iterator_t iter) { prop_object_t obj; const char *pkgver, *repoloc, *filen, *trans; const char *pkgname, *version, *fetchstr; char *binfile; int rv = 0; while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "transaction", &trans); if ((strcmp(trans, "remove") == 0) || (strcmp(trans, "configure") == 0)) continue; prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "version", &version); prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); assert(repoloc != NULL); prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); assert(pkgver != NULL); prop_dictionary_get_cstring_nocopy(obj, "filename", &filen); assert(filen != NULL); binfile = xbps_path_from_repository_uri(xhp, obj, repoloc); if (binfile == NULL) { rv = EINVAL; break; } /* * If downloaded package is in cachedir continue. */ if (access(binfile, R_OK) == 0) { free(binfile); continue; } /* * Create cachedir. */ if (xbps_mkpath(xhp->cachedir, 0755) == -1) { xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD_FAIL, errno, pkgname, version, "%s: [trans] cannot create cachedir `%s': %s", pkgver, xhp->cachedir, strerror(errno)); free(binfile); rv = errno; break; } xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD, 0, pkgname, version, "Downloading binary package `%s' (from `%s')...", filen, repoloc); /* * Fetch binary package. */ rv = xbps_fetch_file(xhp, binfile, xhp->cachedir, false, NULL); if (rv == -1) { fetchstr = xbps_fetch_error_string(); xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD_FAIL, fetchLastErrCode != 0 ? fetchLastErrCode : errno, pkgname, version, "%s: [trans] failed to download binary package " "`%s' from `%s': %s", pkgver, filen, repoloc, fetchstr ? fetchstr : strerror(errno)); free(binfile); break; } rv = 0; free(binfile); } prop_object_iterator_reset(iter); return rv; }