+
+static void
+dumpdir_decoder (struct tar_stat_info *st, 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 *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);
+}
+
+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 *arg,
+ size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), "GNU.sparse.major"))
+ 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 *arg,
+ size_t size)
+{
+ uintmax_t u;
+ if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), "GNU.sparse.minor"))
+ st->sparse_minor = u;
+}
+
+struct xhdr_tab const xhdr_tab[] = {
+ { "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.name", path_coder, path_decoder,
+ true },
+ { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
+ true },
+ { "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
+ true },
+ { "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder, true },