From: Michihiro NAKAJIMA Date: Fri, 25 Mar 2011 09:36:27 +0000 (-0400) Subject: Add an mbs version of ACL control functions in order to reduce X-Git-Tag: v3.0.0a~605 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=830a4e20838c43d55e279f239d04f3fe70a95191;p=thirdparty%2Flibarchive.git Add an mbs version of ACL control functions in order to reduce extra character conversion. previous: Create : Disk -> MBS -> WCS -> MBS -> UTF-8 -> Pax archive file. Extract: Pax archive file -> UTF-8 -> MBS -> WCS ->MBS -> Disk. after: Create : Disk -> MBS -> UTF-8 -> Pax archive file. Extract: Pax archive file -> UTF-8 -> MBS -> Disk. SVN-Revision: 3073 --- diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c index c01372182..577039648 100644 --- a/libarchive/archive_acl.c +++ b/libarchive/archive_acl.c @@ -58,6 +58,15 @@ static int prefix_w(const wchar_t *start, const wchar_t *end, static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, const wchar_t *wname, int perm, int id); static void append_id_w(wchar_t **wp, int id); +static int isint(const char *start, const char *end, int *result); +static int ismode(const char *start, const char *end, int *result); +static void next_field(const char **p, const char **start, + const char **end, char *sep); +static int prefix(const char *start, const char *end, + const char *test); +static void append_entry(char **p, const char *prefix, int tag, + const char *name, int perm, int id); +static void append_id(char **p, int id); void archive_acl_clear(struct archive_acl *acl) @@ -74,6 +83,10 @@ archive_acl_clear(struct archive_acl *acl) free(acl->acl_text_w); acl->acl_text_w = NULL; } + if (acl->acl_text != NULL) { + free(acl->acl_text); + acl->acl_text = NULL; + } acl->acl_p = NULL; acl->acl_state = 0; /* Not counting. */ } @@ -136,6 +149,26 @@ archive_acl_add_entry_w_len(struct archive_acl *acl, return ARCHIVE_OK; } +int +archive_acl_add_entry_len(struct archive_acl *acl, + int type, int permset, int tag, int id, const char *name, size_t len) +{ + struct archive_acl_entry *ap; + + if (acl_special(acl, type, permset, tag) == 0) + return ARCHIVE_OK; + ap = acl_new_entry(acl, type, permset, tag, id); + if (ap == NULL) { + /* XXX Error XXX */ + return ARCHIVE_FAILED; + } + if (name != NULL && *name != '\0' && len > 0) + archive_mstring_copy_mbs_len(&ap->name, name, len); + else + archive_mstring_clean(&ap->name); + return ARCHIVE_OK; +} + /* * If this ACL entry is part of the standard POSIX permissions set, * store the permissions in the stat structure and return zero. @@ -226,6 +259,10 @@ acl_new_entry(struct archive_acl *acl, free(acl->acl_text_w); acl->acl_text_w = NULL; } + if (acl->acl_text != NULL) { + free(acl->acl_text); + acl->acl_text = NULL; + } /* If there's a matching entry already in the list, overwrite it. */ ap = acl->acl_head; @@ -558,6 +595,184 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, **wp = L'\0'; } +const char * +archive_acl_text(struct archive *a, struct archive_acl *acl, int flags) +{ + int count; + size_t length; + const char *name; + const char *prefix; + char separator; + struct archive_acl_entry *ap; + int id; + char *p; + + if (acl->acl_text != NULL) { + free (acl->acl_text); + acl->acl_text = NULL; + } + + separator = ','; + count = 0; + length = 0; + ap = acl->acl_head; + while (ap != NULL) { + if ((ap->type & flags) != 0) { + count++; + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && + (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) + length += 8; /* "default:" */ + length += 5; /* tag name */ + length += 1; /* colon */ + name = archive_mstring_get_mbs(a, &ap->name); + if (name != NULL) + length += strlen(name); + else + length += sizeof(uid_t) * 3 + 1; + length ++; /* colon */ + length += 3; /* rwx */ + length += 1; /* colon */ + length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; + length ++; /* newline */ + } + ap = ap->next; + } + + if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { + length += 10; /* "user::rwx\n" */ + length += 11; /* "group::rwx\n" */ + length += 11; /* "other::rwx\n" */ + } + + if (count == 0) + return (NULL); + + /* Now, allocate the string and actually populate it. */ + p = acl->acl_text = (char *)malloc(length); + if (p == NULL) + __archive_errx(1, "No memory to generate the text version of the ACL"); + count = 0; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + acl->mode & 0700, -1); + *p++ = ','; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + acl->mode & 0070, -1); + *p++ = ','; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + acl->mode & 0007, -1); + count += 3; + + ap = acl->acl_head; + while (ap != NULL) { + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + name = archive_mstring_get_mbs(a, &ap->name); + *p++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry(&p, NULL, ap->tag, name, + ap->permset, id); + count++; + } + ap = ap->next; + } + } + + + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { + if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + prefix = "default:"; + else + prefix = NULL; + ap = acl->acl_head; + count = 0; + while (ap != NULL) { + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { + name = archive_mstring_get_mbs(a, &ap->name); + if (count > 0) + *p++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry(&p, prefix, ap->tag, + name, ap->permset, id); + count ++; + } + ap = ap->next; + } + } + + return (acl->acl_text); +} + +static void +append_id(char **p, int id) +{ + if (id < 0) + id = 0; + if (id > 9) + append_id(p, id / 10); + *(*p)++ = "0123456789"[id % 10]; +} + +static void +append_entry(char **p, const char *prefix, int tag, + const char *name, int perm, int id) +{ + if (prefix != NULL) { + strcpy(*p, prefix); + *p += strlen(*p); + } + switch (tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + name = NULL; + id = -1; + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + strcpy(*p, "user"); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + name = NULL; + id = -1; + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + strcpy(*p, "group"); + break; + case ARCHIVE_ENTRY_ACL_MASK: + strcpy(*p, "mask"); + name = NULL; + id = -1; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + strcpy(*p, "other"); + name = NULL; + id = -1; + break; + } + *p += strlen(*p); + *(*p)++ = ':'; + if (name != NULL) { + strcpy(*p, name); + *p += strlen(*p); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id(p, id); + id = -1; + } + *(*p)++ = ':'; + *(*p)++ = (perm & 0444) ? 'r' : '-'; + *(*p)++ = (perm & 0222) ? 'w' : '-'; + *(*p)++ = (perm & 0111) ? 'x' : '-'; + if (id != -1) { + *(*p)++ = ':'; + append_id(p, id); + } + **p = '\0'; +} + /* * Parse a textual ACL. This automatically recognizes and supports * extensions described above. The 'type' argument is used to @@ -787,3 +1002,232 @@ prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test) return (1); } + +/* + * Parse a textual ACL. This automatically recognizes and supports + * extensions described above. The 'type' argument is used to + * indicate the type that should be used for any entries not + * explicitly marked as "default:". + */ +int +archive_acl_parse(struct archive_acl *acl, + const char *text, int default_type) +{ + struct { + const char *start; + const char *end; + } field[4], name; + + int fields, n; + int type, tag, permset, id; + char sep; + + while (text != NULL && *text != '\0') { + /* + * Parse the fields out of the next entry, + * advance 'text' to start of next entry. + */ + fields = 0; + do { + const char *start, *end; + next_field(&text, &start, &end, &sep); + if (fields < 4) { + field[fields].start = start; + field[fields].end = end; + } + ++fields; + } while (sep == ':'); + + /* Set remaining fields to blank. */ + for (n = fields; n < 4; ++n) + field[n].start = field[n].end = NULL; + + /* Check for a numeric ID in field 1 or 3. */ + id = -1; + isint(field[1].start, field[1].end, &id); + /* Field 3 is optional. */ + if (id == -1 && fields > 3) + isint(field[3].start, field[3].end, &id); + + /* + * Solaris extension: "defaultuser::rwx" is the + * default ACL corresponding to "user::rwx", etc. + */ + if (field[0].end - field[0].start > 7 + && memcmp(field[0].start, "default", 7) == 0) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + field[0].start += 7; + } else + type = default_type; + + name.start = name.end = NULL; + if (prefix(field[0].start, field[0].end, "user")) { + if (!ismode(field[2].start, field[2].end, &permset)) + return (ARCHIVE_WARN); + if (id != -1 || field[1].start < field[1].end) { + tag = ARCHIVE_ENTRY_ACL_USER; + name = field[1]; + } else + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + } else if (prefix(field[0].start, field[0].end, "group")) { + if (!ismode(field[2].start, field[2].end, &permset)) + return (ARCHIVE_WARN); + if (id != -1 || field[1].start < field[1].end) { + tag = ARCHIVE_ENTRY_ACL_GROUP; + name = field[1]; + } else + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + } else if (prefix(field[0].start, field[0].end, "other")) { + if (fields == 2 + && field[1].start < field[1].end + && ismode(field[1].start, field[1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + } else if (fields == 3 + && field[1].start == field[1].end + && field[2].start < field[2].end + && ismode(field[2].start, field[2].end, &permset)) { + /* This is FreeBSD-style "other::rwx" */ + } else + return (ARCHIVE_WARN); + tag = ARCHIVE_ENTRY_ACL_OTHER; + } else if (prefix(field[0].start, field[0].end, "mask")) { + if (fields == 2 + && field[1].start < field[1].end + && ismode(field[1].start, field[1].end, &permset)) { + /* This is Solaris-style "mask:rwx" */ + } else if (fields == 3 + && field[1].start == field[1].end + && field[2].start < field[2].end + && ismode(field[2].start, field[2].end, &permset)) { + /* This is FreeBSD-style "mask::rwx" */ + } else + return (ARCHIVE_WARN); + tag = ARCHIVE_ENTRY_ACL_MASK; + } else + return (ARCHIVE_WARN); + + /* Add entry to the internal list. */ + archive_acl_add_entry_len(acl, type, permset, + tag, id, name.start, name.end - name.start); + } + return (ARCHIVE_OK); +} + +/* + * Parse a string to a positive decimal integer. Returns true if + * the string is non-empty and consists only of decimal digits, + * false otherwise. + */ +static int +isint(const char *start, const char *end, int *result) +{ + int n = 0; + if (start >= end) + return (0); + while (start < end) { + if (*start < '0' || *start > '9') + return (0); + if (n > (INT_MAX / 10) || + (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { + n = INT_MAX; + } else { + n *= 10; + n += *start - '0'; + } + start++; + } + *result = n; + return (1); +} + +/* + * Parse a string as a mode field. Returns true if + * the string is non-empty and consists only of mode characters, + * false otherwise. + */ +static int +ismode(const char *start, const char *end, int *permset) +{ + const char *p; + + if (start >= end) + return (0); + p = start; + *permset = 0; + while (p < end) { + switch (*p++) { + case 'r': case 'R': + *permset |= ARCHIVE_ENTRY_ACL_READ; + break; + case 'w': case 'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE; + break; + case 'x': case 'X': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case '-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated + * to point to just after the separator. *start points to the first + * character of the matched text and *end just after the last + * character of the matched identifier. In particular *end - *start + * is the length of the field body, not including leading or trailing + * whitespace. + */ +static void +next_field(const char **p, const char **start, + const char **end, char *sep) +{ + /* Skip leading whitespace to find start of field. */ + while (**p == ' ' || **p == '\t' || **p == '\n') { + (*p)++; + } + *start = *p; + + /* Scan for the separator. */ + while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n') { + (*p)++; + } + *sep = **p; + + /* Trim trailing whitespace to locate end of field. */ + *end = *p - 1; + while (**end == ' ' || **end == '\t' || **end == '\n') { + (*end)--; + } + (*end)++; + + /* Adjust scanner location. */ + if (**p != '\0') + (*p)++; +} + +/* + * Return true if the characters [start...end) are a prefix of 'test'. + * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. + */ +static int +prefix(const char *start, const char *end, const char *test) +{ + if (start == end) + return (0); + + if (*start++ != *test++) + return (0); + + while (start < end && *start++ == *test++) + ; + + if (start < end) + return (0); + + return (1); +} diff --git a/libarchive/archive_acl_private.h b/libarchive/archive_acl_private.h index 4a967a854..da78333f7 100644 --- a/libarchive/archive_acl_private.h +++ b/libarchive/archive_acl_private.h @@ -49,6 +49,7 @@ struct archive_acl { struct archive_acl_entry *acl_p; int acl_state; /* See acl_next for details. */ wchar_t *acl_text_w; + char *acl_text; int acl_types; }; @@ -62,8 +63,11 @@ int archive_acl_next(struct archive *, struct archive_acl *, int, int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *); int archive_acl_add_entry_w_len(struct archive_acl *, int, int, int, int, const wchar_t *, size_t); +int archive_acl_add_entry_len(struct archive_acl *, + int, int, int, int, const char *, size_t); const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int); +const char *archive_acl_text(struct archive *, struct archive_acl *, int); /* * Private ACL parser. This is private because it handles some @@ -75,5 +79,7 @@ const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int); */ int archive_acl_parse_w(struct archive_acl *, const wchar_t *, int /* type */); +int archive_acl_parse(struct archive_acl *, + const char *, int /* type */); #endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index 17ba5b648..deb0abedc 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -1119,6 +1119,12 @@ archive_entry_acl_text_w(struct archive_entry *entry, int flags) return archive_acl_text_w(entry->archive, &entry->acl, flags); } +const char * +archive_entry_acl_text(struct archive_entry *entry, int flags) +{ + return archive_acl_text(entry->archive, &entry->acl, flags); +} + /* * Following code is modified from UC Berkeley sources, and * is subject to the following copyright notice. diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index c2b9d6f6c..905598b78 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -505,6 +505,8 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type #define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 __LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, int /* flags */); +__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, + int /* flags */); /* Return a count of entries matching 'want_type' */ __LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 46c0beab5..33af3d4ac 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -142,7 +142,6 @@ struct tar { int sparse_gnu_minor; char sparse_gnu_pending; - struct archive_wstring wacl; struct archive_string localname; struct archive_string opt_charset; struct archive_string hdr_charset; @@ -273,7 +272,6 @@ archive_read_format_tar_cleanup(struct archive_read *a) archive_string_free(&tar->opt_charset); archive_string_free(&tar->hdr_charset); archive_string_free(&tar->localname); - archive_wstring_free(&tar->wacl); free(tar); (a->format->data) = NULL; return (ARCHIVE_OK); @@ -888,15 +886,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, "Malformed Solaris ACL attribute (unconvertible)"); return(ARCHIVE_WARN); } - archive_wstring_empty(&(tar->wacl)); - if (archive_wstring_append_from_mbs(&(a->archive), &(tar->wacl), - tar->localname.s, tar->localname.length) != 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Malformed Solaris ACL attribute (unconvertible)"); - return(ARCHIVE_WARN); - } - err = archive_acl_parse_w(archive_entry_acl(entry), tar->wacl.s, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + err = archive_acl_parse(archive_entry_acl(entry), + tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); if (err != ARCHIVE_OK) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed Solaris ACL attribute (unparsable)"); @@ -1692,20 +1683,10 @@ pax_attribute(struct archive_read *a, struct tar *tar, ARCHIVE_ERRNO_FILE_FORMAT, "SCHILY.acl.access can't be converted " "from UTF-8 to current locale."); - } - archive_wstring_empty(&(tar->wacl)); - if (archive_wstring_append_from_mbs( - &(a->archive), &(tar->wacl), tar->localname.s, - tar->localname.length) != 0) { - err = ARCHIVE_WARN; - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "SCHILY.acl.access can't be converted" - " to wide-character."); - } else { - archive_acl_parse_w(archive_entry_acl(entry), - tar->wacl.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); - } + } else + archive_acl_parse(archive_entry_acl(entry), + tar->localname.s, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); } else if (strcmp(key, "SCHILY.acl.default")==0) { if (archive_strcpy_from_locale(&(a->archive), &(tar->localname), value, "UTF-8") != 0) { @@ -1714,20 +1695,10 @@ pax_attribute(struct archive_read *a, struct tar *tar, ARCHIVE_ERRNO_FILE_FORMAT, "SCHILY.acl.default can't be converted " "from UTF-8 to current locale."); - } - archive_wstring_empty(&(tar->wacl)); - if (archive_wstring_append_from_mbs( - &(a->archive), &(tar->wacl), tar->localname.s, - tar->localname.length) != 0) { - err = ARCHIVE_WARN; - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "SCHILY.acl.default can't be converted" - " to wide-character."); - } else { - archive_acl_parse_w(archive_entry_acl(entry), - tar->wacl.s, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); - } + } else + archive_acl_parse(archive_entry_acl(entry), + tar->localname.s, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); } else if (strcmp(key, "SCHILY.devmajor")==0) { archive_entry_set_rdevmajor(entry, tar_atol10(value, strlen(value))); diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index f8c011eae..739990949 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -1812,13 +1812,24 @@ archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes) int archive_mstring_copy_mbs(struct archive_mstring *aes, const char *mbs) +{ + if (mbs == NULL) { + aes->aes_set = 0; + return (0); + } + return (archive_mstring_copy_mbs_len(aes, mbs, strlen(mbs))); +} + +int +archive_mstring_copy_mbs_len(struct archive_mstring *aes, const char *mbs, + size_t len) { if (mbs == NULL) { aes->aes_set = 0; return (0); } aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */ - archive_strcpy(&(aes->aes_mbs), mbs); + archive_strncpy(&(aes->aes_mbs), mbs, len); archive_string_empty(&(aes->aes_utf8)); archive_wstring_empty(&(aes->aes_wcs)); return (0); diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h index 80307e528..4c778805f 100644 --- a/libarchive/archive_string.h +++ b/libarchive/archive_string.h @@ -226,6 +226,8 @@ const char * archive_mstring_get_mbs(struct archive *, struct archive_mstring *) const char * archive_mstring_get_utf8(struct archive *, struct archive_mstring *); const wchar_t * archive_mstring_get_wcs(struct archive *, struct archive_mstring *); int archive_mstring_copy_mbs(struct archive_mstring *, const char *mbs); +int archive_mstring_copy_mbs_len(struct archive_mstring *, const char *mbs, + size_t); int archive_mstring_copy_utf8(struct archive_mstring *, const char *utf8); int archive_mstring_copy_wcs(struct archive_mstring *, const wchar_t *wcs); int archive_mstring_copy_wcs_len(struct archive_mstring *, const wchar_t *wcs, size_t); diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index 8507f6a83..322223b40 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -57,7 +57,6 @@ struct pax { struct archive_string l_gname; struct archive_string l_linkpath; struct archive_string l_url_encoded_name; - struct archive_string l_acl_mbs; struct archive_string l_acl_utf8; struct archive_string pax_header; struct archive_string sparse_map; @@ -360,9 +359,8 @@ archive_write_pax_header(struct archive_write *a, struct archive_entry *entry_main; const char *p; char *t; - const wchar_t *wp; const char *suffix; - int binary, need_extension, r, r2, ret; + int binary, need_extension, r, ret; int sparse_count; uint64_t sparse_total, real_size; struct pax *pax; @@ -882,22 +880,13 @@ archive_write_pax_header(struct archive_write *a, add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p); /* I use star-compatible ACL attributes. */ - wp = archive_entry_acl_text_w(entry_original, + p = archive_entry_acl_text(entry_original, ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); - if (wp != NULL && *wp != L'\0') { - archive_string_empty(&(pax->l_acl_mbs)); - r2 = archive_string_append_from_unicode_to_mbs( - &(a->archive), &(pax->l_acl_mbs), - wp, wcslen(wp)); - if (r2 == 0) { - r = archive_strncpy_to_locale( - &(a->archive), &(pax->l_acl_utf8), - pax->l_acl_mbs.s, pax->l_acl_mbs.length, - "UTF-8"); - } else - r = 0; - if (r2 || r) { + if (p != NULL && *p != '\0') { + r = archive_strcpy_to_locale( + &(a->archive), &(pax->l_acl_utf8), p, "UTF-8"); + if (r != 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate ACL.access to UTF-8"); @@ -907,22 +896,13 @@ archive_write_pax_header(struct archive_write *a, "SCHILY.acl.access", pax->l_acl_utf8.s); } } - wp = archive_entry_acl_text_w(entry_original, + p = archive_entry_acl_text(entry_original, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); - if (wp != NULL && *wp != L'\0') { - archive_string_empty(&(pax->l_acl_mbs)); - r2 = archive_string_append_from_unicode_to_mbs( - &(a->archive), &(pax->l_acl_mbs), - wp, wcslen(wp)); - if (r2 == 0) { - r = archive_strncpy_to_locale( - &(a->archive), &(pax->l_acl_utf8), - pax->l_acl_mbs.s, pax->l_acl_mbs.length, - "UTF-8"); - } else - r = 0; - if (r2 || r) { + if (p != NULL && *p != '\0') { + r = archive_strcpy_to_locale( + &(a->archive), &(pax->l_acl_utf8), p, "UTF-8"); + if (r != 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate ACL.default to UTF-8"); @@ -1455,7 +1435,6 @@ archive_write_pax_free(struct archive_write *a) archive_string_free(&pax->l_gname); archive_string_free(&pax->l_linkpath); archive_string_free(&pax->l_url_encoded_name); - archive_string_free(&pax->l_acl_mbs); archive_string_free(&pax->l_acl_utf8); free(pax->opt_charset); sparse_list_clear(pax);