From 11d2ff5ffac9382be0d6971b8ac84df21eca85df Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 8 Aug 2015 19:21:42 -0500 Subject: First pass at proper bunzip2 command line handling. --- lib/lib.c | 2 +- toys/other/bzcat.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 81c989ab..4b87f8cf 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -575,7 +575,7 @@ void delete_tempfile(int fdin, int fdout, char **tempname) { close(fdin); close(fdout); - unlink(*tempname); + if (*tempname) unlink(*tempname); tempfile2zap = (char *)1; free(*tempname); *tempname = NULL; diff --git a/toys/other/bzcat.c b/toys/other/bzcat.c index 642590d1..850c51ce 100644 --- a/toys/other/bzcat.c +++ b/toys/other/bzcat.c @@ -1,4 +1,4 @@ -/* bzcat.c - decompress stdin to stdout using bunzip2. +/* bzcat.c - bzip2 decompression * * Copyright 2003, 2007 Rob Landley * @@ -12,16 +12,33 @@ USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN)) +USE_BUNZIP2(NEWTOY(bunzip2, "cftkv", TOYFLAG_USR|TOYFLAG_BIN)) + +config BUNZIP2 + bool "bunzip2" + default y + help + usage: bunzip2 [-cftkv] [FILE...] + + Decompress listed files (file.bz becomes file) deleting archive file(s). + Read from stdin if no files listed. + + -c force output to stdout + -f force decompression. (If FILE doesn't end in .bz, replace original.) + -k keep input files (-c and -t imply this) + -t test integrity + -v verbose config BZCAT bool "bzcat" default y help - usage: bzcat [filename...] + usage: bzcat [FILE...] Decompress listed files to stdout. Use stdin if no files listed. */ +#define FOR_bunzip2 #include "toys.h" #define THREADS 1 @@ -421,7 +438,7 @@ static int read_huffman_data(struct bunzip_data *bd, struct bwdata *bw) } // Flush output buffer to disk -void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) +static void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) { if (bd->outbufPos) { if (write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) @@ -430,7 +447,7 @@ void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) } } -void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) +static void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) { int ii, jj; unsigned int *dbuf = bw->dbuf; @@ -474,7 +491,7 @@ void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) } // Decompress a block of text to intermediate buffer -int read_bunzip_data(struct bunzip_data *bd) +static int read_bunzip_data(struct bunzip_data *bd) { int rc = read_block_header(bd, bd->bwdata); if (!rc) rc=read_huffman_data(bd, bd->bwdata); @@ -493,7 +510,8 @@ int read_bunzip_data(struct bunzip_data *bd) // http://dogma.net/markn/articles/bwt/bwt.htm // http://marknelson.us/1996/09/01/bwt/ -int write_bunzip_data(struct bunzip_data *bd, struct bwdata *bw, int out_fd, char *outbuf, int len) +static int write_bunzip_data(struct bunzip_data *bd, struct bwdata *bw, + int out_fd, char *outbuf, int len) { unsigned int *dbuf = bw->dbuf; int count, pos, current, run, copies, outbyte, previous, gotcount = 0; @@ -584,7 +602,8 @@ dataus_interruptus: // Allocate the structure, read file header. If !len, src_fd contains // filehandle to read from. Else inbuf contains data. -int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, int len) +static int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, + int len) { struct bunzip_data *bd; unsigned int i; @@ -622,10 +641,10 @@ int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, int len) // Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, // not end of file.) -void bunzipStream(int src_fd, int dst_fd) +static char *bunzipStream(int src_fd, int dst_fd) { struct bunzip_data *bd; - char *bunzip_errors[]={NULL, "not bzip", "bad data", "old format"}; + char *bunzip_errors[] = {0, "not bzip", "bad data", "old format"}; int i, j; if (!(i = start_bunzip(&bd,src_fd, 0, 0))) { @@ -636,15 +655,67 @@ void bunzipStream(int src_fd, int dst_fd) for (j=0; jbwdata[j].dbuf); free(bd); - if (i) error_exit(bunzip_errors[-i]); + + return bunzip_errors[-i]; } static void do_bzcat(int fd, char *name) { - bunzipStream(fd, 1); + char *err = bunzipStream(fd, 1); + + if (err) error_exit(err); } void bzcat_main(void) { loopfiles(toys.optargs, do_bzcat); } + +static void do_bunzip2(int fd, char *name) +{ + int outfd = 1, rename = 0, len = strlen(name); + char *tmp, *err, *dotbz = 0; + + // Trim off .bz or .bz2 extension + dotbz = name+len-3; + if ((len>3 && !strcmp(dotbz, ".bz")) || (len>4 && !strcmp(--dotbz, ".bz2"))) + dotbz = 0; + + // For - no replace + if (toys.optflags&FLAG_t) outfd = xopen("/dev/null", O_WRONLY); + else if ((fd || strcmp(name, "-")) && !(toys.optflags&FLAG_c)) { + if (toys.optflags&FLAG_k) { + if (!dotbz || !access(name, X_OK)) { + error_msg("%s exists", name); + + return; + } + } + outfd = copy_tempfile(fd, name, &tmp); + rename++; + } + + if (toys.optflags&FLAG_v) printf("%s:", name); + err = bunzipStream(fd, outfd); + if (toys.optflags&FLAG_v) { + printf("%s\n", err ? err : "ok"); + toys.exitval |= !!err; + } else if (err) error_msg(err); + + // can't test outfd==1 because may have been called with stdin+stdout closed + if (rename) { + if (toys.optflags&FLAG_k) { + free(tmp); + tmp = 0; + } else { + if (dotbz) *dotbz = '.'; + if (!unlink(name)) perror_msg("%s", name); + } + (err ? delete_tempfile : replace_tempfile)(-1, outfd, &tmp); + } +} + +void bunzip2_main(void) +{ + loopfiles(toys.optargs, do_bunzip2); +} -- cgit v1.2.3