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