From a6516505e96c5b388906febace26bfd52c8562e5 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Mon, 17 Nov 2014 15:45:46 +0100 Subject: [PATCH] xbps-query(8: added --cat=FILE mode support. - This mode prints to stdout the matching FILE stored in a binary package. - ABI break: renamed xbps_get_pkg_plist_from_binpkg() xbps_binpkg_get_plist(). - Added xbps_binpkg_get_file() as a generic way to get pkg file contents. - Removed useless comments from xbps_api_impl.h. --- NEWS | 5 + bin/xbps-query/defs.h | 1 + bin/xbps-query/main.c | 15 ++- bin/xbps-query/ownedby.c | 2 +- bin/xbps-query/show-info-files.c | 25 +++++ bin/xbps-query/xbps-query.8 | 8 +- bin/xbps-rindex/index-add.c | 2 +- include/xbps.h.in | 35 ++++--- include/xbps_api_impl.h | 162 ++++++------------------------- lib/archive.c | 26 +++-- lib/plist_fetch.c | 64 ++++++------ lib/repo.c | 2 +- lib/rpool.c | 2 +- 13 files changed, 144 insertions(+), 205 deletions(-) diff --git a/NEWS b/NEWS index 1338ffac..dabdb4bf 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ xbps-0.42 (???): + * xbps-query(8): added --cat=FILE mode to print FILE stored in a binary package + to stdout. This works exactly as the --files mode: if the matching binary package + is not available in the cachedir, xbps will establish a network connection + to the target repository to get the contents of FILE on the fly. + * Get rid of repodata index-files, that contained all pkg files of a repository in the archive. That file was so huge that incresed the repository archive size by 8x. That means that `xbps-query -Ro` will now make N parallel connections diff --git a/bin/xbps-query/defs.h b/bin/xbps-query/defs.h index f16b51ff..5d883948 100644 --- a/bin/xbps-query/defs.h +++ b/bin/xbps-query/defs.h @@ -46,6 +46,7 @@ int show_pkg_info_from_metadir(struct xbps_handle *, const char *, int show_pkg_files(xbps_dictionary_t); int show_pkg_files_from_metadir(struct xbps_handle *, const char *); int repo_show_pkg_files(struct xbps_handle *, const char *); +int repo_cat_file(struct xbps_handle *, const char *, const char *); int repo_show_pkg_info(struct xbps_handle *, const char *, const char *); int repo_show_pkg_namedesc(struct xbps_handle *, xbps_object_t, void *, bool *); diff --git a/bin/xbps-query/main.c b/bin/xbps-query/main.c index 199b5e50..237eeb69 100644 --- a/bin/xbps-query/main.c +++ b/bin/xbps-query/main.c @@ -62,6 +62,7 @@ usage(bool fail) " -o --ownedby FILE Search for package files by matching STRING or REGEX\n" " -S --show PKG Show information for PKG [default mode]\n" " -s --search PKG Search for packages by matching PKG, STRING or REGEX\n" + " --cat=FILE PKG Print FILE from PKG binpkg to stdout\n" " -f --files PKG Show package files for PKG\n" " -x --deps PKG Show dependencies for PKG\n" " -X --revdeps PKG Show reverse dependencies for PKG\n"); @@ -86,7 +87,6 @@ main(int argc, char **argv) { "ownedby", required_argument, NULL, 'o' }, { "property", required_argument, NULL, 'p' }, { "repository", optional_argument, NULL, 'R' }, - { "regex", no_argument, NULL, 0 }, { "rootdir", required_argument, NULL, 'r' }, { "show", required_argument, NULL, 'S' }, { "search", required_argument, NULL, 's' }, @@ -95,17 +95,19 @@ main(int argc, char **argv) { "files", required_argument, NULL, 'f' }, { "deps", required_argument, NULL, 'x' }, { "revdeps", required_argument, NULL, 'X' }, + { "regex", no_argument, NULL, 0 }, { "fulldeptree", no_argument, NULL, 1 }, + { "cat", required_argument, NULL, 2 }, { NULL, 0, NULL, 0 }, }; struct xbps_handle xh; - const char *pkg, *rootdir, *cachedir, *confdir, *props; + const char *pkg, *rootdir, *cachedir, *confdir, *props, *catfile; int c, flags, rv; bool list_pkgs, list_repos, orphans, own; bool list_manual, list_hold, show_prop, show_files, show_deps, show_rdeps; bool show, pkg_search, regex, repo_mode, opmode, fulldeptree; - rootdir = cachedir = confdir = props = pkg = NULL; + rootdir = cachedir = confdir = props = pkg = catfile = NULL; flags = rv = c = 0; list_pkgs = list_repos = list_hold = orphans = pkg_search = own = false; list_manual = show_prop = show_files = false; @@ -195,6 +197,9 @@ main(int argc, char **argv) case 1: fulldeptree = true; break; + case 2: + catfile = optarg; + break; case '?': usage(true); /* NOTREACHED */ @@ -256,6 +261,10 @@ main(int argc, char **argv) /* search mode */ rv = search(&xh, repo_mode, pkg, props, regex); + } else if (catfile) { + /* repo cat file mode */ + rv = repo_cat_file(&xh, pkg, catfile); + } else if (show || show_prop) { /* show mode */ if (repo_mode) diff --git a/bin/xbps-query/ownedby.c b/bin/xbps-query/ownedby.c index 2ad70df9..9395daff 100644 --- a/bin/xbps-query/ownedby.c +++ b/bin/xbps-query/ownedby.c @@ -136,7 +136,7 @@ repo_match_cb(struct xbps_handle *xhp, bfile = xbps_repository_pkg_path(xhp, obj); assert(bfile); - filesd = xbps_get_pkg_plist_from_binpkg(bfile, "./files.plist"); + filesd = xbps_binpkg_get_plist(bfile, "/files.plist"); if (filesd == NULL) { xbps_dbg_printf(xhp, "%s: couldn't fetch files.plist from %s: %s\n", pkgver, bfile, strerror(errno)); diff --git a/bin/xbps-query/show-info-files.c b/bin/xbps-query/show-info-files.c index 72750d3c..a3d587d3 100644 --- a/bin/xbps-query/show-info-files.c +++ b/bin/xbps-query/show-info-files.c @@ -307,6 +307,31 @@ repo_show_pkg_info(struct xbps_handle *xhp, return 0; } +int +repo_cat_file(struct xbps_handle *xhp, const char *pkg, const char *file) +{ + xbps_dictionary_t pkgd; + char *url, *buf; + + pkgd = xbps_rpool_get_pkg(xhp, pkg); + if (pkgd == NULL) + return errno; + + url = xbps_repository_pkg_path(xhp, pkgd); + if (url == NULL) + return EINVAL; + + xbps_dbg_printf(xhp, "matched pkg at %s\n", url); + buf = xbps_binpkg_get_file(url, file); + free(url); + if (buf == NULL) + return ENOENT; + + printf("%s", buf); + free(buf); + return 0; +} + int repo_show_pkg_files(struct xbps_handle *xhp, const char *pkg) { diff --git a/bin/xbps-query/xbps-query.8 b/bin/xbps-query/xbps-query.8 index d2e35c1a..47b25f74 100644 --- a/bin/xbps-query/xbps-query.8 +++ b/bin/xbps-query/xbps-query.8 @@ -1,4 +1,4 @@ -.Dd November 5, 2014 +.Dd November 17, 2014 .Dt XBPS-QUERY 8 .Sh NAME .Nm xbps-query @@ -211,6 +211,12 @@ If the option is set, the matched .Ar PKG in repositories will be shown. +.It Fl -repository Fl -cat Ar FILE Ar PKG +Prints the file +.Ar FILE +stored in binary package +.Ar PKG +to stdout. This expects an absolute path. .El .Sh ENVIRONMENT .Bl -tag -width XBPS_TARGET_ARCH diff --git a/bin/xbps-rindex/index-add.c b/bin/xbps-rindex/index-add.c index 1fc8feb2..3289b7ad 100644 --- a/bin/xbps-rindex/index-add.c +++ b/bin/xbps-rindex/index-add.c @@ -80,7 +80,7 @@ index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force /* * Read metadata props plist dictionary from binary package. */ - binpkgd = xbps_get_pkg_plist_from_binpkg(pkg, "./props.plist"); + binpkgd = xbps_binpkg_get_plist(pkg, "/props.plist"); if (binpkgd == NULL) { fprintf(stderr, "index: failed to read %s metadata for " "`%s', skipping!\n", XBPS_PKGPROPS, pkg); diff --git a/include/xbps.h.in b/include/xbps.h.in index 7ff67e10..4aa04c30 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20141113-1" +#define XBPS_API_VERSION "20141117" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -1131,17 +1131,27 @@ int xbps_transaction_commit(struct xbps_handle *xhp); /*@{*/ /** - * Internalizes a plist file in a binary package file stored locally or - * remotely as specified in \a fname. + * Returns a buffer of a file stored in a binary package locally or + * remotely as specified in the url \a url. * - * @param[in] fname Full URL to binary package file (local or remote path). - * @param[in] plistf Plist file name to internalize. + * @param[in] url Full URL to binary package file (local or remote path). + * @param[in] fname File name to match. + * + * @return A malloc(3)ed buffer with the contents of \a fname, NULL otherwise + * and errno is set appropiately. + */ +char *xbps_binpkg_get_file(const char *url, const char *fname); +/** + * Internalizes a plist file in a binary package file stored locally or + * remotely as specified in the url \a url. + * + * @param[in] url Full URL to binary package file (local or remote path). + * @param[in] p Proplist file name to internalize as a dictionary. * * @return An internalized proplib dictionary, otherwise NULL and * errno is set appropiately. */ -xbps_dictionary_t xbps_get_pkg_plist_from_binpkg(const char *fname, - const char *plistf); +xbps_dictionary_t xbps_binpkg_get_plist(const char *url, const char *p); /*@}*/ @@ -1410,17 +1420,6 @@ int xbps_repo_key_import(struct xbps_repo *repo); /** @addtogroup archive_util */ /*@{*/ -/** - * Returns a proplib dictionary if \a entry is matched in the \a ar archive. - * - * @param[in] ar The archive object. - * @param[in] entry The archive_entry object (must be filled in properly). - * - * @return The internalized proplib dictionary, NULL otherwise. - */ -xbps_dictionary_t xbps_archive_get_dictionary(struct archive *ar, - struct archive_entry *entry); - /** * Appends a file to the \a ar archive by using a memory buffer \a buf of * size \a sizelen. diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index a8b00c62..7c25abc0 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -96,166 +96,58 @@ /** * @private - * From lib/external/dewey.c */ int HIDDEN dewey_match(const char *, const char *); - -/** - * @private - * From lib/pkgdb.c - */ int HIDDEN xbps_pkgdb_init(struct xbps_handle *); void HIDDEN xbps_pkgdb_release(struct xbps_handle *); int HIDDEN xbps_pkgdb_conversion(struct xbps_handle *); - -/** - * @private - * From lib/plist.c - */ -int HIDDEN xbps_array_replace_dict_by_name(xbps_array_t, - xbps_dictionary_t, - const char *); -int HIDDEN xbps_array_replace_dict_by_pattern(xbps_array_t, - xbps_dictionary_t, - const char *); - -/** - * @private - * From lib/plist_remove.c - */ +int HIDDEN xbps_array_replace_dict_by_name(xbps_array_t, xbps_dictionary_t, + const char *); +int HIDDEN xbps_array_replace_dict_by_pattern(xbps_array_t, xbps_dictionary_t, + const char *); bool HIDDEN xbps_remove_pkg_from_array_by_name(xbps_array_t, const char *); bool HIDDEN xbps_remove_pkg_from_array_by_pattern(xbps_array_t, const char *); bool HIDDEN xbps_remove_pkg_from_array_by_pkgver(xbps_array_t, const char *); - -/** - * @private - * From lib/download.c - */ void HIDDEN xbps_fetch_set_cache_connection(int, int); void HIDDEN xbps_fetch_unset_cache_connection(void); - -/** - * @private - * From lib/package_msg.c - */ int HIDDEN xbps_cb_message(struct xbps_handle *, xbps_dictionary_t, const char *); - -/** - * @private - * From lib/package_config_files.c - */ int HIDDEN xbps_entry_is_a_conf_file(xbps_dictionary_t, const char *); -int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, - xbps_dictionary_t, - xbps_dictionary_t, - struct archive_entry *, - const char *, - const char *); - -/** - * @private - * From lib/repo.c - */ -void HIDDEN xbps_repo_invalidate(struct xbps_repo *); - -/** - * @private - * From lib/repo_pkgdeps.c - */ -int HIDDEN xbps_repository_find_deps(struct xbps_handle *, - xbps_array_t, - xbps_dictionary_t); - -/** - * @private - * From lib/plist_find.c - */ +int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, xbps_dictionary_t, + xbps_dictionary_t, struct archive_entry *, const char *, + const char *); +int HIDDEN xbps_repository_find_deps(struct xbps_handle *, xbps_array_t, + xbps_dictionary_t); xbps_dictionary_t HIDDEN xbps_find_pkg_in_dict(xbps_dictionary_t, const char *); -xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_dict(struct xbps_handle *, xbps_dictionary_t, const char *); -xbps_dictionary_t HIDDEN xbps_find_pkg_in_array(xbps_array_t, const char *, const char *); -xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_array(struct xbps_handle *, xbps_array_t, const char *, const char *); -/** - * @private - * From lib/transaction_revdeps.c - */ +xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_dict(struct xbps_handle *, + xbps_dictionary_t, const char *); +xbps_dictionary_t HIDDEN xbps_find_pkg_in_array(xbps_array_t, const char *, + const char *); +xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_array(struct xbps_handle *, + xbps_array_t, const char *, const char *); void HIDDEN xbps_transaction_revdeps(struct xbps_handle *, xbps_array_t); - -/** - * @privuate - * From lib/transaction_shlibs.c - */ -bool HIDDEN xbps_transaction_shlibs(struct xbps_handle *, xbps_array_t, xbps_array_t); - -/** - * @private - * From lib/transaction_dictionary.c - */ +bool HIDDEN xbps_transaction_shlibs(struct xbps_handle *, xbps_array_t, + xbps_array_t); int HIDDEN xbps_transaction_init(struct xbps_handle *); - -int HIDDEN xbps_transaction_store(struct xbps_handle *, xbps_array_t, xbps_dictionary_t, bool); - -/** - * @private - * From lib/repo_sync.c - */ +int HIDDEN xbps_transaction_store(struct xbps_handle *, xbps_array_t, + xbps_dictionary_t, bool); char HIDDEN *xbps_get_remote_repo_string(const char *); int HIDDEN xbps_repo_sync(struct xbps_handle *, const char *); - -/** - * @private - * From lib/util_hash.c - */ int HIDDEN xbps_file_hash_check_dictionary(struct xbps_handle *, - xbps_dictionary_t d, - const char *, - const char *); - -/** - * @private - * From lib/external/fexec.c - */ + xbps_dictionary_t, const char *, const char *); int HIDDEN xbps_file_exec(struct xbps_handle *, const char *, ...); - -/** - * @private - * From lib/cb_util.c - */ void HIDDEN xbps_set_cb_fetch(struct xbps_handle *, off_t, off_t, off_t, - const char *, bool, bool, bool); + const char *, bool, bool, bool); int HIDDEN xbps_set_cb_state(struct xbps_handle *, xbps_state_t, int, - const char *, const char *, ...); - -/** - * @private - * From lib/package_unpack.c - */ + const char *, const char *, ...); int HIDDEN xbps_unpack_binary_pkg(struct xbps_handle *, xbps_dictionary_t); - int HIDDEN xbps_transaction_package_replace(struct xbps_handle *, xbps_array_t); - -/** - * @private - * From lib/package_remove.c - */ int HIDDEN xbps_remove_pkg(struct xbps_handle *, const char *, bool); - -/** - * @private - * From lib/package_register.c - */ int HIDDEN xbps_register_pkg(struct xbps_handle *, xbps_dictionary_t); - -/** - * @private - * From lib/package_conflicts.c - */ -void HIDDEN xbps_pkg_find_conflicts(struct xbps_handle *, - xbps_array_t, - xbps_dictionary_t); -/** - * @private - * From lib/plist_find.c - */ +void HIDDEN xbps_pkg_find_conflicts(struct xbps_handle *, xbps_array_t, + xbps_dictionary_t); +char HIDDEN *xbps_archive_get_file(struct archive *, struct archive_entry *); +xbps_dictionary_t HIDDEN xbps_archive_get_dictionary(struct archive *, + struct archive_entry *); const char HIDDEN *vpkg_user_conf(struct xbps_handle *, const char *, bool); #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/archive.c b/lib/archive.c index da3c0757..1afb25ed 100644 --- a/lib/archive.c +++ b/lib/archive.c @@ -31,10 +31,9 @@ #include "xbps_api_impl.h" -xbps_dictionary_t HIDDEN -xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) +char HIDDEN * +xbps_archive_get_file(struct archive *ar, struct archive_entry *entry) { - xbps_dictionary_t d = NULL; size_t buflen; ssize_t nbytes = -1; char *buf; @@ -43,7 +42,7 @@ xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) assert(entry != NULL); buflen = (size_t)archive_entry_size(entry); - buf = malloc(buflen); + buf = malloc(buflen+1); if (buf == NULL) return NULL; @@ -52,14 +51,23 @@ xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) free(buf); return NULL; } + buf[buflen] = '\0'; + return buf; +} + +xbps_dictionary_t HIDDEN +xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) +{ + xbps_dictionary_t d = NULL; + char *buf; + + if ((buf = xbps_archive_get_file(ar, entry)) == NULL) + return NULL; /* If blob is already a dictionary we are done */ d = xbps_dictionary_internalize(buf); - if (xbps_object_type(d) == XBPS_TYPE_DICTIONARY) { - free(buf); - return d; - } - return NULL; + free(buf); + return d; } int diff --git a/lib/plist_fetch.c b/lib/plist_fetch.c index 519fc22e..20ea5cb3 100644 --- a/lib/plist_fetch.c +++ b/lib/plist_fetch.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2013 Juan Romero Pardines. + * Copyright (c) 2009-2014 Juan Romero Pardines. * Copyright (c) 2008, 2009 Joerg Sonnenberger * All rights reserved. * @@ -139,51 +139,45 @@ open_archive(const char *url) return a; } -xbps_dictionary_t -xbps_get_pkg_plist_from_binpkg(const char *fname, const char *plistf) +char * +xbps_binpkg_get_file(const char *url, const char *fname) { - xbps_dictionary_t plistd = NULL; struct archive *a; struct archive_entry *entry; - const char *comptype; - int i = 0; + char *buf = NULL; - assert(fname != NULL); - assert(plistf != NULL); + assert(url); + assert(fname); - if ((a = open_archive(fname)) == NULL) + if ((a = open_archive(url)) == NULL) return NULL; - /* - * Save compression type string for future use. - */ - comptype = archive_compression_name(a); - while ((archive_read_next_header(a, &entry)) == ARCHIVE_OK) { - if (strcmp(archive_entry_pathname(entry), plistf)) { - archive_read_data_skip(a); - if (i >= 3) { - /* - * Archive does not contain required - * plist file, discard it completely. - */ - errno = ENOENT; - break; - } - i++; - continue; - } - plistd = xbps_archive_get_dictionary(a, entry); - if (plistd == NULL) { - errno = EINVAL; + const char *bfile; + + bfile = archive_entry_pathname(entry); + bfile++; /* skip first dot */ + if (strcmp(bfile, fname) == 0) { + buf = xbps_archive_get_file(a, entry); break; } - xbps_dictionary_set_cstring_nocopy(plistd, - "archive-compression-type", comptype); - - break; + archive_read_data_skip(a); } archive_read_finish(a); - return plistd; + return buf; +} + +xbps_dictionary_t +xbps_binpkg_get_plist(const char *url, const char *plistf) +{ + xbps_dictionary_t d; + char *buf; + + if ((buf = xbps_binpkg_get_file(url, plistf)) == NULL) + return NULL; + + d = xbps_dictionary_internalize(buf); + free(buf); + return d; } diff --git a/lib/repo.c b/lib/repo.c index 8d835033..855de1dd 100644 --- a/lib/repo.c +++ b/lib/repo.c @@ -277,7 +277,7 @@ xbps_repo_get_pkg_plist(struct xbps_handle *xhp, xbps_dictionary_t pkgd, if (url == NULL) return NULL; - bpkgd = xbps_get_pkg_plist_from_binpkg(url, plist); + bpkgd = xbps_binpkg_get_plist(url, plist); free(url); return bpkgd; } diff --git a/lib/rpool.c b/lib/rpool.c index be92b9fe..47c728f8 100644 --- a/lib/rpool.c +++ b/lib/rpool.c @@ -315,7 +315,7 @@ xbps_rpool_get_pkg_plist(struct xbps_handle *xhp, errno = EINVAL; goto out; } - plistd = xbps_get_pkg_plist_from_binpkg(url, plistf); + plistd = xbps_binpkg_get_plist(url, plistf); free(url); out: