aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-05-04 21:14:12 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-05-04 21:14:12 +0200
commit9180c6045e8b2465b3e18a22eb08ee8438ae8544 (patch)
tree154bd3a352b89e73098e7923941bb76393dcf604
parent882062915d52581fb754e5721addca72aa789ab7 (diff)
downloadbusybox-w32-9180c6045e8b2465b3e18a22eb08ee8438ae8544.tar.gz
busybox-w32-9180c6045e8b2465b3e18a22eb08ee8438ae8544.tar.bz2
busybox-w32-9180c6045e8b2465b3e18a22eb08ee8438ae8544.zip
tar: store negative mtime as 0; pack very large files using base-256 encoding
function old new delta writeTarHeader 841 979 +138 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/tar.c36
-rw-r--r--include/archive.h2
2 files changed, 33 insertions, 5 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 01b83d5e2..ebaa183b4 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -264,7 +264,8 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
264 PUT_OCTAL(header.uid, statbuf->st_uid); 264 PUT_OCTAL(header.uid, statbuf->st_uid);
265 PUT_OCTAL(header.gid, statbuf->st_gid); 265 PUT_OCTAL(header.gid, statbuf->st_gid);
266 memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ 266 memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */
267 PUT_OCTAL(header.mtime, statbuf->st_mtime); 267 /* users report that files with negative st_mtime cause trouble, so: */
268 PUT_OCTAL(header.mtime, statbuf->st_mtime >= 0 ? statbuf->st_mtime : 0);
268 269
269 /* Enter the user and group names */ 270 /* Enter the user and group names */
270 safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname)); 271 safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname));
@@ -316,15 +317,42 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
316 } else if (S_ISFIFO(statbuf->st_mode)) { 317 } else if (S_ISFIFO(statbuf->st_mode)) {
317 header.typeflag = FIFOTYPE; 318 header.typeflag = FIFOTYPE;
318 } else if (S_ISREG(statbuf->st_mode)) { 319 } else if (S_ISREG(statbuf->st_mode)) {
319 if (sizeof(statbuf->st_size) > 4 320 /* header.size field is 12 bytes long */
320 && statbuf->st_size > (off_t)0777777777777LL 321 /* Does octal-encoded size fit? */
322 uoff_t filesize = statbuf->st_size;
323 if (sizeof(filesize) <= 4
324 || filesize <= (uoff_t)0777777777777LL
321 ) { 325 ) {
326 PUT_OCTAL(header.size, filesize);
327 }
328 /* Does base256-encoded size fit?
329 * It always does unless off_t is wider than 64 bits.
330 */
331 else if (ENABLE_FEATURE_TAR_GNU_EXTENSIONS
332#if ULLONG_MAX > 0xffffffffffffffffLL /* 2^64-1 */
333 && (filesize <= 0x3fffffffffffffffffffffffLL)
334#endif
335 ) {
336 /* GNU tar uses "base-256 encoding" for very large numbers.
337 * Encoding is binary, with highest bit always set as a marker
338 * and sign in next-highest bit:
339 * 80 00 .. 00 - zero
340 * bf ff .. ff - largest positive number
341 * ff ff .. ff - minus 1
342 * c0 00 .. 00 - smallest negative number
343 */
344 char *p8 = header.size + sizeof(header.size);
345 do {
346 *--p8 = (uint8_t)filesize;
347 filesize >>= 8;
348 } while (p8 != header.size);
349 *p8 |= 0x80;
350 } else {
322 bb_error_msg_and_die("can't store file '%s' " 351 bb_error_msg_and_die("can't store file '%s' "
323 "of size %"OFF_FMT"u, aborting", 352 "of size %"OFF_FMT"u, aborting",
324 fileName, statbuf->st_size); 353 fileName, statbuf->st_size);
325 } 354 }
326 header.typeflag = REGTYPE; 355 header.typeflag = REGTYPE;
327 PUT_OCTAL(header.size, statbuf->st_size);
328 } else { 356 } else {
329 bb_error_msg("%s: unknown file type", fileName); 357 bb_error_msg("%s: unknown file type", fileName);
330 return FALSE; 358 return FALSE;
diff --git a/include/archive.h b/include/archive.h
index b139dc5be..9e176d335 100644
--- a/include/archive.h
+++ b/include/archive.h
@@ -125,7 +125,7 @@ typedef struct archive_handle_t {
125#define TAR_BLOCK_SIZE 512 125#define TAR_BLOCK_SIZE 512
126#define NAME_SIZE 100 126#define NAME_SIZE 100
127#define NAME_SIZE_STR "100" 127#define NAME_SIZE_STR "100"
128typedef struct tar_header_t { /* byte offset */ 128typedef struct tar_header_t { /* byte offset */
129 char name[NAME_SIZE]; /* 0-99 */ 129 char name[NAME_SIZE]; /* 0-99 */
130 char mode[8]; /* 100-107 */ 130 char mode[8]; /* 100-107 */
131 char uid[8]; /* 108-115 */ 131 char uid[8]; /* 108-115 */