2 * Copyright (c) 2003-2007 Tim Kientzle
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.45 2007/12/30 04:58:21 kientzle Exp $");
29 #ifdef HAVE_SYS_STAT_H
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
36 #include <sys/mkdev.h>
38 #ifdef MAJOR_IN_SYSMACROS
39 #include <sys/sysmacros.h>
42 #ifdef HAVE_EXT2FS_EXT2_FS_H
43 #include <ext2fs/ext2_fs.h> /* for Linux file flags */
48 #ifdef HAVE_LINUX_FS_H
49 #include <linux/fs.h> /* for Linux file flags */
51 #ifdef HAVE_LINUX_EXT2_FS_H
52 #include <linux/ext2_fs.h> /* for Linux file flags */
67 #include "archive_entry.h"
68 #include "archive_private.h"
69 #include "archive_entry_private.h"
72 #define max(a, b) ((a)>(b)?(a):(b))
74 /* Play games to come up with a suitable makedev() definition. */
77 #include <sys/netmgr.h>
78 #define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
80 /* There's a "makedev" macro. */
81 #define ae_makedev(maj, min) makedev((maj), (min))
82 #elif defined mkdev || defined _WIN32 || defined __WIN32__
84 #define ae_makedev(maj, min) mkdev((maj), (min))
86 /* There's a "makedev" function. */
87 #define ae_makedev(maj, min) makedev((maj), (min))
90 static void aes_clean(struct aes
*);
91 static void aes_copy(struct aes
*dest
, struct aes
*src
);
92 static const char * aes_get_mbs(struct aes
*);
93 static const wchar_t * aes_get_wcs(struct aes
*);
94 static void aes_set_mbs(struct aes
*, const char *mbs
);
95 static void aes_copy_mbs(struct aes
*, const char *mbs
);
96 /* static void aes_set_wcs(struct aes *, const wchar_t *wcs); */
97 static void aes_copy_wcs(struct aes
*, const wchar_t *wcs
);
98 static void aes_copy_wcs_len(struct aes
*, const wchar_t *wcs
, size_t);
100 static char * ae_fflagstostr(unsigned long bitset
, unsigned long bitclear
);
101 static const wchar_t *ae_wcstofflags(const wchar_t *stringp
,
102 unsigned long *setp
, unsigned long *clrp
);
103 static void append_entry_w(wchar_t **wp
, const wchar_t *prefix
, int tag
,
104 const wchar_t *wname
, int perm
, int id
);
105 static void append_id_w(wchar_t **wp
, int id
);
107 static int acl_special(struct archive_entry
*entry
,
108 int type
, int permset
, int tag
);
109 static struct ae_acl
*acl_new_entry(struct archive_entry
*entry
,
110 int type
, int permset
, int tag
, int id
);
111 static int isint_w(const wchar_t *start
, const wchar_t *end
, int *result
);
112 static void next_field_w(const wchar_t **wp
, const wchar_t **start
,
113 const wchar_t **end
, wchar_t *sep
);
114 static int prefix_w(const wchar_t *start
, const wchar_t *end
,
115 const wchar_t *test
);
117 archive_entry_acl_add_entry_w_len(struct archive_entry
*entry
, int type
,
118 int permset
, int tag
, int id
, const wchar_t *name
, size_t);
122 static wchar_t * wcscpy(wchar_t *s1
, const wchar_t *s2
)
125 while ((*s1
= *s2
) != L
'\0')
131 static size_t wcslen(const wchar_t *s
)
133 const wchar_t *p
= s
;
140 /* Good enough for simple equality testing, but not for sorting. */
141 #define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))
144 #define wmemcpy(a,b,i) (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t))
149 aes_clean(struct aes
*aes
)
151 if (aes
->aes_mbs_alloc
) {
152 free(aes
->aes_mbs_alloc
);
153 aes
->aes_mbs_alloc
= NULL
;
155 if (aes
->aes_wcs_alloc
) {
156 free(aes
->aes_wcs_alloc
);
157 aes
->aes_wcs_alloc
= NULL
;
159 memset(aes
, 0, sizeof(*aes
));
163 aes_copy(struct aes
*dest
, struct aes
*src
)
166 if (src
->aes_mbs
!= NULL
) {
167 dest
->aes_mbs_alloc
= strdup(src
->aes_mbs
);
168 dest
->aes_mbs
= dest
->aes_mbs_alloc
;
169 if (dest
->aes_mbs
== NULL
)
170 __archive_errx(1, "No memory for aes_copy()");
173 if (src
->aes_wcs
!= NULL
) {
174 dest
->aes_wcs_alloc
= (wchar_t *)malloc((wcslen(src
->aes_wcs
) + 1)
176 dest
->aes_wcs
= dest
->aes_wcs_alloc
;
177 if (dest
->aes_wcs
== NULL
)
178 __archive_errx(1, "No memory for aes_copy()");
179 wcscpy(dest
->aes_wcs_alloc
, src
->aes_wcs
);
184 aes_get_mbs(struct aes
*aes
)
186 if (aes
->aes_mbs
== NULL
&& aes
->aes_wcs
== NULL
)
188 if (aes
->aes_mbs
== NULL
&& aes
->aes_wcs
!= NULL
) {
190 * XXX Need to estimate the number of byte in the
191 * multi-byte form. Assume that, on average, wcs
192 * chars encode to no more than 3 bytes. There must
193 * be a better way... XXX
195 size_t mbs_length
= wcslen(aes
->aes_wcs
) * 3 + 64;
197 aes
->aes_mbs_alloc
= (char *)malloc(mbs_length
);
198 aes
->aes_mbs
= aes
->aes_mbs_alloc
;
199 if (aes
->aes_mbs
== NULL
)
200 __archive_errx(1, "No memory for aes_get_mbs()");
201 wcstombs(aes
->aes_mbs_alloc
, aes
->aes_wcs
, mbs_length
- 1);
202 aes
->aes_mbs_alloc
[mbs_length
- 1] = 0;
204 return (aes
->aes_mbs
);
207 static const wchar_t *
208 aes_get_wcs(struct aes
*aes
)
212 if (aes
->aes_wcs
== NULL
&& aes
->aes_mbs
== NULL
)
214 if (aes
->aes_wcs
== NULL
&& aes
->aes_mbs
!= NULL
) {
216 * No single byte will be more than one wide character,
217 * so this length estimate will always be big enough.
219 size_t wcs_length
= strlen(aes
->aes_mbs
);
222 = (wchar_t *)malloc((wcs_length
+ 1) * sizeof(wchar_t));
223 aes
->aes_wcs
= aes
->aes_wcs_alloc
;
224 if (aes
->aes_wcs
== NULL
)
225 __archive_errx(1, "No memory for aes_get_wcs()");
226 r
= mbstowcs(aes
->aes_wcs_alloc
, aes
->aes_mbs
, wcs_length
);
227 aes
->aes_wcs_alloc
[wcs_length
] = 0;
229 /* Conversion failed, don't lie to our clients. */
230 free(aes
->aes_wcs_alloc
);
231 aes
->aes_wcs
= aes
->aes_wcs_alloc
= NULL
;
234 return (aes
->aes_wcs
);
238 aes_set_mbs(struct aes
*aes
, const char *mbs
)
240 if (aes
->aes_mbs_alloc
) {
241 free(aes
->aes_mbs_alloc
);
242 aes
->aes_mbs_alloc
= NULL
;
244 if (aes
->aes_wcs_alloc
) {
245 free(aes
->aes_wcs_alloc
);
246 aes
->aes_wcs_alloc
= NULL
;
253 aes_copy_mbs(struct aes
*aes
, const char *mbs
)
255 if (aes
->aes_mbs_alloc
) {
256 free(aes
->aes_mbs_alloc
);
257 aes
->aes_mbs_alloc
= NULL
;
259 if (aes
->aes_wcs_alloc
) {
260 free(aes
->aes_wcs_alloc
);
261 aes
->aes_wcs_alloc
= NULL
;
263 aes
->aes_mbs_alloc
= (char *)malloc((strlen(mbs
) + 1) * sizeof(char));
264 if (aes
->aes_mbs_alloc
== NULL
)
265 __archive_errx(1, "No memory for aes_copy_mbs()");
266 strcpy(aes
->aes_mbs_alloc
, mbs
);
267 aes
->aes_mbs
= aes
->aes_mbs_alloc
;
273 aes_set_wcs(struct aes
*aes
, const wchar_t *wcs
)
275 if (aes
->aes_mbs_alloc
) {
276 free(aes
->aes_mbs_alloc
);
277 aes
->aes_mbs_alloc
= NULL
;
279 if (aes
->aes_wcs_alloc
) {
280 free(aes
->aes_wcs_alloc
);
281 aes
->aes_wcs_alloc
= NULL
;
289 aes_copy_wcs(struct aes
*aes
, const wchar_t *wcs
)
291 aes_copy_wcs_len(aes
, wcs
, wcslen(wcs
));
295 aes_copy_wcs_len(struct aes
*aes
, const wchar_t *wcs
, size_t len
)
297 if (aes
->aes_mbs_alloc
) {
298 free(aes
->aes_mbs_alloc
);
299 aes
->aes_mbs_alloc
= NULL
;
301 if (aes
->aes_wcs_alloc
) {
302 free(aes
->aes_wcs_alloc
);
303 aes
->aes_wcs_alloc
= NULL
;
306 aes
->aes_wcs_alloc
= (wchar_t *)malloc((len
+ 1) * sizeof(wchar_t));
307 if (aes
->aes_wcs_alloc
== NULL
)
308 __archive_errx(1, "No memory for aes_copy_wcs()");
309 wmemcpy(aes
->aes_wcs_alloc
, wcs
, len
);
310 aes
->aes_wcs_alloc
[len
] = L
'\0';
311 aes
->aes_wcs
= aes
->aes_wcs_alloc
;
314 struct archive_entry
*
315 archive_entry_clear(struct archive_entry
*entry
)
319 aes_clean(&entry
->ae_fflags_text
);
320 aes_clean(&entry
->ae_gname
);
321 aes_clean(&entry
->ae_hardlink
);
322 aes_clean(&entry
->ae_pathname
);
323 aes_clean(&entry
->ae_symlink
);
324 aes_clean(&entry
->ae_uname
);
325 archive_entry_acl_clear(entry
);
326 archive_entry_xattr_clear(entry
);
328 memset(entry
, 0, sizeof(*entry
));
332 struct archive_entry
*
333 archive_entry_clone(struct archive_entry
*entry
)
335 struct archive_entry
*entry2
;
336 struct ae_acl
*ap
, *ap2
;
339 /* Allocate new structure and copy over all of the fields. */
340 entry2
= (struct archive_entry
*)malloc(sizeof(*entry2
));
343 memset(entry2
, 0, sizeof(*entry2
));
344 entry2
->ae_stat
= entry
->ae_stat
;
345 entry2
->ae_fflags_set
= entry
->ae_fflags_set
;
346 entry2
->ae_fflags_clear
= entry
->ae_fflags_clear
;
348 aes_copy(&entry2
->ae_fflags_text
, &entry
->ae_fflags_text
);
349 aes_copy(&entry2
->ae_gname
, &entry
->ae_gname
);
350 aes_copy(&entry2
->ae_hardlink
, &entry
->ae_hardlink
);
351 aes_copy(&entry2
->ae_pathname
, &entry
->ae_pathname
);
352 aes_copy(&entry2
->ae_symlink
, &entry
->ae_symlink
);
353 aes_copy(&entry2
->ae_uname
, &entry
->ae_uname
);
355 /* Copy ACL data over. */
356 ap
= entry
->acl_head
;
358 ap2
= acl_new_entry(entry2
,
359 ap
->type
, ap
->permset
, ap
->tag
, ap
->id
);
361 aes_copy(&ap2
->name
, &ap
->name
);
365 /* Copy xattr data over. */
366 xp
= entry
->xattr_head
;
368 archive_entry_xattr_add_entry(entry2
,
369 xp
->name
, xp
->value
, xp
->size
);
377 archive_entry_free(struct archive_entry
*entry
)
379 archive_entry_clear(entry
);
383 struct archive_entry
*
384 archive_entry_new(void)
386 struct archive_entry
*entry
;
388 entry
= (struct archive_entry
*)malloc(sizeof(*entry
));
391 memset(entry
, 0, sizeof(*entry
));
396 * Functions for reading fields from an archive_entry.
400 archive_entry_atime(struct archive_entry
*entry
)
402 return (entry
->ae_stat
.aest_atime
);
406 archive_entry_atime_nsec(struct archive_entry
*entry
)
408 return (entry
->ae_stat
.aest_atime_nsec
);
412 archive_entry_ctime(struct archive_entry
*entry
)
414 return (entry
->ae_stat
.aest_ctime
);
418 archive_entry_ctime_nsec(struct archive_entry
*entry
)
420 return (entry
->ae_stat
.aest_ctime_nsec
);
424 archive_entry_dev(struct archive_entry
*entry
)
426 if (entry
->ae_stat
.aest_dev_is_broken_down
)
427 return ae_makedev(entry
->ae_stat
.aest_devmajor
,
428 entry
->ae_stat
.aest_devminor
);
430 return (entry
->ae_stat
.aest_dev
);
434 archive_entry_devmajor(struct archive_entry
*entry
)
436 if (entry
->ae_stat
.aest_dev_is_broken_down
)
437 return (entry
->ae_stat
.aest_devmajor
);
439 return major(entry
->ae_stat
.aest_dev
);
443 archive_entry_devminor(struct archive_entry
*entry
)
445 if (entry
->ae_stat
.aest_dev_is_broken_down
)
446 return (entry
->ae_stat
.aest_devminor
);
448 return minor(entry
->ae_stat
.aest_dev
);
452 archive_entry_filetype(struct archive_entry
*entry
)
454 return (AE_IFMT
& entry
->ae_stat
.aest_mode
);
458 archive_entry_fflags(struct archive_entry
*entry
,
459 unsigned long *set
, unsigned long *clear
)
461 *set
= entry
->ae_fflags_set
;
462 *clear
= entry
->ae_fflags_clear
;
466 * Note: if text was provided, this just returns that text. If you
467 * really need the text to be rebuilt in a canonical form, set the
468 * text, ask for the bitmaps, then set the bitmaps. (Setting the
469 * bitmaps clears any stored text.) This design is deliberate: if
470 * we're editing archives, we don't want to discard flags just because
471 * they aren't supported on the current system. The bitmap<->text
472 * conversions are platform-specific (see below).
475 archive_entry_fflags_text(struct archive_entry
*entry
)
480 f
= aes_get_mbs(&entry
->ae_fflags_text
);
484 if (entry
->ae_fflags_set
== 0 && entry
->ae_fflags_clear
== 0)
487 p
= ae_fflagstostr(entry
->ae_fflags_set
, entry
->ae_fflags_clear
);
491 aes_copy_mbs(&entry
->ae_fflags_text
, p
);
493 f
= aes_get_mbs(&entry
->ae_fflags_text
);
498 archive_entry_gid(struct archive_entry
*entry
)
500 return (entry
->ae_stat
.aest_gid
);
504 archive_entry_gname(struct archive_entry
*entry
)
506 return (aes_get_mbs(&entry
->ae_gname
));
510 archive_entry_gname_w(struct archive_entry
*entry
)
512 return (aes_get_wcs(&entry
->ae_gname
));
516 archive_entry_hardlink(struct archive_entry
*entry
)
518 return (aes_get_mbs(&entry
->ae_hardlink
));
522 archive_entry_hardlink_w(struct archive_entry
*entry
)
524 return (aes_get_wcs(&entry
->ae_hardlink
));
528 archive_entry_ino(struct archive_entry
*entry
)
530 return (entry
->ae_stat
.aest_ino
);
534 archive_entry_mode(struct archive_entry
*entry
)
536 return (entry
->ae_stat
.aest_mode
);
540 archive_entry_mtime(struct archive_entry
*entry
)
542 return (entry
->ae_stat
.aest_mtime
);
546 archive_entry_mtime_nsec(struct archive_entry
*entry
)
548 return (entry
->ae_stat
.aest_mtime_nsec
);
552 archive_entry_nlink(struct archive_entry
*entry
)
554 return (entry
->ae_stat
.aest_nlink
);
558 archive_entry_pathname(struct archive_entry
*entry
)
560 return (aes_get_mbs(&entry
->ae_pathname
));
564 archive_entry_pathname_w(struct archive_entry
*entry
)
566 return (aes_get_wcs(&entry
->ae_pathname
));
570 archive_entry_rdev(struct archive_entry
*entry
)
572 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
573 return ae_makedev(entry
->ae_stat
.aest_rdevmajor
,
574 entry
->ae_stat
.aest_rdevminor
);
576 return (entry
->ae_stat
.aest_rdev
);
580 archive_entry_rdevmajor(struct archive_entry
*entry
)
582 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
583 return (entry
->ae_stat
.aest_rdevmajor
);
585 return major(entry
->ae_stat
.aest_rdev
);
589 archive_entry_rdevminor(struct archive_entry
*entry
)
591 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
592 return (entry
->ae_stat
.aest_rdevminor
);
594 return minor(entry
->ae_stat
.aest_rdev
);
598 archive_entry_size(struct archive_entry
*entry
)
600 return (entry
->ae_stat
.aest_size
);
604 archive_entry_symlink(struct archive_entry
*entry
)
606 return (aes_get_mbs(&entry
->ae_symlink
));
610 archive_entry_symlink_w(struct archive_entry
*entry
)
612 return (aes_get_wcs(&entry
->ae_symlink
));
616 archive_entry_uid(struct archive_entry
*entry
)
618 return (entry
->ae_stat
.aest_uid
);
622 archive_entry_uname(struct archive_entry
*entry
)
624 return (aes_get_mbs(&entry
->ae_uname
));
628 archive_entry_uname_w(struct archive_entry
*entry
)
630 return (aes_get_wcs(&entry
->ae_uname
));
634 * Functions to set archive_entry properties.
638 archive_entry_set_filetype(struct archive_entry
*entry
, unsigned int type
)
640 entry
->stat_valid
= 0;
641 entry
->ae_stat
.aest_mode
&= ~AE_IFMT
;
642 entry
->ae_stat
.aest_mode
|= AE_IFMT
& type
;
646 archive_entry_set_fflags(struct archive_entry
*entry
,
647 unsigned long set
, unsigned long clear
)
649 aes_clean(&entry
->ae_fflags_text
);
650 entry
->ae_fflags_set
= set
;
651 entry
->ae_fflags_clear
= clear
;
655 archive_entry_copy_fflags_text_w(struct archive_entry
*entry
,
656 const wchar_t *flags
)
658 aes_copy_wcs(&entry
->ae_fflags_text
, flags
);
659 return (ae_wcstofflags(flags
,
660 &entry
->ae_fflags_set
, &entry
->ae_fflags_clear
));
664 archive_entry_set_gid(struct archive_entry
*entry
, gid_t g
)
666 entry
->stat_valid
= 0;
667 entry
->ae_stat
.aest_gid
= g
;
671 archive_entry_set_gname(struct archive_entry
*entry
, const char *name
)
673 aes_set_mbs(&entry
->ae_gname
, name
);
677 archive_entry_copy_gname(struct archive_entry
*entry
, const char *name
)
679 aes_copy_mbs(&entry
->ae_gname
, name
);
683 archive_entry_copy_gname_w(struct archive_entry
*entry
, const wchar_t *name
)
685 aes_copy_wcs(&entry
->ae_gname
, name
);
689 archive_entry_set_ino(struct archive_entry
*entry
, unsigned long ino
)
691 entry
->stat_valid
= 0;
692 entry
->ae_stat
.aest_ino
= ino
;
696 archive_entry_set_hardlink(struct archive_entry
*entry
, const char *target
)
698 aes_set_mbs(&entry
->ae_hardlink
, target
);
702 archive_entry_copy_hardlink(struct archive_entry
*entry
, const char *target
)
704 aes_copy_mbs(&entry
->ae_hardlink
, target
);
708 archive_entry_copy_hardlink_w(struct archive_entry
*entry
, const wchar_t *target
)
710 aes_copy_wcs(&entry
->ae_hardlink
, target
);
714 archive_entry_set_atime(struct archive_entry
*entry
, time_t t
, long ns
)
716 entry
->stat_valid
= 0;
717 entry
->ae_stat
.aest_atime
= t
;
718 entry
->ae_stat
.aest_atime_nsec
= ns
;
722 archive_entry_set_ctime(struct archive_entry
*entry
, time_t t
, long ns
)
724 entry
->stat_valid
= 0;
725 entry
->ae_stat
.aest_ctime
= t
;
726 entry
->ae_stat
.aest_ctime_nsec
= ns
;
730 archive_entry_set_dev(struct archive_entry
*entry
, dev_t d
)
732 entry
->stat_valid
= 0;
733 entry
->ae_stat
.aest_dev_is_broken_down
= 0;
734 entry
->ae_stat
.aest_dev
= d
;
738 archive_entry_set_devmajor(struct archive_entry
*entry
, dev_t m
)
740 entry
->stat_valid
= 0;
741 entry
->ae_stat
.aest_dev_is_broken_down
= 1;
742 entry
->ae_stat
.aest_devmajor
= m
;
746 archive_entry_set_devminor(struct archive_entry
*entry
, dev_t m
)
748 entry
->stat_valid
= 0;
749 entry
->ae_stat
.aest_dev_is_broken_down
= 1;
750 entry
->ae_stat
.aest_devminor
= m
;
753 /* Set symlink if symlink is already set, else set hardlink. */
755 archive_entry_set_link(struct archive_entry
*entry
, const char *target
)
757 if (entry
->ae_symlink
.aes_mbs
!= NULL
||
758 entry
->ae_symlink
.aes_wcs
!= NULL
)
759 aes_set_mbs(&entry
->ae_symlink
, target
);
761 aes_set_mbs(&entry
->ae_hardlink
, target
);
764 /* Set symlink if symlink is already set, else set hardlink. */
766 archive_entry_copy_link(struct archive_entry
*entry
, const char *target
)
768 if (entry
->ae_symlink
.aes_mbs
!= NULL
||
769 entry
->ae_symlink
.aes_wcs
!= NULL
)
770 aes_copy_mbs(&entry
->ae_symlink
, target
);
772 aes_copy_mbs(&entry
->ae_hardlink
, target
);
775 /* Set symlink if symlink is already set, else set hardlink. */
777 archive_entry_copy_link_w(struct archive_entry
*entry
, const wchar_t *target
)
779 if (entry
->ae_symlink
.aes_mbs
!= NULL
||
780 entry
->ae_symlink
.aes_wcs
!= NULL
)
781 aes_copy_wcs(&entry
->ae_symlink
, target
);
783 aes_copy_wcs(&entry
->ae_hardlink
, target
);
787 archive_entry_set_mode(struct archive_entry
*entry
, mode_t m
)
789 entry
->stat_valid
= 0;
790 entry
->ae_stat
.aest_mode
= m
;
794 archive_entry_set_mtime(struct archive_entry
*entry
, time_t m
, long ns
)
796 entry
->stat_valid
= 0;
797 entry
->ae_stat
.aest_mtime
= m
;
798 entry
->ae_stat
.aest_mtime_nsec
= ns
;
802 archive_entry_set_nlink(struct archive_entry
*entry
, unsigned int nlink
)
804 entry
->stat_valid
= 0;
805 entry
->ae_stat
.aest_nlink
= nlink
;
809 archive_entry_set_pathname(struct archive_entry
*entry
, const char *name
)
811 aes_set_mbs(&entry
->ae_pathname
, name
);
815 archive_entry_copy_pathname(struct archive_entry
*entry
, const char *name
)
817 aes_copy_mbs(&entry
->ae_pathname
, name
);
821 archive_entry_copy_pathname_w(struct archive_entry
*entry
, const wchar_t *name
)
823 aes_copy_wcs(&entry
->ae_pathname
, name
);
827 archive_entry_set_perm(struct archive_entry
*entry
, mode_t p
)
829 entry
->stat_valid
= 0;
830 entry
->ae_stat
.aest_mode
&= AE_IFMT
;
831 entry
->ae_stat
.aest_mode
|= ~AE_IFMT
& p
;
835 archive_entry_set_rdev(struct archive_entry
*entry
, dev_t m
)
837 entry
->stat_valid
= 0;
838 entry
->ae_stat
.aest_rdev
= m
;
839 entry
->ae_stat
.aest_rdev_is_broken_down
= 0;
843 archive_entry_set_rdevmajor(struct archive_entry
*entry
, dev_t m
)
845 entry
->stat_valid
= 0;
846 entry
->ae_stat
.aest_rdev_is_broken_down
= 1;
847 entry
->ae_stat
.aest_rdevmajor
= m
;
851 archive_entry_set_rdevminor(struct archive_entry
*entry
, dev_t m
)
853 entry
->stat_valid
= 0;
854 entry
->ae_stat
.aest_rdev_is_broken_down
= 1;
855 entry
->ae_stat
.aest_rdevminor
= m
;
859 archive_entry_set_size(struct archive_entry
*entry
, int64_t s
)
861 entry
->stat_valid
= 0;
862 entry
->ae_stat
.aest_size
= s
;
866 archive_entry_set_symlink(struct archive_entry
*entry
, const char *linkname
)
868 aes_set_mbs(&entry
->ae_symlink
, linkname
);
872 archive_entry_copy_symlink(struct archive_entry
*entry
, const char *linkname
)
874 aes_copy_mbs(&entry
->ae_symlink
, linkname
);
878 archive_entry_copy_symlink_w(struct archive_entry
*entry
, const wchar_t *linkname
)
880 aes_copy_wcs(&entry
->ae_symlink
, linkname
);
884 archive_entry_set_uid(struct archive_entry
*entry
, uid_t u
)
886 entry
->stat_valid
= 0;
887 entry
->ae_stat
.aest_uid
= u
;
891 archive_entry_set_uname(struct archive_entry
*entry
, const char *name
)
893 aes_set_mbs(&entry
->ae_uname
, name
);
897 archive_entry_copy_uname(struct archive_entry
*entry
, const char *name
)
899 aes_copy_mbs(&entry
->ae_uname
, name
);
903 archive_entry_copy_uname_w(struct archive_entry
*entry
, const wchar_t *name
)
905 aes_copy_wcs(&entry
->ae_uname
, name
);
909 * ACL management. The following would, of course, be a lot simpler
910 * if: 1) the last draft of POSIX.1e were a really thorough and
911 * complete standard that addressed the needs of ACL archiving and 2)
912 * everyone followed it faithfully. Alas, neither is true, so the
913 * following is a lot more complex than might seem necessary to the
918 archive_entry_acl_clear(struct archive_entry
*entry
)
922 while (entry
->acl_head
!= NULL
) {
923 ap
= entry
->acl_head
->next
;
924 aes_clean(&entry
->acl_head
->name
);
925 free(entry
->acl_head
);
926 entry
->acl_head
= ap
;
928 if (entry
->acl_text_w
!= NULL
) {
929 free(entry
->acl_text_w
);
930 entry
->acl_text_w
= NULL
;
933 entry
->acl_state
= 0; /* Not counting. */
937 * Add a single ACL entry to the internal list of ACL data.
940 archive_entry_acl_add_entry(struct archive_entry
*entry
,
941 int type
, int permset
, int tag
, int id
, const char *name
)
945 if (acl_special(entry
, type
, permset
, tag
) == 0)
947 ap
= acl_new_entry(entry
, type
, permset
, tag
, id
);
952 if (name
!= NULL
&& *name
!= '\0')
953 aes_copy_mbs(&ap
->name
, name
);
955 aes_clean(&ap
->name
);
959 * As above, but with a wide-character name.
962 archive_entry_acl_add_entry_w(struct archive_entry
*entry
,
963 int type
, int permset
, int tag
, int id
, const wchar_t *name
)
965 archive_entry_acl_add_entry_w_len(entry
, type
, permset
, tag
, id
, name
, wcslen(name
));
969 archive_entry_acl_add_entry_w_len(struct archive_entry
*entry
,
970 int type
, int permset
, int tag
, int id
, const wchar_t *name
, size_t len
)
974 if (acl_special(entry
, type
, permset
, tag
) == 0)
976 ap
= acl_new_entry(entry
, type
, permset
, tag
, id
);
981 if (name
!= NULL
&& *name
!= L
'\0' && len
> 0)
982 aes_copy_wcs_len(&ap
->name
, name
, len
);
984 aes_clean(&ap
->name
);
988 * If this ACL entry is part of the standard POSIX permissions set,
989 * store the permissions in the stat structure and return zero.
992 acl_special(struct archive_entry
*entry
, int type
, int permset
, int tag
)
994 if (type
== ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) {
996 case ARCHIVE_ENTRY_ACL_USER_OBJ
:
997 entry
->ae_stat
.aest_mode
&= ~0700;
998 entry
->ae_stat
.aest_mode
|= (permset
& 7) << 6;
1000 case ARCHIVE_ENTRY_ACL_GROUP_OBJ
:
1001 entry
->ae_stat
.aest_mode
&= ~0070;
1002 entry
->ae_stat
.aest_mode
|= (permset
& 7) << 3;
1004 case ARCHIVE_ENTRY_ACL_OTHER
:
1005 entry
->ae_stat
.aest_mode
&= ~0007;
1006 entry
->ae_stat
.aest_mode
|= permset
& 7;
1014 * Allocate and populate a new ACL entry with everything but the
1017 static struct ae_acl
*
1018 acl_new_entry(struct archive_entry
*entry
,
1019 int type
, int permset
, int tag
, int id
)
1023 if (type
!= ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&&
1024 type
!= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
)
1026 if (entry
->acl_text_w
!= NULL
) {
1027 free(entry
->acl_text_w
);
1028 entry
->acl_text_w
= NULL
;
1031 /* XXX TODO: More sanity-checks on the arguments XXX */
1033 /* If there's a matching entry already in the list, overwrite it. */
1034 for (ap
= entry
->acl_head
; ap
!= NULL
; ap
= ap
->next
) {
1035 if (ap
->type
== type
&& ap
->tag
== tag
&& ap
->id
== id
) {
1036 ap
->permset
= permset
;
1041 /* Add a new entry to the list. */
1042 ap
= (struct ae_acl
*)malloc(sizeof(*ap
));
1045 memset(ap
, 0, sizeof(*ap
));
1046 ap
->next
= entry
->acl_head
;
1047 entry
->acl_head
= ap
;
1051 ap
->permset
= permset
;
1056 * Return a count of entries matching "want_type".
1059 archive_entry_acl_count(struct archive_entry
*entry
, int want_type
)
1065 ap
= entry
->acl_head
;
1066 while (ap
!= NULL
) {
1067 if ((ap
->type
& want_type
) != 0)
1072 if (count
> 0 && ((want_type
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0))
1078 * Prepare for reading entries from the ACL data. Returns a count
1079 * of entries matching "want_type", or zero if there are no
1080 * non-extended ACL entries of that type.
1083 archive_entry_acl_reset(struct archive_entry
*entry
, int want_type
)
1087 count
= archive_entry_acl_count(entry
, want_type
);
1090 * If the only entries are the three standard ones,
1091 * then don't return any ACL data. (In this case,
1092 * client can just use chmod(2) to set permissions.)
1094 if ((want_type
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0)
1100 entry
->acl_state
= ARCHIVE_ENTRY_ACL_USER_OBJ
;
1102 entry
->acl_state
= 0;
1103 entry
->acl_p
= entry
->acl_head
;
1108 * Return the next ACL entry in the list. Fake entries for the
1109 * standard permissions and include them in the returned list.
1113 archive_entry_acl_next(struct archive_entry
*entry
, int want_type
, int *type
,
1114 int *permset
, int *tag
, int *id
, const char **name
)
1120 * The acl_state is either zero (no entries available), -1
1121 * (reading from list), or an entry type (retrieve that type
1122 * from ae_stat.aest_mode).
1124 if (entry
->acl_state
== 0)
1125 return (ARCHIVE_WARN
);
1127 /* The first three access entries are special. */
1128 if ((want_type
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0) {
1129 switch (entry
->acl_state
) {
1130 case ARCHIVE_ENTRY_ACL_USER_OBJ
:
1131 *permset
= (entry
->ae_stat
.aest_mode
>> 6) & 7;
1132 *type
= ARCHIVE_ENTRY_ACL_TYPE_ACCESS
;
1133 *tag
= ARCHIVE_ENTRY_ACL_USER_OBJ
;
1134 entry
->acl_state
= ARCHIVE_ENTRY_ACL_GROUP_OBJ
;
1135 return (ARCHIVE_OK
);
1136 case ARCHIVE_ENTRY_ACL_GROUP_OBJ
:
1137 *permset
= (entry
->ae_stat
.aest_mode
>> 3) & 7;
1138 *type
= ARCHIVE_ENTRY_ACL_TYPE_ACCESS
;
1139 *tag
= ARCHIVE_ENTRY_ACL_GROUP_OBJ
;
1140 entry
->acl_state
= ARCHIVE_ENTRY_ACL_OTHER
;
1141 return (ARCHIVE_OK
);
1142 case ARCHIVE_ENTRY_ACL_OTHER
:
1143 *permset
= entry
->ae_stat
.aest_mode
& 7;
1144 *type
= ARCHIVE_ENTRY_ACL_TYPE_ACCESS
;
1145 *tag
= ARCHIVE_ENTRY_ACL_OTHER
;
1146 entry
->acl_state
= -1;
1147 entry
->acl_p
= entry
->acl_head
;
1148 return (ARCHIVE_OK
);
1154 while (entry
->acl_p
!= NULL
&& (entry
->acl_p
->type
& want_type
) == 0)
1155 entry
->acl_p
= entry
->acl_p
->next
;
1156 if (entry
->acl_p
== NULL
) {
1157 entry
->acl_state
= 0;
1158 return (ARCHIVE_EOF
); /* End of ACL entries. */
1160 *type
= entry
->acl_p
->type
;
1161 *permset
= entry
->acl_p
->permset
;
1162 *tag
= entry
->acl_p
->tag
;
1163 *id
= entry
->acl_p
->id
;
1164 *name
= aes_get_mbs(&entry
->acl_p
->name
);
1165 entry
->acl_p
= entry
->acl_p
->next
;
1166 return (ARCHIVE_OK
);
1170 * Generate a text version of the ACL. The flags parameter controls
1171 * the style of the generated ACL.
1174 archive_entry_acl_text_w(struct archive_entry
*entry
, int flags
)
1178 const wchar_t *wname
;
1179 const wchar_t *prefix
;
1185 if (entry
->acl_text_w
!= NULL
) {
1186 free (entry
->acl_text_w
);
1187 entry
->acl_text_w
= NULL
;
1193 ap
= entry
->acl_head
;
1194 while (ap
!= NULL
) {
1195 if ((ap
->type
& flags
) != 0) {
1197 if ((flags
& ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
) &&
1198 (ap
->type
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
))
1199 length
+= 8; /* "default:" */
1200 length
+= 5; /* tag name */
1201 length
+= 1; /* colon */
1202 wname
= aes_get_wcs(&ap
->name
);
1204 length
+= wcslen(wname
);
1206 length
+= sizeof(uid_t
) * 3 + 1;
1207 length
++; /* colon */
1208 length
+= 3; /* rwx */
1209 length
+= 1; /* colon */
1210 length
+= max(sizeof(uid_t
), sizeof(gid_t
)) * 3 + 1;
1211 length
++; /* newline */
1216 if (count
> 0 && ((flags
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0)) {
1217 length
+= 10; /* "user::rwx\n" */
1218 length
+= 11; /* "group::rwx\n" */
1219 length
+= 11; /* "other::rwx\n" */
1225 /* Now, allocate the string and actually populate it. */
1226 wp
= entry
->acl_text_w
= (wchar_t *)malloc(length
* sizeof(wchar_t));
1228 __archive_errx(1, "No memory to generate the text version of the ACL");
1230 if ((flags
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0) {
1231 append_entry_w(&wp
, NULL
, ARCHIVE_ENTRY_ACL_USER_OBJ
, NULL
,
1232 entry
->ae_stat
.aest_mode
& 0700, -1);
1234 append_entry_w(&wp
, NULL
, ARCHIVE_ENTRY_ACL_GROUP_OBJ
, NULL
,
1235 entry
->ae_stat
.aest_mode
& 0070, -1);
1237 append_entry_w(&wp
, NULL
, ARCHIVE_ENTRY_ACL_OTHER
, NULL
,
1238 entry
->ae_stat
.aest_mode
& 0007, -1);
1241 ap
= entry
->acl_head
;
1242 while (ap
!= NULL
) {
1243 if ((ap
->type
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS
) != 0) {
1244 wname
= aes_get_wcs(&ap
->name
);
1246 if (flags
& ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
)
1250 append_entry_w(&wp
, NULL
, ap
->tag
, wname
,
1259 if ((flags
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
) != 0) {
1260 if (flags
& ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
)
1261 prefix
= L
"default:";
1264 ap
= entry
->acl_head
;
1266 while (ap
!= NULL
) {
1267 if ((ap
->type
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
) != 0) {
1268 wname
= aes_get_wcs(&ap
->name
);
1271 if (flags
& ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
)
1275 append_entry_w(&wp
, prefix
, ap
->tag
,
1276 wname
, ap
->permset
, id
);
1283 return (entry
->acl_text_w
);
1287 append_id_w(wchar_t **wp
, int id
)
1292 append_id_w(wp
, id
/ 10);
1293 *(*wp
)++ = L
"0123456789"[id
% 10];
1297 append_entry_w(wchar_t **wp
, const wchar_t *prefix
, int tag
,
1298 const wchar_t *wname
, int perm
, int id
)
1300 if (prefix
!= NULL
) {
1301 wcscpy(*wp
, prefix
);
1305 case ARCHIVE_ENTRY_ACL_USER_OBJ
:
1309 case ARCHIVE_ENTRY_ACL_USER
:
1310 wcscpy(*wp
, L
"user");
1312 case ARCHIVE_ENTRY_ACL_GROUP_OBJ
:
1316 case ARCHIVE_ENTRY_ACL_GROUP
:
1317 wcscpy(*wp
, L
"group");
1319 case ARCHIVE_ENTRY_ACL_MASK
:
1320 wcscpy(*wp
, L
"mask");
1324 case ARCHIVE_ENTRY_ACL_OTHER
:
1325 wcscpy(*wp
, L
"other");
1332 if (wname
!= NULL
) {
1335 } else if (tag
== ARCHIVE_ENTRY_ACL_USER
1336 || tag
== ARCHIVE_ENTRY_ACL_GROUP
) {
1337 append_id_w(wp
, id
);
1341 *(*wp
)++ = (perm
& 0444) ? L
'r' : L
'-';
1342 *(*wp
)++ = (perm
& 0222) ? L
'w' : L
'-';
1343 *(*wp
)++ = (perm
& 0111) ? L
'x' : L
'-';
1346 append_id_w(wp
, id
);
1352 * Parse a textual ACL. This automatically recognizes and supports
1353 * extensions described above. The 'type' argument is used to
1354 * indicate the type that should be used for any entries not
1355 * explicitly marked as "default:".
1358 __archive_entry_acl_parse_w(struct archive_entry
*entry
,
1359 const wchar_t *text
, int default_type
)
1362 const wchar_t *start
;
1367 int type
, tag
, permset
, id
;
1371 while (text
!= NULL
&& *text
!= L
'\0') {
1373 * Parse the fields out of the next entry,
1374 * advance 'text' to start of next entry.
1378 const wchar_t *start
, *end
;
1379 next_field_w(&text
, &start
, &end
, &sep
);
1381 field
[fields
].start
= start
;
1382 field
[fields
].end
= end
;
1385 } while (sep
== L
':');
1388 return (ARCHIVE_WARN
);
1390 /* Check for a numeric ID in field 1 or 3. */
1392 isint_w(field
[1].start
, field
[1].end
, &id
);
1393 /* Field 3 is optional. */
1394 if (id
== -1 && fields
> 3)
1395 isint_w(field
[3].start
, field
[3].end
, &id
);
1397 /* Parse the permissions from field 2. */
1400 while (p
< field
[2].end
) {
1403 permset
|= ARCHIVE_ENTRY_ACL_READ
;
1406 permset
|= ARCHIVE_ENTRY_ACL_WRITE
;
1409 permset
|= ARCHIVE_ENTRY_ACL_EXECUTE
;
1414 return (ARCHIVE_WARN
);
1419 * Solaris extension: "defaultuser::rwx" is the
1420 * default ACL corresponding to "user::rwx", etc.
1422 if (field
[0].end
-field
[0].start
> 7
1423 && wmemcmp(field
[0].start
, L
"default", 7) == 0) {
1424 type
= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
;
1425 field
[0].start
+= 7;
1427 type
= default_type
;
1429 if (prefix_w(field
[0].start
, field
[0].end
, L
"user")) {
1430 if (id
!= -1 || field
[1].start
< field
[1].end
)
1431 tag
= ARCHIVE_ENTRY_ACL_USER
;
1433 tag
= ARCHIVE_ENTRY_ACL_USER_OBJ
;
1434 } else if (prefix_w(field
[0].start
, field
[0].end
, L
"group")) {
1435 if (id
!= -1 || field
[1].start
< field
[1].end
)
1436 tag
= ARCHIVE_ENTRY_ACL_GROUP
;
1438 tag
= ARCHIVE_ENTRY_ACL_GROUP_OBJ
;
1439 } else if (prefix_w(field
[0].start
, field
[0].end
, L
"other")) {
1440 if (id
!= -1 || field
[1].start
< field
[1].end
)
1441 return (ARCHIVE_WARN
);
1442 tag
= ARCHIVE_ENTRY_ACL_OTHER
;
1443 } else if (prefix_w(field
[0].start
, field
[0].end
, L
"mask")) {
1444 if (id
!= -1 || field
[1].start
< field
[1].end
)
1445 return (ARCHIVE_WARN
);
1446 tag
= ARCHIVE_ENTRY_ACL_MASK
;
1448 return (ARCHIVE_WARN
);
1450 /* Add entry to the internal list. */
1451 archive_entry_acl_add_entry_w_len(entry
, type
, permset
,
1452 tag
, id
, field
[1].start
, field
[1].end
- field
[1].start
);
1454 return (ARCHIVE_OK
);
1458 * extended attribute handling
1462 archive_entry_xattr_clear(struct archive_entry
*entry
)
1464 struct ae_xattr
*xp
;
1466 while (entry
->xattr_head
!= NULL
) {
1467 xp
= entry
->xattr_head
->next
;
1468 free(entry
->xattr_head
->name
);
1469 free(entry
->xattr_head
->value
);
1470 free(entry
->xattr_head
);
1471 entry
->xattr_head
= xp
;
1474 entry
->xattr_head
= NULL
;
1478 archive_entry_xattr_add_entry(struct archive_entry
*entry
,
1479 const char *name
, const void *value
, size_t size
)
1481 struct ae_xattr
*xp
;
1483 for (xp
= entry
->xattr_head
; xp
!= NULL
; xp
= xp
->next
)
1486 if ((xp
= (struct ae_xattr
*)malloc(sizeof(struct ae_xattr
))) == NULL
)
1490 xp
->name
= strdup(name
);
1491 if ((xp
->value
= malloc(size
)) != NULL
) {
1492 memcpy(xp
->value
, value
, size
);
1497 xp
->next
= entry
->xattr_head
;
1498 entry
->xattr_head
= xp
;
1503 * returns number of the extended attribute entries
1506 archive_entry_xattr_count(struct archive_entry
*entry
)
1508 struct ae_xattr
*xp
;
1511 for (xp
= entry
->xattr_head
; xp
!= NULL
; xp
= xp
->next
)
1518 archive_entry_xattr_reset(struct archive_entry
* entry
)
1520 entry
->xattr_p
= entry
->xattr_head
;
1522 return archive_entry_xattr_count(entry
);
1526 archive_entry_xattr_next(struct archive_entry
* entry
,
1527 const char **name
, const void **value
, size_t *size
)
1529 if (entry
->xattr_p
) {
1530 *name
= entry
->xattr_p
->name
;
1531 *value
= entry
->xattr_p
->value
;
1532 *size
= entry
->xattr_p
->size
;
1534 entry
->xattr_p
= entry
->xattr_p
->next
;
1536 return (ARCHIVE_OK
);
1541 return (ARCHIVE_WARN
);
1546 * end of xattr handling
1550 * Parse a string to a positive decimal integer. Returns true if
1551 * the string is non-empty and consists only of decimal digits,
1555 isint_w(const wchar_t *start
, const wchar_t *end
, int *result
)
1560 while (start
< end
) {
1561 if (*start
< '0' || *start
> '9')
1563 if (n
> (INT_MAX
/ 10))
1576 * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
1577 * to point to just after the separator. *start points to the first
1578 * character of the matched text and *end just after the last
1579 * character of the matched identifier. In particular *end - *start
1580 * is the length of the field body, not including leading or trailing
1584 next_field_w(const wchar_t **wp
, const wchar_t **start
,
1585 const wchar_t **end
, wchar_t *sep
)
1587 /* Skip leading whitespace to find start of field. */
1588 while (**wp
== L
' ' || **wp
== L
'\t' || **wp
== L
'\n') {
1593 /* Scan for the separator. */
1594 while (**wp
!= L
'\0' && **wp
!= L
',' && **wp
!= L
':' &&
1600 /* Trim trailing whitespace to locate end of field. */
1602 while (**end
== L
' ' || **end
== L
'\t' || **end
== L
'\n') {
1607 /* Adjust scanner location. */
1613 * Return true if the characters [start...end) are a prefix of 'test'.
1614 * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
1617 prefix_w(const wchar_t *start
, const wchar_t *end
, const wchar_t *test
)
1622 if (*start
++ != *test
++)
1625 while (start
< end
&& *start
++ == *test
++)
1636 * Following code is modified from UC Berkeley sources, and
1637 * is subject to the following copyright notice.
1641 * Copyright (c) 1993
1642 * The Regents of the University of California. All rights reserved.
1644 * Redistribution and use in source and binary forms, with or without
1645 * modification, are permitted provided that the following conditions
1647 * 1. Redistributions of source code must retain the above copyright
1648 * notice, this list of conditions and the following disclaimer.
1649 * 2. Redistributions in binary form must reproduce the above copyright
1650 * notice, this list of conditions and the following disclaimer in the
1651 * documentation and/or other materials provided with the distribution.
1652 * 4. Neither the name of the University nor the names of its contributors
1653 * may be used to endorse or promote products derived from this software
1654 * without specific prior written permission.
1656 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1657 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1658 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1659 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1660 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1661 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1662 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1663 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1664 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1665 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1669 static struct flag
{
1671 const wchar_t *wname
;
1673 unsigned long clear
;
1675 /* Preferred (shorter) names per flag first, all prefixed by "no" */
1677 { "nosappnd", L
"nosappnd", SF_APPEND
, 0 },
1678 { "nosappend", L
"nosappend", SF_APPEND
, 0 },
1680 #ifdef EXT2_APPEND_FL /* 'a' */
1681 { "nosappnd", L
"nosappnd", EXT2_APPEND_FL
, 0 },
1682 { "nosappend", L
"nosappend", EXT2_APPEND_FL
, 0 },
1685 { "noarch", L
"noarch", SF_ARCHIVED
, 0 },
1686 { "noarchived", L
"noarchived", SF_ARCHIVED
, 0 },
1689 { "noschg", L
"noschg", SF_IMMUTABLE
, 0 },
1690 { "noschange", L
"noschange", SF_IMMUTABLE
, 0 },
1691 { "nosimmutable", L
"nosimmutable", SF_IMMUTABLE
, 0 },
1693 #ifdef EXT2_IMMUTABLE_FL /* 'i' */
1694 { "noschg", L
"noschg", EXT2_IMMUTABLE_FL
, 0 },
1695 { "noschange", L
"noschange", EXT2_IMMUTABLE_FL
, 0 },
1696 { "nosimmutable", L
"nosimmutable", EXT2_IMMUTABLE_FL
, 0 },
1699 { "nosunlnk", L
"nosunlnk", SF_NOUNLINK
, 0 },
1700 { "nosunlink", L
"nosunlink", SF_NOUNLINK
, 0 },
1703 { "nosnapshot", L
"nosnapshot", SF_SNAPSHOT
, 0 },
1706 { "nouappnd", L
"nouappnd", UF_APPEND
, 0 },
1707 { "nouappend", L
"nouappend", UF_APPEND
, 0 },
1710 { "nouchg", L
"nouchg", UF_IMMUTABLE
, 0 },
1711 { "nouchange", L
"nouchange", UF_IMMUTABLE
, 0 },
1712 { "nouimmutable", L
"nouimmutable", UF_IMMUTABLE
, 0 },
1715 { "nodump", L
"nodump", 0, UF_NODUMP
},
1717 #ifdef EXT2_NODUMP_FL /* 'd' */
1718 { "nodump", L
"nodump", 0, EXT2_NODUMP_FL
},
1721 { "noopaque", L
"noopaque", UF_OPAQUE
, 0 },
1724 { "nouunlnk", L
"nouunlnk", UF_NOUNLINK
, 0 },
1725 { "nouunlink", L
"nouunlink", UF_NOUNLINK
, 0 },
1727 #ifdef EXT2_COMPR_FL /* 'c' */
1728 { "nocompress", L
"nocompress", EXT2_COMPR_FL
, 0 },
1731 #ifdef EXT2_NOATIME_FL /* 'A' */
1732 { "noatime", L
"noatime", 0, EXT2_NOATIME_FL
},
1734 { NULL
, NULL
, 0, 0 }
1739 * Convert file flags to a comma-separated string. If no flags
1740 * are set, return the empty string.
1743 ae_fflagstostr(unsigned long bitset
, unsigned long bitclear
)
1751 bits
= bitset
| bitclear
;
1753 for (flag
= flags
; flag
->name
!= NULL
; flag
++)
1754 if (bits
& (flag
->set
| flag
->clear
)) {
1755 length
+= strlen(flag
->name
) + 1;
1756 bits
&= ~(flag
->set
| flag
->clear
);
1761 string
= (char *)malloc(length
);
1766 for (flag
= flags
; flag
->name
!= NULL
; flag
++) {
1767 if (bitset
& flag
->set
|| bitclear
& flag
->clear
) {
1768 sp
= flag
->name
+ 2;
1769 } else if (bitset
& flag
->clear
|| bitclear
& flag
->set
) {
1773 bitset
&= ~(flag
->set
| flag
->clear
);
1774 bitclear
&= ~(flag
->set
| flag
->clear
);
1777 while ((*dp
++ = *sp
++) != '\0')
1788 * Take string of arguments and return file flags. This
1789 * version works a little differently than strtofflags(3).
1790 * In particular, it always tests every token, skipping any
1791 * unrecognized tokens. It returns a pointer to the first
1792 * unrecognized token, or NULL if every token was recognized.
1793 * This version is also const-correct and does not modify the
1797 ae_wcstofflags(const wchar_t *s
, unsigned long *setp
, unsigned long *clrp
)
1799 const wchar_t *start
, *end
;
1801 unsigned long set
, clear
;
1802 const wchar_t *failed
;
1807 /* Find start of first token. */
1808 while (*start
== L
'\t' || *start
== L
' ' || *start
== L
',')
1810 while (*start
!= L
'\0') {
1811 /* Locate end of token. */
1813 while (*end
!= L
'\0' && *end
!= L
'\t' &&
1814 *end
!= L
' ' && *end
!= L
',')
1816 for (flag
= flags
; flag
->wname
!= NULL
; flag
++) {
1817 if (wmemcmp(start
, flag
->wname
, end
- start
) == 0) {
1818 /* Matched "noXXXX", so reverse the sense. */
1822 } else if (wmemcmp(start
, flag
->wname
+ 2, end
- start
)
1824 /* Matched "XXXX", so don't reverse. */
1826 clear
|= flag
->clear
;
1830 /* Ignore unknown flag names. */
1831 if (flag
->wname
== NULL
&& failed
== NULL
)
1834 /* Find start of next token. */
1836 while (*start
== L
'\t' || *start
== L
' ' || *start
== L
',')
1846 /* Return location of first failure. */
1854 main(int argc
, char **argv
)
1856 struct archive_entry
*entry
= archive_entry_new();
1857 unsigned long set
, clear
;
1858 const wchar_t *remainder
;
1860 remainder
= archive_entry_copy_fflags_text_w(entry
, L
"nosappnd dump archive,,,,,,,");
1861 archive_entry_fflags(entry
, &set
, &clear
);
1863 wprintf(L
"set=0x%lX clear=0x%lX remainder='%ls'\n", set
, clear
, remainder
);
1865 wprintf(L
"new flags='%s'\n", archive_entry_fflags_text(entry
));