From: Michihiro NAKAJIMA Date: Sat, 26 Mar 2011 06:13:43 +0000 (-0400) Subject: Add support for charset option to xar reader although we expect X-Git-Tag: v3.0.0a~598 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23707f1efda92ae4a184679be6fdfac0731c7e55;p=thirdparty%2Flibarchive.git Add support for charset option to xar reader although we expect charset=UTF-8-MAC is specified. SVN-Revision: 3080 --- diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index 0d5f1fc60..18fe4e7ca 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -357,6 +357,8 @@ struct xar { enum enctype entry_encoding; struct chksumval entry_a_sum; struct chksumval entry_e_sum; + + char *charset; }; struct xmlattr { @@ -371,6 +373,7 @@ struct xmlattr_list { }; static int xar_bid(struct archive_read *); +static int xar_options(struct archive_read *, const char *, const char *); static int xar_read_header(struct archive_read *, struct archive_entry *); static int xar_read_data(struct archive_read *, @@ -443,12 +446,13 @@ archive_read_support_format_xar(struct archive *_a) "Can't allocate xar data"); return (ARCHIVE_FATAL); } + xar->charset = strdup("UTF-8"); r = __archive_read_register_format(a, xar, "xar", xar_bid, - NULL, + xar_options, xar_read_header, xar_read_data, xar_read_data_skip, @@ -503,6 +507,34 @@ xar_bid(struct archive_read *a) return (bid); } +static int +xar_options(struct archive_read *a, const char *key, const char *val) +{ + struct xar *xar; + int ret = ARCHIVE_FAILED; + + xar = (struct xar *)(a->format->data); + if (strcmp(key, "charset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "xar: charset option needs a character-set name"); + else if (archive_string_conversion_from_charset( + &a->archive, val) == 0) { + /* + * TODO: Should we allow UTF-8-MAC only ? + */ + free(xar->charset); + xar->charset = strdup(val); + ret = ARCHIVE_OK; + } else + ret = ARCHIVE_FATAL; + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "xar: unknown keyword ``%s''", key); + + return (ret); +} + static int read_toc(struct archive_read *a) { @@ -673,14 +705,14 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) archive_entry_set_mtime(entry, file->mtime, 0); archive_entry_set_gid(entry, file->gid); if (file->gname.length > 0) - archive_entry_update_gname_utf8(entry, file->gname.s); + archive_entry_set_gname(entry, file->gname.s); archive_entry_set_uid(entry, file->uid); if (file->uname.length > 0) - archive_entry_update_uname_utf8(entry, file->uname.s); + archive_entry_set_uname(entry, file->uname.s); archive_entry_set_mode(entry, file->mode); - archive_entry_update_pathname_utf8(entry, file->pathname.s); + archive_entry_set_pathname(entry, file->pathname.s); if (file->symlink.length > 0) - archive_entry_update_symlink_utf8(entry, file->symlink.s); + archive_entry_set_symlink(entry, file->symlink.s); /* Set proper nlink. */ if ((file->mode & AE_IFMT) == AE_IFDIR) archive_entry_set_nlink(entry, file->subdirs + 2); @@ -688,8 +720,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) archive_entry_set_nlink(entry, file->nlink); archive_entry_set_size(entry, file->size); if (archive_strlen(&(file->hardlink)) > 0) - archive_entry_update_hardlink_utf8(entry, - file->hardlink.s); + archive_entry_set_hardlink(entry, file->hardlink.s); archive_entry_set_ino64(entry, file->ino64); if (file->has & HAS_DEV) archive_entry_set_dev(entry, file->dev); @@ -867,6 +898,7 @@ xar_cleanup(struct archive_read *a) archive_string_free(&(tag->name)); free(tag); } + free(xar->charset); free(xar); a->format->data = NULL; return (r); @@ -2493,7 +2525,8 @@ static const int base64[256] = { }; static void -strappend_base64(struct archive_string *as, const char *s, size_t l) +strappend_base64(struct archive_read *a, struct xar *xar, + struct archive_string *as, const char *s, size_t l) { unsigned char buff[256]; unsigned char *out; @@ -2538,7 +2571,8 @@ strappend_base64(struct archive_string *as, const char *s, size_t l) } } if (len > 0) - archive_strncat(as, (const char *)buff, len); + archive_strncat_from_locale(&(a->archive), as, + (const char *)buff, len, xar->charset); } static void @@ -2582,13 +2616,16 @@ xml_data(void *userData, const char *s, int len) } xar->file->has |= HAS_PATHNAME; if (xar->base64text) - strappend_base64(&(xar->file->pathname), s, len); + strappend_base64(a, xar, + &(xar->file->pathname), s, len); else - archive_strncat(&(xar->file->pathname), s, len); + archive_strncat_from_locale(&(a->archive), + &(xar->file->pathname), s, len, xar->charset); break; case FILE_LINK: xar->file->has |= HAS_SYMLINK; - archive_strncpy(&(xar->file->symlink), s, len); + archive_strncpy_from_locale(&(a->archive), + &(xar->file->symlink), s, len, xar->charset); break; case FILE_TYPE: if (strncmp("file", s, len) == 0 || @@ -2639,7 +2676,8 @@ xml_data(void *userData, const char *s, int len) break; case FILE_GROUP: xar->file->has |= HAS_GID; - archive_strncpy(&(xar->file->gname), s, len); + archive_strncpy_from_locale(&(a->archive), + &(xar->file->gname), s, len, xar->charset); break; case FILE_GID: xar->file->has |= HAS_GID; @@ -2647,7 +2685,8 @@ xml_data(void *userData, const char *s, int len) break; case FILE_USER: xar->file->has |= HAS_UID; - archive_strncpy(&(xar->file->uname), s, len); + archive_strncpy_from_locale(&(a->archive), + &(xar->file->uname), s, len, xar->charset); break; case FILE_UID: xar->file->has |= HAS_UID;