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