From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id A56A313997D for ; Fri, 15 Nov 2019 13:52:21 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id EC13FE0843; Fri, 15 Nov 2019 13:52:20 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id C6C2CE0843 for ; Fri, 15 Nov 2019 13:52:20 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 5B86A34CE76 for ; Fri, 15 Nov 2019 13:52:19 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id D88DC8AB for ; Fri, 15 Nov 2019 13:52:17 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1573825810.5ec1f4368412c8d6f02148d3d9cb109050c8c626.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: /, libq/ X-VCS-Repository: proj/portage-utils X-VCS-Files: libq/xpak.c libq/xpak.h qxpak.c X-VCS-Directories: / libq/ X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: 5ec1f4368412c8d6f02148d3d9cb109050c8c626 X-VCS-Branch: master Date: Fri, 15 Nov 2019 13:52:17 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 6b4c0a54-f939-4a09-b91c-dd7d1657150b X-Archives-Hash: fc674690ffb163a1f768d0570cf9ad7d commit: 5ec1f4368412c8d6f02148d3d9cb109050c8c626 Author: Fabian Groffen gentoo org> AuthorDate: Fri Nov 15 13:50:10 2019 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Fri Nov 15 13:50:10 2019 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=5ec1f436 libq/xpak: rework to reuse more code - introduce xpak_process{,_fd} to replace the very similar list and extract - add _fd variant to be able to pass already open filedescriptor - rework interface to carry a context pointer for the callback func for more flexibility - adapt qxpak for the interface changes Signed-off-by: Fabian Groffen gentoo.org> libq/xpak.c | 132 ++++++++++++++++++++++++++---------------------------------- libq/xpak.h | 26 +++--------- qxpak.c | 98 ++++++++++++++++++++++++++------------------ 3 files changed, 120 insertions(+), 136 deletions(-) diff --git a/libq/xpak.c b/libq/xpak.c index c2e93f9..9692eab 100644 --- a/libq/xpak.c +++ b/libq/xpak.c @@ -39,23 +39,22 @@ #define XPAK_END_MSG_LEN 8 typedef struct { - int dir_fd; + void *ctx; FILE *fp; - int index_len; - int data_len; + unsigned int index_len; + unsigned int data_len; char *index, *data; } _xpak_archive; -typedef void (*xpak_callback_t)(int,char*,int,int,int,char*); - static void _xpak_walk_index( _xpak_archive *x, - int argc, - char **argv, xpak_callback_t func) { - int i, pathname_len, data_offset, data_len; - char *p, pathname[100]; + unsigned int pathname_len; + unsigned int data_offset; + unsigned int data_len; + char *p; + char pathname[100]; p = x->index; while ((p - x->index) < x->index_len) { @@ -73,43 +72,26 @@ static void _xpak_walk_index( p += 4; data_len = READ_BE_INT32((unsigned char*)p); p += 4; - if (argc) { - for (i = 0; i < argc; ++i) { - if (argv[i] && !strcmp(pathname, argv[i])) { - argv[i] = NULL; - break; - } - } - if (i == argc) - continue; - } - (*func)(x->dir_fd, pathname, pathname_len, + (*func)(x->ctx, pathname, pathname_len, data_offset, data_len, x->data); } - - if (argc) - for (i = 0; i < argc; ++i) - if (argv[i]) - warn("Could not locate '%s' in archive", argv[i]); } -static _xpak_archive *_xpak_open(const char *file) +static _xpak_archive *_xpak_open(const int fd) { static _xpak_archive ret; char buf[XPAK_START_LEN]; /* init the file */ memset(&ret, 0x00, sizeof(ret)); - if (file[0] == '-' && file[1] == '\0') - ret.fp = stdin; - else if ((ret.fp = fopen(file, "r")) == NULL) + if ((ret.fp = fdopen(fd, "r")) == NULL) return NULL; /* verify this xpak doesnt suck */ if (fread(buf, 1, XPAK_START_LEN, ret.fp) != XPAK_START_LEN) goto close_and_ret; if (memcmp(buf, XPAK_START_MSG, XPAK_START_MSG_LEN)) { - warn("%s: Invalid xpak", file); + warn("Not an xpak file"); goto close_and_ret; } @@ -117,7 +99,7 @@ static _xpak_archive *_xpak_open(const char *file) ret.index_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN); ret.data_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN+4); if (!ret.index_len || !ret.data_len) { - warn("Skipping empty archive '%s'", file); + warn("Skipping empty archive"); goto close_and_ret; } @@ -135,52 +117,21 @@ static void _xpak_close(_xpak_archive *x) } int -xpak_list( - int dir_fd, - const char *file, - int argc, - char **argv, - xpak_callback_t func) -{ - _xpak_archive *x; - char buf[BUFSIZE]; - size_t ret; - - x = _xpak_open(file); - if (!x) - return 1; - - x->dir_fd = dir_fd; - x->index = buf; - if (x->index_len >= sizeof(buf)) - err("index length %d exceeds limit %zd", x->index_len, sizeof(buf)); - ret = fread(x->index, 1, x->index_len, x->fp); - if (ret != (size_t)x->index_len) - err("insufficient data read, got %zd, requested %d", ret, x->index_len); - _xpak_walk_index(x, argc, argv, func); - - _xpak_close(x); - - return 0; -} - -int -xpak_extract( - int dir_fd, - const char *file, - int argc, - char **argv, +xpak_process_fd( + int fd, + bool get_data, + void *ctx, xpak_callback_t func) { _xpak_archive *x; char buf[BUFSIZE], ext[BUFSIZE*32]; size_t in; - x = _xpak_open(file); + x = _xpak_open(fd); if (!x) return 1; - x->dir_fd = dir_fd; + x->ctx = ctx; x->index = buf; if (x->index_len >= sizeof(buf)) @@ -189,22 +140,51 @@ xpak_extract( if (in != (size_t)x->index_len) err("insufficient data read, got %zd, requested %d", in, x->index_len); - /* the xpak may be large (like when it has CONTENTS) #300744 */ - x->data = (size_t)x->data_len < sizeof(ext) ? ext : xmalloc(x->data_len); - in = fread(x->data, 1, x->data_len, x->fp); - if (in != (size_t)x->data_len) - err("insufficient data read, got %zd, requested %d", in, x->data_len); + if (get_data) { + /* the xpak may be large (like when it has CONTENTS) #300744 */ + x->data = (size_t)x->data_len < sizeof(ext) ? + ext : xmalloc(x->data_len); + in = fread(x->data, 1, x->data_len, x->fp); + if (in != (size_t)x->data_len) + err("insufficient data read, got %zd, requested %d", + in, x->data_len); + } else { + x->data = NULL; + x->data_len = 0; + } - _xpak_walk_index(x, argc, argv, func); + _xpak_walk_index(x, func); _xpak_close(x); - if (x->data != ext) + if (get_data && x->data != ext) free(x->data); return 0; } +int +xpak_process( + const char *file, + bool get_data, + void *ctx, + xpak_callback_t func) +{ + int fd = -1; + int ret; + + if (file[0] == '-' && file[1] == '\0') + fd = 0; + else if ((fd = open(file, O_RDONLY | O_CLOEXEC)) == -1) + return -1; + + ret = xpak_process_fd(fd, get_data, ctx, func); + if (ret != 0) + warn("Unable to open file '%s'", file); + + return ret; +} + static void _xpak_add_file( int dir_fd, @@ -279,7 +259,7 @@ xpak_create( const char *file, int argc, char **argv, - char append, + bool append, int verbose) { FILE *findex, *fdata, *fout; diff --git a/libq/xpak.h b/libq/xpak.h index 0b318b2..aeafdae 100644 --- a/libq/xpak.h +++ b/libq/xpak.h @@ -6,26 +6,12 @@ #ifndef _XPAK_H #define _XPAK_H 1 -typedef void (*xpak_callback_t)(int,char*,int,int,int,char*); +typedef void (*xpak_callback_t)(void *, char *, int, int, int, char *); -int xpak_list( - int dir_fd, - const char *file, - int argc, - char **argv, - xpak_callback_t func); -int xpak_extract( - int dir_fd, - const char *file, - int argc, - char **argv, - xpak_callback_t func); -int xpak_create( - int dir_fd, - const char *file, - int argc, - char **argv, - char append, - int v); +int xpak_process_fd(int, bool, void *, xpak_callback_t); +int xpak_process(const char *, bool, void *, xpak_callback_t); +#define xpak_list(A,B,C) xpak_process(A,false,B,C) +#define xpak_extract(A,B,C) xpak_process(A,true,B,C) +int xpak_create(int, const char *, int, char **, bool, int); #endif diff --git a/qxpak.c b/qxpak.c index eb19cae..fd0ec5d 100644 --- a/qxpak.c +++ b/qxpak.c @@ -42,31 +42,16 @@ static const char * const qxpak_opts_help[] = { static char xpak_stdout; -static void -_xpak_list_callback( - int dir_fd, - char *pathname, - int pathname_len, - int data_offset, - int data_len, - char *data) -{ - (void)dir_fd; - (void)pathname_len; - (void)data; - - if (!verbose) - puts(pathname); - else if (verbose == 1) - printf("%s: %i byte%c\n", pathname, data_len, (data_len>1?'s':' ')); - else - printf("%s: %i byte%c @ offset byte %i\n", - pathname, data_len, (data_len>1?'s':' '), data_offset); -} +struct qxpak_cb { + int dir_fd; + int argc; + char **argv; + bool extract; +}; static void -_xpak_extract_callback( - int dir_fd, +_xpak_callback( + void *ctx, char *pathname, int pathname_len, int data_offset, @@ -74,16 +59,38 @@ _xpak_extract_callback( char *data) { FILE *out; - (void)pathname_len; + struct qxpak_cb *xctx = (struct qxpak_cb *)ctx; + + /* see if there is a match when there is a selection */ + if (xctx->argc > 0) { + int i; + for (i = 0; i < xctx->argc; i++) { + if (xctx->argv[i] && !strcmp(pathname, xctx->argv[i])) { + xctx->argv[i] = NULL; + break; + } + } + if (i == xctx->argc) + return; + } - if (verbose == 1) - puts(pathname); - else if (verbose > 1) - printf("%s: %i byte%c\n", pathname, data_len, (data_len>1?'s':' ')); + if (verbose == 0 + (xctx->extract ? 1 : 0)) + printf("%.*s", pathname_len, pathname); + else if (verbose == 1 + (xctx->extract ? 1 : 0)) + printf("%.*s: %d byte%s\n", + pathname_len, pathname, + data_len, (data_len > 1 ? "s" : "")); + else + printf("%.*s: %d byte%s @ offset byte %d\n", + pathname_len, pathname, + data_len, (data_len > 1 ? "s" : ""), data_offset); + + if (!xctx->extract) + return; if (!xpak_stdout) { - int fd = openat(dir_fd, pathname, - O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, 0644); + int fd = openat(xctx->dir_fd, pathname, + O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, 0644); if (fd < 0) return; out = fdopen(fd, "w"); @@ -101,12 +108,14 @@ _xpak_extract_callback( int qxpak_main(int argc, char **argv) { enum { XPAK_ACT_NONE, XPAK_ACT_LIST, XPAK_ACT_EXTRACT, XPAK_ACT_CREATE }; - int i, ret, dir_fd; + int i, ret; char *xpak; char action = XPAK_ACT_NONE; + struct qxpak_cb cbctx; - dir_fd = AT_FDCWD; xpak_stdout = 0; + cbctx.dir_fd = AT_FDCWD; + cbctx.extract = false; while ((i = GETOPT_LONG(QXPAK, qxpak, "")) != -1) { switch (i) { @@ -116,10 +125,10 @@ int qxpak_main(int argc, char **argv) case 'c': action = XPAK_ACT_CREATE; break; case 'O': xpak_stdout = 1; break; case 'd': - if (dir_fd != AT_FDCWD) + if (cbctx.dir_fd != AT_FDCWD) err("Only use -d once"); - dir_fd = open(optarg, O_RDONLY|O_CLOEXEC|O_PATH); - if (dir_fd < 0) + cbctx.dir_fd = open(optarg, O_RDONLY|O_CLOEXEC|O_PATH); + if (cbctx.dir_fd < 0) errp("Could not open directory %s", optarg); break; } @@ -130,23 +139,32 @@ int qxpak_main(int argc, char **argv) xpak = argv[optind++]; argc -= optind; argv += optind; + cbctx.argc = argc; + cbctx.argv = argv; switch (action) { case XPAK_ACT_LIST: - ret = xpak_list(dir_fd, xpak, argc, argv, &_xpak_list_callback); + ret = xpak_list(xpak, &cbctx, &_xpak_callback); break; case XPAK_ACT_EXTRACT: - ret = xpak_extract(dir_fd, xpak, argc, argv, &_xpak_extract_callback); + cbctx.extract = true; + ret = xpak_extract(xpak, &cbctx, &_xpak_callback); break; case XPAK_ACT_CREATE: - ret = xpak_create(dir_fd, xpak, argc, argv, 0, verbose); + ret = xpak_create(cbctx.dir_fd, xpak, argc, argv, 0, verbose); break; default: ret = EXIT_FAILURE; } - if (dir_fd != AT_FDCWD) - close(dir_fd); + if (cbctx.dir_fd != AT_FDCWD) + close(cbctx.dir_fd); + + /* warn about non-matched args */ + if (argc > 0 && (action == XPAK_ACT_LIST || action == XPAK_ACT_EXTRACT)) + for (i = 0; i < argc; ++i) + if (argv[i]) + warn("Could not locate '%s' in archive", argv[i]); return ret; }