]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libarchive/archive_entry.c
This commit was generated by cvs2svn to compensate for changes in r169808,
[FreeBSD/FreeBSD.git] / lib / libarchive / archive_entry.c
1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
28
29 #ifdef HAVE_SYS_STAT_H
30 #include <sys/stat.h>
31 #endif
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35 #ifdef MAJOR_IN_MKDEV
36 #include <sys/mkdev.h>
37 #else
38 #ifdef MAJOR_IN_SYSMACROS
39 #include <sys/sysmacros.h>
40 #endif
41 #endif
42 #ifdef HAVE_EXT2FS_EXT2_FS_H
43 #include <ext2fs/ext2_fs.h>     /* for Linux file flags */
44 #endif
45 #ifdef HAVE_LIMITS_H
46 #include <limits.h>
47 #endif
48 #ifdef HAVE_LINUX_FS_H
49 #include <linux/fs.h>   /* for Linux file flags */
50 #endif
51 #ifdef HAVE_LINUX_EXT2_FS_H
52 #include <linux/ext2_fs.h>      /* for Linux file flags */
53 #endif
54 #include <stddef.h>
55 #include <stdio.h>
56 #ifdef HAVE_STDLIB_H
57 #include <stdlib.h>
58 #endif
59 #ifdef HAVE_STRING_H
60 #include <string.h>
61 #endif
62 #ifdef HAVE_WCHAR_H
63 #include <wchar.h>
64 #endif
65
66 #ifndef HAVE_WCSCPY
67 static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
68 {
69         wchar_t *dest = s1;
70         while ((*s1 = *s2) != L'\0')
71                 ++s1, ++s2;
72         return dest;
73 }
74 #endif
75 #ifndef HAVE_WCSLEN
76 static size_t wcslen(const wchar_t *s)
77 {
78         const wchar_t *p = s;
79         while (*p != L'\0')
80                 ++p;
81         return p - s;
82 }
83 #endif
84 #ifndef HAVE_WMEMCMP
85 /* Good enough for simple equality testing, but not for sorting. */
86 #define wmemcmp(a,b,i)  memcmp((a), (b), (i) * sizeof(wchar_t))
87 #endif
88 #ifndef HAVE_WMEMCPY
89 #define wmemcpy(a,b,i)  (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t))
90 #endif
91
92 #include "archive.h"
93 #include "archive_entry.h"
94 #include "archive_private.h"
95
96 #undef max
97 #define max(a, b)       ((a)>(b)?(a):(b))
98
99 /*
100  * Handle wide character (i.e., Unicode) and non-wide character
101  * strings transparently.
102  *
103  */
104
105 struct aes {
106         const char *aes_mbs;
107         char *aes_mbs_alloc;
108         const wchar_t *aes_wcs;
109         wchar_t *aes_wcs_alloc;
110 };
111
112 struct ae_acl {
113         struct ae_acl *next;
114         int     type;                   /* E.g., access or default */
115         int     tag;                    /* E.g., user/group/other/mask */
116         int     permset;                /* r/w/x bits */
117         int     id;                     /* uid/gid for user/group */
118         struct aes name;                /* uname/gname */
119 };
120
121 struct ae_xattr {
122         struct ae_xattr *next;
123
124         char    *name;
125         void    *value;
126         size_t  size;
127 };
128
129 static void     aes_clean(struct aes *);
130 static void     aes_copy(struct aes *dest, struct aes *src);
131 static const char *     aes_get_mbs(struct aes *);
132 static const wchar_t *  aes_get_wcs(struct aes *);
133 static void     aes_set_mbs(struct aes *, const char *mbs);
134 static void     aes_copy_mbs(struct aes *, const char *mbs);
135 /* static void  aes_set_wcs(struct aes *, const wchar_t *wcs); */
136 static void     aes_copy_wcs(struct aes *, const wchar_t *wcs);
137 static void     aes_copy_wcs_len(struct aes *, const wchar_t *wcs, size_t);
138
139 static char *    ae_fflagstostr(unsigned long bitset, unsigned long bitclear);
140 static const wchar_t    *ae_wcstofflags(const wchar_t *stringp,
141                     unsigned long *setp, unsigned long *clrp);
142 static void     append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
143                     const wchar_t *wname, int perm, int id);
144 static void     append_id_w(wchar_t **wp, int id);
145
146 static int      acl_special(struct archive_entry *entry,
147                     int type, int permset, int tag);
148 static struct ae_acl *acl_new_entry(struct archive_entry *entry,
149                     int type, int permset, int tag, int id);
150 static int      isint_w(const wchar_t *start, const wchar_t *end, int *result);
151 static void     next_field_w(const wchar_t **wp, const wchar_t **start,
152                     const wchar_t **end, wchar_t *sep);
153 static int      prefix_w(const wchar_t *start, const wchar_t *end,
154                     const wchar_t *test);
155 static void
156 archive_entry_acl_add_entry_w_len(struct archive_entry *entry, int type,
157                     int permset, int tag, int id, const wchar_t *name, size_t);
158
159
160 /*
161  * Description of an archive entry.
162  *
163  * Basically, this is a "struct stat" with a few text fields added in.
164  *
165  * TODO: Add "comment", "charset", and possibly other entries
166  * that are supported by "pax interchange" format.  However, GNU, ustar,
167  * cpio, and other variants don't support these features, so they're not an
168  * excruciatingly high priority right now.
169  *
170  * TODO: "pax interchange" format allows essentially arbitrary
171  * key/value attributes to be attached to any entry.  Supporting
172  * such extensions may make this library useful for special
173  * applications (e.g., a package manager could attach special
174  * package-management attributes to each entry).  There are tricky
175  * API issues involved, so this is not going to happen until
176  * there's a real demand for it.
177  *
178  * TODO: Design a good API for handling sparse files.
179  */
180 struct archive_entry {
181         /*
182          * Note that ae_stat.st_mode & S_IFMT  can be  0!
183          *
184          * This occurs when the actual file type of the object is not
185          * in the archive.  For example, 'tar' archives store
186          * hardlinks without marking the type of the underlying
187          * object.
188          */
189         struct stat ae_stat;
190
191         /*
192          * Use aes here so that we get transparent mbs<->wcs conversions.
193          */
194         struct aes ae_fflags_text;      /* Text fflags per fflagstostr(3) */
195         unsigned long ae_fflags_set;            /* Bitmap fflags */
196         unsigned long ae_fflags_clear;
197         struct aes ae_gname;            /* Name of owning group */
198         struct aes ae_hardlink; /* Name of target for hardlink */
199         struct aes ae_pathname; /* Name of entry */
200         struct aes ae_symlink;          /* symlink contents */
201         struct aes ae_uname;            /* Name of owner */
202
203         struct ae_acl   *acl_head;
204         struct ae_acl   *acl_p;
205         int              acl_state;     /* See acl_next for details. */
206         wchar_t         *acl_text_w;
207
208         struct ae_xattr *xattr_head;
209         struct ae_xattr *xattr_p;
210 };
211
212 static void
213 aes_clean(struct aes *aes)
214 {
215         if (aes->aes_mbs_alloc) {
216                 free(aes->aes_mbs_alloc);
217                 aes->aes_mbs_alloc = NULL;
218         }
219         if (aes->aes_wcs_alloc) {
220                 free(aes->aes_wcs_alloc);
221                 aes->aes_wcs_alloc = NULL;
222         }
223         memset(aes, 0, sizeof(*aes));
224 }
225
226 static void
227 aes_copy(struct aes *dest, struct aes *src)
228 {
229         *dest = *src;
230         if (src->aes_mbs != NULL) {
231                 dest->aes_mbs_alloc = strdup(src->aes_mbs);
232                 dest->aes_mbs = dest->aes_mbs_alloc;
233                 if (dest->aes_mbs == NULL)
234                         __archive_errx(1, "No memory for aes_copy()");
235         }
236
237         if (src->aes_wcs != NULL) {
238                 dest->aes_wcs_alloc = (wchar_t *)malloc((wcslen(src->aes_wcs) + 1)
239                     * sizeof(wchar_t));
240                 dest->aes_wcs = dest->aes_wcs_alloc;
241                 if (dest->aes_wcs == NULL)
242                         __archive_errx(1, "No memory for aes_copy()");
243                 wcscpy(dest->aes_wcs_alloc, src->aes_wcs);
244         }
245 }
246
247 static const char *
248 aes_get_mbs(struct aes *aes)
249 {
250         if (aes->aes_mbs == NULL && aes->aes_wcs == NULL)
251                 return NULL;
252         if (aes->aes_mbs == NULL && aes->aes_wcs != NULL) {
253                 /*
254                  * XXX Need to estimate the number of byte in the
255                  * multi-byte form.  Assume that, on average, wcs
256                  * chars encode to no more than 3 bytes.  There must
257                  * be a better way... XXX
258                  */
259                 size_t mbs_length = wcslen(aes->aes_wcs) * 3 + 64;
260
261                 aes->aes_mbs_alloc = (char *)malloc(mbs_length);
262                 aes->aes_mbs = aes->aes_mbs_alloc;
263                 if (aes->aes_mbs == NULL)
264                         __archive_errx(1, "No memory for aes_get_mbs()");
265                 wcstombs(aes->aes_mbs_alloc, aes->aes_wcs, mbs_length - 1);
266                 aes->aes_mbs_alloc[mbs_length - 1] = 0;
267         }
268         return (aes->aes_mbs);
269 }
270
271 static const wchar_t *
272 aes_get_wcs(struct aes *aes)
273 {
274         if (aes->aes_wcs == NULL && aes->aes_mbs == NULL)
275                 return NULL;
276         if (aes->aes_wcs == NULL && aes->aes_mbs != NULL) {
277                 /*
278                  * No single byte will be more than one wide character,
279                  * so this length estimate will always be big enough.
280                  */
281                 size_t wcs_length = strlen(aes->aes_mbs);
282
283                 aes->aes_wcs_alloc
284                     = (wchar_t *)malloc((wcs_length + 1) * sizeof(wchar_t));
285                 aes->aes_wcs = aes->aes_wcs_alloc;
286                 if (aes->aes_wcs == NULL)
287                         __archive_errx(1, "No memory for aes_get_wcs()");
288                 mbstowcs(aes->aes_wcs_alloc, aes->aes_mbs, wcs_length);
289                 aes->aes_wcs_alloc[wcs_length] = 0;
290         }
291         return (aes->aes_wcs);
292 }
293
294 static void
295 aes_set_mbs(struct aes *aes, const char *mbs)
296 {
297         if (aes->aes_mbs_alloc) {
298                 free(aes->aes_mbs_alloc);
299                 aes->aes_mbs_alloc = NULL;
300         }
301         if (aes->aes_wcs_alloc) {
302                 free(aes->aes_wcs_alloc);
303                 aes->aes_wcs_alloc = NULL;
304         }
305         aes->aes_mbs = mbs;
306         aes->aes_wcs = NULL;
307 }
308
309 static void
310 aes_copy_mbs(struct aes *aes, const char *mbs)
311 {
312         if (aes->aes_mbs_alloc) {
313                 free(aes->aes_mbs_alloc);
314                 aes->aes_mbs_alloc = NULL;
315         }
316         if (aes->aes_wcs_alloc) {
317                 free(aes->aes_wcs_alloc);
318                 aes->aes_wcs_alloc = NULL;
319         }
320         aes->aes_mbs_alloc = (char *)malloc((strlen(mbs) + 1) * sizeof(char));
321         if (aes->aes_mbs_alloc == NULL)
322                 __archive_errx(1, "No memory for aes_copy_mbs()");
323         strcpy(aes->aes_mbs_alloc, mbs);
324         aes->aes_mbs = aes->aes_mbs_alloc;
325         aes->aes_wcs = NULL;
326 }
327
328 #if 0
329 static void
330 aes_set_wcs(struct aes *aes, const wchar_t *wcs)
331 {
332         if (aes->aes_mbs_alloc) {
333                 free(aes->aes_mbs_alloc);
334                 aes->aes_mbs_alloc = NULL;
335         }
336         if (aes->aes_wcs_alloc) {
337                 free(aes->aes_wcs_alloc);
338                 aes->aes_wcs_alloc = NULL;
339         }
340         aes->aes_mbs = NULL;
341         aes->aes_wcs = wcs;
342 }
343 #endif
344
345 static void
346 aes_copy_wcs(struct aes *aes, const wchar_t *wcs)
347 {
348         aes_copy_wcs_len(aes, wcs, wcslen(wcs));
349 }
350
351 static void
352 aes_copy_wcs_len(struct aes *aes, const wchar_t *wcs, size_t len)
353 {
354         if (aes->aes_mbs_alloc) {
355                 free(aes->aes_mbs_alloc);
356                 aes->aes_mbs_alloc = NULL;
357         }
358         if (aes->aes_wcs_alloc) {
359                 free(aes->aes_wcs_alloc);
360                 aes->aes_wcs_alloc = NULL;
361         }
362         aes->aes_mbs = NULL;
363         aes->aes_wcs_alloc = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
364         if (aes->aes_wcs_alloc == NULL)
365                 __archive_errx(1, "No memory for aes_copy_wcs()");
366         wmemcpy(aes->aes_wcs_alloc, wcs, len);
367         aes->aes_wcs_alloc[len] = L'\0';
368         aes->aes_wcs = aes->aes_wcs_alloc;
369 }
370
371 struct archive_entry *
372 archive_entry_clear(struct archive_entry *entry)
373 {
374         aes_clean(&entry->ae_fflags_text);
375         aes_clean(&entry->ae_gname);
376         aes_clean(&entry->ae_hardlink);
377         aes_clean(&entry->ae_pathname);
378         aes_clean(&entry->ae_symlink);
379         aes_clean(&entry->ae_uname);
380         archive_entry_acl_clear(entry);
381         archive_entry_xattr_clear(entry);
382         memset(entry, 0, sizeof(*entry));
383         return entry;
384 }
385
386 struct archive_entry *
387 archive_entry_clone(struct archive_entry *entry)
388 {
389         struct archive_entry *entry2;
390
391         /* Allocate new structure and copy over all of the fields. */
392         entry2 = (struct archive_entry *)malloc(sizeof(*entry2));
393         if (entry2 == NULL)
394                 return (NULL);
395         memset(entry2, 0, sizeof(*entry2));
396         entry2->ae_stat = entry->ae_stat;
397         entry2->ae_fflags_set = entry->ae_fflags_set;
398         entry2->ae_fflags_clear = entry->ae_fflags_clear;
399
400         aes_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
401         aes_copy(&entry2->ae_gname, &entry->ae_gname);
402         aes_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
403         aes_copy(&entry2->ae_pathname, &entry->ae_pathname);
404         aes_copy(&entry2->ae_symlink, &entry->ae_symlink);
405         aes_copy(&entry2->ae_uname, &entry->ae_uname);
406
407         /* XXX TODO: Copy ACL data over as well. XXX */
408         /* XXX TODO: Copy xattr data over as well. XXX */
409         return (entry2);
410 }
411
412 void
413 archive_entry_free(struct archive_entry *entry)
414 {
415         archive_entry_clear(entry);
416         free(entry);
417 }
418
419 struct archive_entry *
420 archive_entry_new(void)
421 {
422         struct archive_entry *entry;
423
424         entry = (struct archive_entry *)malloc(sizeof(*entry));
425         if (entry == NULL)
426                 return (NULL);
427         memset(entry, 0, sizeof(*entry));
428         return (entry);
429 }
430
431 /*
432  * Functions for reading fields from an archive_entry.
433  */
434
435 time_t
436 archive_entry_atime(struct archive_entry *entry)
437 {
438         return (entry->ae_stat.st_atime);
439 }
440
441 long
442 archive_entry_atime_nsec(struct archive_entry *entry)
443 {
444         (void)entry; /* entry can be unused here. */
445         return (ARCHIVE_STAT_ATIME_NANOS(&entry->ae_stat));
446 }
447
448 time_t
449 archive_entry_ctime(struct archive_entry *entry)
450 {
451         return (entry->ae_stat.st_ctime);
452 }
453
454 long
455 archive_entry_ctime_nsec(struct archive_entry *entry)
456 {
457         (void)entry; /* entry can be unused here. */
458         return (ARCHIVE_STAT_CTIME_NANOS(&entry->ae_stat));
459 }
460
461 dev_t
462 archive_entry_dev(struct archive_entry *entry)
463 {
464         return (entry->ae_stat.st_dev);
465 }
466
467 void
468 archive_entry_fflags(struct archive_entry *entry,
469     unsigned long *set, unsigned long *clear)
470 {
471         *set = entry->ae_fflags_set;
472         *clear = entry->ae_fflags_clear;
473 }
474
475 /*
476  * Note: if text was provided, this just returns that text.  If you
477  * really need the text to be rebuilt in a canonical form, set the
478  * text, ask for the bitmaps, then set the bitmaps.  (Setting the
479  * bitmaps clears any stored text.)  This design is deliberate: if
480  * we're editing archives, we don't want to discard flags just because
481  * they aren't supported on the current system.  The bitmap<->text
482  * conversions are platform-specific (see below).
483  */
484 const char *
485 archive_entry_fflags_text(struct archive_entry *entry)
486 {
487         const char *f;
488         char *p;
489
490         f = aes_get_mbs(&entry->ae_fflags_text);
491         if (f != NULL)
492                 return (f);
493
494         if (entry->ae_fflags_set == 0  &&  entry->ae_fflags_clear == 0)
495                 return (NULL);
496
497         p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);
498         if (p == NULL)
499                 return (NULL);
500
501         aes_copy_mbs(&entry->ae_fflags_text, p);
502         free(p);
503         f = aes_get_mbs(&entry->ae_fflags_text);
504         return (f);
505 }
506
507 gid_t
508 archive_entry_gid(struct archive_entry *entry)
509 {
510         return (entry->ae_stat.st_gid);
511 }
512
513 const char *
514 archive_entry_gname(struct archive_entry *entry)
515 {
516         return (aes_get_mbs(&entry->ae_gname));
517 }
518
519 const wchar_t *
520 archive_entry_gname_w(struct archive_entry *entry)
521 {
522         return (aes_get_wcs(&entry->ae_gname));
523 }
524
525 const char *
526 archive_entry_hardlink(struct archive_entry *entry)
527 {
528         return (aes_get_mbs(&entry->ae_hardlink));
529 }
530
531 const wchar_t *
532 archive_entry_hardlink_w(struct archive_entry *entry)
533 {
534         return (aes_get_wcs(&entry->ae_hardlink));
535 }
536
537 ino_t
538 archive_entry_ino(struct archive_entry *entry)
539 {
540         return (entry->ae_stat.st_ino);
541 }
542
543 mode_t
544 archive_entry_mode(struct archive_entry *entry)
545 {
546         return (entry->ae_stat.st_mode);
547 }
548
549 time_t
550 archive_entry_mtime(struct archive_entry *entry)
551 {
552         return (entry->ae_stat.st_mtime);
553 }
554
555 long
556 archive_entry_mtime_nsec(struct archive_entry *entry)
557 {
558         (void)entry; /* entry can be unused here. */
559         return (ARCHIVE_STAT_MTIME_NANOS(&entry->ae_stat));
560 }
561
562 const char *
563 archive_entry_pathname(struct archive_entry *entry)
564 {
565         return (aes_get_mbs(&entry->ae_pathname));
566 }
567
568 const wchar_t *
569 archive_entry_pathname_w(struct archive_entry *entry)
570 {
571         return (aes_get_wcs(&entry->ae_pathname));
572 }
573
574 dev_t
575 archive_entry_rdev(struct archive_entry *entry)
576 {
577         return (entry->ae_stat.st_rdev);
578 }
579
580 dev_t
581 archive_entry_rdevmajor(struct archive_entry *entry)
582 {
583         return (major(entry->ae_stat.st_rdev));
584 }
585
586 dev_t
587 archive_entry_rdevminor(struct archive_entry *entry)
588 {
589         return (minor(entry->ae_stat.st_rdev));
590 }
591
592 int64_t
593 archive_entry_size(struct archive_entry *entry)
594 {
595         return (entry->ae_stat.st_size);
596 }
597
598 const struct stat *
599 archive_entry_stat(struct archive_entry *entry)
600 {
601         return (&entry->ae_stat);
602 }
603
604 const char *
605 archive_entry_symlink(struct archive_entry *entry)
606 {
607         return (aes_get_mbs(&entry->ae_symlink));
608 }
609
610 const wchar_t *
611 archive_entry_symlink_w(struct archive_entry *entry)
612 {
613         return (aes_get_wcs(&entry->ae_symlink));
614 }
615
616 uid_t
617 archive_entry_uid(struct archive_entry *entry)
618 {
619         return (entry->ae_stat.st_uid);
620 }
621
622 const char *
623 archive_entry_uname(struct archive_entry *entry)
624 {
625         return (aes_get_mbs(&entry->ae_uname));
626 }
627
628 const wchar_t *
629 archive_entry_uname_w(struct archive_entry *entry)
630 {
631         return (aes_get_wcs(&entry->ae_uname));
632 }
633
634 /*
635  * Functions to set archive_entry properties.
636  */
637
638 /*
639  * Note "copy" not "set" here.  The "set" functions that accept a pointer
640  * only store the pointer; they don't copy the underlying object.
641  */
642 void
643 archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
644 {
645         entry->ae_stat = *st;
646 }
647
648 void
649 archive_entry_set_fflags(struct archive_entry *entry,
650     unsigned long set, unsigned long clear)
651 {
652         aes_clean(&entry->ae_fflags_text);
653         entry->ae_fflags_set = set;
654         entry->ae_fflags_clear = clear;
655 }
656
657 const wchar_t *
658 archive_entry_copy_fflags_text_w(struct archive_entry *entry,
659     const wchar_t *flags)
660 {
661         aes_copy_wcs(&entry->ae_fflags_text, flags);
662         return (ae_wcstofflags(flags,
663                     &entry->ae_fflags_set, &entry->ae_fflags_clear));
664 }
665
666 void
667 archive_entry_set_gid(struct archive_entry *entry, gid_t g)
668 {
669         entry->ae_stat.st_gid = g;
670 }
671
672 void
673 archive_entry_set_gname(struct archive_entry *entry, const char *name)
674 {
675         aes_set_mbs(&entry->ae_gname, name);
676 }
677
678 void
679 archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
680 {
681         aes_copy_wcs(&entry->ae_gname, name);
682 }
683
684 void
685 archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
686 {
687         aes_set_mbs(&entry->ae_hardlink, target);
688 }
689
690 void
691 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
692 {
693         aes_copy_mbs(&entry->ae_hardlink, target);
694 }
695
696 void
697 archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
698 {
699         aes_copy_wcs(&entry->ae_hardlink, target);
700 }
701
702 void
703 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
704 {
705         entry->ae_stat.st_atime = t;
706         ARCHIVE_STAT_SET_ATIME_NANOS(&entry->ae_stat, ns);
707 }
708
709 void
710 archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
711 {
712         entry->ae_stat.st_ctime = t;
713         ARCHIVE_STAT_SET_CTIME_NANOS(&entry->ae_stat, ns);
714 }
715
716 /* Set symlink if symlink is already set, else set hardlink. */
717 void
718 archive_entry_set_link(struct archive_entry *entry, const char *target)
719 {
720         if (entry->ae_symlink.aes_mbs != NULL ||
721             entry->ae_symlink.aes_wcs != NULL)
722                 aes_set_mbs(&entry->ae_symlink, target);
723         else
724                 aes_set_mbs(&entry->ae_hardlink, target);
725 }
726
727 void
728 archive_entry_set_mode(struct archive_entry *entry, mode_t m)
729 {
730         entry->ae_stat.st_mode = m;
731 }
732
733 void
734 archive_entry_set_mtime(struct archive_entry *entry, time_t m, long ns)
735 {
736         entry->ae_stat.st_mtime = m;
737         ARCHIVE_STAT_SET_MTIME_NANOS(&entry->ae_stat, ns);
738 }
739
740 void
741 archive_entry_set_pathname(struct archive_entry *entry, const char *name)
742 {
743         aes_set_mbs(&entry->ae_pathname, name);
744 }
745
746 void
747 archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
748 {
749         aes_copy_mbs(&entry->ae_pathname, name);
750 }
751
752 void
753 archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
754 {
755         aes_copy_wcs(&entry->ae_pathname, name);
756 }
757
758 void
759 archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
760 {
761         dev_t d;
762
763         d = entry->ae_stat.st_rdev;
764         entry->ae_stat.st_rdev = makedev(major(m), minor(d));
765 }
766
767 void
768 archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
769 {
770         dev_t d;
771
772         d = entry->ae_stat.st_rdev;
773         entry->ae_stat.st_rdev = makedev(major(d), minor(m));
774 }
775
776 void
777 archive_entry_set_size(struct archive_entry *entry, int64_t s)
778 {
779         entry->ae_stat.st_size = s;
780 }
781
782 void
783 archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
784 {
785         aes_set_mbs(&entry->ae_symlink, linkname);
786 }
787
788 void
789 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
790 {
791         aes_copy_mbs(&entry->ae_symlink, linkname);
792 }
793
794 void
795 archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
796 {
797         aes_copy_wcs(&entry->ae_symlink, linkname);
798 }
799
800 void
801 archive_entry_set_uid(struct archive_entry *entry, uid_t u)
802 {
803         entry->ae_stat.st_uid = u;
804 }
805
806 void
807 archive_entry_set_uname(struct archive_entry *entry, const char *name)
808 {
809         aes_set_mbs(&entry->ae_uname, name);
810 }
811
812 void
813 archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
814 {
815         aes_copy_wcs(&entry->ae_uname, name);
816 }
817
818 /*
819  * ACL management.  The following would, of course, be a lot simpler
820  * if: 1) the last draft of POSIX.1e were a really thorough and
821  * complete standard that addressed the needs of ACL archiving and 2)
822  * everyone followed it faithfully.  Alas, neither is true, so the
823  * following is a lot more complex than might seem necessary to the
824  * uninitiated.
825  */
826
827 void
828 archive_entry_acl_clear(struct archive_entry *entry)
829 {
830         struct ae_acl   *ap;
831
832         while (entry->acl_head != NULL) {
833                 ap = entry->acl_head->next;
834                 aes_clean(&entry->acl_head->name);
835                 free(entry->acl_head);
836                 entry->acl_head = ap;
837         }
838         if (entry->acl_text_w != NULL) {
839                 free(entry->acl_text_w);
840                 entry->acl_text_w = NULL;
841         }
842         entry->acl_p = NULL;
843         entry->acl_state = 0; /* Not counting. */
844 }
845
846 /*
847  * Add a single ACL entry to the internal list of ACL data.
848  */
849 void
850 archive_entry_acl_add_entry(struct archive_entry *entry,
851     int type, int permset, int tag, int id, const char *name)
852 {
853         struct ae_acl *ap;
854
855         if (acl_special(entry, type, permset, tag) == 0)
856                 return;
857         ap = acl_new_entry(entry, type, permset, tag, id);
858         if (ap == NULL) {
859                 /* XXX Error XXX */
860                 return;
861         }
862         if (name != NULL  &&  *name != '\0')
863                 aes_copy_mbs(&ap->name, name);
864         else
865                 aes_clean(&ap->name);
866 }
867
868 /*
869  * As above, but with a wide-character name.
870  */
871 void
872 archive_entry_acl_add_entry_w(struct archive_entry *entry,
873     int type, int permset, int tag, int id, const wchar_t *name)
874 {
875         archive_entry_acl_add_entry_w_len(entry, type, permset, tag, id, name, wcslen(name));
876 }
877
878 void
879 archive_entry_acl_add_entry_w_len(struct archive_entry *entry,
880     int type, int permset, int tag, int id, const wchar_t *name, size_t len)
881 {
882         struct ae_acl *ap;
883
884         if (acl_special(entry, type, permset, tag) == 0)
885                 return;
886         ap = acl_new_entry(entry, type, permset, tag, id);
887         if (ap == NULL) {
888                 /* XXX Error XXX */
889                 return;
890         }
891         if (name != NULL  &&  *name != L'\0' && len > 0)
892                 aes_copy_wcs_len(&ap->name, name, len);
893         else
894                 aes_clean(&ap->name);
895 }
896
897 /*
898  * If this ACL entry is part of the standard POSIX permissions set,
899  * store the permissions in the stat structure and return zero.
900  */
901 static int
902 acl_special(struct archive_entry *entry, int type, int permset, int tag)
903 {
904         if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
905                 switch (tag) {
906                 case ARCHIVE_ENTRY_ACL_USER_OBJ:
907                         entry->ae_stat.st_mode &= ~0700;
908                         entry->ae_stat.st_mode |= (permset & 7) << 6;
909                         return (0);
910                 case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
911                         entry->ae_stat.st_mode &= ~0070;
912                         entry->ae_stat.st_mode |= (permset & 7) << 3;
913                         return (0);
914                 case ARCHIVE_ENTRY_ACL_OTHER:
915                         entry->ae_stat.st_mode &= ~0007;
916                         entry->ae_stat.st_mode |= permset & 7;
917                         return (0);
918                 }
919         }
920         return (1);
921 }
922
923 /*
924  * Allocate and populate a new ACL entry with everything but the
925  * name.
926  */
927 static struct ae_acl *
928 acl_new_entry(struct archive_entry *entry,
929     int type, int permset, int tag, int id)
930 {
931         struct ae_acl *ap;
932
933         if (type != ARCHIVE_ENTRY_ACL_TYPE_ACCESS &&
934             type != ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
935                 return (NULL);
936         if (entry->acl_text_w != NULL) {
937                 free(entry->acl_text_w);
938                 entry->acl_text_w = NULL;
939         }
940
941         /* XXX TODO: More sanity-checks on the arguments XXX */
942
943         /* If there's a matching entry already in the list, overwrite it. */
944         for (ap = entry->acl_head; ap != NULL; ap = ap->next) {
945                 if (ap->type == type && ap->tag == tag && ap->id == id) {
946                         ap->permset = permset;
947                         return (ap);
948                 }
949         }
950
951         /* Add a new entry to the list. */
952         ap = (struct ae_acl *)malloc(sizeof(*ap));
953         if (ap == NULL)
954                 return (NULL);
955         memset(ap, 0, sizeof(*ap));
956         ap->next = entry->acl_head;
957         entry->acl_head = ap;
958         ap->type = type;
959         ap->tag = tag;
960         ap->id = id;
961         ap->permset = permset;
962         return (ap);
963 }
964
965 /*
966  * Return a count of entries matching "want_type".
967  */
968 int
969 archive_entry_acl_count(struct archive_entry *entry, int want_type)
970 {
971         int count;
972         struct ae_acl *ap;
973
974         count = 0;
975         ap = entry->acl_head;
976         while (ap != NULL) {
977                 if ((ap->type & want_type) != 0)
978                         count++;
979                 ap = ap->next;
980         }
981
982         if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
983                 count += 3;
984         return (count);
985 }
986
987 /*
988  * Prepare for reading entries from the ACL data.  Returns a count
989  * of entries matching "want_type", or zero if there are no
990  * non-extended ACL entries of that type.
991  */
992 int
993 archive_entry_acl_reset(struct archive_entry *entry, int want_type)
994 {
995         int count, cutoff;
996
997         count = archive_entry_acl_count(entry, want_type);
998
999         /*
1000          * If the only entries are the three standard ones,
1001          * then don't return any ACL data.  (In this case,
1002          * client can just use chmod(2) to set permissions.)
1003          */
1004         if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
1005                 cutoff = 3;
1006         else
1007                 cutoff = 0;
1008
1009         if (count > cutoff)
1010                 entry->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
1011         else
1012                 entry->acl_state = 0;
1013         entry->acl_p = entry->acl_head;
1014         return (count);
1015 }
1016
1017 /*
1018  * Return the next ACL entry in the list.  Fake entries for the
1019  * standard permissions and include them in the returned list.
1020  */
1021
1022 int
1023 archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
1024     int *permset, int *tag, int *id, const char **name)
1025 {
1026         *name = NULL;
1027         *id = -1;
1028
1029         /*
1030          * The acl_state is either zero (no entries available), -1
1031          * (reading from list), or an entry type (retrieve that type
1032          * from ae_stat.st_mode).
1033          */
1034         if (entry->acl_state == 0)
1035                 return (ARCHIVE_WARN);
1036
1037         /* The first three access entries are special. */
1038         if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
1039                 switch (entry->acl_state) {
1040                 case ARCHIVE_ENTRY_ACL_USER_OBJ:
1041                         *permset = (entry->ae_stat.st_mode >> 6) & 7;
1042                         *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
1043                         *tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
1044                         entry->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1045                         return (ARCHIVE_OK);
1046                 case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
1047                         *permset = (entry->ae_stat.st_mode >> 3) & 7;
1048                         *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
1049                         *tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1050                         entry->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
1051                         return (ARCHIVE_OK);
1052                 case ARCHIVE_ENTRY_ACL_OTHER:
1053                         *permset = entry->ae_stat.st_mode & 7;
1054                         *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
1055                         *tag = ARCHIVE_ENTRY_ACL_OTHER;
1056                         entry->acl_state = -1;
1057                         entry->acl_p = entry->acl_head;
1058                         return (ARCHIVE_OK);
1059                 default:
1060                         break;
1061                 }
1062         }
1063
1064         while (entry->acl_p != NULL && (entry->acl_p->type & want_type) == 0)
1065                 entry->acl_p = entry->acl_p->next;
1066         if (entry->acl_p == NULL) {
1067                 entry->acl_state = 0;
1068                 return (ARCHIVE_EOF); /* End of ACL entries. */
1069         }
1070         *type = entry->acl_p->type;
1071         *permset = entry->acl_p->permset;
1072         *tag = entry->acl_p->tag;
1073         *id = entry->acl_p->id;
1074         *name = aes_get_mbs(&entry->acl_p->name);
1075         entry->acl_p = entry->acl_p->next;
1076         return (ARCHIVE_OK);
1077 }
1078
1079 /*
1080  * Generate a text version of the ACL.  The flags parameter controls
1081  * the style of the generated ACL.
1082  */
1083 const wchar_t *
1084 archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1085 {
1086         int count;
1087         int length;
1088         const wchar_t *wname;
1089         const wchar_t *prefix;
1090         wchar_t separator;
1091         struct ae_acl *ap;
1092         int id;
1093         wchar_t *wp;
1094
1095         if (entry->acl_text_w != NULL) {
1096                 free (entry->acl_text_w);
1097                 entry->acl_text_w = NULL;
1098         }
1099
1100         separator = L',';
1101         count = 0;
1102         length = 0;
1103         ap = entry->acl_head;
1104         while (ap != NULL) {
1105                 if ((ap->type & flags) != 0) {
1106                         count++;
1107                         if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
1108                             (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
1109                                 length += 8; /* "default:" */
1110                         length += 5; /* tag name */
1111                         length += 1; /* colon */
1112                         wname = aes_get_wcs(&ap->name);
1113                         if (wname != NULL)
1114                                 length += wcslen(wname);
1115                         else
1116                                 length += sizeof(uid_t) * 3 + 1;
1117                         length ++; /* colon */
1118                         length += 3; /* rwx */
1119                         length += 1; /* colon */
1120                         length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
1121                         length ++; /* newline */
1122                 }
1123                 ap = ap->next;
1124         }
1125
1126         if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
1127                 length += 10; /* "user::rwx\n" */
1128                 length += 11; /* "group::rwx\n" */
1129                 length += 11; /* "other::rwx\n" */
1130         }
1131
1132         if (count == 0)
1133                 return (NULL);
1134
1135         /* Now, allocate the string and actually populate it. */
1136         wp = entry->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
1137         if (wp == NULL)
1138                 __archive_errx(1, "No memory to generate the text version of the ACL");
1139         count = 0;
1140         if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
1141                 append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
1142                     entry->ae_stat.st_mode & 0700, -1);
1143                 *wp++ = ',';
1144                 append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
1145                     entry->ae_stat.st_mode & 0070, -1);
1146                 *wp++ = ',';
1147                 append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
1148                     entry->ae_stat.st_mode & 0007, -1);
1149                 count += 3;
1150
1151                 ap = entry->acl_head;
1152                 while (ap != NULL) {
1153                         if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
1154                                 wname = aes_get_wcs(&ap->name);
1155                                 *wp++ = separator;
1156                                 if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
1157                                         id = ap->id;
1158                                 else
1159                                         id = -1;
1160                                 append_entry_w(&wp, NULL, ap->tag, wname,
1161                                     ap->permset, id);
1162                                 count++;
1163                         }
1164                         ap = ap->next;
1165                 }
1166         }
1167
1168
1169         if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
1170                 if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
1171                         prefix = L"default:";
1172                 else
1173                         prefix = NULL;
1174                 ap = entry->acl_head;
1175                 count = 0;
1176                 while (ap != NULL) {
1177                         if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
1178                                 wname = aes_get_wcs(&ap->name);
1179                                 if (count > 0)
1180                                         *wp++ = separator;
1181                                 if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
1182                                         id = ap->id;
1183                                 else
1184                                         id = -1;
1185                                 append_entry_w(&wp, prefix, ap->tag,
1186                                     wname, ap->permset, id);
1187                                 count ++;
1188                         }
1189                         ap = ap->next;
1190                 }
1191         }
1192
1193         return (entry->acl_text_w);
1194 }
1195
1196 static void
1197 append_id_w(wchar_t **wp, int id)
1198 {
1199         if (id < 0)
1200                 id = 0;
1201         if (id > 9)
1202                 append_id_w(wp, id / 10);
1203         *(*wp)++ = L"0123456789"[id % 10];
1204 }
1205
1206 static void
1207 append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
1208     const wchar_t *wname, int perm, int id)
1209 {
1210         if (prefix != NULL) {
1211                 wcscpy(*wp, prefix);
1212                 *wp += wcslen(*wp);
1213         }
1214         switch (tag) {
1215         case ARCHIVE_ENTRY_ACL_USER_OBJ:
1216                 wname = NULL;
1217                 id = -1;
1218                 /* FALLTHROUGH */
1219         case ARCHIVE_ENTRY_ACL_USER:
1220                 wcscpy(*wp, L"user");
1221                 break;
1222         case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
1223                 wname = NULL;
1224                 id = -1;
1225                 /* FALLTHROUGH */
1226         case ARCHIVE_ENTRY_ACL_GROUP:
1227                 wcscpy(*wp, L"group");
1228                 break;
1229         case ARCHIVE_ENTRY_ACL_MASK:
1230                 wcscpy(*wp, L"mask");
1231                 wname = NULL;
1232                 id = -1;
1233                 break;
1234         case ARCHIVE_ENTRY_ACL_OTHER:
1235                 wcscpy(*wp, L"other");
1236                 wname = NULL;
1237                 id = -1;
1238                 break;
1239         }
1240         *wp += wcslen(*wp);
1241         *(*wp)++ = L':';
1242         if (wname != NULL) {
1243                 wcscpy(*wp, wname);
1244                 *wp += wcslen(*wp);
1245         } else if (tag == ARCHIVE_ENTRY_ACL_USER
1246             || tag == ARCHIVE_ENTRY_ACL_GROUP) {
1247                 append_id_w(wp, id);
1248                 id = -1;
1249         }
1250         *(*wp)++ = L':';
1251         *(*wp)++ = (perm & 0444) ? L'r' : L'-';
1252         *(*wp)++ = (perm & 0222) ? L'w' : L'-';
1253         *(*wp)++ = (perm & 0111) ? L'x' : L'-';
1254         if (id != -1) {
1255                 *(*wp)++ = L':';
1256                 append_id_w(wp, id);
1257         }
1258         **wp = L'\0';
1259 }
1260
1261 /*
1262  * Parse a textual ACL.  This automatically recognizes and supports
1263  * extensions described above.  The 'type' argument is used to
1264  * indicate the type that should be used for any entries not
1265  * explicitly marked as "default:".
1266  */
1267 int
1268 __archive_entry_acl_parse_w(struct archive_entry *entry,
1269     const wchar_t *text, int default_type)
1270 {
1271         struct {
1272                 const wchar_t *start;
1273                 const wchar_t *end;
1274         } field[4];
1275
1276         int fields;
1277         int type, tag, permset, id;
1278         const wchar_t *p;
1279         wchar_t sep;
1280
1281         while (text != NULL  &&  *text != L'\0') {
1282                 /*
1283                  * Parse the fields out of the next entry,
1284                  * advance 'text' to start of next entry.
1285                  */
1286                 fields = 0;
1287                 do {
1288                         const wchar_t *start, *end;
1289                         next_field_w(&text, &start, &end, &sep);
1290                         if (fields < 4) {
1291                                 field[fields].start = start;
1292                                 field[fields].end = end;
1293                         }
1294                         ++fields;
1295                 } while (sep == L':');
1296
1297                 if (fields < 3)
1298                         return (ARCHIVE_WARN);
1299
1300                 /* Check for a numeric ID in field 1 or 3. */
1301                 id = -1;
1302                 isint_w(field[1].start, field[1].end, &id);
1303                 /* Field 3 is optional. */
1304                 if (id == -1 && fields > 3)
1305                         isint_w(field[3].start, field[3].end, &id);
1306
1307                 /* Parse the permissions from field 2. */
1308                 permset = 0;
1309                 p = field[2].start;
1310                 while (p < field[2].end) {
1311                         switch (*p++) {
1312                         case 'r': case 'R':
1313                                 permset |= ARCHIVE_ENTRY_ACL_READ;
1314                                 break;
1315                         case 'w': case 'W':
1316                                 permset |= ARCHIVE_ENTRY_ACL_WRITE;
1317                                 break;
1318                         case 'x': case 'X':
1319                                 permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
1320                                 break;
1321                         case '-':
1322                                 break;
1323                         default:
1324                                 return (ARCHIVE_WARN);
1325                         }
1326                 }
1327
1328                 /*
1329                  * Solaris extension:  "defaultuser::rwx" is the
1330                  * default ACL corresponding to "user::rwx", etc.
1331                  */
1332                 if (field[0].end-field[0].start > 7
1333                     && wmemcmp(field[0].start, L"default", 7) == 0) {
1334                         type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
1335                         field[0].start += 7;
1336                 } else
1337                         type = default_type;
1338
1339                 if (prefix_w(field[0].start, field[0].end, L"user")) {
1340                         if (id != -1 || field[1].start < field[1].end)
1341                                 tag = ARCHIVE_ENTRY_ACL_USER;
1342                         else
1343                                 tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
1344                 } else if (prefix_w(field[0].start, field[0].end, L"group")) {
1345                         if (id != -1 || field[1].start < field[1].end)
1346                                 tag = ARCHIVE_ENTRY_ACL_GROUP;
1347                         else
1348                                 tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1349                 } else if (prefix_w(field[0].start, field[0].end, L"other")) {
1350                         if (id != -1 || field[1].start < field[1].end)
1351                                 return (ARCHIVE_WARN);
1352                         tag = ARCHIVE_ENTRY_ACL_OTHER;
1353                 } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
1354                         if (id != -1 || field[1].start < field[1].end)
1355                                 return (ARCHIVE_WARN);
1356                         tag = ARCHIVE_ENTRY_ACL_MASK;
1357                 } else
1358                         return (ARCHIVE_WARN);
1359
1360                 /* Add entry to the internal list. */
1361                 archive_entry_acl_add_entry_w_len(entry, type, permset,
1362                     tag, id, field[1].start, field[1].end - field[1].start);
1363         }
1364         return (ARCHIVE_OK);
1365 }
1366
1367 /*
1368  * extended attribute handling
1369  */
1370
1371 void
1372 archive_entry_xattr_clear(struct archive_entry *entry)
1373 {
1374         struct ae_xattr *xp;
1375
1376         while (entry->xattr_head != NULL) {
1377                 xp = entry->xattr_head->next;
1378                 free(entry->xattr_head->name);
1379                 free(entry->xattr_head->value);
1380                 free(entry->xattr_head);
1381                 entry->xattr_head = xp;
1382         }
1383
1384         entry->xattr_head = NULL;
1385 }
1386
1387 void
1388 archive_entry_xattr_add_entry(struct archive_entry *entry,
1389         const char *name, const void *value, size_t size)
1390 {
1391         struct ae_xattr *xp;
1392
1393         for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
1394                 ;
1395
1396         if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL)
1397                 /* XXX Error XXX */
1398                 return;
1399
1400         xp->name = strdup(name);
1401         if ((xp->value = malloc(size)) != NULL) {
1402                 memcpy(xp->value, value, size);
1403                 xp->size = size;
1404         } else
1405                 xp->size = 0;
1406
1407         xp->next = entry->xattr_head;
1408         entry->xattr_head = xp;
1409 }
1410
1411
1412 /*
1413  * returns number of the extended attribute entries
1414  */
1415 int
1416 archive_entry_xattr_count(struct archive_entry *entry)
1417 {
1418         struct ae_xattr *xp;
1419         int count = 0;
1420
1421         for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
1422                 count++;
1423
1424         return count;
1425 }
1426
1427 int
1428 archive_entry_xattr_reset(struct archive_entry * entry)
1429 {
1430         entry->xattr_p = entry->xattr_head;
1431
1432         return archive_entry_xattr_count(entry);
1433 }
1434
1435 int
1436 archive_entry_xattr_next(struct archive_entry * entry,
1437         const char **name, const void **value, size_t *size)
1438 {
1439         if (entry->xattr_p) {
1440                 *name = entry->xattr_p->name;
1441                 *value = entry->xattr_p->value;
1442                 *size = entry->xattr_p->size;
1443
1444                 entry->xattr_p = entry->xattr_p->next;
1445
1446                 return (ARCHIVE_OK);
1447         } else {
1448                 *name = NULL;
1449                 *name = NULL;
1450                 *size = (size_t)0;
1451                 return (ARCHIVE_WARN);
1452         }
1453 }
1454
1455 /*
1456  * end of xattr handling
1457  */
1458
1459 /*
1460  * Parse a string to a positive decimal integer.  Returns true if
1461  * the string is non-empty and consists only of decimal digits,
1462  * false otherwise.
1463  */
1464 static int
1465 isint_w(const wchar_t *start, const wchar_t *end, int *result)
1466 {
1467         int n = 0;
1468         if (start >= end)
1469                 return (0);
1470         while (start < end) {
1471                 if (*start < '0' || *start > '9')
1472                         return (0);
1473                 if (n > (INT_MAX / 10))
1474                         n = INT_MAX;
1475                 else {
1476                         n *= 10;
1477                         n += *start - '0';
1478                 }
1479                 start++;
1480         }
1481         *result = n;
1482         return (1);
1483 }
1484
1485 /*
1486  * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
1487  * to point to just after the separator.  *start points to the first
1488  * character of the matched text and *end just after the last
1489  * character of the matched identifier.  In particular *end - *start
1490  * is the length of the field body, not including leading or trailing
1491  * whitespace.
1492  */
1493 static void
1494 next_field_w(const wchar_t **wp, const wchar_t **start,
1495     const wchar_t **end, wchar_t *sep)
1496 {
1497         /* Skip leading whitespace to find start of field. */
1498         while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
1499                 (*wp)++;
1500         }
1501         *start = *wp;
1502
1503         /* Scan for the separator. */
1504         while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
1505             **wp != L'\n') {
1506                 (*wp)++;
1507         }
1508         *sep = **wp;
1509
1510         /* Trim trailing whitespace to locate end of field. */
1511         *end = *wp - 1;
1512         while (**end == L' ' || **end == L'\t' || **end == L'\n') {
1513                 (*end)--;
1514         }
1515         (*end)++;
1516
1517         /* Adjust scanner location. */
1518         if (**wp != L'\0')
1519                 (*wp)++;
1520 }
1521
1522 /*
1523  * Return true if the characters [start...end) are a prefix of 'test'.
1524  * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
1525  */
1526 static int
1527 prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test)
1528 {
1529         if (start == end)
1530                 return (0);
1531
1532         if (*start++ != *test++)
1533                 return (0);
1534
1535         while (start < end  &&  *start++ == *test++)
1536                 ;
1537
1538         if (start < end)
1539                 return (0);
1540
1541         return (1);
1542 }
1543
1544
1545 /*
1546  * Following code is modified from UC Berkeley sources, and
1547  * is subject to the following copyright notice.
1548  */
1549
1550 /*-
1551  * Copyright (c) 1993
1552  *      The Regents of the University of California.  All rights reserved.
1553  *
1554  * Redistribution and use in source and binary forms, with or without
1555  * modification, are permitted provided that the following conditions
1556  * are met:
1557  * 1. Redistributions of source code must retain the above copyright
1558  *    notice, this list of conditions and the following disclaimer.
1559  * 2. Redistributions in binary form must reproduce the above copyright
1560  *    notice, this list of conditions and the following disclaimer in the
1561  *    documentation and/or other materials provided with the distribution.
1562  * 4. Neither the name of the University nor the names of its contributors
1563  *    may be used to endorse or promote products derived from this software
1564  *    without specific prior written permission.
1565  *
1566  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1567  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1568  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1569  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1570  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1571  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1572  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1573  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1574  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1575  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1576  * SUCH DAMAGE.
1577  */
1578
1579 static struct flag {
1580         const char      *name;
1581         const wchar_t   *wname;
1582         unsigned long    set;
1583         unsigned long    clear;
1584 } flags[] = {
1585         /* Preferred (shorter) names per flag first, all prefixed by "no" */
1586 #ifdef SF_APPEND
1587         { "nosappnd",   L"nosappnd",            SF_APPEND,      0 },
1588         { "nosappend",  L"nosappend",           SF_APPEND,      0 },
1589 #endif
1590 #ifdef  EXT2_APPEND_FL                          /* 'a' */
1591         { "nosappnd",   L"nosappnd",            EXT2_APPEND_FL, 0 },
1592         { "nosappend",  L"nosappend",           EXT2_APPEND_FL, 0 },
1593 #endif
1594 #ifdef SF_ARCHIVED
1595         { "noarch",     L"noarch",              SF_ARCHIVED,    0 },
1596         { "noarchived", L"noarchived",          SF_ARCHIVED,    0 },
1597 #endif
1598 #ifdef SF_IMMUTABLE
1599         { "noschg",     L"noschg",              SF_IMMUTABLE,   0 },
1600         { "noschange",  L"noschange",           SF_IMMUTABLE,   0 },
1601         { "nosimmutable",       L"nosimmutable",        SF_IMMUTABLE,   0 },
1602 #endif
1603 #ifdef EXT2_IMMUTABLE_FL                        /* 'i' */
1604         { "noschg",     L"noschg",              EXT2_IMMUTABLE_FL,      0 },
1605         { "noschange",  L"noschange",           EXT2_IMMUTABLE_FL,      0 },
1606         { "nosimmutable",       L"nosimmutable",        EXT2_IMMUTABLE_FL,      0 },
1607 #endif
1608 #ifdef SF_NOUNLINK
1609         { "nosunlnk",   L"nosunlnk",            SF_NOUNLINK,    0 },
1610         { "nosunlink",  L"nosunlink",           SF_NOUNLINK,    0 },
1611 #endif
1612 #ifdef SF_SNAPSHOT
1613         { "nosnapshot", L"nosnapshot",  SF_SNAPSHOT,    0 },
1614 #endif
1615 #ifdef UF_APPEND
1616         { "nouappnd",   L"nouappnd",            UF_APPEND,      0 },
1617         { "nouappend",  L"nouappend",           UF_APPEND,      0 },
1618 #endif
1619 #ifdef UF_IMMUTABLE
1620         { "nouchg",     L"nouchg",              UF_IMMUTABLE,   0 },
1621         { "nouchange",  L"nouchange",           UF_IMMUTABLE,   0 },
1622         { "nouimmutable",       L"nouimmutable",        UF_IMMUTABLE,   0 },
1623 #endif
1624 #ifdef UF_NODUMP
1625         { "nodump",     L"nodump",              0,              UF_NODUMP},
1626 #endif
1627 #ifdef EXT2_NODUMP_FL                           /* 'd' */
1628         { "nodump",     L"nodump",              0,              EXT2_NODUMP_FL},
1629 #endif
1630 #ifdef UF_OPAQUE
1631         { "noopaque",   L"noopaque",            UF_OPAQUE,      0 },
1632 #endif
1633 #ifdef UF_NOUNLINK
1634         { "nouunlnk",   L"nouunlnk",            UF_NOUNLINK,    0 },
1635         { "nouunlink",  L"nouunlink",           UF_NOUNLINK,    0 },
1636 #endif
1637 #ifdef EXT2_COMPR_FL                            /* 'c' */
1638         { "nocompress", L"nocompress",          EXT2_COMPR_FL,  0 },
1639 #endif
1640
1641 #ifdef EXT2_NOATIME_FL                          /* 'A' */
1642         { "noatime",    L"noatime",             0,              EXT2_NOATIME_FL},
1643 #endif
1644         { NULL,         NULL,                   0,              0 }
1645 };
1646
1647 /*
1648  * fflagstostr --
1649  *      Convert file flags to a comma-separated string.  If no flags
1650  *      are set, return the empty string.
1651  */
1652 char *
1653 ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
1654 {
1655         char *string, *dp;
1656         const char *sp;
1657         unsigned long bits;
1658         struct flag *flag;
1659         size_t  length;
1660
1661         bits = bitset | bitclear;
1662         length = 0;
1663         for (flag = flags; flag->name != NULL; flag++)
1664                 if (bits & (flag->set | flag->clear)) {
1665                         length += strlen(flag->name) + 1;
1666                         bits &= ~(flag->set | flag->clear);
1667                 }
1668
1669         if (length == 0)
1670                 return (NULL);
1671         string = (char *)malloc(length);
1672         if (string == NULL)
1673                 return (NULL);
1674
1675         dp = string;
1676         for (flag = flags; flag->name != NULL; flag++) {
1677                 if (bitset & flag->set || bitclear & flag->clear) {
1678                         sp = flag->name + 2;
1679                 } else if (bitset & flag->clear  ||  bitclear & flag->set) {
1680                         sp = flag->name;
1681                 } else
1682                         continue;
1683                 bitset &= ~(flag->set | flag->clear);
1684                 bitclear &= ~(flag->set | flag->clear);
1685                 if (dp > string)
1686                         *dp++ = ',';
1687                 while ((*dp++ = *sp++) != '\0')
1688                         ;
1689                 dp--;
1690         }
1691
1692         *dp = '\0';
1693         return (string);
1694 }
1695
1696 /*
1697  * wcstofflags --
1698  *      Take string of arguments and return file flags.  This
1699  *      version works a little differently than strtofflags(3).
1700  *      In particular, it always tests every token, skipping any
1701  *      unrecognized tokens.  It returns a pointer to the first
1702  *      unrecognized token, or NULL if every token was recognized.
1703  *      This version is also const-correct and does not modify the
1704  *      provided string.
1705  */
1706 const wchar_t *
1707 ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
1708 {
1709         const wchar_t *start, *end;
1710         struct flag *flag;
1711         unsigned long set, clear;
1712         const wchar_t *failed;
1713
1714         set = clear = 0;
1715         start = s;
1716         failed = NULL;
1717         /* Find start of first token. */
1718         while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
1719                 start++;
1720         while (*start != L'\0') {
1721                 /* Locate end of token. */
1722                 end = start;
1723                 while (*end != L'\0'  &&  *end != L'\t'  &&
1724                     *end != L' '  &&  *end != L',')
1725                         end++;
1726                 for (flag = flags; flag->wname != NULL; flag++) {
1727                         if (wmemcmp(start, flag->wname, end - start) == 0) {
1728                                 /* Matched "noXXXX", so reverse the sense. */
1729                                 clear |= flag->set;
1730                                 set |= flag->clear;
1731                                 break;
1732                         } else if (wmemcmp(start, flag->wname + 2, end - start)
1733                             == 0) {
1734                                 /* Matched "XXXX", so don't reverse. */
1735                                 set |= flag->set;
1736                                 clear |= flag->clear;
1737                                 break;
1738                         }
1739                 }
1740                 /* Ignore unknown flag names. */
1741                 if (flag->wname == NULL  &&  failed == NULL)
1742                         failed = start;
1743
1744                 /* Find start of next token. */
1745                 start = end;
1746                 while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
1747                         start++;
1748
1749         }
1750
1751         if (setp)
1752                 *setp = set;
1753         if (clrp)
1754                 *clrp = clear;
1755
1756         /* Return location of first failure. */
1757         return (failed);
1758 }
1759
1760
1761 #ifdef TEST
1762 #include <stdio.h>
1763 int
1764 main(int argc, char **argv)
1765 {
1766         struct archive_entry *entry = archive_entry_new();
1767         unsigned long set, clear;
1768         const wchar_t *remainder;
1769
1770         remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
1771         archive_entry_fflags(entry, &set, &clear);
1772
1773         wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
1774
1775         wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
1776         return (0);
1777 }
1778 #endif