From: Michihiro NAKAJIMA Date: Thu, 17 Mar 2011 01:03:05 +0000 (-0400) Subject: Move a conversion of UTF-16BE, which is used for Joliet extensions, into X-Git-Tag: v3.0.0a~653 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a0891c6963a0970cd1dcd1872832e6d1ee98ec92;p=thirdparty%2Flibarchive.git Move a conversion of UTF-16BE, which is used for Joliet extensions, into archive_string.c, and Use iconv for it if available. SVN-Revision: 3019 --- diff --git a/libarchive/archive_private.h b/libarchive/archive_private.h index 5ad95ca82..e279e6564 100644 --- a/libarchive/archive_private.h +++ b/libarchive/archive_private.h @@ -115,6 +115,8 @@ struct archive { #if HAVE_ICONV iconv_t unicode_to_current; iconv_t current_to_unicode; + iconv_t utf16be_to_current; + iconv_t current_to_utf16be; char *current_code; #endif }; diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index 3abcb697b..47aed09ab 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2009 Andreas Henriksson - * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2009-2011 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1764,19 +1764,9 @@ parse_file_info(struct archive_read *a, struct file_info *parent, * names which are 103 UCS2 characters(206 bytes) by their * option '-joliet-long'. */ - wchar_t wbuff[103+1], *wp; - const unsigned char *c; - if (name_len > 206) name_len = 206; - /* convert BE UTF-16 to wchar_t */ - for (c = p, wp = wbuff; - c < (p + name_len) && - wp < (wbuff + sizeof(wbuff)/sizeof(*wbuff) - 1); - c += 2) { - *wp++ = (((255 & (int)c[0]) << 8) | (255 & (int)c[1])); - } - *wp = L'\0'; + name_len &= ~1; /* trim trailing first version and dot from filename. * @@ -1789,19 +1779,19 @@ parse_file_info(struct archive_read *a, struct file_info *parent, * *, /, :, ;, ? and \. */ /* Chop off trailing ';1' from files. */ - if (wp > (wbuff + 2) && *(wp-2) == L';' && *(wp-1) == L'1') { - wp-=2; - *wp = L'\0'; - } - + if (name_len > 4 && p[name_len-4] == 0 && p[name_len-3] == ';' + && p[name_len-2] == 0 && p[name_len-1] == '1') + name_len -= 4; #if 0 /* XXX: this somehow manages to strip of single-character file extensions, like '.c'. */ /* Chop off trailing '.' from filenames. */ - if (*(wp-1) == L'.') - *(--wp) = L'\0'; + if (name_len > 2 && p[name_len-2] == 0 && p[name_len-1] == '.') + name_len -= 2; #endif - /* store the result in the file name field. */ - archive_string_append_from_unicode_to_utf8(&file->name, wbuff, wcslen(wbuff)); + /* Convert UTF-16BE of a filename to local locale MBS and store + * the result into a filename field. */ + archive_string_copy_from_utf16be(&a->archive, &file->name, + p, name_len); } else { /* Chop off trailing ';1' from files. */ if (name_len > 2 && p[name_len - 2] == ';' && diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 547788b21..6d271bded 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2003-2011 Tim Kientzle + * Copyright (c) 2011 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +58,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string.c 201095 2009-12-28 02:33 #include #endif +#include "archive_endian.h" #include "archive_private.h" #include "archive_string.h" @@ -755,6 +757,322 @@ archive_string_append_from_unicode_to_mbs(struct archive *a, struct archive_stri #endif /* _WIN32 && ! __CYGWIN__ */ +/* + * Conversion functions between local locale MBS and UTF-16BE. + * archive_string_copy_from_utf16be() : UTF-16BE --> MBS + * archive_string_copy_to_utf16be() : MBS --> UTF16BE + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Convert a UTF-16BE string to current locale and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_from_utf16be(struct archive *a, + struct archive_string *as, const unsigned char *utf16, size_t bytes) +{ + int ll; + BOOL defchar; + char *mbs; + size_t mbs_size; + int ret = 0; + + archive_string_empty(as); + bytes &= ~1; + archive_string_ensure(as, bytes+1); + mbs = as->s; + mbs_size = as->buffer_length-1; + while (bytes) { + uint16_t val = archive_be16dec(utf16); + ll = WideCharToMultiByte(CP_OEMCP, 0, + (LPCWSTR)&val, 1, mbs, mbs_size, + NULL, &defchar); + if (ll == 0) { + *mbs = '\0'; + return (-1); + } else if (defchar) + ret = -1; + as->length += ll; + mbs += ll; + mbs_size -= ll; + bytes -= 2; + utf16 += 2; + } + *mbs = '\0'; + return (ret); +} + +static int +is_big_endian() +{ + uint16_t d = 1; + + return (archive_be16dec(&d) == 1); +} + +/* + * Convert a current locale string to UTF-16BE and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_to_utf16be(struct archive *a, + struct archive_string *a16be, struct archive_string *as) +{ + size_t count; + + archive_string_ensure(a16be, (as->length + 1) * 2); + archive_string_empty(a16be); + do { + count = MultiByteToWideChar(CP_OEMCP, + MB_PRECOMPOSED, as->s, as->length, + (LPWSTR)a16be->s, (int)a16be->buffer_length - 2); + if (count == 0 && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + /* Need more buffer for UTF-16 string */ + count = MultiByteToWideChar(CP_OEMCP, + MB_PRECOMPOSED, as->s, as->length, NULL, 0); + archive_string_ensure(a16be, (count +1) * 2); + continue; + } + if (count == 0) + return (-1); + } while (0); + a16be->length = count * 2; + a16be->s[a16be->length] = 0; + a16be->s[a16be->length+1] = 0; + + if (!is_big_endian()) { + char *s = a16be->s; + size_t l = a16be->length; + while (l > 0) { + uint16_t v = archive_le16dec(s); + archive_be16enc(s, v); + s += 2; + l -= 2; + } + } + return (0); +} + +#elif HAVE_ICONV + +/* + * Convert a UTF-16BE string to current locale and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_from_utf16be(struct archive *a, + struct archive_string *as, const unsigned char *utf16, size_t bytes) +{ + ICONV_CONST char *inp; + size_t remaining; + iconv_t cd; + char *outp; + size_t avail, outbase; + int return_value = 0; /* success */ + + archive_string_empty(as); + + if (a == NULL) + cd = iconv_open(default_iconv_charset(""), "UTF-16BE"); + else if (a->utf16be_to_current == (iconv_t)(0)) + cd = iconv_open(default_iconv_charset(a->current_code), + "UTF-16BE"); + else { + /* Use the cached conversion descriptor after resetting it. */ + cd = a->utf16be_to_current; + iconv(cd, NULL, NULL, NULL, NULL); + } + if (cd == (iconv_t)(-1)) { + /* XXX do something here XXX */ + return (-1); + } + + bytes &= ~1; + archive_string_ensure(as, bytes+1); + + inp = (char *)(uintptr_t)utf16; + remaining = bytes; + outp = as->s; + avail = outbase = bytes; + while (remaining > 0) { + size_t result = iconv(cd, &inp, &remaining, &outp, &avail); + + if (result != (size_t)-1) { + *outp = '\0'; + as->length = outbase - avail; + break; /* Conversion completed. */ + } else if (errno == EILSEQ || errno == EINVAL) { + /* Skip the illegal input bytes. */ + *outp++ = '?'; + avail --; + inp += 2; + remaining -= 2; + return_value = -1; /* failure */ + } else { + /* E2BIG no output buffer, + * Increase an output buffer. */ + as->length = outbase - avail; + outbase *= 2; + archive_string_ensure(as, outbase+1); + outp = as->s + as->length; + avail = outbase - as->length; + } + } + /* Dispose of the conversion descriptor or cache it. */ + if (a == NULL) + iconv_close(cd); + else if (a->utf16be_to_current == (iconv_t)(0)) + a->utf16be_to_current = cd; + return (return_value); +} + +/* + * Convert a current locale string to UTF-16BE and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_to_utf16be(struct archive *a, + struct archive_string *a16be, struct archive_string *as) +{ + ICONV_CONST char *inp; + size_t remaining; + iconv_t cd; + char *outp; + size_t avail, outbase; + int return_value = 0; /* success */ + + archive_string_empty(a16be); + + if (a == NULL) + cd = iconv_open("UTF-16BE", default_iconv_charset("")); + else if (a->current_to_utf16be == (iconv_t)(0)) + cd = iconv_open("UTF-16BE", + default_iconv_charset(a->current_code)); + else { + /* Use the cached conversion descriptor after resetting it. */ + cd = a->current_to_utf16be; + iconv(cd, NULL, NULL, NULL, NULL); + } + if (cd == (iconv_t)(-1)) { + /* XXX do something here XXX */ + return (-1); + } + + archive_string_ensure(a16be, (as->length+1)*2); + + inp = (char *)(uintptr_t)as->s; + remaining = as->length; + outp = a16be->s; + avail = outbase = as->length * 2; + while (remaining > 0) { + size_t result = iconv(cd, &inp, &remaining, &outp, &avail); + + if (result != (size_t)-1) { + outp[0] = 0; outp[1] = 0; + a16be->length = outbase - avail; + break; /* Conversion completed. */ + } else if (errno == EILSEQ || errno == EINVAL) { + /* Skip the illegal input bytes. */ + *outp++ = 0; *outp++ = '?'; + avail -= 2; + inp ++; + remaining --; + return_value = -1; /* failure */ + } else { + /* E2BIG no output buffer, + * Increase an output buffer. */ + a16be->length = outbase - avail; + outbase *= 2; + archive_string_ensure(as, outbase+2); + outp = as->s + a16be->length; + avail = outbase - a16be->length; + } + } + /* Dispose of the conversion descriptor or cache it. */ + if (a == NULL) + iconv_close(cd); + else if (a->current_to_utf16be == (iconv_t)(0)) + a->current_to_utf16be = cd; + return (return_value); +} + +#else + +/* + * In case the platform does not have iconv nor other character-set + * conversion functions; We cannot handle UTF-16BE character-set, + * but there is a chance if a string consists just ASCII code. + * + * TODO: if current locale is UTF-8, it can be converted to UTF-16BE. + */ + +/* + * Convert a UTF-16BE string to current locale and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_from_utf16be(struct archive *a, + struct archive_string *as, const unsigned char *utf16, size_t bytes) +{ + char *mbs; + int ret = 0; + + archive_string_empty(as); + bytes &= ~1; + archive_string_ensure(as, bytes+1); + mbs = as->s; + while (bytes) { + uint16_t val = archive_be16dec(utf16); + if (val >= 0x80) { + /* We cannot handle it. */ + *mbs++ = '?'; + ret = -1; + } else + *mbs++ = (char)val; + as->length ++; + bytes -= 2; + utf16 += 2; + } + *mbs = '\0'; + return (ret); +} + +/* + * Convert a current locale string to UTF-16BE and copy the result. + * Return -1 if conversion failes. + */ +int +archive_string_copy_to_utf16be(struct archive *a, + struct archive_string *a16be, struct archive_string *as) +{ + const char *s = as->s; + char *utf16; + size_t remaining = as->length; + int ret = 0; + + archive_string_ensure(a16be, (as->length + 1) * 2); + archive_string_empty(a16be); + utf16 = a16be->s; + while (remaining--) { + if (*(unsigned char *)s >= 0x80) { + /* We cannot handle it. */ + *utf16++ = 0; + *utf16++ = '?'; + ret = -1; + } else { + *utf16++ = 0; + *utf16++ = *s++; + } + a16be->length += 2; + } + a16be->s[a16be->length] = 0; + a16be->s[a16be->length+1] = 0; + return (ret); +} + +#endif /* * Multistring operations. diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h index 292d54583..be5af7094 100644 --- a/libarchive/archive_string.h +++ b/libarchive/archive_string.h @@ -86,6 +86,18 @@ archive_string_append_from_unicode_to_utf8(struct archive_string *, const wchar_ int archive_string_append_from_unicode_to_mbs(struct archive *, struct archive_string *, const wchar_t *, size_t); +/* Convert a UTF-16BE string to current locale and copy the result. + * Return -1 if conversion failes. */ +int +archive_string_copy_from_utf16be(struct archive *a, + struct archive_string *as, const unsigned char *utf16, size_t bytes); + +/* Convert a current locale string to UTF-16BE and copy the result. + * Return -1 if conversion failes. */ +int +archive_string_copy_to_utf16be(struct archive *a, + struct archive_string *a16be, struct archive_string *as); + /* Copy one archive_string to another */ #define archive_string_copy(dest, src) \ ((dest)->length = 0, archive_string_concat((dest), (src))) diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index 17e9ad5d1..d2fabbe7c 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -57,6 +57,10 @@ __archive_clean(struct archive *a) iconv_close(a->unicode_to_current); if (a->current_to_unicode != (iconv_t)0) iconv_close(a->current_to_unicode); + if (a->utf16be_to_current != (iconv_t)0) + iconv_close(a->utf16be_to_current); + if (a->current_to_utf16be != (iconv_t)0) + iconv_close(a->current_to_utf16be); #endif return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 69d12a7f3..396952066 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009,2010 Michihiro NAKAJIMA + * Copyright (c) 2009-2011 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -695,6 +695,10 @@ struct iso9660 { uint64_t bytes_remaining; int need_multi_extent; + /* Temporary string buffer for Joliet extension. */ + struct archive_string utf16be; + struct archive_string mbs; + /* A list of all of struct isofile entries. */ struct { struct isofile *first; @@ -898,12 +902,12 @@ static void get_system_identitier(char *, size_t); static void set_str(unsigned char *, const char *, size_t, char, const char *); static inline int joliet_allowed_char(unsigned char, unsigned char); -static void set_str_beutf16(unsigned char *, const char *, size_t, - uint16_t, enum vdc); -static void set_str_a_characters_bp(unsigned char *, int, int, - const char *, enum vdc); -static void set_str_d_characters_bp(unsigned char *, int, int, - const char *, enum vdc); +static void set_str_utf16be(struct archive_write *, unsigned char *, + const char *, size_t, uint16_t, enum vdc); +static void set_str_a_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); +static void set_str_d_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); static void set_VD_bp(unsigned char *, enum VD_type, unsigned char); static inline void set_unused_field_bp(unsigned char *, int, int); @@ -1017,9 +1021,6 @@ static size_t fd_boot_image_size(int); static void make_boot_catalog(struct iso9660 *, unsigned char *); static int setup_boot_information(struct archive_write *); -static size_t mbstobeutf16s(unsigned char *, size_t, const char *, int); -static size_t mblen_of_beutf16(const unsigned char *, size_t); - static int zisofs_init(struct archive_write *, struct isofile *); static void zisofs_detect_magic(struct archive_write *, const void *, size_t); @@ -1065,6 +1066,8 @@ archive_write_set_format_iso9660(struct archive *_a) iso9660->directories_too_deep = NULL; iso9660->dircnt_max = 1; iso9660->wbuff_remaining = 0; + archive_string_init(&(iso9660->utf16be)); + archive_string_init(&(iso9660->mbs)); /* * Init Identifiers used for PVD and SVD. @@ -1529,6 +1532,17 @@ iso9660_write_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); } isofile_gen_utility_names(file); + if (iso9660->opt.joliet) { + /* Test whether a filename can be converted to UTF-16BE or not. */ + if (0 > archive_string_copy_to_utf16be(&a->archive, + &iso9660->utf16be, &file->basename)) { + isofile_free(file); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "A filename cannot be converted to UTF-16BE;" + "You should disable making Joliet extension"); + return (ARCHIVE_FAILED); + } + } isofile_add_entry(iso9660, file); isoent = isoent_new(file); if (isoent == NULL) { @@ -1994,6 +2008,8 @@ iso9660_free(struct archive_write *a) archive_string_free(&(iso9660->el_torito.catalog_filename)); archive_string_free(&(iso9660->el_torito.boot_filename)); archive_string_free(&(iso9660->el_torito.id)); + archive_string_free(&(iso9660->utf16be)); + archive_string_free(&(iso9660->mbs)); free(iso9660); a->format_data = NULL; @@ -2068,8 +2084,8 @@ joliet_allowed_char(unsigned char high, unsigned char low) } static void -set_str_beutf16(unsigned char *p, const char *s, size_t l, uint16_t uf, - enum vdc vdc) +set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s, + size_t l, uint16_t uf, enum vdc vdc) { size_t size, i; int onepad; @@ -2082,7 +2098,12 @@ set_str_beutf16(unsigned char *p, const char *s, size_t l, uint16_t uf, } else onepad = 0; if (vdc == VDC_UCS2) { - size = mbstobeutf16s(p, l, s, strlen(s)); + struct iso9660 *iso9660 = a->format_data; + archive_strncpy(&iso9660->mbs, s, l); + archive_string_copy_to_utf16be(&a->archive, + &iso9660->utf16be, &iso9660->mbs); + memcpy(p, iso9660->utf16be.s, iso9660->utf16be.length); + size = iso9660->utf16be.length; } else { const uint16_t *u16 = (const uint16_t *)s; @@ -2156,8 +2177,8 @@ static const char d1_characters_map[0x80] = { }; static void -set_str_a_characters_bp(unsigned char *bp, int from, int to, - const char *s, enum vdc vdc) +set_str_a_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) { switch (vdc) { @@ -2171,15 +2192,15 @@ set_str_a_characters_bp(unsigned char *bp, int from, int to, break; case VDC_UCS2: case VDC_UCS2_DIRECT: - set_str_beutf16(bp+from, s, to - from + 1, + set_str_utf16be(a, bp+from, s, to - from + 1, 0x0020, vdc); break; } } static void -set_str_d_characters_bp(unsigned char *bp, int from, int to, - const char *s, enum vdc vdc) +set_str_d_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) { switch (vdc) { @@ -2193,7 +2214,7 @@ set_str_d_characters_bp(unsigned char *bp, int from, int to, break; case VDC_UCS2: case VDC_UCS2_DIRECT: - set_str_beutf16(bp+from, s, to - from + 1, + set_str_utf16be(a, bp+from, s, to - from + 1, 0x0020, vdc); break; } @@ -3523,9 +3544,9 @@ set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, if (id->length > 0 && leading_under && id->s[0] != '_') { if (char_type == A_CHAR) - set_str_a_characters_bp(bp, from, to, id->s, vdc); + set_str_a_characters_bp(a, bp, from, to, id->s, vdc); else - set_str_d_characters_bp(bp, from, to, id->s, vdc); + set_str_d_characters_bp(a, bp, from, to, id->s, vdc); } else if (id->length > 0) { ids = id->s; if (leading_under) @@ -3552,16 +3573,16 @@ set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, vdc = VDC_UCS2_DIRECT; } if (char_type == A_CHAR) - set_str_a_characters_bp(bp, from, to, + set_str_a_characters_bp(a, bp, from, to, identifier, vdc); else - set_str_d_characters_bp(bp, from, to, + set_str_d_characters_bp(a, bp, from, to, identifier, vdc); } else { if (char_type == A_CHAR) - set_str_a_characters_bp(bp, from, to, NULL, vdc); + set_str_a_characters_bp(a, bp, from, to, NULL, vdc); else - set_str_d_characters_bp(bp, from, to, NULL, vdc); + set_str_d_characters_bp(a, bp, from, to, NULL, vdc); } return (ARCHIVE_OK); } @@ -3612,9 +3633,9 @@ write_VD(struct archive_write *a, struct vdd *vdd) set_unused_field_bp(bp, 8, 8); /* System Identifier */ get_system_identitier(identifier, sizeof(identifier)); - set_str_a_characters_bp(bp, 9, 40, identifier, vdc); + set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc); /* Volume Identifier */ - set_str_d_characters_bp(bp, 41, 72, + set_str_d_characters_bp(a, bp, 41, 72, iso9660->volume_identifier.s, vdc); /* Unused Field */ set_unused_field_bp(bp, 73, 80); @@ -3650,7 +3671,7 @@ write_VD(struct archive_write *a, struct vdd *vdd) set_directory_record(bp+157, 190-157+1, vdd->rootent, iso9660, DIR_REC_VD, vdd->vdd_type); /* Volume Set Identifier */ - set_str_d_characters_bp(bp, 191, 318, "", vdc); + set_str_d_characters_bp(a, bp, 191, 318, "", vdc); /* Publisher Identifier */ r = set_file_identifier(bp, 319, 446, vdc, a, vdd, &(iso9660->publisher_identifier), @@ -5943,18 +5964,21 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, int ext_off, noff, weight; size_t lt; - l = mbstobeutf16s(NULL, 0, np->file->basename.s, - np->file->basename.length); - p = malloc(l+6+2); + archive_string_copy_to_utf16be(&a->archive, + &iso9660->utf16be, &np->file->basename); + if ((int)(l = iso9660->utf16be.length) > ffmax) + l = ffmax; + + p = malloc((l+1)*2); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); return (ARCHIVE_FATAL); } - l = mbstobeutf16s(p, l, np->file->basename.s, - np->file->basename.length); - if ((int)l > ffmax) - l = ffmax; + memcpy(p, iso9660->utf16be.s, l); + p[l] = 0; + p[l+1] = 0; + np->identifier = (char *)p; lt = l; dot = p + l; @@ -5973,23 +5997,27 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, np->id_len = l; /* - * Check full-path name length. + * Get a length of MBS of a full-pathname. */ - if ((int)l == ffmax) { - np->mb_len = mblen_of_beutf16( + if ((int)iso9660->utf16be.length > ffmax) { + archive_string_copy_from_utf16be(&a->archive, + &iso9660->mbs, (const unsigned char *)np->identifier, l); + np->mb_len = iso9660->mbs.length; if (np->mb_len != (int)np->file->basename.length) weight = np->mb_len; } else np->mb_len = np->file->basename.length; - /* If length of full path name is longer than 240, + /* If a length of full-pathname is longer than 240 bytes, * it violates Joliet extensions regulation. */ if (parent_len + np->mb_len > 240) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "A lenght of a full-path name of `%s' is " - "longer than 240 bytes.", - archive_entry_pathname(np->file->entry)); + "The regulation of Joliet extensions;" + " A lenght of a full-pathname of `%s' is " + "longer than 240 bytes, (p=%d, b=%d)", + archive_entry_pathname(np->file->entry), + (int)parent_len, (int)np->mb_len); return (ARCHIVE_FATAL); } @@ -7023,166 +7051,6 @@ setup_boot_information(struct archive_write *a) return (write_to_temp(a, iso9660->temp_fd, iso9660->wbuff, 56)); } -#if defined(_WIN32) && !defined(__CYGWIN__) -static size_t -mbstobeutf16s(unsigned char *utf16, size_t utf16_size, - const char *s, int len) -{ - size_t count; - - if (utf16 != NULL && utf16_size > 1) { - count = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, - s, len, (LPWSTR)utf16, (int)utf16_size/2); - if (count == 0 && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - unsigned char *tp; - size_t tl; - - tl = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, - s, len, NULL, 0); - if (tl) { - tp = malloc(tl*2); - if (tp != NULL) { - count = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, - s, len, (LPWSTR)tp, (int)tl); - if (count) { - uint16_t val = 1; - - count = utf16_size / 2; - if (archive_be16dec(&val) != 1) { - unsigned char *xp = tp; - while (utf16_size > 0) { - archive_be16enc( - utf16, - *(uint16_t *)xp); - utf16 += 2; - xp += 2; - utf16_size -= 2; - } - } else - memcpy(utf16, tp, utf16_size); - } - free(tp); - } - } - } else if (count > 0) { - uint16_t val = 1; - if (archive_be16dec(&val) != 1) { - while (utf16_size > 0) { - archive_be16enc(utf16, *(uint16_t *)utf16); - utf16 += 2; - utf16_size -= 2; - } - } - } - } else - count = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, - s, len, NULL, 0); - return (count * 2); -} - -static size_t -mblen_of_beutf16(const unsigned char *utf16, size_t utf16_size) -{ - int count; - BOOL defchar; - - count = WideCharToMultiByte(CP_ACP, 0, - (LPCWSTR)utf16, (int)utf16_size/2, - NULL, 0, NULL, &defchar); - if (count == 0 || defchar) - return (0); - return ((size_t)count); -} - -#else - -/* - * NOTE: if wchar_t is not UCS4, mbstoutf16s() and mblen_of_beutf16() - * couldn't work as we have expected. - */ -static size_t -mbstobeutf16s(unsigned char *utf16, size_t utf16_size, - const char *s, int len) -{ - size_t utf16_avail; - wchar_t wc; -#if HAVE_MBRTOWC - mbstate_t ps; - - memset(&ps, 0, sizeof(ps)); -#else - mbtowc(NULL, NULL, 0); -#endif - utf16_size &= ~1; - if (utf16_size == 0) { - utf16 = NULL; - utf16_avail = utf16_size = SIZE_MAX; - } else - utf16_avail = utf16_size; - while (*s && len > 0 && utf16_avail > 0) { - int mlen; - -#if HAVE_MBRTOWC - mlen = mbrtowc(&wc, s, len, &ps); -#else - mlen = mbtowc(&wc, s, len); -#endif - if (mlen < 0) - return (0); - if (mlen == 0) - break; - if (utf16 != NULL) { - *utf16++ = (wc >> 8) & 0xFF; - *utf16++ = wc & 0xFF; - } - utf16_avail -= 2; - s += mlen; - len -= mlen; - } - return (utf16_size - utf16_avail); -} - -static size_t -mblen_of_beutf16(const unsigned char *utf16, size_t utf16_size) -{ - size_t mlen; - char mbchars[MB_LEN_MAX]; -#if HAVE_WCRTOMB - mbstate_t ps; - - memset(&ps, 0, sizeof(ps)); -#else - wctomb(NULL, L'\0'); -#endif - mlen = 0; - utf16_size &= ~1; - while (utf16_size) { - int len; - wchar_t wc; - - wc = *(const uint16_t *)utf16; -#if HAVE_WCRTOMB - len = wcrtomb(mbchars, wc, &ps); -#else - len = wctomb(mbchars, wc); -#endif - if (len < 0) - return (0); - if (len == 0) - break; - mlen += len; - utf16 += 2; - utf16_size -= 2; - } - return (mlen); -} -#endif - #ifdef HAVE_ZLIB_H static int