static char *url_decode(const char *);
static void tar_flush_unconsumed(struct archive_read *, size_t *);
-/*
- * PAX hdrcharset.
- */
-static const struct {
- const char *isoname;
- const char *cnvname;
-} pax_charset[] = {
- { "BINARY", NULL },
- { "ISO-IR 10646 2000 UTF-8", "UTF-8" },
- { "ISO-IR 8859 1 1998", "ISO-8859-1" },
- { "ISO-IR 8859 1 1998", "ISO-8859-1" },
- { "ISO-IR 8859 2 1999", "ISO-8859-2" },
- { "ISO-IR 8859 3 1999", "ISO-8859-3" },
- { "ISO-IR 8859 4 1998", "ISO-8859-4" },
- { "ISO-IR 8859 5 1999", "ISO-8859-5" },
- { "ISO-IR 8859 6 1999", "ISO-8859-6" },
- { "ISO-IR 8859 7 1987", "ISO-8859-7" },
- { "ISO-IR 8859 8 1999", "ISO-8859-8" },
- { "ISO-IR 8859 9 1999", "ISO-8859-9" },
- { "ISO-IR 8859 10 1998", "ISO-8859-10" },
- { "ISO-IR 8859 13 1998", "ISO-8859-13" },
- { "ISO-IR 8859 14 1998", "ISO-8859-14" },
- { "ISO-IR 8859 15 1999", "ISO-8859-15" },
- { NULL, NULL}
-};
-
int
archive_read_support_format_gnutar(struct archive *a)
}
static int
-set_conversion_failed_error(struct archive_read *a, struct tar *tar,
- const char *name)
+set_conversion_failed_error(struct archive_read *a,
+ struct archive_string_conv *sconv, const char *name)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"%s can't be converted from %s to current locale.",
- name, archive_string_conversion_charset_name(tar->sconv));
+ name, archive_string_conversion_charset_name(sconv));
return (ARCHIVE_WARN);
}
if (tar->sconv != NULL) {
if (archive_strncpy_in_locale(&(tar->localname),
tar->longname.s, tar->longname.length, tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar, "Pathname");
+ err = set_conversion_failed_error(a, tar->sconv, "Pathname");
archive_entry_copy_pathname(entry, tar->localname.s);
} else
archive_entry_copy_pathname(entry, tar->longname.s);
if (archive_strncpy_in_locale(&(tar->entry_linkpath),
header->linkname, sizeof(header->linkname),
tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar, "Linkname");
+ err = set_conversion_failed_error(a, tar->sconv, "Linkname");
} else
archive_string_empty(&(tar->entry_linkpath));
header = (const struct archive_entry_header_ustar *)h;
if (archive_strncpy_in_locale(&(tar->entry_pathname),
header->name, sizeof(header->name), tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar, "Pathname");
+ err = set_conversion_failed_error(a, tar->sconv, "Pathname");
archive_entry_copy_pathname(entry, tar->entry_pathname.s);
/* Grab rest of common fields */
r2 = 0;
}
if (r != 0 || r2 != 0)
- err = set_conversion_failed_error(a, tar, "Pathname");
+ err = set_conversion_failed_error(a, tar->sconv, "Pathname");
archive_entry_copy_pathname(entry, as->s);
r = archive_strncpy_in_locale(&(tar->entry_uname),
header->uname, sizeof(header->uname), tar->sconv);
if (r != 0)
- err = set_conversion_failed_error(a, tar, "Uname");
+ err = set_conversion_failed_error(a, tar->sconv, "Uname");
archive_entry_copy_uname(entry, tar->entry_uname.s);
r = archive_strncpy_in_locale(&(tar->entry_gname),
header->gname, sizeof(header->gname), tar->sconv);
if (r != 0)
- err = set_conversion_failed_error(a, tar, "Gname");
+ err = set_conversion_failed_error(a, tar->sconv, "Gname");
archive_entry_copy_gname(entry, tar->entry_gname.s);
/* Parse out device numbers only for char and block specials. */
size_t attr_length, l, line_length;
char *p;
char *key, *value;
+ struct archive_string_conv *sconv;
int err, err2;
attr_length = strlen(attr);
attr_length -= line_length;
}
- /* Default charset is UTF-8. */
- if (tar->pax_hdrcharset_binary == 0 && tar->sconv == NULL)
- tar->sconv = archive_string_conversion_from_charset(
+ /* Note: Should we use the specified charset only if hdrcharset is
+ * BINARY ? */
+ sconv = tar->sconv;
+ if (sconv == NULL && !tar->pax_hdrcharset_binary) {
+ /*
+ * Even if charset for filenames is not specified
+ * PAX format uses UTF-8 as default charset for its header
+ * unless hdrcharset=BINARY is present.
+ */
+ sconv = archive_string_conversion_from_charset(
&(a->archive), "UTF-8", 1);
+ }
if (archive_strlen(&(tar->entry_gname)) > 0) {
value = tar->entry_gname.s;
- if (tar->sconv != NULL) {
+ if (sconv != NULL) {
if (archive_strcpy_in_locale(&(tar->localname),
- value, tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar,
+ value, sconv) != 0)
+ err = set_conversion_failed_error(a, sconv,
"Gname");
else
/* Use a converted name. */
}
if (archive_strlen(&(tar->entry_linkpath)) > 0) {
value = tar->entry_linkpath.s;
- if (tar->sconv != NULL) {
+ if (sconv != NULL) {
if (archive_strcpy_in_locale(&(tar->localname),
- value, tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar,
+ value, sconv) != 0)
+ err = set_conversion_failed_error(a, sconv,
"Linkname");
else
/* Use a converted name. */
else if (archive_strlen(&(tar->entry_pathname)) > 0)
value = tar->entry_pathname.s;
if (value != NULL) {
- if (tar->sconv != NULL) {
+ if (sconv != NULL) {
if (archive_strcpy_in_locale(&(tar->localname),
- value, tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar,
+ value, sconv) != 0)
+ err = set_conversion_failed_error(a, sconv,
"Pathname");
else
/* Use a converted name. */
}
if (archive_strlen(&(tar->entry_uname)) > 0) {
value = tar->entry_uname.s;
- if (tar->sconv != NULL) {
+ if (sconv != NULL) {
if (archive_strcpy_in_locale(&(tar->localname),
- value, tar->sconv) != 0)
- err = set_conversion_failed_error(a, tar,
+ value, sconv) != 0)
+ err = set_conversion_failed_error(a, sconv,
"Uname");
else
/* Use a converted name. */
break;
case 'h':
if (strcmp(key, "hdrcharset") == 0 && tar->sconv == NULL) {
- int i;
- for (i = 0; pax_charset[i].isoname != NULL; i++) {
- if (strcmp(pax_charset[i].isoname, value) == 0) {
- if (pax_charset[i].cnvname == NULL) {
- /* Binary mode. */
- tar->pax_hdrcharset_binary = 1;
- break;
- }
- tar->pax_hdrcharset_binary = 0;
- tar->sconv =
- archive_string_conversion_from_charset(
- &(a->archive),
- pax_charset[i].cnvname, 1);
- break;
- }
- }
+ if (strcmp(value, "BINARY") == 0)
+ /* Binary mode. */
+ tar->pax_hdrcharset_binary = 1;
+ else if (strcmp(value, "ISO-IR 10646 2000 UTF-8") == 0)
+ tar->pax_hdrcharset_binary = 0;
}
break;
case 'l':
r = archive_strncpy_in_locale(&(tar->entry_pathname),
header->name, sizeof(header->name), tar->sconv);
if (r != 0)
- err = set_conversion_failed_error(a, tar, "Pathname");
+ err = set_conversion_failed_error(a, tar->sconv, "Pathname");
archive_entry_copy_pathname(entry, tar->entry_pathname.s);
/* Fields common to ustar and GNU */
r = archive_strncpy_in_locale(&(tar->entry_uname),
header->uname, sizeof(header->uname), tar->sconv);
if (r != 0)
- err = set_conversion_failed_error(a, tar, "Uname");
+ err = set_conversion_failed_error(a, tar->sconv, "Uname");
archive_entry_copy_uname(entry, tar->entry_uname.s);
r = archive_strncpy_in_locale(&(tar->entry_gname),
header->gname, sizeof(header->gname), tar->sconv);
if (r != 0)
- err = set_conversion_failed_error(a, tar, "Gname");
+ err = set_conversion_failed_error(a, tar->sconv, "Gname");
archive_entry_copy_gname(entry, tar->entry_gname.s);
/* Parse out device numbers only for char and block specials */
size_t sparse_map_padding;
struct sparse_block *sparse_list;
struct sparse_block *sparse_tail;
- struct archive_string_conv *opt_sconv;
struct archive_string_conv *sconv_utf8;
int opt_binary;
- const char *hdrcharset;
};
static void add_pax_attr(struct archive_string *, const char *key,
archive_write_pax_options(struct archive_write *a, const char *key,
const char *val)
{
- static const char *iso_charset[] = {
- NULL,
- "ISO-IR 8859 1 1998",
- "ISO-IR 8859 2 1999",
- "ISO-IR 8859 3 1999",
- "ISO-IR 8859 4 1998",
- "ISO-IR 8859 5 1999",
- "ISO-IR 8859 6 1999",
- "ISO-IR 8859 7 1987",
- "ISO-IR 8859 8 1999",
- "ISO-IR 8859 9 1999",
- "ISO-IR 8859 10 1998",
- NULL,
- NULL,
- "ISO-IR 8859 13 1998",
- "ISO-IR 8859 14 1998",
- "ISO-IR 8859 15 1999",
- };
struct pax *pax = (struct pax *)a->format_data;
int ret = ARCHIVE_FAILED;
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"pax: charset option needs a character-set name");
- else {
- int try_conv = 0;
- const char *p;
-
- switch (val[0]) {
- case 'b':
- case 'B':
- /*
- * Specify binary mode. We will not convert
- * filenames, uname and gname to any charsets.
- */
- if (strcmp(val, "BINARY") == 0 ||
- strcmp(val, "binary") == 0) {
- pax->opt_binary = 1;
- pax->opt_sconv = NULL;
- pax->hdrcharset = "BINARY";
- ret = ARCHIVE_OK;
- }
- break;
- case 'I':
- /*
- * ISO-8859-1 ISO8859-1
- * ISO-8859-2 ISO8859-2
- * ISO-8859-3 ISO8859-3
- * ISO-8859-4 ISO8859-4
- * ISO-8859-5 ISO8859-5
- * ISO-8859-6 ISO8859-6
- * ISO-8859-7 ISO8859-7
- * ISO-8859-8 ISO8859-8
- * ISO-8859-9 ISO8859-9
- * ISO-8859-10 ISO8859-10
- * ISO-8859-13 ISO8859-13
- * ISO-8859-14 ISO8859-14
- * ISO-8859-15 ISO8859-15
- */
- if (strncmp(val, "ISO-8859-", 9) == 0 ||
- strncmp(val, "ISO8859-", 8) == 0) {
- int d;
- if (val[3] == '-')
- p = val + 9;
- else
- p = val + 8;
- if (p[0] >= '1' && p[0] <= '9') {
- d = p[0] - '0';
- if (p[1] >= '0' && p[1] <= '5'
- && p[2] == '\0')
- d = d * 10 + (p[1] - '0');
- else if (p[1] != '\0')
- d = -1;
- } else
- d = -1;
- if (d >= 1 && d <= 15 &&
- iso_charset[d] != NULL) {
- try_conv = 1;
- pax->hdrcharset =
- iso_charset[d];
- }
- }
- break;
- case 'U':
- /* UTF-8 is default charset. */
- if (strcmp(val, "UTF-8") == 0) {
- try_conv = 1;
- pax->hdrcharset = NULL;
- }
- break;
- }
+ else if (strcmp(val, "BINARY") == 0 ||
+ strcmp(val, "binary") == 0) {
/*
- * Can this platform convert names to specified
- * charset ?
+ * Specify binary mode. We will not convert
+ * filenames, uname and gname to any charsets.
*/
- if (try_conv) {
- pax->opt_binary = 0;
- pax->opt_sconv =
- archive_string_conversion_to_charset(
- &a->archive, val, 0);
- if (pax->opt_sconv != NULL)
- ret = ARCHIVE_OK;
- else {
- pax->hdrcharset = NULL;
- ret = ARCHIVE_FATAL;
- }
- } else if (ret != ARCHIVE_OK)
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "pax: invalid charset name");
- }
+ pax->opt_binary = 1;
+ ret = ARCHIVE_OK;
+ } else
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "pax: invalid charset name");
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"pax: unknown keyword ``%s''", key);
*/
if ((binary = pax->opt_binary) != 0)
sconv = NULL;
- else if (pax->opt_sconv != NULL && pax->hdrcharset != NULL)
- sconv = pax->opt_sconv;
else
sconv = pax->sconv_utf8;
/* Store the header encoding first, to be nice to readers. */
if (binary)
add_pax_attr(&(pax->pax_header), "hdrcharset", "BINARY");
- else if (pax->hdrcharset != NULL)
- add_pax_attr(&(pax->pax_header), "hdrcharset", pax->hdrcharset);
/*
* numeric fields, though they're less critical.
*/
__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0,
- pax->opt_sconv);
+ NULL);
/* If we built any extended attributes, write that entry first. */
if (archive_strlen(&(pax->pax_header)) > 0) {
archive_entry_set_ctime(pax_attr_entry, 0, 0);
r = __archive_write_format_header_ustar(a, paxbuff,
- pax_attr_entry, 'x', 1, pax->opt_sconv);
+ pax_attr_entry, 'x', 1, NULL);
archive_entry_free(pax_attr_entry);