📄 xheader.c
字号:
return false; } if (len_max < len) { int len_len = len_lim - p; ERROR ((0, 0, _("Extended header length %*s is out of range"), len_len, p)); return false; } nextp = start + len; 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; } if (nextp[-1] != '\n') { ERROR ((0, 0, _("Malformed extended header: missing newline"))); return false; } *p = nextp[-1] = '\0'; handler (data, keyword, p + 1, nextp - p - 2); /* '=' + trailing '\n' */ *p = '='; nextp[-1] = '\n'; *ptr = nextp; return true;}static voidrun_override_list (struct keyword_list *kp, struct tar_stat_info *st){ for (; kp; kp = kp->next) { struct xhdr_tab const *t = locate_handler (kp->pattern); if (t) t->decoder (st, t->keyword, kp->value, strlen (kp->value)); }}static voiddecx (void *data, char const *keyword, char const *value, size_t size){ struct xhdr_tab const *t; struct tar_stat_info *st = data; if (xheader_keyword_deleted_p (keyword) || xheader_keyword_override_p (keyword)) return; t = locate_handler (keyword); if (t) t->decoder (st, keyword, value, size); else WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"), keyword));}voidxheader_decode (struct tar_stat_info *st){ run_override_list (keyword_global_override_list, st); run_override_list (global_header_override_list, st); if (st->xhdr.size) { char *p = st->xhdr.buffer + BLOCKSIZE; while (decode_record (&st->xhdr, &p, decx, st)) continue; } run_override_list (keyword_override_list, st);}static voiddecg (void *data, char const *keyword, char const *value, size_t size __attribute__((unused))){ struct keyword_list **kwl = data; xheader_list_append (kwl, keyword, value);}voidxheader_decode_global (struct xheader *xhdr){ if (xhdr->size) { char *p = xhdr->buffer + BLOCKSIZE; xheader_list_destroy (&global_header_override_list); while (decode_record (xhdr, &p, decg, &global_header_override_list)) continue; }}voidxheader_init (struct xheader *xhdr){ if (!xhdr->stk) { xhdr->stk = xmalloc (sizeof *xhdr->stk); obstack_init (xhdr->stk); }}voidxheader_store (char const *keyword, struct tar_stat_info *st, void const *data){ struct xhdr_tab const *t; if (st->xhdr.buffer) return; t = locate_handler (keyword); if (!t || !t->coder) return; if (xheader_keyword_deleted_p (keyword) || xheader_keyword_override_p (keyword)) return; xheader_init (&st->xhdr); t->coder (st, keyword, &st->xhdr, data);}voidxheader_read (struct xheader *xhdr, union block *p, size_t size){ size_t j = 0; xheader_init (xhdr); size += BLOCKSIZE; xhdr->size = size; xhdr->buffer = xmalloc (size + 1); xhdr->buffer[size] = '\0'; do { size_t len = size; if (len > BLOCKSIZE) len = BLOCKSIZE; memcpy (&xhdr->buffer[j], p->buffer, len); set_next_block_after (p); p = find_next_block (); j += len; size -= len; } while (size > 0);}static voidxheader_print_n (struct xheader *xhdr, char const *keyword, char const *value, size_t vsize){ size_t len = strlen (keyword) + vsize + 3; /* ' ' + '=' + '\n' */ size_t p; size_t n = 0; char nbuf[UINTMAX_STRSIZE_BOUND]; char const *np; do { p = n; np = umaxtostr (len + p, nbuf); n = nbuf + sizeof nbuf - 1 - np; } while (n != p); x_obstack_grow (xhdr, np, n); x_obstack_1grow (xhdr, ' '); x_obstack_grow (xhdr, keyword, strlen (keyword)); x_obstack_1grow (xhdr, '='); x_obstack_grow (xhdr, value, vsize); x_obstack_1grow (xhdr, '\n');}static voidxheader_print (struct xheader *xhdr, char const *keyword, char const *value){ xheader_print_n (xhdr, keyword, value, strlen (value));}voidxheader_finish (struct xheader *xhdr){ struct keyword_list *kp; for (kp = keyword_override_list; kp; kp = kp->next) code_string (kp->value, kp->pattern, xhdr); xhdr->buffer = obstack_finish (xhdr->stk);}voidxheader_destroy (struct xheader *xhdr){ if (xhdr->stk) { obstack_free (xhdr->stk, NULL); free (xhdr->stk); xhdr->stk = NULL; } else free (xhdr->buffer); xhdr->buffer = 0; xhdr->size = 0;}/* Buildable strings */voidxheader_string_begin (struct xheader *xhdr){ xhdr->string_length = 0;}voidxheader_string_add (struct xheader *xhdr, char const *s){ if (xhdr->buffer) return; xheader_init (xhdr); xhdr->string_length += strlen (s); x_obstack_grow (xhdr, s, strlen (s));}boolxheader_string_end (struct xheader *xhdr, char const *keyword){ uintmax_t len; uintmax_t p; uintmax_t n = 0; size_t size; char nbuf[UINTMAX_STRSIZE_BOUND]; char const *np; char *cp; if (xhdr->buffer) return false; xheader_init (xhdr); len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */ do { p = n; np = umaxtostr (len + p, nbuf); n = nbuf + sizeof nbuf - 1 - np; } while (n != p); p = strlen (keyword) + n + 2; size = p; if (size != p) { ERROR ((0, 0, _("Generated keyword/value pair is too long (keyword=%s, length=%s)"), keyword, nbuf)); obstack_free (xhdr->stk, obstack_finish (xhdr->stk)); return false; } x_obstack_blank (xhdr, p); x_obstack_1grow (xhdr, '\n'); cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1; memmove (cp + p, cp, xhdr->string_length); cp = stpcpy (cp, np); *cp++ = ' '; cp = stpcpy (cp, keyword); *cp++ = '='; return true;}/* Implementations */static voidout_of_range_header (char const *keyword, char const *value, uintmax_t minus_minval, uintmax_t maxval){ char minval_buf[UINTMAX_STRSIZE_BOUND + 1]; char maxval_buf[UINTMAX_STRSIZE_BOUND]; char *minval_string = umaxtostr (minus_minval, minval_buf + 1); char *maxval_string = umaxtostr (maxval, maxval_buf); if (minus_minval) *--minval_string = '-'; /* TRANSLATORS: The first %s is the pax extended header keyword (atime, gid, etc.). */ ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"), keyword, value, minval_string, maxval_string));}static voidcode_string (char const *string, char const *keyword, struct xheader *xhdr){ char *outstr; if (!utf8_convert (true, string, &outstr)) { /* FIXME: report error */ outstr = xstrdup (string); } xheader_print (xhdr, keyword, outstr); free (outstr);}static voiddecode_string (char **string, char const *arg){ if (*string) { free (*string); *string = NULL; } if (!utf8_convert (false, arg, string)) { /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */ assign_string (string, arg); }}static voidcode_time (struct timespec t, char const *keyword, struct xheader *xhdr){ char buf[TIMESPEC_STRSIZE_BOUND]; xheader_print (xhdr, keyword, code_timespec (t, buf));}enum decode_time_status { decode_time_success, decode_time_range, decode_time_bad_header };static enum decode_time_status_decode_time (struct timespec *ts, char const *arg, char const *keyword){ time_t s; unsigned long int ns = 0; char *p; char *arg_lim; bool negative = *arg == '-'; errno = 0; if (ISDIGIT (arg[negative])) { if (negative) { intmax_t i = strtoimax (arg, &arg_lim, 10); if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0) return decode_time_range; s = i; } else { uintmax_t i = strtoumax (arg, &arg_lim, 10); if (TYPE_MAXIMUM (time_t) < i) return decode_time_range; s = i; } p = arg_lim; if (errno == ERANGE) return decode_time_range; if (*p == '.') { int digits = 0; bool trailing_nonzero = false; while (ISDIGIT (*++p)) if (digits < LOG10_BILLION) { ns = 10 * ns + (*p - '0'); digits++; } else trailing_nonzero |= *p != '0'; while (digits++ < LOG10_BILLION) ns *= 10; if (negative) { /* Convert "-1.10000000000001" to s == -2, ns == 89999999. I.e., truncate time stamps towards minus infinity while converting them to internal form. */ ns += trailing_nonzero; if (ns != 0) { if (s == TYPE_MINIMUM (time_t)) return decode_time_range; s--; ns = BILLION - ns; } } } if (! *p) { ts->tv_sec = s; ts->tv_nsec = ns; return decode_time_success; } } return decode_time_bad_header;}static booldecode_time (struct timespec *ts, char const *arg, char const *keyword){ switch (_decode_time (ts, arg, keyword)) { case decode_time_success: return true; case decode_time_bad_header: ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"), keyword, arg)); return false; case decode_time_range: out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t)); return false; } return true;}static voidcode_num (uintmax_t value, char const *keyword, struct xheader *xhdr){ char sbuf[UINTMAX_STRSIZE_BOUND]; xheader_print (xhdr, keyword, umaxtostr (value, sbuf));}static booldecode_num (uintmax_t *num, char const *arg, uintmax_t maxval, char const *keyword){ uintmax_t u; char *arg_lim; if (! (ISDIGIT (*arg) && (errno = 0, u = strtoumax (arg, &arg_lim, 10), !*arg_lim))) { ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"), keyword, arg)); return false; } if (! (u <= maxval && errno != ERANGE)) { out_of_range_header (keyword, arg, 0, maxval); return false; } *num = u; return true;}static voiddummy_coder (struct tar_stat_info const *st __attribute__ ((unused)), char const *keyword __attribute__ ((unused)), struct xheader *xhdr __attribute__ ((unused)), void const *data __attribute__ ((unused))){}static voiddummy_decoder (struct tar_stat_info *st __attribute__ ((unused)), char const *keyword __attribute__ ((unused)), char const *arg __attribute__ ((unused)), size_t size __attribute__((unused))){}static voidatime_coder (struct tar_stat_info const *st, char const *keyword, struct xheader *xhdr, void const *data __attribute__ ((unused))){ code_time (st->atime, keyword, xhdr);}static voidatime_decoder (struct tar_stat_info *st,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -