X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fxheader.c;h=d5a75b3e32d8678348fca82b7dcdbe37db3751bc;hb=4ed709c3c2376017c04ab827eaf93bd8ccf7c3a5;hp=6f8c140b12cdd229b8551ca26a4386893f906534;hpb=10edb315da532371e65a7d83a16f50ade5b545e4;p=chaz%2Ftar diff --git a/src/xheader.c b/src/xheader.c index 6f8c140..d5a75b3 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -18,10 +18,9 @@ #include "system.h" -#include #include -#include #include +#include #include "common.h" @@ -38,7 +37,13 @@ struct xhdr_tab void (*decoder) (struct tar_stat_info *, char const *); }; -static struct xhdr_tab const xhdr_tab[]; +/* This declaration must be extern, because ISO C99 section 6.9.2 + prohibits a tentative definition that has both internal linkage and + incomplete type. If we made it static, we'd have to declare its + size which would be a maintenance pain; if we put its initializer + here, we'd need a boatload of forward declarations, which would be + even more of a pain. */ +extern struct xhdr_tab const xhdr_tab[]; static struct xhdr_tab const * locate_handler (char const *keyword) @@ -51,6 +56,9 @@ locate_handler (char const *keyword) return NULL; } +/* Decodes a single extended header record. Advances P to the next + record. + Returns true on success, false otherwise. */ static bool decode_record (char **p, struct tar_stat_info *st) { @@ -61,13 +69,13 @@ decode_record (char **p, struct tar_stat_info *st) struct xhdr_tab const *t; if (**p == 0) - return true; + return false; len = strtoul (*p, p, 10); if (**p != ' ') { - ERROR ((0, 0, _("Malformed extended header"))); - return true; + ERROR ((0, 0, _("Malformed extended header: missing whitespace after the length"))); + return false; } keyword = ++*p; @@ -77,8 +85,8 @@ decode_record (char **p, struct tar_stat_info *st) if (**p != '=') { - ERROR ((0, 0, _("Malformed extended header"))); - return true; + ERROR ((0, 0, _("Malformed extended header: missing equal sign"))); + return false; } eqp = *p; @@ -98,17 +106,17 @@ decode_record (char **p, struct tar_stat_info *st) } *eqp = '='; *p = &start[len]; - return false; + return true; } void xheader_decode (struct tar_stat_info *st) { - char *p = extended_header.buffer; + char *p = extended_header.buffer + BLOCKSIZE; char *endp = &extended_header.buffer[extended_header.size-1]; while (p < endp) - if (decode_record (&p, st)) + if (!decode_record (&p, st)) break; } @@ -133,29 +141,31 @@ xheader_store (char const *keyword, struct tar_stat_info const *st) void xheader_read (union block *p, size_t size) { - size_t i, j; + size_t j = 0; size_t nblocks; free (extended_header.buffer); + size += BLOCKSIZE; extended_header.size = size; nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE; extended_header.buffer = xmalloc (size + 1); - set_next_block_after (p); - for (i = j = 0; i < nblocks; i++) + do { - size_t len; + size_t len = size; - p = find_next_block (); - len = size; if (len > BLOCKSIZE) len = BLOCKSIZE; + memcpy (&extended_header.buffer[j], p->buffer, len); set_next_block_after (p); + p = find_next_block (); + j += len; size -= len; } + while (size > 0); } static size_t @@ -281,7 +291,9 @@ atime_coder (struct tar_stat_info const *st, char const *keyword, static void atime_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_atime = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_atime = u; } static void @@ -294,7 +306,9 @@ gid_coder (struct tar_stat_info const *st, char const *keyword, static void gid_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_gid = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_gid = u; } static void @@ -333,7 +347,9 @@ ctime_coder (struct tar_stat_info const *st, char const *keyword, static void ctime_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_ctime = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_ctime = u; } static void @@ -346,7 +362,9 @@ mtime_coder (struct tar_stat_info const *st, char const *keyword, static void mtime_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_mtime = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_mtime = u; } static void @@ -374,7 +392,9 @@ size_coder (struct tar_stat_info const *st, char const *keyword, static void size_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_size = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_size = u; } static void @@ -387,7 +407,9 @@ uid_coder (struct tar_stat_info const *st, char const *keyword, static void uid_decoder (struct tar_stat_info *st, char const *arg) { - st->stat.st_uid = strtoul (arg, NULL, 0); + uintmax_t u; + if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK) + st->stat.st_uid = u; } static void @@ -403,7 +425,7 @@ uname_decoder (struct tar_stat_info *st, char const *arg) assign_string (&st->uname, arg); } -static struct xhdr_tab const xhdr_tab[] = { +struct xhdr_tab const xhdr_tab[] = { { "atime", atime_coder, atime_decoder }, { "comment", dummy_coder, dummy_decoder }, { "charset", dummy_coder, dummy_decoder }, @@ -417,6 +439,9 @@ static struct xhdr_tab const xhdr_tab[] = { { "uid", uid_coder, uid_decoder }, { "uname", uname_coder, uname_decoder }, + /* The number of entries in xhdr_tab must agree with the array + bounds in xhdr_tab's forward declaration. */ + #if 0 /* GNU private keywords (not yet implemented) */ /* Sparse file handling */ { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder },