diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-02-28 18:21:42 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-02-28 18:21:42 +0000 |
commit | 24fa17818a2170034cc89cff830c65b921d2a56e (patch) | |
tree | 13044016eee1c259c8b78b7f29fbd1fe5b688322 /qtbz2.c | |
parent | need stdarg for new helper (diff) | |
download | portage-utils-24fa17818a2170034cc89cff830c65b921d2a56e.tar.gz portage-utils-24fa17818a2170034cc89cff830c65b921d2a56e.tar.bz2 portage-utils-24fa17818a2170034cc89cff830c65b921d2a56e.zip |
redo -d dir option so that it avoids chdir, and redo some of the state so that these applets can be run by other applets
Diffstat (limited to 'qtbz2.c')
-rw-r--r-- | qtbz2.c | 198 |
1 files changed, 131 insertions, 67 deletions
@@ -1,7 +1,7 @@ /* * Copyright 2005-2010 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/qtbz2.c,v 1.17 2011/02/21 01:33:47 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/qtbz2.c,v 1.18 2011/02/28 18:21:42 vapier Exp $ * * Copyright 2005-2010 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2010 Mike Frysinger - <vapier@gentoo.org> @@ -27,8 +27,9 @@ #define TBZ2_END_MSG_LEN 4 #define TBZ2_END_LEN (4 + TBZ2_END_MSG_LEN) -#define QTBZ2_FLAGS "jstxO" COMMON_FLAGS +#define QTBZ2_FLAGS "d:jstxO" COMMON_FLAGS static struct option const qtbz2_long_opts[] = { + {"dir", a_argument, NULL, 'd'}, {"join", no_argument, NULL, 'j'}, {"split", no_argument, NULL, 's'}, {"tarbz2", no_argument, NULL, 't'}, @@ -37,6 +38,7 @@ static struct option const qtbz2_long_opts[] = { COMMON_LONG_OPTS }; static const char * const qtbz2_opts_help[] = { + "Change to specified directory", "Join tar.bz2 + xpak into a tbz2", "Split a tbz2 into a tar.bz2 + xpak", "Just split the tar.bz2", @@ -44,7 +46,7 @@ static const char * const qtbz2_opts_help[] = { "Write files to stdout", COMMON_OPTS_HELP }; -static const char qtbz2_rcsid[] = "$Id: qtbz2.c,v 1.17 2011/02/21 01:33:47 vapier Exp $"; +static const char qtbz2_rcsid[] = "$Id: qtbz2.c,v 1.18 2011/02/28 18:21:42 vapier Exp $"; #define qtbz2_usage(ret) usage(ret, QTBZ2_FLAGS, qtbz2_long_opts, qtbz2_opts_help, lookup_applet_idx("qtbz2")) static char tbz2_stdout = 0; @@ -83,28 +85,52 @@ void _tbz2_copy_file(FILE *src, FILE *dst) } } -char tbz2_compose(const char *tarbz2, const char *xpak, const char *tbz2); -char tbz2_compose(const char *tarbz2, const char *xpak, const char *tbz2) +static int +tbz2_compose(int dir_fd, const char *tarbz2, const char *xpak, const char *tbz2) { FILE *out, *in_tarbz2, *in_xpak; struct stat st; - char ret = 1; + int ret = 1, fd; + + if (verbose) + printf("input xpak: %s\ninput tar.bz2: %s\noutput tbz2: %s\n", + xpak, tarbz2, tbz2); /* open tbz2 output */ if ((out = fopen(tbz2, "w")) == NULL) return ret; /* open tar.bz2 input */ - if ((in_tarbz2 = fopen(tarbz2, "r")) == NULL) { + fd = openat(dir_fd, tarbz2, O_RDONLY|O_CLOEXEC); + if (fd < 0) { fclose(out); return ret; } + in_tarbz2 = fdopen(fd, "r"); + if (in_tarbz2 == NULL) { + fclose(out); + close(fd); + return ret; + } /* open xpak input */ - if ((in_xpak = fopen(xpak, "r")) == NULL) { + fd = openat(dir_fd, xpak, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + fclose(out); + fclose(in_tarbz2); + return ret; + } + in_xpak = fdopen(fd, "r"); + if (in_xpak == NULL) { + fclose(out); + fclose(in_tarbz2); + close(fd); + return ret; + } + if (fstat(fd, &st)) { fclose(out); fclose(in_tarbz2); + fclose(in_xpak); return ret; } - fstat(fileno(in_xpak), &st); /* save [tarball] */ _tbz2_copy_file(in_tarbz2, out); @@ -123,8 +149,8 @@ char tbz2_compose(const char *tarbz2, const char *xpak, const char *tbz2) } #define _TBZ2_MIN(a,b) (a < b ? : b) -void _tbz2_write_file(FILE *src, const char *dst, size_t len); -void _tbz2_write_file(FILE *src, const char *dst, size_t len) +static void +_tbz2_write_file(FILE *src, int dir_fd, const char *dst, size_t len) { unsigned char buffer[BUFSIZE*32]; size_t this_write; @@ -135,10 +161,17 @@ void _tbz2_write_file(FILE *src, const char *dst, size_t len) return; } - if (tbz2_stdout) + if (!tbz2_stdout) { + int fd; + + out = NULL; + fd = openat(dir_fd, dst, O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, 0644); + if (fd >= 0) + out = fdopen(fd, "w"); + if (out == NULL) + errp("cannot write to '%s'", dst); + } else out = stdout; - else if ((out = fopen(dst, "w")) == NULL) - errp("cannot write to '%s'", dst); do { this_write = fread(buffer, 1, _TBZ2_MIN(len, sizeof(buffer)), src); @@ -150,19 +183,25 @@ void _tbz2_write_file(FILE *src, const char *dst, size_t len) fclose(out); } -char tbz2_decompose(const char *tbz2, const char *tarbz2, const char *xpak); -char tbz2_decompose(const char *tbz2, const char *tarbz2, const char *xpak) +static int +tbz2_decompose(int dir_fd, const char *tbz2, const char *tarbz2, const char *xpak) { FILE *in; unsigned char tbz2_tail[TBZ2_END_LEN]; long xpak_size, tarbz2_size; struct stat st; - char ret = 1; + int ret = 1; /* open tbz2 input */ - if ((in = fopen(tbz2, "r")) == NULL) + in = fopen(tbz2, "r"); + if (in == NULL) return ret; - fstat(fileno(in), &st); + if (fstat(fileno(in), &st)) + goto close_in_and_ret; + + if (verbose) + printf("input tbz2: %s (%s)\n", tbz2, make_human_readable_str(st.st_size, 1, 0)); + /* verify the tail signature */ if (fseek(in, -TBZ2_END_LEN, SEEK_END) != 0) goto close_in_and_ret; @@ -181,60 +220,71 @@ char tbz2_decompose(const char *tbz2, const char *tarbz2, const char *xpak) /* reset to the start of the tbz2 */ rewind(in); /* dump the tar.bz2 */ - _tbz2_write_file(in, tarbz2, tarbz2_size); + if (verbose) + printf("output tar.bz2: %s (%s)\n", tarbz2, make_human_readable_str(tarbz2_size, 1, 0)); + _tbz2_write_file(in, dir_fd, tarbz2, tarbz2_size); /* dump the xpak */ - _tbz2_write_file(in, xpak, xpak_size); + if (verbose) + printf("output xpak: %s (%s)\n", xpak, make_human_readable_str(xpak_size, 1, 0)); + _tbz2_write_file(in, dir_fd, xpak, xpak_size); ret = 0; -close_in_and_ret: + close_in_and_ret: fclose(in); return ret; } int qtbz2_main(int argc, char **argv) { - int i; - char action = 0, split_xpak = 1, split_tarbz2 = 1; + enum { TBZ2_ACT_NONE, TBZ2_ACT_JOIN, TBZ2_ACT_SPLIT }; + int i, dir_fd; + char action, split_xpak = 1, split_tarbz2 = 1; char *heap_tbz2, *heap_xpak, *heap_tarbz2; char *tbz2, *xpak, *tarbz2; DBG("argc=%d argv[0]=%s argv[1]=%s", argc, argv[0], argc > 1 ? argv[1] : "NULL?"); + action = TBZ2_ACT_NONE; + dir_fd = AT_FDCWD; + while ((i = GETOPT_LONG(QTBZ2, qtbz2, "")) != -1) { switch (i) { COMMON_GETOPTS_CASES(qtbz2) - case 'j': action = 1; break; - case 's': action = 2; break; + case 'j': action = TBZ2_ACT_JOIN; break; + case 's': action = TBZ2_ACT_SPLIT; break; case 't': split_xpak = 0; break; case 'x': split_tarbz2 = 0; break; case 'O': tbz2_stdout = 1; break; + case 'd': + if (dir_fd != AT_FDCWD) + err("Only use -d once"); + dir_fd = open(optarg, O_RDONLY|O_CLOEXEC); + break; } } if (optind == argc) { switch (action) { - case 1: join_usage: - err("Join usage: <input tar.bz2> <input xpak> [<output tbz2>]"); - case 2: split_usage: - err("Split usage <input tbz2> [<output tar.bz2> <output xpak>]"); - default: qtbz2_usage(EXIT_FAILURE); + case TBZ2_ACT_JOIN: err("Join usage: <input tar.bz2> <input xpak> [<output tbz2>]"); + case TBZ2_ACT_SPLIT: err("Split usage: <input tbz2> [<output tar.bz2> <output xpak>]"); + default: qtbz2_usage(EXIT_FAILURE); } } heap_tbz2 = heap_xpak = heap_tarbz2 = NULL; tbz2 = xpak = tarbz2 = NULL; - if (action == 0) { + if (action == TBZ2_ACT_NONE) { if (strstr(argv[optind], ".tar.bz2") != NULL) - action = 1; + action = TBZ2_ACT_JOIN; else if (strstr(argv[optind], ".tbz2") != NULL) - action = 2; + action = TBZ2_ACT_SPLIT; else qtbz2_usage(EXIT_FAILURE); } /* tbz2tool join .tar.bz2 .xpak .tbz2 */ - if (action == 1) { + if (action == TBZ2_ACT_JOIN) { /* grab the params if the user gave them */ tarbz2 = argv[optind++]; if (optind < argc) { @@ -243,20 +293,27 @@ int qtbz2_main(int argc, char **argv) tbz2 = argv[optind]; } /* otherwise guess what they should be */ - if (!xpak) { - i = strlen(tarbz2); - if (i <= 5) goto join_usage; - xpak = heap_xpak = xstrdup(tarbz2); - strcpy(xpak+i-7, "xpak"); - } - if (!tbz2) { - i = strlen(tarbz2); - if (i <= 5) goto join_usage; - tbz2 = heap_tbz2 = xstrdup(tarbz2); - strcpy(tbz2+i-6, "bz2"); + if (!xpak || !tbz2) { + const char *s = basename(tarbz2); + size_t len = strlen(s); + + /* autostrip the tarball extension */ + if (len >= 8 && !strcmp(s + len - 8, ".tar.bz2")) + len -= 8; + + if (!xpak) { + xpak = heap_xpak = xmalloc(len + 5 + 1); + memcpy(xpak, s, len); + strcpy(xpak + len, ".xpak"); + } + if (!tbz2) { + tbz2 = heap_tbz2 = xmalloc(len + 5 + 1); + memcpy(tbz2, s, len); + strcpy(tbz2 + len, ".tbz2"); + } } - if (tbz2_compose(tarbz2, xpak, tbz2)) + if (tbz2_compose(dir_fd, tarbz2, xpak, tbz2)) warn("Could not compose '%s' and '%s'", tarbz2, xpak); /* tbz2tool split .tbz2 .tar.bz2 .xpak */ @@ -269,29 +326,36 @@ int qtbz2_main(int argc, char **argv) xpak = argv[optind]; } /* otherwise guess what they should be */ - if (!tarbz2 && split_tarbz2) { - i = strlen(tbz2); - if (i <= 5) goto split_usage; - tarbz2 = heap_tarbz2 = xmalloc(i + 4); - strcpy(tarbz2, tbz2); - strcpy(tarbz2+i-3, "ar.bz2"); - } else if (!split_tarbz2) - tarbz2 = NULL; - if (!xpak && split_xpak) { - i = strlen(tbz2); - if (i <= 5) goto split_usage; - xpak = heap_xpak = xstrdup(tbz2); - strcpy(xpak+i-4, "xpak"); - } else if (!split_xpak) - xpak = NULL; - - if (tbz2_decompose(tbz2, tarbz2, xpak)) + if ((!tarbz2 && split_tarbz2) || (!xpak && split_xpak)) { + const char *s = basename(tbz2); + size_t len = strlen(s); + + /* autostrip the package extension */ + if (len >= 5 && !strcmp(s + len - 5, ".tbz2")) + len -= 5; + + if (!tarbz2 && split_tarbz2) { + tarbz2 = heap_tarbz2 = xmalloc(len + 8 + 1); + memcpy(tarbz2, s, len); + strcpy(tarbz2 + len, ".tar.bz2"); + } else if (!split_tarbz2) + tarbz2 = NULL; + + if (!xpak && split_xpak) { + xpak = heap_xpak = xmalloc(len + 5 + 1); + memcpy(xpak, s, len); + strcpy(xpak + len, ".xpak"); + } else if (!split_xpak) + xpak = NULL; + } + + if (tbz2_decompose(dir_fd, tbz2, tarbz2, xpak)) warn("Could not decompose '%s'", tbz2); } - if (heap_tbz2) free(heap_tbz2); - if (heap_xpak) free(heap_xpak); - if (heap_tarbz2) free(heap_tarbz2); + free(heap_tbz2); + free(heap_xpak); + free(heap_tarbz2); return EXIT_SUCCESS; } |