>From ce21d1046792a3a918ef85037a28216350511a06 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Fri, 25 Jan 2013 13:24:23 +0100 Subject: [PATCH] sparse: Fix bug in POSIX_FORMAT Archive the file size correctly (and do not fail) when the shrunken size of file is >= 8^11 (8589934592) bytes. In that case use the 'size' posix extended header instead of using the size into header field which has not enough capacity. * src/common.h: Generalize macros from create.c. * src/create.c: Move macros to common.h. * src/sparse.c: Use "size" field when shrunken size >= 8^11 bytes. --- src/common.h | 11 +++++++++++ src/create.c | 11 ----------- src/sparse.c | 11 ++++++++++- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/common.h b/src/common.h index 4f7c19f..d8d7638 100644 --- a/src/common.h +++ b/src/common.h @@ -493,6 +493,17 @@ void exclusion_tag_warning (const char *dirname, const char *tagname, enum exclusion_tag_type check_exclusion_tags (struct tar_stat_info const *st, const char **tag_file_name); +/* The maximum uintmax_t value that can be represented with DIGITS digits, + assuming that each digit is BITS_PER_DIGIT wide. */ +#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \ + ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \ + ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \ + : (uintmax_t) -1) + +/* The maximum uintmax_t value that can be represented with octal + - digits and a trailing NUL in BUFFER. */ +#define MAX_OCTAL_VAL(buffer) MAX_VAL_WITH_DIGITS (sizeof (buffer) - 1, LG_8) + #define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where)) #define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where)) diff --git a/src/create.c b/src/create.c index e14e13d..ad9db70 100644 --- a/src/create.c +++ b/src/create.c @@ -121,17 +121,6 @@ cachedir_file_p (int fd) } -/* The maximum uintmax_t value that can be represented with DIGITS digits, - assuming that each digit is BITS_PER_DIGIT wide. */ -#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \ - ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \ - ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \ - : (uintmax_t) -1) - -/* The maximum uintmax_t value that can be represented with octal - digits and a trailing NUL in BUFFER. */ -#define MAX_OCTAL_VAL(buffer) MAX_VAL_WITH_DIGITS (sizeof (buffer) - 1, LG_8) - /* Convert VALUE to an octal representation suitable for tar headers. Output to buffer WHERE with size SIZE. The result is undefined if SIZE is 0 or if VALUE is too large to fit. */ diff --git a/src/sparse.c b/src/sparse.c index b93cdc2..1f3b0b5 100644 --- a/src/sparse.c +++ b/src/sparse.c @@ -987,6 +987,7 @@ pax_dump_header_1 (struct tar_sparse_file *file) size_t i; char nbuf[UINTMAX_STRSIZE_BOUND]; off_t size = 0; + off_t shrunken_size = 0; struct sp_array *map = file->stat_info->sparse_map; char *save_file_name = file->stat_info->file_name; @@ -1034,8 +1035,16 @@ pax_dump_header_1 (struct tar_sparse_file *file) file->stat_info->file_name[NAME_FIELD_SIZE] = 0; blk = start_header (file->stat_info); + /* Store the effective (shrunken) file size */ - OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size); + shrunken_size = file->stat_info->archive_file_size; + if (MAX_OCTAL_VAL (blk->header.size) < shrunken_size) + { + xheader_store ("size", file->stat_info, NULL); + shrunken_size = 0; + } + OFF_TO_CHARS (shrunken_size, blk->header.size); + finish_header (file->stat_info, blk, block_ordinal); free (file->stat_info->file_name); file->stat_info->file_name = save_file_name; -- 1.7.11.7