X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=8147def1961246dfdef3f3704432416431c6f932;hb=338add8d10a787aafb6fd57aeae497a79a8d5855;hp=f419dd7bcb357232ca76f254a78417c0a6794142;hpb=28f2669b15f2ddf5a25e4d7a7f36023ae0268c8b;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index f419dd7..8147def 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -201,6 +201,7 @@ enum compress_type { ct_compress, ct_gzip, ct_bzip2, + ct_lzip, ct_lzma, ct_lzop, ct_xz @@ -221,6 +222,7 @@ static struct zip_magic const magic[] = { { 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, "\0xFD7zXZ", XZ_PROGRAM, "-J" }, @@ -854,16 +856,16 @@ seek_archive (off_t size) off_t start = current_block_ordinal (); off_t offset; off_t nrec, nblk; - off_t skipped = (blocking_factor - (current_block - record_start)); + off_t skipped = (blocking_factor - (current_block - record_start)) + * BLOCKSIZE; - size -= skipped * BLOCKSIZE; - - if (size < record_size) + if (size <= skipped) return 0; - /* FIXME: flush? */ - + /* Compute number of records to skip */ - nrec = size / record_size; + nrec = (size - skipped) / record_size; + if (nrec == 0) + return 0; offset = rmtlseek (archive, nrec * record_size, SEEK_CUR); if (offset < 0) return offset; @@ -1165,7 +1167,7 @@ read_header0 (struct tar_stat_info *info) enum read_header rc; tar_stat_init (info); - rc = read_header (¤t_header, info, false); + rc = read_header (¤t_header, info, read_header_auto); if (rc == HEADER_SUCCESS) { set_next_block_after (current_header); @@ -1213,17 +1215,42 @@ try_new_volume () { case XGLTYPE: { - if (!read_header0 (&dummy)) - return false; + tar_stat_init (&dummy); + if (read_header (&header, &dummy, read_header_x_global) + != HEADER_SUCCESS_EXTENDED) + { + ERROR ((0, 0, _("This does not look like a tar archive"))); + return false; + } + xheader_decode (&dummy); /* decodes values from the global header */ tar_stat_destroy (&dummy); - if (!real_s_name) - { - /* We have read the extended header of the first member in - this volume. Put it back, so next read_header works as - expected. */ - current_block = record_start; - } + + /* The initial global header must be immediately followed by + an extended PAX header for the first member in this volume. + However, in some cases tar may split volumes in the middle + of a PAX header. This is incorrect, and should be fixed + in the future versions. In the meantime we must be + prepared to correctly list and extract such archives. + + If this happens, the following call to read_header returns + HEADER_FAILURE, which is ignored. + + See also tests/multiv07.at */ + + switch (read_header (&header, &dummy, read_header_auto)) + { + case HEADER_SUCCESS: + set_next_block_after (header); + break; + + case HEADER_FAILURE: + break; + + default: + ERROR ((0, 0, _("This does not look like a tar archive"))); + return false; + } break; }