/*- * Copyright (c) 2008-2012 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "defs.h" #include "../xbps-bin/defs.h" static void __attribute__((noreturn)) usage(bool fail) { fprintf(stderr, "Usage: xbps-repo [options] target [arguments]\n\n" "[options]\n" " -C file Full path to configuration file\n" " -c cachedir Full path to cachedir to store downloaded binpkgs\n" " -d Debug mode shown to stderr\n" " -h Print usage help\n" " -o key[,key] Print package metadata keys in show target\n" " -r rootdir Full path to rootdir\n" " -V Show XBPS version\n\n" "[targets]\n" " clean\n" " Removes obsolete binary packages from cachedir.\n" " find-files [patterns]\n" " Print package name/version for any pattern matched.\n" " genindex \n" " Generate a local repository in `directory'.\n" " list\n" " List registered repositories.\n" " pkg-list [repo]\n" " Print packages in repository matching `repo' URI.\n" " If `repo' not specified, all registered repositories will be used.\n" " search [patterns]\n" " Search for packages in repositories matching the patterns.\n" " show \n" " Print package information for `pkgname' or `pkgpattern'.\n" " show-deps \n" " Print package's required dependencies for `pkgname' or `pkgpattern'.\n" " show-files \n" " Print package's files list for `pkgname' or `pkgpattern'.\n" " sync [repo]\n" " Synchronize package index file for `repo'.\n" " If `repo' not specified, all remote repositories will be used. \n\n" "Refer to xbps-repo(8) for a more detailed description.\n"); exit(fail ? EXIT_FAILURE : EXIT_SUCCESS); } int main(int argc, char **argv) { struct xbps_handle xh; struct xferstat xfer; struct repo_search_data *rsd = NULL; prop_dictionary_t pkgd; const char *rootdir, *cachedir, *conffile, *option; int flags = 0, c, rv = 0; rootdir = cachedir = conffile = option = NULL; while ((c = getopt(argc, argv, "C:c:dho:r:V")) != -1) { switch (c) { case 'C': conffile = optarg; break; case 'c': cachedir = optarg; break; case 'd': flags |= XBPS_FLAG_DEBUG; break; case 'h': usage(false); break; case 'o': option = optarg; break; case 'r': /* To specify the root directory */ rootdir = optarg; break; case 'V': printf("%s\n", XBPS_RELVER); exit(EXIT_SUCCESS); case '?': default: usage(true); } } argc -= optind; argv += optind; if (argc < 1) usage(true); /* * Initialize XBPS subsystems. */ memset(&xh, 0, sizeof(xh)); xh.flags = flags; xh.state_cb = state_cb; xh.fetch_cb = fetch_file_progress_cb; xh.fetch_cb_data = &xfer; xh.rootdir = rootdir; xh.cachedir = cachedir; xh.conffile = conffile; if ((rv = xbps_init(&xh)) != 0) { xbps_error_printf("xbps-repo: couldn't initialize library: %s\n", strerror(rv)); exit(EXIT_FAILURE); } if (strcasecmp(argv[0], "list") == 0) { /* Lists all repositories registered in pool. */ if (argc != 1) usage(true); rv = xbps_rpool_foreach(&xh, repo_list_uri_cb, NULL); if (rv == ENOTSUP) xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); else if (rv != 0 && rv != ENOTSUP) xbps_error_printf("xbps-repo: failed to initialize " "rpool: %s\n", strerror(rv)); } else if (strcasecmp(argv[0], "pkg-list") == 0) { /* * Only list packages for the target repository. */ if (argc < 1 || argc > 2) usage(true); rv = xbps_rpool_foreach(&xh, repo_pkg_list_cb, argv[1]); if (rv == ENOTSUP) xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); else if (rv != 0) xbps_error_printf("xbps-repo: failed to initialize " "rpool: %s\n", strerror(rv)); } else if (strcasecmp(argv[0], "search") == 0) { /* * Search for a package by looking at pkgname/short_desc * by using shell style match patterns (fnmatch(3)). */ if (argc < 2) usage(true); rsd = malloc(sizeof(*rsd)); if (rsd == NULL) { rv = ENOMEM; goto out; } rsd->npatterns = argc; rsd->patterns = argv; rv = xbps_rpool_foreach(&xh, repo_search_pkgs_cb, rsd); free(rsd); if (rv == ENOTSUP) xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); else if (rv != 0 && rv != ENOTSUP) xbps_error_printf("xbps-repo: failed to initialize " "rpool: %s\n", strerror(rv)); } else if (strcasecmp(argv[0], "show") == 0) { /* Shows info about a binary package. */ if (argc != 2) usage(true); rv = show_pkg_info_from_repolist(&xh, argv[1], option); if (rv == ENOENT) { xbps_error_printf("Unable to locate package " "`%s' in repository pool.\n", argv[1]); } else if (rv == ENOTSUP) { xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } else if (rv != 0 && rv != ENOENT) { xbps_error_printf("xbps-repo: unexpected error '%s' ", "searching for '%s'\n", strerror(rv), argv[1]); } } else if (strcasecmp(argv[0], "show-deps") == 0) { /* Shows the required run dependencies for a package. */ if (argc != 2) usage(true); rv = show_pkg_deps_from_repolist(&xh, argv[1]); if (rv == ENOENT) { xbps_error_printf("Unable to locate package " "`%s' in repository pool.\n", argv[1]); } else if (rv == ENOTSUP) { xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } else if (rv != 0 && rv != ENOENT) { xbps_error_printf("xbps-repo: unexpected error '%s' " "searching for '%s'\n", strerror(errno), argv[1]); } } else if (strcasecmp(argv[0], "show-files") == 0) { /* Shows the package files in a binary package */ if (argc != 2) usage(true); pkgd = xbps_rpool_dictionary_metadata_plist(&xh, argv[1], "./files.plist"); if (pkgd == NULL) { if (errno == ENOTSUP) { xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } else if (errno == ENOENT) { xbps_error_printf("Unable to locate package `%s' " "in repository pool.\n", argv[1]); } else { xbps_error_printf("xbps-repo: unexpected " "error '%s' searching for '%s'\n", strerror(errno), argv[1]); } rv = errno; goto out; } rv = show_pkg_files(pkgd); prop_object_release(pkgd); } else if (strcasecmp(argv[0], "find-files") == 0) { /* Finds files by patterns, exact matches and components. */ if (argc < 2) usage(true); rv = repo_find_files_in_packages(&xh, argc, argv); if (rv == ENOTSUP) { xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } } else if (strcasecmp(argv[0], "genindex") == 0) { /* Generates a package repository index plist file. */ if (argc != 2) usage(true); rv = repo_genindex(&xh, argv[1]); if (rv == 0) rv = repo_genindex_files(&xh, argv[1]); } else if (strcasecmp(argv[0], "sync") == 0) { /* Syncs the pkg index for all registered remote repos */ if (argc < 1 || argc > 2) usage(true); rv = xbps_rpool_sync(&xh, argv[1]); if (rv == ENOTSUP) { xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } } else if (strcasecmp(argv[0], "clean") == 0) { /* Cleans up cache directory */ if (argc != 1) usage(true); rv = cachedir_clean(&xh); } else { usage(true); } out: xbps_end(&xh); exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); }