]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
acl: Use archive_string/archive_wstring
authorTobias Stoeckmann <tobias@stoeckmann.org>
Sat, 16 May 2026 13:06:21 +0000 (15:06 +0200)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Sat, 16 May 2026 19:35:58 +0000 (21:35 +0200)
Since libarchive already contains infrastructure to safely work with
strings, use it instead of manually constructing strings.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
libarchive/archive_acl.c

index 32719ac4fc9f24a048ac31861c799d636de546c6..c991df2ea231ba1814d6c3a48506b2edd7eae5df 100644 (file)
@@ -56,9 +56,7 @@ static int    archive_acl_add_entry_len_l(struct archive_acl *acl,
                    int type, int permset, int tag, int id, const char *name,
                    size_t len, struct archive_string_conv *sc);
 static int     archive_acl_text_want_type(struct archive_acl *acl, int flags);
-static size_t  archive_acl_text_len(struct archive_acl *acl, int want_type,
-                   int flags, int wide, struct archive *a,
-                   struct archive_string_conv *sc);
+static size_t  archive_acl_text_empty(struct archive_acl *acl, int want_type);
 static int     isint_w(const wchar_t *start, const wchar_t *end, int *result);
 static int     ismode_w(const wchar_t *start, const wchar_t *end, int *result);
 static int     is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
@@ -67,9 +65,9 @@ static int    is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
                    int *result);
 static void    next_field_w(const wchar_t **wp, const wchar_t **start,
                    const wchar_t **end, wchar_t *sep);
-static void    append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+static void    append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type,
                    int tag, int flags, const wchar_t *wname, int perm, int id);
-static void    append_id_w(wchar_t **wp, int id);
+static void    append_id_w(struct archive_wstring *ws, 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 int     is_nfs4_flags(const char *start, const char *end,
@@ -78,9 +76,9 @@ static int    is_nfs4_perms(const char *start, const char *end,
                    int *result);
 static void    next_field(const char **p, size_t *l, const char **start,
                    const char **end, char *sep);
-static void    append_entry(char **p, const char *prefix, int type,
+static void    append_entry(struct archive_string *s, const char *prefix, int type,
                    int tag, int flags, const char *name, int perm, int id);
-static void    append_id(char **p, int id);
+static void    append_id(struct archive_string *s, int id);
 
 static const struct {
        const int perm;
@@ -539,20 +537,12 @@ archive_acl_text_want_type(struct archive_acl *acl, int flags)
 }
 
 /*
- * Calculate ACL text string length
+ * Check if ACL text would be empty
  */
 static size_t
-archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
-    int wide, struct archive *a, struct archive_string_conv *sc) {
+archive_acl_text_empty(struct archive_acl *acl, int want_type) {
        struct archive_acl_entry *ap;
-       const char *name;
-       const wchar_t *wname;
-       int count, idlen, tmp, r;
-       size_t length;
-       size_t len;
 
-       count = 0;
-       length = 0;
        for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
                if ((ap->type & want_type) == 0)
                        continue;
@@ -565,108 +555,11 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
                    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
                    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
                        continue;
-               count++;
-               if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
-                   && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-                       length += 8; /* "default:" */
-               switch (ap->tag) {
-               case ARCHIVE_ENTRY_ACL_USER_OBJ:
-                       if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-                               length += 6; /* "owner@" */
-                               break;
-                       }
-                       /* FALLTHROUGH */
-               case ARCHIVE_ENTRY_ACL_USER:
-               case ARCHIVE_ENTRY_ACL_MASK:
-                       length += 4; /* "user", "mask" */
-                       break;
-               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-                       if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-                               length += 6; /* "group@" */
-                               break;
-                       }
-                       /* FALLTHROUGH */
-               case ARCHIVE_ENTRY_ACL_GROUP:
-               case ARCHIVE_ENTRY_ACL_OTHER:
-                       length += 5; /* "group", "other" */
-                       break;
-               case ARCHIVE_ENTRY_ACL_EVERYONE:
-                       length += 9; /* "everyone@" */
-                       break;
-               }
-               length += 1; /* colon after tag */
-               if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-                   ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
-                       if (wide) {
-                               r = archive_mstring_get_wcs(a, &ap->name,
-                                   &wname);
-                               if (r == 0 && wname != NULL)
-                                       length += wcslen(wname);
-                               else if (r < 0 && errno == ENOMEM)
-                                       return (0);
-                               else
-                                       length += sizeof(uid_t) * 3 + 1;
-                       } else {
-                               r = archive_mstring_get_mbs_l(a, &ap->name, &name,
-                                   &len, sc);
-                               if (r != 0)
-                                       return (0);
-                               if (len > 0 && name != NULL)
-                                       length += len;
-                               else
-                                       length += sizeof(uid_t) * 3 + 1;
-                       }
-                       length += 1; /* colon after user or group name */
-               } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
-                       length += 1; /* 2nd colon empty user,group or other */
-
-               if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
-                   && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
-                   && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
-                   || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
-                       /* Solaris has no colon after other: and mask: */
-                       length = length - 1;
-               }
-
-               if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-                       /* rwxpdDaARWcCos:fdinSFI:deny */
-                       length += 27;
-                       if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
-                               length += 1; /* allow, alarm, audit */
-               } else
-                       length += 3; /* rwx */
-
-               if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-                   ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
-                   ((flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0 ||
-                   (wide ? wname == NULL : name == NULL))) {
-                       length += 1; /* colon */
-                       /* ID digit count */
-                       idlen = 1;
-                       tmp = ap->id;
-                       while (tmp > 9) {
-                               tmp = tmp / 10;
-                               idlen++;
-                       }
-                       length += idlen;
-               }
-               length ++; /* entry separator */
-       }
 
-       /* Add filemode-mapping access entries to the length */
-       if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-               if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
-                       /* "user::rwx\ngroup::rwx\nother:rwx\n" */
-                       length += 31;
-               } else {
-                       /* "user::rwx\ngroup::rwx\nother::rwx\n" */
-                       length += 32;
-               }
-       } else if (count == 0)
                return (0);
+       }
 
-       /* The terminating character is included in count */
-       return (length);
+       return (1);
 }
 
 /*
@@ -678,14 +571,12 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
     struct archive *a)
 {
        int count;
-       size_t length;
-       size_t len;
        const wchar_t *wname;
        const wchar_t *prefix;
        wchar_t separator;
        struct archive_acl_entry *ap;
+       struct archive_wstring ws;
        int id, r, want_type;
-       wchar_t *wp, *ws;
 
        want_type = archive_acl_text_want_type(acl, flags);
 
@@ -696,9 +587,7 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
        if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
                flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
 
-       length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
-
-       if (length == 0)
+       if (archive_acl_text_empty(acl, want_type))
                return (NULL);
 
        if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
@@ -706,25 +595,19 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
        else
                separator = L'\n';
 
-       /* Now, allocate the string and actually populate it. */
-       wp = ws = malloc(length * sizeof(*wp));
-       if (wp == NULL) {
-               if (errno == ENOMEM)
-                       __archive_errx(1, "No memory");
-               return (NULL);
-       }
+       archive_string_init(&ws);
        count = 0;
 
        if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-               append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
                    acl->mode & 0700, -1);
-               *wp++ = separator;
-               append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               archive_wstrappend_wchar(&ws, separator);
+               append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
                    acl->mode & 0070, -1);
-               *wp++ = separator;
-               append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               archive_wstrappend_wchar(&ws, separator);
+               append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
                    acl->mode & 0007, -1);
                count += 3;
@@ -750,108 +633,95 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
                r = archive_mstring_get_wcs(a, &ap->name, &wname);
                if (r == 0) {
                        if (count > 0)
-                               *wp++ = separator;
+                               archive_wstrappend_wchar(&ws, separator);
                        if ((flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) ||
                            wname == NULL)
                                id = ap->id;
                        else
                                id = -1;
-                       append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
+                       append_entry_w(&ws, prefix, ap->type, ap->tag, flags,
                            wname, ap->permset, id);
                        count++;
                } else if (r < 0 && errno == ENOMEM) {
-                       free(ws);
+                       archive_wstring_free(&ws);
                        return (NULL);
                }
        }
 
-       /* Add terminating character */
-       *wp++ = L'\0';
-
-       len = wcslen(ws);
-
-       if (len > length - 1)
-               __archive_errx(1, "Buffer overrun");
-
        if (text_len != NULL)
-               *text_len = len;
+               *text_len = ws.length;
 
-       return (ws);
+       return (ws.s);
 }
 
 static void
-append_id_w(wchar_t **wp, int id)
+append_id_w(struct archive_wstring *ws, int id)
 {
        if (id < 0)
                id = 0;
        if (id > 9)
-               append_id_w(wp, id / 10);
-       *(*wp)++ = L"0123456789"[id % 10];
+               append_id_w(ws, id / 10);
+       archive_wstrappend_wchar(ws, L"0123456789"[id % 10]);
 }
 
 static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type,
     int tag, int flags, const wchar_t *wname, int perm, int id)
 {
        int i;
 
-       if (prefix != NULL) {
-               wcscpy(*wp, prefix);
-               *wp += wcslen(*wp);
-       }
+       if (prefix != NULL)
+               archive_wstrcat(ws, prefix);
        switch (tag) {
        case ARCHIVE_ENTRY_ACL_USER_OBJ:
                wname = NULL;
                id = -1;
                if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-                       wcscpy(*wp, L"owner@");
+                       archive_wstrcat(ws, L"owner@");
                        break;
                }
                /* FALLTHROUGH */
        case ARCHIVE_ENTRY_ACL_USER:
-               wcscpy(*wp, L"user");
+               archive_wstrcat(ws, L"user");
                break;
        case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
                wname = NULL;
                id = -1;
                if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-                       wcscpy(*wp, L"group@");
+                       archive_wstrcat(ws, L"group@");
                        break;
                }
                /* FALLTHROUGH */
        case ARCHIVE_ENTRY_ACL_GROUP:
-               wcscpy(*wp, L"group");
+               archive_wstrcat(ws, L"group");
                break;
        case ARCHIVE_ENTRY_ACL_MASK:
-               wcscpy(*wp, L"mask");
+               archive_wstrcat(ws, L"mask");
                wname = NULL;
                id = -1;
                break;
        case ARCHIVE_ENTRY_ACL_OTHER:
-               wcscpy(*wp, L"other");
+               archive_wstrcat(ws, L"other");
                wname = NULL;
                id = -1;
                break;
        case ARCHIVE_ENTRY_ACL_EVERYONE:
-               wcscpy(*wp, L"everyone@");
+               archive_wstrcat(ws, L"everyone@");
                wname = NULL;
                id = -1;
                break;
        default:
-               **wp = '\0';
                break;
        }
-       *wp += wcslen(*wp);
-       *(*wp)++ = L':';
+       archive_wstrappend_wchar(ws, L':');
        if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
            tag == ARCHIVE_ENTRY_ACL_USER ||
            tag == ARCHIVE_ENTRY_ACL_GROUP) {
                if (wname != NULL) {
-                       wcscpy(*wp, wname);
-                       *wp += wcslen(*wp);
+                       archive_wstrcat(ws, wname);
                } else if (tag == ARCHIVE_ENTRY_ACL_USER
                    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-                       append_id_w(wp, id);
+                       append_id_w(ws, id);
                        if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
                                id = -1;
                }
@@ -859,51 +729,49 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
                if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
                    || (tag != ARCHIVE_ENTRY_ACL_OTHER
                    && tag != ARCHIVE_ENTRY_ACL_MASK))
-                       *(*wp)++ = L':';
+                       archive_wstrappend_wchar(ws, L':');
        }
        if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
                /* POSIX.1e ACL perms */
-               *(*wp)++ = (perm & 0444) ? L'r' : L'-';
-               *(*wp)++ = (perm & 0222) ? L'w' : L'-';
-               *(*wp)++ = (perm & 0111) ? L'x' : L'-';
+               archive_wstrappend_wchar(ws, (perm & 0444) ? L'r' : L'-');
+               archive_wstrappend_wchar(ws, (perm & 0222) ? L'w' : L'-');
+               archive_wstrappend_wchar(ws, (perm & 0111) ? L'x' : L'-');
        } else {
                /* NFSv4 ACL perms */
                for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
                        if (perm & nfsv4_acl_perm_map[i].perm)
-                               *(*wp)++ = nfsv4_acl_perm_map[i].wc;
+                               archive_wstrappend_wchar(ws, nfsv4_acl_perm_map[i].wc);
                        else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-                               *(*wp)++ = L'-';
+                               archive_wstrappend_wchar(ws, L'-');
                }
-               *(*wp)++ = L':';
+               archive_wstrappend_wchar(ws, L':');
                for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
                        if (perm & nfsv4_acl_flag_map[i].perm)
-                               *(*wp)++ = nfsv4_acl_flag_map[i].wc;
+                               archive_wstrappend_wchar(ws, nfsv4_acl_flag_map[i].wc);
                        else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-                               *(*wp)++ = L'-';
+                               archive_wstrappend_wchar(ws, L'-');
                }
-               *(*wp)++ = L':';
+               archive_wstrappend_wchar(ws, L':');
                switch (type) {
                case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-                       wcscpy(*wp, L"allow");
+                       archive_wstrcat(ws, L"allow");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-                       wcscpy(*wp, L"deny");
+                       archive_wstrcat(ws, L"deny");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-                       wcscpy(*wp, L"audit");
+                       archive_wstrcat(ws, L"audit");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-                       wcscpy(*wp, L"alarm");
+                       archive_wstrcat(ws, L"alarm");
                        break;
                default:
-                       *(*wp) = L'\0';
                        break;
                }
-               *wp += wcslen(*wp);
        }
        if (id != -1) {
-               *(*wp)++ = L':';
-               append_id_w(wp, id);
+               archive_wstrappend_wchar(ws, L':');
+               append_id_w(ws, id);
        }
 }
 
@@ -916,14 +784,13 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
     struct archive_string_conv *sc)
 {
        int count;
-       size_t length;
        size_t len;
        const char *name;
        const char *prefix;
        char separator;
        struct archive_acl_entry *ap;
+       struct archive_string s;
        int id, r, want_type;
-       char *p, *s;
 
        want_type = archive_acl_text_want_type(acl, flags);
 
@@ -934,9 +801,7 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
        if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
                flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
 
-       length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc);
-
-       if (length == 0)
+       if (archive_acl_text_empty(acl, want_type))
                return (NULL);
 
        if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
@@ -944,25 +809,19 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
        else
                separator = '\n';
 
-       /* Now, allocate the string and actually populate it. */
-       p = s = malloc(length * sizeof(*p));
-       if (p == NULL) {
-               if (errno == ENOMEM)
-                       __archive_errx(1, "No memory");
-               return (NULL);
-       }
+       archive_string_init(&s);
        count = 0;
 
        if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-               append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
                    acl->mode & 0700, -1);
-               *p++ = separator;
-               append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               archive_strappend_char(&s, separator);
+               append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
                    acl->mode & 0070, -1);
-               *p++ = separator;
-               append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+               archive_strappend_char(&s, separator);
+               append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
                    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
                    acl->mode & 0007, -1);
                count += 3;
@@ -988,109 +847,96 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
                r = archive_mstring_get_mbs_l(
                    NULL, &ap->name, &name, &len, sc);
                if (r != 0) {
-                       free(s);
+                       archive_string_free(&s);
                        return (NULL);
                }
                if (count > 0)
-                       *p++ = separator;
+                       archive_strappend_char(&s, separator);
                if (name == NULL ||
                    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
                        id = ap->id;
                } else {
                        id = -1;
                }
-               append_entry(&p, prefix, ap->type, ap->tag, flags, name,
+               append_entry(&s, prefix, ap->type, ap->tag, flags, name,
                    ap->permset, id);
                count++;
        }
 
-       /* Add terminating character */
-       *p++ = '\0';
-
-       len = strlen(s);
-
-       if (len > length - 1)
-               __archive_errx(1, "Buffer overrun");
-
        if (text_len != NULL)
-               *text_len = len;
+               *text_len = s.length;
 
-       return (s);
+       return (s.s);
 }
 
 static void
-append_id(char **p, int id)
+append_id(struct archive_string *s, int id)
 {
        if (id < 0)
                id = 0;
        if (id > 9)
-               append_id(p, id / 10);
-       *(*p)++ = "0123456789"[id % 10];
+               append_id(s, id / 10);
+       archive_strappend_char(s, "0123456789"[id % 10]);
 }
 
 static void
-append_entry(char **p, const char *prefix, int type,
+append_entry(struct archive_string *s, const char *prefix, int type,
     int tag, int flags, const char *name, int perm, int id)
 {
        int i;
 
-       if (prefix != NULL) {
-               strcpy(*p, prefix);
-               *p += strlen(*p);
-       }
+       if (prefix != NULL)
+               archive_strcat(s, prefix);
        switch (tag) {
        case ARCHIVE_ENTRY_ACL_USER_OBJ:
                name = NULL;
                id = -1;
                if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-                       strcpy(*p, "owner@");
+                       archive_strcat(s, "owner@");
                        break;
                }
                /* FALLTHROUGH */
        case ARCHIVE_ENTRY_ACL_USER:
-               strcpy(*p, "user");
+               archive_strcat(s, "user");
                break;
        case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
                name = NULL;
                id = -1;
                if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-                       strcpy(*p, "group@");
+                       archive_strcat(s, "group@");
                        break;
                }
                /* FALLTHROUGH */
        case ARCHIVE_ENTRY_ACL_GROUP:
-               strcpy(*p, "group");
+               archive_strcat(s, "group");
                break;
        case ARCHIVE_ENTRY_ACL_MASK:
-               strcpy(*p, "mask");
+               archive_strcat(s, "mask");
                name = NULL;
                id = -1;
                break;
        case ARCHIVE_ENTRY_ACL_OTHER:
-               strcpy(*p, "other");
+               archive_strcat(s, "other");
                name = NULL;
                id = -1;
                break;
        case ARCHIVE_ENTRY_ACL_EVERYONE:
-               strcpy(*p, "everyone@");
+               archive_strcat(s, "everyone@");
                name = NULL;
                id = -1;
                break;
        default:
-               **p = '\0';
                break;
        }
-       *p += strlen(*p);
-       *(*p)++ = ':';
+       archive_strappend_char(s, ':');
        if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
            tag == ARCHIVE_ENTRY_ACL_USER ||
            tag == ARCHIVE_ENTRY_ACL_GROUP) {
                if (name != NULL) {
-                       strcpy(*p, name);
-                       *p += strlen(*p);
+                       archive_strcat(s, name);
                } else if (tag == ARCHIVE_ENTRY_ACL_USER
                    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-                       append_id(p, id);
+                       append_id(s, id);
                        if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
                                id = -1;
                }
@@ -1098,51 +944,49 @@ append_entry(char **p, const char *prefix, int type,
                if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
                    || (tag != ARCHIVE_ENTRY_ACL_OTHER
                    && tag != ARCHIVE_ENTRY_ACL_MASK))
-                       *(*p)++ = ':';
+                       archive_strappend_char(s, ':');
        }
        if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
                /* POSIX.1e ACL perms */
-               *(*p)++ = (perm & 0444) ? 'r' : '-';
-               *(*p)++ = (perm & 0222) ? 'w' : '-';
-               *(*p)++ = (perm & 0111) ? 'x' : '-';
+               archive_strappend_char(s, (perm & 0444) ? 'r' : '-');
+               archive_strappend_char(s, (perm & 0222) ? 'w' : '-');
+               archive_strappend_char(s, (perm & 0111) ? 'x' : '-');
        } else {
                /* NFSv4 ACL perms */
                for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
                        if (perm & nfsv4_acl_perm_map[i].perm)
-                               *(*p)++ = nfsv4_acl_perm_map[i].c;
+                               archive_strappend_char(s, nfsv4_acl_perm_map[i].c);
                        else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-                               *(*p)++ = '-';
+                               archive_strappend_char(s, '-');
                }
-               *(*p)++ = ':';
+               archive_strappend_char(s, ':');
                for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
                        if (perm & nfsv4_acl_flag_map[i].perm)
-                               *(*p)++ = nfsv4_acl_flag_map[i].c;
+                               archive_strappend_char(s, nfsv4_acl_flag_map[i].c);
                        else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-                               *(*p)++ = '-';
+                               archive_strappend_char(s, '-');
                }
-               *(*p)++ = ':';
+               archive_strappend_char(s, ':');
                switch (type) {
                case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-                       strcpy(*p, "allow");
+                       archive_strcat(s, "allow");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-                       strcpy(*p, "deny");
+                       archive_strcat(s, "deny");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-                       strcpy(*p, "audit");
+                       archive_strcat(s, "audit");
                        break;
                case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-                       strcpy(*p, "alarm");
+                       archive_strcat(s, "alarm");
                        break;
                default:
-                       *(*p) = '\0';
                        break;
                }
-               *p += strlen(*p);
        }
        if (id != -1) {
-               *(*p)++ = ':';
-               append_id(p, id);
+               archive_strappend_char(s, ':');
+               append_id(s, id);
        }
 }