mirror of
https://github.com/sheumann/hush.git
synced 2024-12-22 14:30:31 +00:00
header_verbose_list: show off_t size, not cast to (unsigned)
get_header_tar: support GNU tar's "base256" encoding function old new delta get_header_tar 1536 1600 +64 header_verbose_list 242 257 +15
This commit is contained in:
parent
12abcb36c8
commit
ab6b446e95
@ -14,6 +14,74 @@
|
|||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include "unarchive.h"
|
#include "unarchive.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNU tar uses "base-256 encoding" for very large numbers (>8 billion).
|
||||||
|
* Encoding is binary, with highest bit always set as a marker
|
||||||
|
* and sign in next-highest bit:
|
||||||
|
* 80 00 .. 00 - zero
|
||||||
|
* bf ff .. ff - largest positive number
|
||||||
|
* ff ff .. ff - minus 1
|
||||||
|
* c0 00 .. 00 - smallest negative number
|
||||||
|
*
|
||||||
|
* We expect it only in size field, where negative numbers don't make sense.
|
||||||
|
*/
|
||||||
|
static off_t getBase256_len12(const char *str)
|
||||||
|
{
|
||||||
|
off_t value;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* if (*str & 0x40) error; - caller prevents this */
|
||||||
|
|
||||||
|
if (sizeof(off_t) >= 12) {
|
||||||
|
/* Probably 128-bit (16 byte) off_t. Can be optimized. */
|
||||||
|
len = 12;
|
||||||
|
value = *str++ & 0x3f;
|
||||||
|
while (--len)
|
||||||
|
value = (value << 8) + (unsigned char) *str++;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CHECK_FOR_OVERFLOW
|
||||||
|
/* Can be optimized to eat 32-bit chunks */
|
||||||
|
char c = *str++ & 0x3f;
|
||||||
|
len = 12;
|
||||||
|
while (1) {
|
||||||
|
if (c)
|
||||||
|
bb_error_msg_and_die("overflow in base-256 encoded file size");
|
||||||
|
if (--len == sizeof(off_t))
|
||||||
|
break;
|
||||||
|
c = *str++;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
str += (12 - sizeof(off_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now str points to sizeof(off_t) least significant bytes.
|
||||||
|
*
|
||||||
|
* Example of tar file with 8914993153 (0x213600001) byte file.
|
||||||
|
* Field starts at offset 7c:
|
||||||
|
* 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....|
|
||||||
|
* 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336|
|
||||||
|
*
|
||||||
|
* str is at offset 80 or 84 now (64-bit or 32-bit off_t).
|
||||||
|
* We (ab)use the fact that value happens to be aligned,
|
||||||
|
* and fetch it in one go:
|
||||||
|
*/
|
||||||
|
if (sizeof(off_t) == 8) {
|
||||||
|
value = *(off_t*)str;
|
||||||
|
value = SWAP_BE64(value);
|
||||||
|
} else if (sizeof(off_t) == 4) {
|
||||||
|
value = *(off_t*)str;
|
||||||
|
value = SWAP_BE32(value);
|
||||||
|
} else {
|
||||||
|
value = 0;
|
||||||
|
len = sizeof(off_t);
|
||||||
|
while (--len)
|
||||||
|
value = (value << 8) + (unsigned char) *str++;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/* NB: _DESTROYS_ str[len] character! */
|
/* NB: _DESTROYS_ str[len] character! */
|
||||||
static unsigned long long getOctal(char *str, int len)
|
static unsigned long long getOctal(char *str, int len)
|
||||||
{
|
{
|
||||||
@ -234,7 +302,10 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
|
|||||||
file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
|
file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
|
||||||
#endif
|
#endif
|
||||||
file_header->mtime = GET_OCTAL(tar.mtime);
|
file_header->mtime = GET_OCTAL(tar.mtime);
|
||||||
file_header->size = GET_OCTAL(tar.size);
|
/* Size field: handle GNU tar's "base256 encoding" */
|
||||||
|
file_header->size = (*tar.size & 0xc0) == 0x80 /* positive base256? */
|
||||||
|
? getBase256_len12(tar.size)
|
||||||
|
: GET_OCTAL(tar.size);
|
||||||
file_header->gid = GET_OCTAL(tar.gid);
|
file_header->gid = GET_OCTAL(tar.gid);
|
||||||
file_header->uid = GET_OCTAL(tar.uid);
|
file_header->uid = GET_OCTAL(tar.uid);
|
||||||
/* Set bits 0-11 of the files mode */
|
/* Set bits 0-11 of the files mode */
|
||||||
|
@ -24,11 +24,11 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
|
|||||||
snprintf(gid, sizeof(gid), "%u", (unsigned)file_header->gid);
|
snprintf(gid, sizeof(gid), "%u", (unsigned)file_header->gid);
|
||||||
group = gid;
|
group = gid;
|
||||||
}
|
}
|
||||||
printf("%s %s/%s %9u %4u-%02u-%02u %02u:%02u:%02u %s",
|
printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
|
||||||
bb_mode_string(file_header->mode),
|
bb_mode_string(file_header->mode),
|
||||||
user,
|
user,
|
||||||
group,
|
group,
|
||||||
(unsigned int) file_header->size,
|
file_header->size,
|
||||||
1900 + mtime->tm_year,
|
1900 + mtime->tm_year,
|
||||||
1 + mtime->tm_mon,
|
1 + mtime->tm_mon,
|
||||||
mtime->tm_mday,
|
mtime->tm_mday,
|
||||||
|
@ -357,7 +357,8 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
|
|||||||
if (tbInfo->verboseFlag) {
|
if (tbInfo->verboseFlag) {
|
||||||
FILE *vbFd = stdout;
|
FILE *vbFd = stdout;
|
||||||
|
|
||||||
if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */
|
/* If archive goes to stdout, verbose goes to stderr */
|
||||||
|
if (tbInfo->tarFd == STDOUT_FILENO)
|
||||||
vbFd = stderr;
|
vbFd = stderr;
|
||||||
/* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
|
/* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
|
||||||
/* We don't have such excesses here: for us "v" == "vv" */
|
/* We don't have such excesses here: for us "v" == "vv" */
|
||||||
|
Loading…
Reference in New Issue
Block a user