X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fxheader.c;h=4c728d2d9fbbe9485eda5908ec96abc2ea6d92a7;hb=5b3dc9e3dd5082af1241aa56bae17afde29892fd;hp=029bebf3b5eb55b53eb10e3836dcc777be472b1d;hpb=374ae10d39e9e52789a00202c831a1c7c45e1610;p=chaz%2Ftar diff --git a/src/xheader.c b/src/xheader.c index 029bebf..4c728d2 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -225,15 +225,17 @@ xheader_set_option (char *string) to the result of the basename utility on the translated file name. %p The process ID of the pax process. + %n The value of the 3rd argument. %% A '%' character. */ -static char * -xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) +char * +xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n) { char *buf; size_t len = strlen (fmt); char *q; const char *p; + char *dirp = NULL; char *dir = NULL; char *base = NULL; char pidbuf[UINTMAX_STRSIZE_BOUND]; @@ -252,9 +254,10 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) case 'd': if (st) { - dir = safer_name_suffix (dir_name (st->orig_file_name), - false, absolute_names_option); - len += strlen (dir) - 1; + if (!dirp) + dirp = dir_name (st->orig_file_name); + dir = safer_name_suffix (dirp, false, absolute_names_option); + len += strlen (dir) - 2; } break; @@ -262,21 +265,18 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) if (st) { base = base_name (st->orig_file_name); - len += strlen (base) - 1; + len += strlen (base) - 2; } break; case 'p': pptr = umaxtostr (getpid (), pidbuf); - len += pidbuf + sizeof pidbuf - 1 - pptr - 1; + len += pidbuf + sizeof pidbuf - 1 - pptr - 2; break; case 'n': - if (allow_n) - { - nptr = umaxtostr (global_header_count + 1, nbuf); - len += nbuf + sizeof nbuf - 1 - nptr - 1; - } + nptr = umaxtostr (n, nbuf); + len += nbuf + sizeof nbuf - 1 - nptr - 2; break; } p++; @@ -316,6 +316,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) { q = stpcpy (q, nptr); p += 2; + break; } /* else fall through */ @@ -329,6 +330,8 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n) *q++ = *p++; } + free (dirp); + /* Do not allow it to end in a slash */ while (q > buf && ISSLASH (q[-1])) q--; @@ -341,7 +344,7 @@ xheader_xhdr_name (struct tar_stat_info *st) { if (!exthdr_name) assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f"); - return xheader_format_name (st, exthdr_name, false); + return xheader_format_name (st, exthdr_name, 0); } #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n" @@ -361,7 +364,7 @@ xheader_ghdr_name (void) strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE); } - return xheader_format_name (NULL, globexthdr_name, true); + return xheader_format_name (NULL, globexthdr_name, global_header_count + 1); } void @@ -396,6 +399,9 @@ xheader_write (char type, char *name, struct xheader *xhdr) } while (size > 0); xheader_destroy (xhdr); + + if (type == XGLTYPE) + global_header_count++; } void @@ -414,7 +420,6 @@ xheader_write_global (void) xheader_write (XGLTYPE, name = xheader_ghdr_name (), &extended_header); free (name); - global_header_count++; } @@ -424,7 +429,7 @@ struct xhdr_tab { char const *keyword; void (*coder) (struct tar_stat_info const *, char const *, - struct xheader *, void *data); + struct xheader *, void const *data); void (*decoder) (struct tar_stat_info *, char const *, size_t); bool protect; }; @@ -615,7 +620,8 @@ extended_header_init (void) } void -xheader_store (char const *keyword, struct tar_stat_info const *st, void *data) +xheader_store (char const *keyword, struct tar_stat_info const *st, + void const *data) { struct xhdr_tab const *t; @@ -742,7 +748,7 @@ xheader_string_add (char const *s) void xheader_string_end (char const *keyword) -{ +{ size_t len; size_t p; size_t n = 0; @@ -753,9 +759,9 @@ xheader_string_end (char const *keyword) if (extended_header.buffer) return; extended_header_init (); - + len = strlen (keyword) + string_length + 3; /* ' ' + '=' + '\n' */ - + do { p = n; @@ -950,7 +956,7 @@ static void dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)), char const *keyword __attribute__ ((unused)), struct xheader *xhdr __attribute__ ((unused)), - void *data __attribute__ ((unused))) + void const *data __attribute__ ((unused))) { } @@ -963,7 +969,7 @@ dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)), static void atime_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_time (st->atime, keyword, xhdr); } @@ -979,7 +985,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_num (st->stat.st_gid, keyword, xhdr); } @@ -995,7 +1001,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_string (st->gname, keyword, xhdr); } @@ -1009,7 +1015,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_string (st->link_name, keyword, xhdr); } @@ -1023,7 +1029,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_time (st->ctime, keyword, xhdr); } @@ -1039,7 +1045,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_time (st->mtime, keyword, xhdr); } @@ -1055,7 +1061,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_string (st->file_name, keyword, xhdr); } @@ -1071,7 +1077,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_num (st->stat.st_size, keyword, xhdr); } @@ -1087,7 +1093,7 @@ size_decoder (struct tar_stat_info *st, char const *arg, static void uid_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_num (st->stat.st_uid, keyword, xhdr); } @@ -1103,7 +1109,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 __attribute__ ((unused))) + struct xheader *xhdr, void const *data __attribute__ ((unused))) { code_string (st->uname, keyword, xhdr); } @@ -1117,7 +1123,7 @@ uname_decoder (struct tar_stat_info *st, char const *arg, static void sparse_size_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void const *data) { size_coder (st, keyword, xhdr, data); } @@ -1134,7 +1140,7 @@ sparse_size_decoder (struct tar_stat_info *st, char const *arg, static void sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword, struct xheader *xhdr, - void *data __attribute__ ((unused))) + void const *data __attribute__ ((unused))) { code_num (st->sparse_map_avail, keyword, xhdr); } @@ -1154,9 +1160,9 @@ sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg, static void sparse_offset_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void const *data) { - size_t *pi = data; + size_t const *pi = data; code_num (st->sparse_map[*pi].offset, keyword, xhdr); } @@ -1177,9 +1183,9 @@ sparse_offset_decoder (struct tar_stat_info *st, char const *arg, static void sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void const *data) { - size_t *pi = data; + size_t const *pi = data; code_num (st->sparse_map[*pi].numbytes, keyword, xhdr); } @@ -1204,14 +1210,14 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg, { int offset = 1; static char *keyword = "GNU.sparse.map"; - + st->sparse_map_avail = 0; while (1) { uintmax_t u; char *delim; struct sp_array e; - + if (!ISDIGIT (*arg)) { ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"), @@ -1247,7 +1253,7 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg, return; } } - + offset = !offset; if (*delim == 0) @@ -1271,7 +1277,7 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg, static void dumpdir_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void *data) + struct xheader *xhdr, void const *data) { xheader_print_n (xhdr, keyword, data, dumpdir_size (data)); } @@ -1284,6 +1290,60 @@ dumpdir_decoder (struct tar_stat_info *st, char const *arg, memcpy (st->dumpdir, arg, size); } +static void +volume_label_coder (struct tar_stat_info const *st, char const *keyword, + struct xheader *xhdr, void const *data) +{ + code_string (data, keyword, xhdr); +} + +static void +volume_label_decoder (struct tar_stat_info *st, char const *arg, size_t size) +{ + decode_string (&volume_label, arg); +} + +static void +volume_size_coder (struct tar_stat_info const *st, char const *keyword, + struct xheader *xhdr, void const *data) +{ + off_t v = *(off_t*)data; + code_num (v, keyword, xhdr); +} + +static void +volume_size_decoder (struct tar_stat_info *st, char const *arg, size_t size) +{ + uintmax_t u; + if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.size")) + continued_file_size = u; +} + +/* FIXME: Merge with volume_size_coder */ +static void +volume_offset_coder (struct tar_stat_info const *st, char const *keyword, + struct xheader *xhdr, void const *data) +{ + off_t v = *(off_t*)data; + code_num (v, keyword, xhdr); +} + +static void +volume_offset_decoder (struct tar_stat_info *st, char const *arg, size_t size) +{ + uintmax_t u; + if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.offset")) + continued_file_offset = u; +} + +static void +volume_filename_decoder (struct tar_stat_info *st, char const *arg, + size_t size) +{ + decode_string (&continued_file_name, arg); +} + + struct xhdr_tab const xhdr_tab[] = { { "atime", atime_coder, atime_decoder, false }, { "comment", dummy_coder, dummy_decoder, false }, @@ -1316,12 +1376,10 @@ struct xhdr_tab const xhdr_tab[] = { { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder, true }, - -#if 0 /* GNU private keywords (not yet implemented) */ - /* Keeps the tape/volume header. May be present only in the global headers. + /* Keeps the tape/volume label. May be present only in the global headers. Equivalent to GNUTYPE_VOLHDR. */ - { "GNU.volume.header", volume_header_coder, volume_header_decoder, false }, + { "GNU.volume.label", volume_label_coder, volume_label_decoder, true }, /* These may be present in a first global header of the archive. They provide the same functionality as GNUTYPE_MULTIVOL header. @@ -1329,9 +1387,10 @@ 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, false }, - { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false }, -#endif + { "GNU.volume.filename", volume_label_coder, volume_filename_decoder, + true }, + { "GNU.volume.size", volume_size_coder, volume_size_decoder, true }, + { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true }, { NULL, NULL, NULL, false } };