Use base-256 encoding for files larger 68G
Reference: http://lists.busybox.net/pipermail/busybox/2011-May/075596.html
This commit is contained in:
parent
3cd8e0fef8
commit
17cd1575f6
@ -29,10 +29,8 @@ checkMTarError(int error_code, const boost::filesystem::path &filepath, const st
|
|||||||
case MTAR_ESUCCESS:
|
case MTAR_ESUCCESS:
|
||||||
return;
|
return;
|
||||||
case MTAR_EFAILURE:
|
case MTAR_EFAILURE:
|
||||||
throw util::RuntimeError(filepath.string() + " : " + name,
|
throw util::RuntimeError(
|
||||||
ErrorCode::FileIOError,
|
filepath.string() + " : " + name, ErrorCode::FileIOError, SOURCE_REF);
|
||||||
SOURCE_REF,
|
|
||||||
std::strerror(errno));
|
|
||||||
case MTAR_EOPENFAIL:
|
case MTAR_EOPENFAIL:
|
||||||
throw util::RuntimeError(filepath.string() + " : " + name,
|
throw util::RuntimeError(filepath.string() + " : " + name,
|
||||||
ErrorCode::FileOpenError,
|
ErrorCode::FileOpenError,
|
||||||
|
52
third_party/microtar/src/microtar.c
vendored
52
third_party/microtar/src/microtar.c
vendored
@ -89,6 +89,7 @@ static int write_null_bytes(mtar_t *tar, int n) {
|
|||||||
|
|
||||||
static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) {
|
static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) {
|
||||||
unsigned chksum1, chksum2;
|
unsigned chksum1, chksum2;
|
||||||
|
mtar_size_t filesize;
|
||||||
|
|
||||||
/* If the checksum starts with a null byte we assume the record is NULL */
|
/* If the checksum starts with a null byte we assume the record is NULL */
|
||||||
if (*rh->checksum == '\0') {
|
if (*rh->checksum == '\0') {
|
||||||
@ -105,24 +106,68 @@ static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) {
|
|||||||
/* Load raw header into header */
|
/* Load raw header into header */
|
||||||
sscanf(rh->mode, "%o", &h->mode);
|
sscanf(rh->mode, "%o", &h->mode);
|
||||||
sscanf(rh->owner, "%o", &h->owner);
|
sscanf(rh->owner, "%o", &h->owner);
|
||||||
sscanf(rh->size, "%12lo", &h->size);
|
|
||||||
sscanf(rh->mtime, "%o", &h->mtime);
|
sscanf(rh->mtime, "%o", &h->mtime);
|
||||||
h->type = rh->type;
|
h->type = rh->type;
|
||||||
strcpy(h->name, rh->name);
|
strcpy(h->name, rh->name);
|
||||||
strcpy(h->linkname, rh->linkname);
|
strcpy(h->linkname, rh->linkname);
|
||||||
|
|
||||||
|
/* Load size field */
|
||||||
|
if ((rh->size[0] & 0x80) == 0) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
sscanf(rh->size, "%12llo", &h->size);
|
||||||
|
#else
|
||||||
|
sscanf(rh->size, "%12lo", &h->size);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
h->size = (rh->size[0] & 0x7f) | (rh->size[0] & 0x40 ? 0x80 : 0);
|
||||||
|
uint8_t *p8 = (uint8_t *)&rh->size + 1;
|
||||||
|
while (p8 != (uint8_t *)&rh->size + sizeof(rh->size)) {
|
||||||
|
if (h->size >= ((mtar_size_t)1 << (sizeof(h->size) - 1) * 8)) {
|
||||||
|
return MTAR_EFAILURE;
|
||||||
|
}
|
||||||
|
h->size = ((mtar_size_t)h->size << 8) + *p8++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MTAR_ESUCCESS;
|
return MTAR_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) {
|
static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) {
|
||||||
unsigned chksum;
|
unsigned chksum;
|
||||||
|
mtar_size_t filesize = h->size;
|
||||||
|
|
||||||
/* Load header into raw header */
|
/* Load header into raw header */
|
||||||
memset(rh, 0, sizeof(*rh));
|
memset(rh, 0, sizeof(*rh));
|
||||||
|
|
||||||
|
/* Store size in ASCII octal digits or base-256 formats */
|
||||||
|
if (sizeof(mtar_size_t) <= 4 || filesize <= (mtar_size_t)0777777777777LL) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
sprintf(rh->size, "%llo", h->size);
|
||||||
|
#else
|
||||||
|
sprintf(rh->size, "%lo", h->size);
|
||||||
|
#endif
|
||||||
|
} else if (sizeof(filesize) < sizeof(rh->size)) {
|
||||||
|
/* GNU tar uses "base-256 encoding" for very large numbers.
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
uint8_t *p8 = (uint8_t *)&rh->size + sizeof(rh->size);
|
||||||
|
do {
|
||||||
|
*--p8 = (uint8_t)filesize;
|
||||||
|
filesize >>= 8;
|
||||||
|
} while (p8 != (uint8_t *)&rh->size);
|
||||||
|
*p8 |= 0x80;
|
||||||
|
} else {
|
||||||
|
return MTAR_EFAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(rh->mode, "%o", h->mode);
|
sprintf(rh->mode, "%o", h->mode);
|
||||||
sprintf(rh->owner, "%o", h->owner);
|
sprintf(rh->owner, "%o", h->owner);
|
||||||
sprintf(rh->size, "%lo", h->size);
|
|
||||||
sprintf(rh->mtime, "%o", h->mtime);
|
sprintf(rh->mtime, "%o", h->mtime);
|
||||||
rh->type = h->type ? h->type : MTAR_TREG;
|
rh->type = h->type ? h->type : MTAR_TREG;
|
||||||
strcpy(rh->name, h->name);
|
strcpy(rh->name, h->name);
|
||||||
@ -332,9 +377,6 @@ int mtar_write_header(mtar_t *tar, const mtar_header_t *h) {
|
|||||||
|
|
||||||
int mtar_write_file_header(mtar_t *tar, const char *name, mtar_size_t size) {
|
int mtar_write_file_header(mtar_t *tar, const char *name, mtar_size_t size) {
|
||||||
mtar_header_t h;
|
mtar_header_t h;
|
||||||
if (size >= 0777777777777) {
|
|
||||||
return MTAR_EFAILURE;
|
|
||||||
}
|
|
||||||
/* Build header */
|
/* Build header */
|
||||||
memset(&h, 0, sizeof(h));
|
memset(&h, 0, sizeof(h));
|
||||||
strcpy(h.name, name);
|
strcpy(h.name, name);
|
||||||
|
Loading…
Reference in New Issue
Block a user