+
+ if (!offset)
+ ERROR ((0, 0,
+ _("Malformed extended header: invalid %s: odd number of values"),
+ keyword));
+}
+
+static void
+dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
+}
+
+static void
+dumpdir_decoder (struct tar_stat_info *st,
+ char const *keyword __attribute__((unused)),
+ char const *arg,
+ size_t size)
+{
+ st->dumpdir = xmalloc (size);
+ 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 *keyword __attribute__((unused)),
+ char const *arg,
+ size_t size __attribute__((unused)))
+{
+ 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 const *v = data;
+ code_num (*v, keyword, xhdr);
+}
+
+static void
+volume_size_decoder (struct tar_stat_info *st,
+ char const *keyword,
+ char const *arg, size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
+ 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 const *v = data;
+ code_num (*v, keyword, xhdr);
+}
+
+static void
+volume_offset_decoder (struct tar_stat_info *st,
+ char const *keyword,
+ char const *arg, size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
+ continued_file_offset = u;
+}
+
+static void
+volume_filename_decoder (struct tar_stat_info *st,
+ char const *keyword __attribute__((unused)),
+ char const *arg,
+ size_t size __attribute__((unused)))
+{
+ decode_string (&continued_file_name, arg);
+}
+
+static void
+xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ code_string (st->cntx_name, keyword, xhdr);
+}
+
+static void
+xattr_selinux_decoder (struct tar_stat_info *st,
+ char const *keyword, char const *arg, size_t size)
+{
+ decode_string (&st->cntx_name, arg);
+}
+
+static void
+xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
+}
+
+static void
+xattr_acls_a_decoder (struct tar_stat_info *st,
+ char const *keyword, char const *arg, size_t size)
+{
+ st->acls_a_ptr = xmemdup (arg, size + 1);
+ st->acls_a_len = size;
+}
+
+static void
+xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
+}
+
+static void
+xattr_acls_d_decoder (struct tar_stat_info *st,
+ char const *keyword, char const *arg, size_t size)
+{
+ st->acls_d_ptr = xmemdup (arg, size + 1);
+ st->acls_d_len = size;
+}
+
+static void
+xattr_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ struct xattr_array *xattr_map = st->xattr_map;
+ const size_t *off = data;
+ xheader_print_n (xhdr, keyword,
+ xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
+}
+
+static void
+xattr_decoder (struct tar_stat_info *st,
+ char const *keyword, char const *arg, size_t size)
+{
+ char *xstr, *xkey;
+
+ /* copy keyword */
+ size_t klen_raw = strlen (keyword);
+ xkey = alloca (klen_raw + 1);
+ memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
+
+ /* copy value */
+ xstr = alloca (size + 1);
+ memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
+
+ xattr_decode_keyword (xkey);
+
+ xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
+}
+
+static void
+sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ code_num (st->sparse_major, keyword, xhdr);
+}
+
+static void
+sparse_major_decoder (struct tar_stat_info *st,
+ char const *keyword,
+ char const *arg,
+ size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
+ st->sparse_major = u;
+}
+
+static void
+sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void const *data)
+{
+ code_num (st->sparse_minor, keyword, xhdr);
+}
+
+static void
+sparse_minor_decoder (struct tar_stat_info *st,
+ char const *keyword,
+ char const *arg,
+ size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
+ st->sparse_minor = u;