From 77c6c3e5042466048a719ac36db11970b53525de Mon Sep 17 00:00:00 2001 From: Juan RP Date: Mon, 17 Nov 2014 18:43:08 +0100 Subject: [PATCH] Introduce xbps_binpkg_get_file_into_fd() and use it for xbps-query(8) --cat. This allows you to print to stdout any file stored in a binary package, locally or remotely! $ xbps-query -R --cat=/usr/bin/ls coreutils > ls $ file ls ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=7a195fc46d1d5cdca32bfccd3b30f81784e342ed, stripped $ --- bin/xbps-query/show-info-files.c | 12 ++++-------- include/xbps.h.in | 16 +++++++++++++++- lib/plist_fetch.c | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/bin/xbps-query/show-info-files.c b/bin/xbps-query/show-info-files.c index abbf8bbb..4875bc92 100644 --- a/bin/xbps-query/show-info-files.c +++ b/bin/xbps-query/show-info-files.c @@ -311,7 +311,8 @@ int repo_cat_file(struct xbps_handle *xhp, const char *pkg, const char *file) { xbps_dictionary_t pkgd; - char *url, *buf; + char *url; + int rv; pkgd = xbps_rpool_get_pkg(xhp, pkg); if (pkgd == NULL) @@ -322,14 +323,9 @@ repo_cat_file(struct xbps_handle *xhp, const char *pkg, const char *file) return EINVAL; xbps_dbg_printf(xhp, "matched pkg at %s\n", url); - buf = xbps_binpkg_get_file(url, file); + rv = xbps_binpkg_get_file_into_fd(url, file, STDOUT_FILENO); free(url); - if (buf == NULL) - return ENOENT; - - printf("%s", buf); - free(buf); - return 0; + return rv; } int diff --git a/include/xbps.h.in b/include/xbps.h.in index 4aa04c30..4fe08acb 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 "20141117" +#define XBPS_API_VERSION "20141117-1" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -1141,6 +1141,20 @@ int xbps_transaction_commit(struct xbps_handle *xhp); * and errno is set appropiately. */ char *xbps_binpkg_get_file(const char *url, const char *fname); + +/** + * Returns a file stored in a binary package locally or + * remotely as specified in the url \a url and stores it into the + * file descriptor \a fd. + * + * @param[in] url Full URL to binary package file (local or remote path). + * @param[in] fname File name to match. + * @param[in] fd An open file descriptor to put the file into. + * + * @return 0 on success, an errno value otherwise. + */ +int xbps_binpkg_get_file_into_fd(const char *url, const char *fname, int fd); + /** * Internalizes a plist file in a binary package file stored locally or * remotely as specified in the url \a url. diff --git a/lib/plist_fetch.c b/lib/plist_fetch.c index 20ea5cb3..7dd13075 100644 --- a/lib/plist_fetch.c +++ b/lib/plist_fetch.c @@ -168,6 +168,39 @@ xbps_binpkg_get_file(const char *url, const char *fname) return buf; } +int +xbps_binpkg_get_file_into_fd(const char *url, const char *fname, int fd) +{ + struct archive *a; + struct archive_entry *entry; + int rv = 0; + + assert(url); + assert(fname); + assert(fd != -1); + + if ((a = open_archive(url)) == NULL) + return EINVAL; + + while ((archive_read_next_header(a, &entry)) == ARCHIVE_OK) { + const char *bfile; + + bfile = archive_entry_pathname(entry); + bfile++; /* skip first dot */ + if (strcmp(bfile, fname) == 0) { + rv = archive_read_data_into_fd(a, fd); + if (rv != 0) + rv = archive_errno(a); + + break; + } + archive_read_data_skip(a); + } + archive_read_finish(a); + + return rv; +} + xbps_dictionary_t xbps_binpkg_get_plist(const char *url, const char *plistf) {