struct archive_string_conv *opt_sconv;
struct archive_string_conv *sconv;
struct archive_string_conv *sconv_acl;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
};
static int archive_block_is_null(const unsigned char *p);
tar->sparse_last = NULL;
tar->realsize = -1; /* Mark this as "unset" */
- /* Set a default character-set of names in an archive file. */
+ /* Setup default string conversion. */
tar->sconv = tar->opt_sconv;
+ if (tar->sconv == NULL) {
+ if (!tar->init_default_conversion) {
+ tar->sconv_default =
+ archive_string_default_conversion_for_read(&(a->archive));
+ tar->init_default_conversion = 1;
+ }
+ tar->sconv = tar->sconv_default;
+ }
r = tar_read_header(a, tar, entry, &unconsumed);
struct archive_string pathname;
struct archive_string extra;
struct archive_string_conv *sconv;
+ struct archive_string_conv *sconv_default;
struct archive_string_conv *sconv_utf8;
+ int init_default_conversion;
char format_name[64];
};
{
const struct zip_file_header *p;
const void *h;
+ struct archive_string_conv *sconv;
int ret = ARCHIVE_OK;
+ /* Setup default conversion. */
+ if (zip->sconv == NULL && !zip->init_default_conversion) {
+ zip->sconv_default =
+ archive_string_default_conversion_for_read(&(a->archive));
+ zip->init_default_conversion = 1;
+ }
+
if ((p = __archive_read_ahead(a, sizeof *p, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
}
- if (zip->sconv == NULL && (zip->flags & ZIP_UTF8_NAME) != 0) {
+ if (zip->sconv != NULL)
+ sconv = zip->sconv;
+ else if (zip->flags & ZIP_UTF8_NAME) {
/* The filename is stored to be UTF-8. */
if (zip->sconv_utf8 == NULL) {
zip->sconv_utf8 =
if (zip->sconv_utf8 == NULL)
return (ARCHIVE_FATAL);
}
- if (archive_strncpy_in_locale(&zip->pathname,
- h, zip->filename_length, zip->sconv_utf8) != 0) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Pathname cannot be converted "
- "from UTF-8 to current locale.");
- ret = ARCHIVE_WARN;
- }
- } else {
- if (archive_strncpy_in_locale(&zip->pathname,
- h, zip->filename_length, zip->sconv) != 0) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Pathname cannot be converted "
- "from %s to current locale.",
- archive_string_conversion_charset_name(zip->sconv));
- ret = ARCHIVE_WARN;
- }
+ sconv = zip->sconv_utf8;
+ } else
+ sconv = zip->sconv_default;
+
+ if (archive_strncpy_in_locale(&zip->pathname,
+ h, zip->filename_length, sconv) != 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Pathname cannot be converted "
+ "from %s to current locale.",
+ archive_string_conversion_charset_name(sconv));
+ ret = ARCHIVE_WARN;
}
__archive_read_consume(a, zip->filename_length);
archive_entry_set_pathname(entry, zip->pathname.s);
return (get_sconv_object(a, charset, get_current_charset(a), flag));
}
+/*
+ * archive_string_default_conversion_*_archive() are provided for Windows
+ * platform because other archiver application use CP_OEMCP for
+ * MultiByteToWideChar() and WideCharToMultiByte() for the filenames
+ * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
+ * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
+ * So we should make a string conversion between CP_ACP and CP_OEMCP
+ * for compatibillty.
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+struct archive_string_conv *
+archive_string_default_conversion_for_read(struct archive *a)
+{
+ const char *cur_charset = get_current_charset(a);
+
+ if (a->current_codepage == GetOEMCP())
+ return (NULL);/* no conversion. */
+ return (get_sconv_object(a, "CP_OEMCP", cur_charset,
+ SCONV_FROM_CHARSET));
+}
+
+struct archive_string_conv *
+archive_string_default_conversion_for_write(struct archive *a)
+{
+ const char *cur_charset = get_current_charset(a);
+
+ if (a->current_codepage == GetOEMCP())
+ return (NULL);/* no conversion. */
+ return (get_sconv_object(a, "CP_OEMCP", cur_charset,
+ SCONV_TO_CHARSET));
+}
+#else
+struct archive_string_conv *
+archive_string_default_conversion_for_read(struct archive *a)
+{
+ (void)a; /* UNUSED */
+ return (NULL);
+}
+
+struct archive_string_conv *
+archive_string_default_conversion_for_write(struct archive *a)
+{
+ (void)a; /* UNUSED */
+ return (NULL);
+}
+#endif
+
/*
* Dispose of all character conversion objects in the archive object.
*/
archive_string_append_from_wcs_to_mbs(struct archive *, struct archive_string *, const wchar_t *, size_t);
-/* Test that platform support a character-set conversion.
- * Return -1 and set a error message if the conversion is not supported. */
+/* Create a string conversion object.
+ * Return NULL and set a error message if the conversion is not supported
+ * on the platform. */
struct archive_string_conv *
archive_string_conversion_to_charset(struct archive *, const char *, int);
struct archive_string_conv *
archive_string_conversion_from_charset(struct archive *, const char *, int);
+/* Create the default string conversion object for reading/writing an archive.
+ * Return NULL if the conversion is unneeded.
+ * Note: On non Windows platform this always returns NULL.
+ */
+struct archive_string_conv *
+archive_string_default_conversion_for_read(struct archive *);
+struct archive_string_conv *
+archive_string_default_conversion_for_write(struct archive *);
+/* Dispose of a string conversion object. */
void
archive_string_conversion_free(struct archive *);
const char *
struct archive_string l_uname;
struct archive_string l_gname;
struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
};
/*
int tartype;
const char *linkname;
struct gnutar *gnutar;
+ struct archive_string_conv *sconv;
gnutar = (struct gnutar *)a->format_data;
+ /* Setup default string conversion. */
+ if (gnutar->opt_sconv == NULL) {
+ if (!gnutar->init_default_conversion) {
+ gnutar->sconv_default =
+ archive_string_default_conversion_for_write(&(a->archive));
+ gnutar->init_default_conversion = 1;
+ }
+ sconv = gnutar->sconv_default;
+ } else
+ sconv = gnutar->opt_sconv;
+
/* Only regular files (not hardlinks) have data. */
if (archive_entry_hardlink(entry) != NULL ||
archive_entry_symlink(entry) != NULL ||
}
r = archive_strcpy_in_locale(&(gnutar->l_pathname),
- archive_entry_pathname(entry), gnutar->opt_sconv);
+ archive_entry_pathname(entry), sconv);
if (r != 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
archive_entry_pathname(entry),
- archive_string_conversion_charset_name(gnutar->opt_sconv));
+ archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
if (archive_entry_uname(entry) != NULL) {
r = archive_strcpy_in_locale(&(gnutar->l_uname),
- archive_entry_uname(entry), gnutar->opt_sconv);
+ archive_entry_uname(entry), sconv);
if (r != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate uname '%s' to %s",
archive_entry_uname(entry),
- archive_string_conversion_charset_name(gnutar->opt_sconv));
+ archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
} else
archive_string_empty(&(gnutar->l_uname));
if (archive_entry_gname(entry) != NULL) {
archive_strcpy_in_locale(&(gnutar->l_gname),
- archive_entry_gname(entry), gnutar->opt_sconv);
+ archive_entry_gname(entry), sconv);
if (r != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate gname '%s' to %s",
archive_entry_gname(entry),
- archive_string_conversion_charset_name(gnutar->opt_sconv));
+ archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
} else
linkname = archive_entry_symlink(entry);
if (linkname != NULL) {
archive_strcpy_in_locale(&(gnutar->l_linkname),
- linkname, gnutar->opt_sconv);
+ linkname, sconv);
if (r != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s",
linkname,
- archive_string_conversion_charset_name(gnutar->opt_sconv));
+ archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
} else
uint64_t entry_padding;
struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
};
/*
char buff[512];
int ret, ret2;
struct ustar *ustar;
+ struct archive_string_conv *sconv;
ustar = (struct ustar *)a->format_data;
- /* Sanity check. */
+ /* Setup default string conversion. */
+ if (ustar->opt_sconv == NULL) {
+ if (!ustar->init_default_conversion) {
+ ustar->sconv_default =
+ archive_string_default_conversion_for_write(&(a->archive));
+ ustar->init_default_conversion = 1;
+ }
+ sconv = ustar->sconv_default;
+ } else
+ sconv = ustar->opt_sconv;
+
+ /* Sanity check. */
if (archive_entry_pathname(entry) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in tar file without pathname");
}
}
- ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1,
- ustar->opt_sconv);
+ ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
if (ret < ARCHIVE_WARN)
return (ret);
ret2 = __archive_write_output(a, buff, 512);
enum compression compression;
int flags;
struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
#ifdef HAVE_ZLIB_H
z_stream stream;
struct zip_extra_data_local e;
struct zip_data_descriptor *d;
struct zip_file_header_link *l;
+ struct archive_string_conv *sconv;
int ret, ret2 = ARCHIVE_OK;
int64_t size;
mode_t type;
archive_entry_set_size(entry, 0);
zip = a->format_data;
+ /* Setup default conversion. */
+ if (zip->opt_sconv == NULL && !zip->init_default_conversion) {
+ zip->sconv_default =
+ archive_string_default_conversion_for_write(&(a->archive));
+ zip->init_default_conversion = 1;
+ }
+
if (zip->flags == 0) {
/* Initialize the general purpose flags. */
zip->flags = ZIP_FLAGS;
}
l->entry = archive_entry_clone(entry);
l->flags = zip->flags;
- if (zip->opt_sconv != NULL) {
+ if (zip->opt_sconv != NULL)
+ sconv = zip->opt_sconv;
+ else
+ sconv = zip->sconv_default;
+ if (sconv != NULL) {
if (archive_strcpy_in_locale(&(zip->l_name),
- archive_entry_pathname(entry), zip->opt_sconv) != 0) {
+ archive_entry_pathname(entry), sconv) != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
archive_entry_pathname(entry),
- archive_string_conversion_charset_name(zip->opt_sconv));
+ archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
archive_entry_set_pathname(l->entry, zip->l_name.s);