summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-04-19 20:16:07 +0000
committerkientzle <kientzle@FreeBSD.org>2004-04-19 20:16:07 +0000
commit281173de4aed6c4075d7e6e74d23aa99a1f88a1d (patch)
tree9210e571bd38c4106dde9626f948c7dd43eb38d3 /lib
parent30854287508b0300fa73477e5dd7e53d14405e1e (diff)
downloadFreeBSD-src-281173de4aed6c4075d7e6e74d23aa99a1f88a1d.zip
FreeBSD-src-281173de4aed6c4075d7e6e74d23aa99a1f88a1d.tar.gz
Optimize ustar header formatting.
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_write_set_format_ustar.c168
1 files changed, 79 insertions, 89 deletions
diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c
index 7d3c4a0..42a4ce4 100644
--- a/lib/libarchive/archive_write_set_format_ustar.c
+++ b/lib/libarchive/archive_write_set_format_ustar.c
@@ -37,14 +37,6 @@ __FBSDID("$FreeBSD$");
#include "archive_entry.h"
#include "archive_private.h"
-/* Constants are chosen so that 'term & 15' is number of termination bytes */
-#define TERM_BYTES(n) ((n) & 15)
-#define OCTAL_TERM_SPACE_NULL 0x12
-#define OCTAL_TERM_NULL_SPACE 0x22
-#define OCTAL_TERM_NULL 0x31
-#define OCTAL_TERM_SPACE 0x41
-#define OCTAL_TERM_NONE 0x50
-
struct ustar {
uint64_t entry_bytes_remaining;
uint64_t entry_padding;
@@ -56,11 +48,16 @@ struct ustar {
*/
struct archive_entry_header_ustar {
char name[100];
- char mode[8];
- char uid[8];
- char gid[8];
- char size[12];
- char mtime[12];
+ char mode[6];
+ char mode_padding[2];
+ char uid[6];
+ char uid_padding[2];
+ char gid[6];
+ char gid_padding[2];
+ char size[11];
+ char size_padding[1];
+ char mtime[11];
+ char mtime_padding[1];
char checksum[8];
char typeflag[1];
char linkname[100];
@@ -68,9 +65,35 @@ struct archive_entry_header_ustar {
char version[2]; /* For POSIX: "00" */
char uname[32];
char gname[32];
- char devmajor[8];
- char devminor[8];
+ char devmajor[6];
+ char devmajor_padding[2];
+ char devminor[6];
+ char devminor_padding[2];
char prefix[155];
+ char padding[12];
+};
+
+/*
+ * A filled-in copy of the header for initialization.
+ */
+static const struct archive_entry_header_ustar template_header = {
+ { }, /* name */
+ { "000000" }, { ' ', '\0' }, /* mode, space-null termination. */
+ { "000000" }, { ' ', '\0' }, /* uid, space-null termination. */
+ { "000000" }, { ' ', '\0' }, /* gid, space-null termination. */
+ { "00000000000" }, { ' ' }, /* size, space termination. */
+ { "00000000000" }, { ' ' }, /* mtime, space termination. */
+ { " " }, /* Initial checksum value. */
+ { '0' }, /* default: regular file */
+ { }, /* linkname */
+ { "ustar" }, /* magic */
+ { '0', '0' }, /* version */
+ { }, /* uname */
+ { }, /* gname */
+ { "000000" }, { ' ', '\0' }, /* devmajor, space-null termination */
+ { "000000" }, { ' ', '\0' }, /* devminor, space-null termination */
+ { }, /* prefix */
+ { } /* padding */
};
static int archive_write_ustar_data(struct archive *a, const void *buff,
@@ -79,8 +102,7 @@ static int archive_write_ustar_finish(struct archive *);
static int archive_write_ustar_finish_entry(struct archive *);
static int archive_write_ustar_header(struct archive *,
struct archive_entry *entry);
-static int format_octal(int64_t, char *, int, int term);
-static int64_t format_octal_recursive(int64_t, char *, int);
+static int format_octal(int64_t, char *, int);
static int write_nulls(struct archive *a, size_t);
/*
@@ -156,11 +178,13 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
unsigned int checksum;
struct archive_entry_header_ustar *h;
int i, ret;
+ size_t copy_length;
const char *p, *pp;
const struct stat *st;
ret = 0;
- memset(buff, 0, 512);
+ memcpy(buff, &template_header, 512);
+
h = (struct archive_entry_header_ustar *)buff;
/*
@@ -198,62 +222,63 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
if(p == NULL)
p = archive_entry_symlink(entry);
if (p != NULL && p[0] != '\0') {
- if (strlen(p) > sizeof(h->linkname)) {
+ copy_length = strlen(p);
+ if (copy_length > sizeof(h->linkname)) {
archive_set_error(a, ENAMETOOLONG,
"Link contents too long");
ret = ARCHIVE_WARN;
- } else
- memcpy(h->linkname, p, strlen(p));
+ copy_length = sizeof(h->linkname);
+ }
+ memcpy(h->linkname, p, copy_length);
}
p = archive_entry_uname(entry);
if (p != NULL && p[0] != '\0') {
- if (strlen(p) > sizeof(h->uname)) {
+ copy_length = strlen(p);
+ if (copy_length > sizeof(h->uname)) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Username too long");
ret = ARCHIVE_WARN;
- } else
- memcpy(h->uname, p, strlen(p));
+ copy_length = sizeof(h->uname);
+ }
+ memcpy(h->uname, p, copy_length);
}
p = archive_entry_gname(entry);
if (p != NULL && p[0] != '\0') {
+ copy_length = strlen(p);
if (strlen(p) > sizeof(h->gname)) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Group name too long");
ret = ARCHIVE_WARN;
- } else
- memcpy(h->gname, p, strlen(p));
+ copy_length = sizeof(h->gname);
+ }
+ memcpy(h->gname, p, copy_length);
}
st = archive_entry_stat(entry);
- if (format_octal(st->st_mode & 07777, h->mode, sizeof(h->mode),
- OCTAL_TERM_SPACE_NULL)) {
+ if (format_octal(st->st_mode & 07777, h->mode, sizeof(h->mode))) {
archive_set_error(a, ERANGE, "Numeric mode too large");
ret = ARCHIVE_WARN;
}
- if (format_octal(st->st_uid, h->uid, sizeof(h->uid),
- OCTAL_TERM_SPACE_NULL)) {
+ if (format_octal(st->st_uid, h->uid, sizeof(h->uid))) {
archive_set_error(a, ERANGE, "Numeric user ID too large");
ret = ARCHIVE_WARN;
}
- if (format_octal(st->st_gid, h->gid, sizeof(h->gid),
- OCTAL_TERM_SPACE_NULL)) {
+ if (format_octal(st->st_gid, h->gid, sizeof(h->gid))) {
archive_set_error(a, ERANGE, "Numeric group ID too large");
ret = ARCHIVE_WARN;
}
- if (format_octal(st->st_size, h->size,
- sizeof(h->size), OCTAL_TERM_SPACE)) {
+ if (format_octal(st->st_size, h->size, sizeof(h->size))) {
archive_set_error(a, ERANGE, "File size too large");
ret = ARCHIVE_WARN;
}
- if (format_octal(st->st_mtime, h->mtime,
- sizeof(h->mtime), OCTAL_TERM_SPACE)) {
+ if (format_octal(st->st_mtime, h->mtime, sizeof(h->mtime))) {
archive_set_error(a, ERANGE,
"File modification time too large");
ret = ARCHIVE_WARN;
@@ -261,23 +286,18 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) {
if (format_octal(major(st->st_rdev), h->devmajor,
- sizeof(h->devmajor), OCTAL_TERM_SPACE_NULL)) {
+ sizeof(h->devmajor))) {
archive_set_error(a, ERANGE,
"Major device number too large");
ret = ARCHIVE_WARN;
}
if (format_octal(minor(st->st_rdev), h->devminor,
- sizeof(h->devminor), OCTAL_TERM_SPACE_NULL)) {
+ sizeof(h->devminor))) {
archive_set_error(a, ERANGE,
"Minor device number too large");
ret = ARCHIVE_WARN;
}
- } else {
- format_octal(0, h->devmajor, sizeof(h->devmajor),
- OCTAL_TERM_SPACE_NULL);
- format_octal(0, h->devminor, sizeof(h->devminor),
- OCTAL_TERM_SPACE_NULL);
}
if (tartype >= 0) {
@@ -304,19 +324,12 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
}
}
- memcpy(h->magic, "ustar\0", 6);
- memcpy(h->version, "00", 2);
- memcpy(h->checksum, " ", 8);
checksum = 0;
for (i = 0; i < 512; i++)
checksum += 255 & (unsigned int)buff[i];
- if (format_octal(checksum, h->checksum,
- sizeof(h->checksum), OCTAL_TERM_NULL_SPACE)) {
- archive_set_error(a, ERANGE,
- "Checksum too large (Internal error; this can't happen)");
- ret = ARCHIVE_WARN;
- }
-
+ h->checksum[6] = '\0';
+ h->checksum[7] = ' ';
+ format_octal(checksum, h->checksum, 6);
return (ret);
}
@@ -324,49 +337,26 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
* Format a number into the specified field.
*/
static int
-format_octal(int64_t v, char *p, int s, int term)
+format_octal(int64_t v, char *p, int s)
{
- /* POSIX specifies that all numeric values are unsigned. */
- int64_t max;
- int digits, ret;
+ int len;
- digits = s - TERM_BYTES(term);
- max = (((int64_t)1) << (digits * 3)) - 1;
+ p += s; /* Start at the end and work backwards. */
- if (v >= 0 && v <= max) {
- format_octal_recursive(v, p, digits);
- ret = 0;
- } else {
- format_octal_recursive(max, p, digits);
- ret = -1;
+ len = s;
+ while (s-- > 0) {
+ *--p = '0' + (v & 7);
+ v >>= 3;
}
- switch (term) {
- case OCTAL_TERM_SPACE_NULL:
- p[s-2] = 0x20;
- /* fall through */
- case OCTAL_TERM_NULL:
- p[s-1] = 0;
- break;
- case OCTAL_TERM_NULL_SPACE:
- p[s-2] = 0;
- /* fall through */
- case OCTAL_TERM_SPACE:
- p[s-1] = 0x20;
- break;
- }
- return (ret);
-}
+ if (v == 0)
+ return (0);
-static int64_t
-format_octal_recursive(int64_t v, char *p, int s)
-{
- if (s == 0)
- return (v);
+ /* If it overflowed, fill field with max value. */
+ while (len-- > 0)
+ *p++ = '7';
- v = format_octal_recursive(v, p+1, s-1);
- *p = '0' + (v & 7);
- return (v >>= 3);
+ return (-1);
}
static int
OpenPOWER on IntegriCloud