X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fxheader.c;h=0cb5bb21957b94c08c6950b7cf921b329a7f22ac;hb=29c902bc4949f6020df6470aa1115ce15dab802a;hp=a7d7e9861e18991529f8a6e9de9c8c3ecba7b021;hpb=6bd7b64c780bf133b12df468cfe90df5d262e62a;p=chaz%2Ftar diff --git a/src/xheader.c b/src/xheader.c index a7d7e98..0cb5bb2 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -1,6 +1,6 @@ /* POSIX extended headers for tar. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,25 +16,26 @@ with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "system.h" +#include +#include #include #include +#include #include #include "common.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -#include +#include -bool xheader_protected_pattern_p (const char *pattern); -bool xheader_protected_keyword_p (const char *keyword); +static bool xheader_protected_pattern_p (char const *pattern); +static bool xheader_protected_keyword_p (char const *keyword); +static void xheader_set_single_keyword (char *) __attribute__ ((noreturn)); /* Used by xheader_finish() */ static void code_string (char const *string, char const *keyword, struct xheader *xhdr); -static void extended_header_init (); +static void extended_header_init (void); /* Number of global headers written so far. */ static size_t global_header_count; @@ -78,7 +79,7 @@ static char *exthdr_name; /* Template for the name field of a 'g' type header */ static char *globexthdr_name; -bool +static bool xheader_keyword_deleted_p (const char *kw) { struct keyword_list *kp; @@ -89,7 +90,7 @@ xheader_keyword_deleted_p (const char *kw) return false; } -bool +static bool xheader_keyword_override_p (const char *keyword) { struct keyword_list *kp; @@ -100,7 +101,7 @@ xheader_keyword_override_p (const char *keyword) return false; } -void +static void xheader_list_append (struct keyword_list **root, char const *kw, char const *value) { @@ -111,7 +112,7 @@ xheader_list_append (struct keyword_list **root, char const *kw, *root = kp; } -void +static void xheader_list_destroy (struct keyword_list **root) { if (root) @@ -128,15 +129,14 @@ xheader_list_destroy (struct keyword_list **root) *root = NULL; } } - - -void + +static void xheader_set_single_keyword (char *kw) { USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw)); } -void +static void xheader_set_keyword_equal (char *kw, char *eq) { bool global = true; @@ -155,11 +155,11 @@ xheader_set_keyword_equal (char *kw, char *eq) for (p = eq + 1; *p && isspace (*p); p++) ; - + if (strcmp (kw, "delete") == 0) { if (xheader_protected_pattern_p (p)) - USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), p)); + USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p))); xheader_list_append (&keyword_pattern_list, p, NULL); } else if (strcmp (kw, "exthdr.name") == 0) @@ -216,10 +216,10 @@ to_decimal (uintmax_t value, char *where, size_t size) %d The directory name of the file, equivalent to the result of the dirname utility on the translated - pathname. + file name. %f The filename of the file, equivalent to the result of the basename - utility on the translated pathname. + utility on the translated file name. %p The process ID of the pax process. %% A '%' character. */ @@ -230,11 +230,11 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) size_t len = strlen (fmt); char *q; const char *p; - char *dirname = NULL; - char *basename = NULL; + char *dir = NULL; + char *base = NULL; char pidbuf[64]; char nbuf[64]; - + for (p = fmt; *p && (p = strchr (p, '%')); ) { switch (p[1]) @@ -246,25 +246,24 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) case 'd': if (st) { - dirname = safer_name_suffix (dir_name (st->orig_file_name), - false); - len += strlen (dirname) - 1; + dir = safer_name_suffix (dir_name (st->orig_file_name), false); + len += strlen (dir) - 1; } break; - + case 'f': if (st) { - basename = base_name (st->orig_file_name); - len += strlen (basename) - 1; + base = base_name (st->orig_file_name); + len += strlen (base) - 1; } break; - + case 'p': to_decimal (getpid (), pidbuf, sizeof pidbuf); len += strlen (pidbuf) - 1; break; - + case 'n': if (allow_n) { @@ -275,7 +274,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) } p++; } - + buf = xmalloc (len + 1); for (q = buf, p = fmt; *p; ) { @@ -287,19 +286,19 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) *q++ = *p++; p++; break; - + case 'd': - if (dirname) - q = stpcpy (q, dirname); + if (dir) + q = stpcpy (q, dir); p += 2; break; - + case 'f': - if (basename) - q = stpcpy (q, basename); + if (base) + q = stpcpy (q, base); p += 2; break; - + case 'p': q = stpcpy (q, pidbuf); p += 2; @@ -312,7 +311,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) p += 2; } /* else fall through */ - + default: *q++ = *p++; if (*p) @@ -341,7 +340,7 @@ xheader_xhdr_name (struct tar_stat_info *st) #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n" char * -xheader_ghdr_name () +xheader_ghdr_name (void) { if (!globexthdr_name) { @@ -364,7 +363,7 @@ xheader_write (char type, char *name, struct xheader *xhdr) union block *header; size_t size; char *p; - + size = xhdr->size; header = start_private_header (name, size); header->header.typeflag = type; @@ -372,11 +371,11 @@ xheader_write (char type, char *name, struct xheader *xhdr) simple_finish_header (header); p = xhdr->buffer; - + do { size_t len; - + header = find_next_block (); len = BLOCKSIZE; if (len > size) @@ -390,17 +389,17 @@ xheader_write (char type, char *name, struct xheader *xhdr) } while (size > 0); xheader_destroy (xhdr); -} +} void -xheader_write_global () +xheader_write_global (void) { char *name; struct keyword_list *kp; if (!keyword_global_override_list) return; - + extended_header_init (); for (kp = keyword_global_override_list; kp; kp = kp->next) code_string (kp->value, kp->pattern, &extended_header); @@ -442,7 +441,7 @@ locate_handler (char const *keyword) return NULL; } -bool +static bool xheader_protected_pattern_p (const char *pattern) { struct xhdr_tab const *p; @@ -453,7 +452,7 @@ xheader_protected_pattern_p (const char *pattern) return false; } -bool +static bool xheader_protected_keyword_p (const char *keyword) { struct xhdr_tab const *p; @@ -464,51 +463,70 @@ xheader_protected_keyword_p (const char *keyword) return false; } -/* Decodes a single extended header record. Advances P to the next - record. - Returns true on success, false otherwise. */ +/* Decode a single extended header record, advancing *PTR to the next record. + Return true on success, false otherwise. */ static bool -decode_record (char **p, +decode_record (char **ptr, void (*handler) (void *, char const *, char const *), void *data) { - size_t len; + char *start = *ptr; + char *p = start; + unsigned long int len; + char *len_lim; char const *keyword; - char *start = *p; - char endc; + char *nextp; + size_t len_max = extended_header.buffer + extended_header.size - start; - if (**p == 0) - return false; + while (*p == ' ' || *p == '\t') + p++; - len = strtoul (*p, p, 10); - if (**p != ' ') + if (! ISDIGIT (*p)) { - ERROR ((0, 0, - _("Malformed extended header: missing whitespace after the length"))); + if (*p) + ERROR ((0, 0, _("Malformed extended header: missing length"))); return false; } - keyword = ++*p; - for (;*p < start + len; ++*p) - if (**p == '=') - break; + errno = 0; + len = strtoul (p, &len_lim, 10); - if (**p != '=') + if (len_max < len || (len == ULONG_MAX && errno == ERANGE)) { - ERROR ((0, 0, _("Malformed extended header: missing equal sign"))); + ERROR ((0, 0, _("Malformed extended header: length out of range"))); return false; } - **p = 0; + nextp = start + len; - endc = start[len-1]; - start[len-1] = 0; + for (p = len_lim; *p == ' ' || *p == '\t'; p++) + continue; + if (p == len_lim) + { + ERROR ((0, 0, + _("Malformed extended header: missing blank after length"))); + return false; + } + + keyword = p; + p = strchr (p, '='); + if (! (p && p < nextp)) + { + ERROR ((0, 0, _("Malformed extended header: missing equal sign"))); + return false; + } - handler (data, keyword, *p + 1); + if (nextp[-1] != '\n') + { + ERROR ((0, 0, _("Malformed extended header: missing newline"))); + return false; + } - start[len-1] = endc; - **p = '='; - *p = &start[len]; + *p = nextp[-1] = '\0'; + handler (data, keyword, p + 1); + *p = '='; + nextp[-1] = '\n'; + *ptr = nextp; return true; } @@ -532,7 +550,7 @@ decx (void *data, char const *keyword, char const *value) if (xheader_keyword_deleted_p (keyword) || xheader_keyword_override_p (keyword)) return; - + t = locate_handler (keyword); if (t) t->decoder (st, value); @@ -543,15 +561,12 @@ xheader_decode (struct tar_stat_info *st) { run_override_list (keyword_global_override_list, st); run_override_list (global_header_override_list, st); - + if (extended_header.size) { char *p = extended_header.buffer + BLOCKSIZE; - char *endp = &extended_header.buffer[extended_header.size-1]; - - while (p < endp) - if (!decode_record (&p, decx, st)) - break; + while (decode_record (&p, decx, st)) + continue; } run_override_list (keyword_override_list, st); } @@ -564,22 +579,20 @@ decg (void *data, char const *keyword, char const *value) } void -xheader_decode_global () +xheader_decode_global (void) { if (extended_header.size) { char *p = extended_header.buffer + BLOCKSIZE; - char *endp = &extended_header.buffer[extended_header.size-1]; xheader_list_destroy (&global_header_override_list); - while (p < endp) - if (!decode_record (&p, decg, &global_header_override_list)) - break; + while (decode_record (&p, decg, &global_header_override_list)) + continue; } } static void -extended_header_init () +extended_header_init (void) { if (!extended_header.stk) { @@ -592,8 +605,7 @@ void xheader_store (char const *keyword, struct tar_stat_info const *st, void *data) { struct xhdr_tab const *t; - char *value; - + if (extended_header.buffer) return; t = locate_handler (keyword); @@ -617,6 +629,7 @@ xheader_read (union block *p, size_t size) extended_header.size = size; nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE; extended_header.buffer = xmalloc (size + 1); + extended_header.buffer[size] = '\0'; do { @@ -624,7 +637,7 @@ xheader_read (union block *p, size_t size) if (len > BLOCKSIZE) len = BLOCKSIZE; - + memcpy (&extended_header.buffer[j], p->buffer, len); set_next_block_after (p); @@ -782,19 +795,22 @@ code_num (uintmax_t value, char const *keyword, struct xheader *xhdr) } static void -dummy_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) +dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)), + char const *keyword __attribute__ ((unused)), + struct xheader *xhdr __attribute__ ((unused)), + void *data __attribute__ ((unused))) { } static void -dummy_decoder (struct tar_stat_info *st, char const *arg) +dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)), + char const *arg __attribute__ ((unused))) { } static void atime_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr); } @@ -807,7 +823,7 @@ atime_decoder (struct tar_stat_info *st, char const *arg) static void gid_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_num (st->stat.st_gid, keyword, xhdr); } @@ -822,7 +838,7 @@ gid_decoder (struct tar_stat_info *st, char const *arg) static void gname_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_string (st->gname, keyword, xhdr); } @@ -835,7 +851,7 @@ gname_decoder (struct tar_stat_info *st, char const *arg) static void linkpath_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_string (st->link_name, keyword, xhdr); } @@ -848,7 +864,7 @@ linkpath_decoder (struct tar_stat_info *st, char const *arg) static void ctime_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr); } @@ -861,7 +877,7 @@ ctime_decoder (struct tar_stat_info *st, char const *arg) static void mtime_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr); } @@ -874,7 +890,7 @@ mtime_decoder (struct tar_stat_info *st, char const *arg) static void path_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_string (st->file_name, keyword, xhdr); } @@ -889,7 +905,7 @@ path_decoder (struct tar_stat_info *st, char const *arg) static void size_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_num (st->stat.st_size, keyword, xhdr); } @@ -899,12 +915,12 @@ size_decoder (struct tar_stat_info *st, char const *arg) { uintmax_t u; if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK) - st->stat.st_size = u; + st->archive_file_size = st->stat.st_size = u; } static void uid_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_num (st->stat.st_uid, keyword, xhdr); } @@ -919,7 +935,7 @@ uid_decoder (struct tar_stat_info *st, char const *arg) static void uname_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void *data __attribute__ ((unused))) { code_string (st->uname, keyword, xhdr); } @@ -942,12 +958,13 @@ sparse_size_decoder (struct tar_stat_info *st, char const *arg) { uintmax_t u; if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK) - st->archive_file_size = u; + st->stat.st_size = u; } static void sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, + void *data __attribute__ ((unused))) { code_num (st->sparse_map_avail, keyword, xhdr); } @@ -996,7 +1013,7 @@ sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg) { if (st->sparse_map_avail == st->sparse_map_size) { - size_t newsize = st->sparse_map_size *= 2; + st->sparse_map_size *= 2; st->sparse_map = xrealloc (st->sparse_map, st->sparse_map_size * sizeof st->sparse_map[0]); @@ -1006,18 +1023,18 @@ sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg) } struct xhdr_tab const xhdr_tab[] = { - { "atime", atime_coder, atime_decoder }, - { "comment", dummy_coder, dummy_decoder }, - { "charset", dummy_coder, dummy_decoder }, - { "ctime", ctime_coder, ctime_decoder }, - { "gid", gid_coder, gid_decoder }, - { "gname", gname_coder, gname_decoder }, - { "linkpath", linkpath_coder, linkpath_decoder}, - { "mtime", mtime_coder, mtime_decoder }, - { "path", path_coder, path_decoder }, - { "size", size_coder, size_decoder }, - { "uid", uid_coder, uid_decoder }, - { "uname", uname_coder, uname_decoder }, + { "atime", atime_coder, atime_decoder, false }, + { "comment", dummy_coder, dummy_decoder, false }, + { "charset", dummy_coder, dummy_decoder, false }, + { "ctime", ctime_coder, ctime_decoder, false }, + { "gid", gid_coder, gid_decoder, false }, + { "gname", gname_coder, gname_decoder, false }, + { "linkpath", linkpath_coder, linkpath_decoder, false }, + { "mtime", mtime_coder, mtime_decoder, false }, + { "path", path_coder, path_decoder, false }, + { "size", size_coder, size_decoder, false }, + { "uid", uid_coder, uid_decoder, false }, + { "uname", uname_coder, uname_decoder, false }, /* Sparse file handling */ { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true }, @@ -1033,12 +1050,12 @@ struct xhdr_tab const xhdr_tab[] = { /* The next directory entry actually contains the names of files that were in the directory at the time the dump was made. Supersedes GNUTYPE_DUMPDIR header type. */ - { "GNU.dump.name", dump_name_coder, dump_name_decoder }, - { "GNU.dump.status", dump_status_coder, dump_status_decoder }, + { "GNU.dump.name", dump_name_coder, dump_name_decoder, false }, + { "GNU.dump.status", dump_status_coder, dump_status_decoder, false }, /* Keeps the tape/volume header. May be present only in the global headers. Equivalent to GNUTYPE_VOLHDR. */ - { "GNU.volume.header", volume_header_coder, volume_header_decoder }, + { "GNU.volume.header", volume_header_coder, volume_header_decoder, false }, /* These may be present in a first global header of the archive. They provide the same functionality as GNUTYPE_MULTIVOL header. @@ -1046,9 +1063,9 @@ struct xhdr_tab const xhdr_tab[] = { otherwise kept in the size field of a multivolume header. The GNU.volume.offset keeps the offset of the start of this volume, otherwise kept in oldgnu_header.offset. */ - { "GNU.volume.size", volume_size_coder, volume_size_decoder }, - { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder }, + { "GNU.volume.size", volume_size_coder, volume_size_decoder, false }, + { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false }, #endif - { NULL, NULL, NULL } + { NULL, NULL, NULL, false } };