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 (strcmp(key, "charset") == 0) {
+ /*
+ * The character-set we can use are defined in
+ * IEEE Std 1003.1-2001
+ */
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"pax: charset option needs a character-set name");
- else if (strcmp(val, "BINARY") == 0 ||
- strcmp(val, "binary") == 0) {
+ 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;
+ }
/*
- * Specify binary mode. We will not convert
- * filenames, uname and gname to UTF-8 or others.
+ * Can this platform convert names to specified
+ * charset ?
*/
- pax->opt_binary = 1;
- pax->opt_sconv = NULL;
- ret = ARCHIVE_OK;
- } else {
- pax->opt_sconv = archive_string_conversion_to_charset(
- &a->archive, val, 0);
- if (pax->opt_sconv != NULL) {
+ if (try_conv) {
pax->opt_binary = 0;
- ret = ARCHIVE_OK;
- } else
- ret = ARCHIVE_FATAL;
+ 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");
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
*/
if ((binary = pax->opt_binary) != 0)
sconv = NULL;
- else if (pax->opt_sconv != NULL &&
- strcmp(archive_string_conversion_charset_name(pax->opt_sconv),
- "UTF-8") != 0)
+ 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->opt_sconv != NULL && pax->sconv_utf8 != sconv)
- add_pax_attr(&(pax->pax_header), "hdrcharset",
- archive_string_conversion_charset_name(sconv));
+ else if (pax->hdrcharset != NULL)
+ add_pax_attr(&(pax->pax_header), "hdrcharset", pax->hdrcharset);
/*