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