X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=422798ed32f696bece6e3799ce42caac9525a6ea;hb=cbc51277aa4de1f41434ba073f2e4546ead63005;hp=07b11ab9c487d6c4c70f99c7e03fff0cbd87378e;hpb=ab6dd4948d1736b97a343d3c183f2dedad7421bb;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index 07b11ab..422798e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -76,7 +76,7 @@ static bool read_full_records = false; /* We're reading, but we just read the last block and it's time to update. Declared in update.c - + FIXME: Either eliminate it or move it to common.h. */ extern bool time_to_start_writing; @@ -103,7 +103,7 @@ bool write_archive_to_stdout; /* Multi-volume tracking support */ -/* When creating a multi-volume archive, each `bufmap' represents +/* When creating a multi-volume archive, each 'bufmap' represents a member stored (perhaps partly) in the current record buffer. After flushing the record to the output media, all bufmaps that represent fully written members are removed from the list, then @@ -152,7 +152,7 @@ static struct bufmap * bufmap_locate (size_t off) { struct bufmap *map; - + for (map = bufmap_head; map; map = map->next) { if (!map->next @@ -193,7 +193,7 @@ bufmap_reset (struct bufmap *map, ssize_t fixup) static struct tar_stat_info dummy; void -buffer_write_global_xheader () +buffer_write_global_xheader (void) { xheader_write_global (&dummy.xhdr); } @@ -205,7 +205,7 @@ mv_begin_read (struct tar_stat_info *st) } void -mv_end () +mv_end (void) { if (multi_volume_option) bufmap_free (NULL); @@ -233,7 +233,7 @@ clear_read_error_count (void) double duration; void -set_start_time () +set_start_time (void) { gettime (&start_time); volume_start_time = start_time; @@ -248,7 +248,7 @@ set_volume_start_time (void) } void -compute_duration () +compute_duration (void) { struct timespec now; gettime (&now); @@ -261,8 +261,8 @@ compute_duration () /* Compression detection */ enum compress_type { - ct_tar, /* Plain tar file */ ct_none, /* Unknown compression type */ + ct_tar, /* Plain tar file */ ct_compress, ct_gzip, ct_bzip2, @@ -272,31 +272,102 @@ enum compress_type { ct_xz }; +static enum compress_type archive_compression_type = ct_none; + struct zip_magic { enum compress_type type; size_t length; char const *magic; +}; + +struct zip_program +{ + enum compress_type type; char const *program; char const *option; }; static struct zip_magic const magic[] = { - { ct_tar }, - { ct_none, }, - { ct_compress, 2, "\037\235", COMPRESS_PROGRAM, "-Z" }, - { ct_gzip, 2, "\037\213", GZIP_PROGRAM, "-z" }, - { ct_bzip2, 3, "BZh", BZIP2_PROGRAM, "-j" }, - { ct_lzip, 4, "LZIP", LZIP_PROGRAM, "--lzip" }, - { ct_lzma, 6, "\xFFLZMA", LZMA_PROGRAM, "--lzma" }, - { ct_lzop, 4, "\211LZO", LZOP_PROGRAM, "--lzop" }, - { ct_xz, 6, "\xFD" "7zXZ", XZ_PROGRAM, "-J" }, + { ct_none, 0, 0 }, + { ct_tar, 0, 0 }, + { ct_compress, 2, "\037\235" }, + { ct_gzip, 2, "\037\213" }, + { ct_bzip2, 3, "BZh" }, + { ct_lzip, 4, "LZIP" }, + { ct_lzma, 6, "\xFFLZMA" }, + { ct_lzop, 4, "\211LZO" }, + { ct_xz, 6, "\xFD" "7zXZ" }, }; #define NMAGIC (sizeof(magic)/sizeof(magic[0])) -#define compress_option(t) magic[t].option -#define compress_program(t) magic[t].program +static struct zip_program zip_program[] = { + { ct_compress, COMPRESS_PROGRAM, "-Z" }, + { ct_compress, GZIP_PROGRAM, "-z" }, + { ct_gzip, GZIP_PROGRAM, "-z" }, + { ct_bzip2, BZIP2_PROGRAM, "-j" }, + { ct_bzip2, "lbzip2", "-j" }, + { ct_lzip, LZIP_PROGRAM, "--lzip" }, + { ct_lzma, LZMA_PROGRAM, "--lzma" }, + { ct_lzma, XZ_PROGRAM, "-J" }, + { ct_lzop, LZOP_PROGRAM, "--lzop" }, + { ct_xz, XZ_PROGRAM, "-J" }, + { ct_none } +}; + +static struct zip_program const * +find_zip_program (enum compress_type type, int *pstate) +{ + int i; + + for (i = *pstate; zip_program[i].type != ct_none; i++) + { + if (zip_program[i].type == type) + { + *pstate = i + 1; + return zip_program + i; + } + } + *pstate = i; + return NULL; +} + +const char * +first_decompress_program (int *pstate) +{ + struct zip_program const *zp; + + if (use_compress_program_option) + return use_compress_program_option; + + if (archive_compression_type == ct_none) + return NULL; + + *pstate = 0; + zp = find_zip_program (archive_compression_type, pstate); + return zp ? zp->program : NULL; +} + +const char * +next_decompress_program (int *pstate) +{ + struct zip_program const *zp; + + if (use_compress_program_option) + return NULL; + zp = find_zip_program (archive_compression_type, pstate); + return zp ? zp->program : NULL; +} + +static const char * +compress_option (enum compress_type type) +{ + struct zip_program const *zp; + int i = 0; + zp = find_zip_program (type, &i); + return zp ? zp->option : NULL; +} /* Check if the file ARCHIVE is a compressed archive. */ static enum compress_type @@ -389,13 +460,13 @@ open_compressed_archive (void) case ct_none: if (shortfile) ERROR ((0, 0, _("This does not look like a tar archive"))); - set_comression_program_by_suffix (archive_name_array[0], NULL); + set_compression_program_by_suffix (archive_name_array[0], NULL); if (!use_compress_program_option) return archive; break; default: - use_compress_program_option = compress_program (type); + archive_compression_type = type; break; } } @@ -438,7 +509,7 @@ print_stats (FILE *fp, const char *text, tarlong numbytes) } void -print_total_stats () +print_total_stats (void) { switch (subcommand_option) { @@ -576,7 +647,7 @@ _open_archive (enum access_mode wanted_access) FATAL_ERROR ((0, 0, _("No archive name given"))); tar_stat_destroy (¤t_stat_info); - + record_index = 0; init_buffer (); @@ -749,7 +820,7 @@ _flush_write (void) map = map->next; bufmap_reset (map, map ? (- map->start) : 0); } - } + } return status; } @@ -1771,7 +1842,7 @@ _gnu_flush_write (size_t buffer_level) size_t copy_size; size_t bufsize; struct bufmap *map; - + status = _flush_write (); if (status != record_size && !multi_volume_option) archive_write_error (status); @@ -1788,7 +1859,7 @@ _gnu_flush_write (size_t buffer_level) } map = bufmap_locate (status); - + if (status % BLOCKSIZE) { ERROR ((0, 0, _("write did not end on a block boundary"))); @@ -1811,13 +1882,13 @@ _gnu_flush_write (size_t buffer_level) copy_ptr = record_start->buffer + status; copy_size = buffer_level - status; - + /* Switch to the next buffer */ record_index = !record_index; init_buffer (); inhibit_map = 1; - + if (volume_label_option) add_volume_label (); @@ -1857,13 +1928,13 @@ gnu_flush_write (size_t buffer_level) } void -flush_read () +flush_read (void) { flush_read_ptr (); } void -flush_write () +flush_write (void) { flush_write_ptr (record_size); }