]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
This change almost revert r3148,r3149 because of my misunderstanding.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 4 Apr 2011 05:54:44 +0000 (01:54 -0400)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 4 Apr 2011 05:54:44 +0000 (01:54 -0400)
We should use both BINARY and UTF-8(default) only to a charset for PAX header.
- Pax writer allow charset=BINARY option only.
- For Reader side, Pax header encoding does not affect other tar header, and
  Pax header parser allow only both BINARY and "ISO-IR 10646 2000 UTF-8" for hdrcharset.

SVN-Revision: 3155

libarchive/archive_read_support_format_tar.c
libarchive/archive_write_set_format_pax.c

index c79670596710cc98337b4a1c4ad286c10a20683a..a464637e5ef924c344facc48fc67457017012e7f 100644 (file)
@@ -222,32 +222,6 @@ static int tohex(int c);
 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)
@@ -953,12 +927,12 @@ header_longlink(struct archive_read *a, struct tar *tar,
 }
 
 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);
 }
 
@@ -981,7 +955,7 @@ header_longname(struct archive_read *a, struct tar *tar,
        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);
@@ -1067,7 +1041,7 @@ header_common(struct archive_read *a, struct tar *tar,
                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));
 
@@ -1228,7 +1202,7 @@ header_old_tar(struct archive_read *a, struct tar *tar,
        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 */
@@ -1370,7 +1344,7 @@ header_ustar(struct archive_read *a, struct tar *tar,
                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);
 
@@ -1381,13 +1355,13 @@ header_ustar(struct archive_read *a, struct tar *tar,
        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. */
@@ -1416,6 +1390,7 @@ pax_header(struct archive_read *a, struct tar *tar,
        size_t attr_length, l, line_length;
        char *p;
        char *key, *value;
+       struct archive_string_conv *sconv;
        int err, err2;
 
        attr_length = strlen(attr);
@@ -1495,17 +1470,25 @@ pax_header(struct archive_read *a, struct tar *tar,
                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. */
@@ -1515,10 +1498,10 @@ pax_header(struct archive_read *a, struct tar *tar,
        }
        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. */
@@ -1541,10 +1524,10 @@ pax_header(struct archive_read *a, struct tar *tar,
        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. */
@@ -1554,10 +1537,10 @@ pax_header(struct archive_read *a, struct tar *tar,
        }
        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. */
@@ -1783,22 +1766,11 @@ pax_attribute(struct archive_read *a, struct tar *tar,
                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':
@@ -1933,7 +1905,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
        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 */
@@ -1943,13 +1915,13 @@ header_gnutar(struct archive_read *a, struct tar *tar,
        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 */
index 8980dc27200515995a1bbabc7b9dcd3c754eb6a5..0cf1e6085699afe19a1a841d960733ec09a13c0c 100644 (file)
@@ -63,10 +63,8 @@ struct pax {
        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,
@@ -156,24 +154,6 @@ static int
 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;
 
@@ -185,93 +165,18 @@ archive_write_pax_options(struct archive_write *a, const char *key,
                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);
@@ -489,8 +394,6 @@ archive_write_pax_header(struct archive_write *a,
         */
        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;
 
@@ -685,8 +588,6 @@ archive_write_pax_header(struct archive_write *a,
        /* 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);
 
 
        /*
@@ -1124,7 +1025,7 @@ archive_write_pax_header(struct archive_write *a,
         * 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) {
@@ -1180,7 +1081,7 @@ archive_write_pax_header(struct archive_write *a,
                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);