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: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $");
29 #ifdef HAVE_SYS_STAT_H
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
36 #include <sys/mkdev.h>
38 #elif MAJOR_IN_SYSMACROS
39 #include <sys/sysmacros.h>
48 #ifdef HAVE_LINUX_FS_H
49 #include <linux/fs.h> /* for Linux file flags */
52 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
53 * As the include guards don't agree, the order of include is important.
55 #ifdef HAVE_LINUX_EXT2_FS_H
56 #include <linux/ext2_fs.h> /* for Linux file flags */
58 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
59 #include <ext2fs/ext2_fs.h> /* for Linux file flags */
74 #include "archive_acl_private.h"
75 #include "archive_entry.h"
76 #include "archive_entry_locale.h"
77 #include "archive_private.h"
78 #include "archive_entry_private.h"
80 #if !defined(HAVE_MAJOR) && !defined(major)
81 /* Replacement for major/minor/makedev. */
82 #define major(x) ((int)(0x00ff & ((x) >> 8)))
83 #define minor(x) ((int)(0xffff00ff & (x)))
84 #define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
87 /* Play games to come up with a suitable makedev() definition. */
90 #include <sys/netmgr.h>
91 #define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
93 /* There's a "makedev" macro. */
94 #define ae_makedev(maj, min) makedev((maj), (min))
95 #elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
97 #define ae_makedev(maj, min) mkdev((maj), (min))
99 /* There's a "makedev" function. */
100 #define ae_makedev(maj, min) makedev((maj), (min))
104 * This adjustment is needed to support the following idiom for adding
105 * 1000ns to the stored time:
106 * archive_entry_set_atime(archive_entry_atime(),
107 * archive_entry_atime_nsec() + 1000)
108 * The additional if() here compensates for ambiguity in the C standard,
109 * which permits two possible interpretations of a % b when a is negative.
111 #define FIX_NS(t,ns) \
113 t += ns / 1000000000; \
115 if (ns < 0) { --t; ns += 1000000000; } \
118 static char * ae_fflagstostr(unsigned long bitset
, unsigned long bitclear
);
119 static const wchar_t *ae_wcstofflags(const wchar_t *stringp
,
120 unsigned long *setp
, unsigned long *clrp
);
121 static const char *ae_strtofflags(const char *stringp
,
122 unsigned long *setp
, unsigned long *clrp
);
125 static wchar_t * wcscpy(wchar_t *s1
, const wchar_t *s2
)
128 while ((*s1
= *s2
) != L
'\0')
134 static size_t wcslen(const wchar_t *s
)
136 const wchar_t *p
= s
;
143 /* Good enough for simple equality testing, but not for sorting. */
144 #define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))
147 /****************************************************************************
151 ****************************************************************************/
153 struct archive_entry
*
154 archive_entry_clear(struct archive_entry
*entry
)
158 archive_mstring_clean(&entry
->ae_fflags_text
);
159 archive_mstring_clean(&entry
->ae_gname
);
160 archive_mstring_clean(&entry
->ae_hardlink
);
161 archive_mstring_clean(&entry
->ae_pathname
);
162 archive_mstring_clean(&entry
->ae_sourcepath
);
163 archive_mstring_clean(&entry
->ae_symlink
);
164 archive_mstring_clean(&entry
->ae_uname
);
165 archive_entry_copy_mac_metadata(entry
, NULL
, 0);
166 archive_acl_clear(&entry
->acl
);
167 archive_entry_xattr_clear(entry
);
168 archive_entry_sparse_clear(entry
);
170 memset(entry
, 0, sizeof(*entry
));
174 struct archive_entry
*
175 archive_entry_clone(struct archive_entry
*entry
)
177 struct archive_entry
*entry2
;
179 struct ae_sparse
*sp
;
183 /* Allocate new structure and copy over all of the fields. */
184 /* TODO: Should we copy the archive over? Or require a new archive
186 entry2
= archive_entry_new2(entry
->archive
);
189 entry2
->ae_stat
= entry
->ae_stat
;
190 entry2
->ae_fflags_set
= entry
->ae_fflags_set
;
191 entry2
->ae_fflags_clear
= entry
->ae_fflags_clear
;
193 /* TODO: XXX If clone can have a different archive, what do we do here if
194 * character sets are different? XXX */
195 archive_mstring_copy(&entry2
->ae_fflags_text
, &entry
->ae_fflags_text
);
196 archive_mstring_copy(&entry2
->ae_gname
, &entry
->ae_gname
);
197 archive_mstring_copy(&entry2
->ae_hardlink
, &entry
->ae_hardlink
);
198 archive_mstring_copy(&entry2
->ae_pathname
, &entry
->ae_pathname
);
199 archive_mstring_copy(&entry2
->ae_sourcepath
, &entry
->ae_sourcepath
);
200 archive_mstring_copy(&entry2
->ae_symlink
, &entry
->ae_symlink
);
201 entry2
->ae_set
= entry
->ae_set
;
202 archive_mstring_copy(&entry2
->ae_uname
, &entry
->ae_uname
);
204 /* Copy encryption status */
205 entry2
->encryption
= entry
->encryption
;
207 /* Copy ACL data over. */
208 archive_acl_copy(&entry2
->acl
, &entry
->acl
);
210 /* Copy Mac OS metadata. */
211 p
= archive_entry_mac_metadata(entry
, &s
);
212 archive_entry_copy_mac_metadata(entry2
, p
, s
);
214 /* Copy xattr data over. */
215 xp
= entry
->xattr_head
;
217 archive_entry_xattr_add_entry(entry2
,
218 xp
->name
, xp
->value
, xp
->size
);
222 /* Copy sparse data over. */
223 sp
= entry
->sparse_head
;
225 archive_entry_sparse_add_entry(entry2
,
226 sp
->offset
, sp
->length
);
234 archive_entry_free(struct archive_entry
*entry
)
236 archive_entry_clear(entry
);
240 struct archive_entry
*
241 archive_entry_new(void)
243 return archive_entry_new2(NULL
);
246 struct archive_entry
*
247 archive_entry_new2(struct archive
*a
)
249 struct archive_entry
*entry
;
251 entry
= (struct archive_entry
*)malloc(sizeof(*entry
));
254 memset(entry
, 0, sizeof(*entry
));
260 * Functions for reading fields from an archive_entry.
264 archive_entry_atime(struct archive_entry
*entry
)
266 return (entry
->ae_stat
.aest_atime
);
270 archive_entry_atime_nsec(struct archive_entry
*entry
)
272 return (entry
->ae_stat
.aest_atime_nsec
);
276 archive_entry_atime_is_set(struct archive_entry
*entry
)
278 return (entry
->ae_set
& AE_SET_ATIME
);
282 archive_entry_birthtime(struct archive_entry
*entry
)
284 return (entry
->ae_stat
.aest_birthtime
);
288 archive_entry_birthtime_nsec(struct archive_entry
*entry
)
290 return (entry
->ae_stat
.aest_birthtime_nsec
);
294 archive_entry_birthtime_is_set(struct archive_entry
*entry
)
296 return (entry
->ae_set
& AE_SET_BIRTHTIME
);
300 archive_entry_ctime(struct archive_entry
*entry
)
302 return (entry
->ae_stat
.aest_ctime
);
306 archive_entry_ctime_is_set(struct archive_entry
*entry
)
308 return (entry
->ae_set
& AE_SET_CTIME
);
312 archive_entry_ctime_nsec(struct archive_entry
*entry
)
314 return (entry
->ae_stat
.aest_ctime_nsec
);
318 archive_entry_dev(struct archive_entry
*entry
)
320 if (entry
->ae_stat
.aest_dev_is_broken_down
)
321 return ae_makedev(entry
->ae_stat
.aest_devmajor
,
322 entry
->ae_stat
.aest_devminor
);
324 return (entry
->ae_stat
.aest_dev
);
328 archive_entry_dev_is_set(struct archive_entry
*entry
)
330 return (entry
->ae_set
& AE_SET_DEV
);
334 archive_entry_devmajor(struct archive_entry
*entry
)
336 if (entry
->ae_stat
.aest_dev_is_broken_down
)
337 return (entry
->ae_stat
.aest_devmajor
);
339 return major(entry
->ae_stat
.aest_dev
);
343 archive_entry_devminor(struct archive_entry
*entry
)
345 if (entry
->ae_stat
.aest_dev_is_broken_down
)
346 return (entry
->ae_stat
.aest_devminor
);
348 return minor(entry
->ae_stat
.aest_dev
);
352 archive_entry_filetype(struct archive_entry
*entry
)
354 return (AE_IFMT
& entry
->acl
.mode
);
358 archive_entry_fflags(struct archive_entry
*entry
,
359 unsigned long *set
, unsigned long *clear
)
361 *set
= entry
->ae_fflags_set
;
362 *clear
= entry
->ae_fflags_clear
;
366 * Note: if text was provided, this just returns that text. If you
367 * really need the text to be rebuilt in a canonical form, set the
368 * text, ask for the bitmaps, then set the bitmaps. (Setting the
369 * bitmaps clears any stored text.) This design is deliberate: if
370 * we're editing archives, we don't want to discard flags just because
371 * they aren't supported on the current system. The bitmap<->text
372 * conversions are platform-specific (see below).
375 archive_entry_fflags_text(struct archive_entry
*entry
)
380 if (archive_mstring_get_mbs(entry
->archive
,
381 &entry
->ae_fflags_text
, &f
) == 0) {
384 } else if (errno
== ENOMEM
)
385 __archive_errx(1, "No memory");
387 if (entry
->ae_fflags_set
== 0 && entry
->ae_fflags_clear
== 0)
390 p
= ae_fflagstostr(entry
->ae_fflags_set
, entry
->ae_fflags_clear
);
394 archive_mstring_copy_mbs(&entry
->ae_fflags_text
, p
);
396 if (archive_mstring_get_mbs(entry
->archive
,
397 &entry
->ae_fflags_text
, &f
) == 0)
400 __archive_errx(1, "No memory");
405 archive_entry_gid(struct archive_entry
*entry
)
407 return (entry
->ae_stat
.aest_gid
);
411 archive_entry_gname(struct archive_entry
*entry
)
414 if (archive_mstring_get_mbs(entry
->archive
, &entry
->ae_gname
, &p
) == 0)
417 __archive_errx(1, "No memory");
422 archive_entry_gname_utf8(struct archive_entry
*entry
)
425 if (archive_mstring_get_utf8(entry
->archive
, &entry
->ae_gname
, &p
) == 0)
428 __archive_errx(1, "No memory");
434 archive_entry_gname_w(struct archive_entry
*entry
)
437 if (archive_mstring_get_wcs(entry
->archive
, &entry
->ae_gname
, &p
) == 0)
440 __archive_errx(1, "No memory");
445 _archive_entry_gname_l(struct archive_entry
*entry
,
446 const char **p
, size_t *len
, struct archive_string_conv
*sc
)
448 return (archive_mstring_get_mbs_l(&entry
->ae_gname
, p
, len
, sc
));
452 archive_entry_hardlink(struct archive_entry
*entry
)
455 if ((entry
->ae_set
& AE_SET_HARDLINK
) == 0)
457 if (archive_mstring_get_mbs(
458 entry
->archive
, &entry
->ae_hardlink
, &p
) == 0)
461 __archive_errx(1, "No memory");
466 archive_entry_hardlink_utf8(struct archive_entry
*entry
)
469 if ((entry
->ae_set
& AE_SET_HARDLINK
) == 0)
471 if (archive_mstring_get_utf8(
472 entry
->archive
, &entry
->ae_hardlink
, &p
) == 0)
475 __archive_errx(1, "No memory");
480 archive_entry_hardlink_w(struct archive_entry
*entry
)
483 if ((entry
->ae_set
& AE_SET_HARDLINK
) == 0)
485 if (archive_mstring_get_wcs(
486 entry
->archive
, &entry
->ae_hardlink
, &p
) == 0)
489 __archive_errx(1, "No memory");
494 _archive_entry_hardlink_l(struct archive_entry
*entry
,
495 const char **p
, size_t *len
, struct archive_string_conv
*sc
)
497 if ((entry
->ae_set
& AE_SET_HARDLINK
) == 0) {
502 return (archive_mstring_get_mbs_l(&entry
->ae_hardlink
, p
, len
, sc
));
506 archive_entry_ino(struct archive_entry
*entry
)
508 return (entry
->ae_stat
.aest_ino
);
512 archive_entry_ino_is_set(struct archive_entry
*entry
)
514 return (entry
->ae_set
& AE_SET_INO
);
518 archive_entry_ino64(struct archive_entry
*entry
)
520 return (entry
->ae_stat
.aest_ino
);
524 archive_entry_mode(struct archive_entry
*entry
)
526 return (entry
->acl
.mode
);
530 archive_entry_mtime(struct archive_entry
*entry
)
532 return (entry
->ae_stat
.aest_mtime
);
536 archive_entry_mtime_nsec(struct archive_entry
*entry
)
538 return (entry
->ae_stat
.aest_mtime_nsec
);
542 archive_entry_mtime_is_set(struct archive_entry
*entry
)
544 return (entry
->ae_set
& AE_SET_MTIME
);
548 archive_entry_nlink(struct archive_entry
*entry
)
550 return (entry
->ae_stat
.aest_nlink
);
554 archive_entry_pathname(struct archive_entry
*entry
)
557 if (archive_mstring_get_mbs(
558 entry
->archive
, &entry
->ae_pathname
, &p
) == 0)
561 __archive_errx(1, "No memory");
566 archive_entry_pathname_utf8(struct archive_entry
*entry
)
569 if (archive_mstring_get_utf8(
570 entry
->archive
, &entry
->ae_pathname
, &p
) == 0)
573 __archive_errx(1, "No memory");
578 archive_entry_pathname_w(struct archive_entry
*entry
)
581 if (archive_mstring_get_wcs(
582 entry
->archive
, &entry
->ae_pathname
, &p
) == 0)
585 __archive_errx(1, "No memory");
590 _archive_entry_pathname_l(struct archive_entry
*entry
,
591 const char **p
, size_t *len
, struct archive_string_conv
*sc
)
593 return (archive_mstring_get_mbs_l(&entry
->ae_pathname
, p
, len
, sc
));
597 archive_entry_perm(struct archive_entry
*entry
)
599 return (~AE_IFMT
& entry
->acl
.mode
);
603 archive_entry_rdev(struct archive_entry
*entry
)
605 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
606 return ae_makedev(entry
->ae_stat
.aest_rdevmajor
,
607 entry
->ae_stat
.aest_rdevminor
);
609 return (entry
->ae_stat
.aest_rdev
);
613 archive_entry_rdevmajor(struct archive_entry
*entry
)
615 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
616 return (entry
->ae_stat
.aest_rdevmajor
);
618 return major(entry
->ae_stat
.aest_rdev
);
622 archive_entry_rdevminor(struct archive_entry
*entry
)
624 if (entry
->ae_stat
.aest_rdev_is_broken_down
)
625 return (entry
->ae_stat
.aest_rdevminor
);
627 return minor(entry
->ae_stat
.aest_rdev
);
631 archive_entry_size(struct archive_entry
*entry
)
633 return (entry
->ae_stat
.aest_size
);
637 archive_entry_size_is_set(struct archive_entry
*entry
)
639 return (entry
->ae_set
& AE_SET_SIZE
);
643 archive_entry_sourcepath(struct archive_entry
*entry
)
646 if (archive_mstring_get_mbs(
647 entry
->archive
, &entry
->ae_sourcepath
, &p
) == 0)
650 __archive_errx(1, "No memory");
655 archive_entry_sourcepath_w(struct archive_entry
*entry
)
658 if (archive_mstring_get_wcs(
659 entry
->archive
, &entry
->ae_sourcepath
, &p
) == 0)
665 archive_entry_symlink(struct archive_entry
*entry
)
668 if ((entry
->ae_set
& AE_SET_SYMLINK
) == 0)
670 if (archive_mstring_get_mbs(
671 entry
->archive
, &entry
->ae_symlink
, &p
) == 0)
674 __archive_errx(1, "No memory");
679 archive_entry_symlink_utf8(struct archive_entry
*entry
)
682 if ((entry
->ae_set
& AE_SET_SYMLINK
) == 0)
684 if (archive_mstring_get_utf8(
685 entry
->archive
, &entry
->ae_symlink
, &p
) == 0)
688 __archive_errx(1, "No memory");
693 archive_entry_symlink_w(struct archive_entry
*entry
)
696 if ((entry
->ae_set
& AE_SET_SYMLINK
) == 0)
698 if (archive_mstring_get_wcs(
699 entry
->archive
, &entry
->ae_symlink
, &p
) == 0)
702 __archive_errx(1, "No memory");
707 _archive_entry_symlink_l(struct archive_entry
*entry
,
708 const char **p
, size_t *len
, struct archive_string_conv
*sc
)
710 if ((entry
->ae_set
& AE_SET_SYMLINK
) == 0) {
715 return (archive_mstring_get_mbs_l( &entry
->ae_symlink
, p
, len
, sc
));
719 archive_entry_uid(struct archive_entry
*entry
)
721 return (entry
->ae_stat
.aest_uid
);
725 archive_entry_uname(struct archive_entry
*entry
)
728 if (archive_mstring_get_mbs(entry
->archive
, &entry
->ae_uname
, &p
) == 0)
731 __archive_errx(1, "No memory");
736 archive_entry_uname_utf8(struct archive_entry
*entry
)
739 if (archive_mstring_get_utf8(entry
->archive
, &entry
->ae_uname
, &p
) == 0)
742 __archive_errx(1, "No memory");
747 archive_entry_uname_w(struct archive_entry
*entry
)
750 if (archive_mstring_get_wcs(entry
->archive
, &entry
->ae_uname
, &p
) == 0)
753 __archive_errx(1, "No memory");
758 _archive_entry_uname_l(struct archive_entry
*entry
,
759 const char **p
, size_t *len
, struct archive_string_conv
*sc
)
761 return (archive_mstring_get_mbs_l(&entry
->ae_uname
, p
, len
, sc
));
765 archive_entry_is_data_encrypted(struct archive_entry
*entry
)
767 return ((entry
->encryption
& AE_ENCRYPTION_DATA
) == AE_ENCRYPTION_DATA
);
771 archive_entry_is_metadata_encrypted(struct archive_entry
*entry
)
773 return ((entry
->encryption
& AE_ENCRYPTION_METADATA
) == AE_ENCRYPTION_METADATA
);
777 archive_entry_is_encrypted(struct archive_entry
*entry
)
779 return (entry
->encryption
& (AE_ENCRYPTION_DATA
|AE_ENCRYPTION_METADATA
));
783 * Functions to set archive_entry properties.
787 archive_entry_set_filetype(struct archive_entry
*entry
, unsigned int type
)
789 entry
->stat_valid
= 0;
790 entry
->acl
.mode
&= ~AE_IFMT
;
791 entry
->acl
.mode
|= AE_IFMT
& type
;
795 archive_entry_set_fflags(struct archive_entry
*entry
,
796 unsigned long set
, unsigned long clear
)
798 archive_mstring_clean(&entry
->ae_fflags_text
);
799 entry
->ae_fflags_set
= set
;
800 entry
->ae_fflags_clear
= clear
;
804 archive_entry_copy_fflags_text(struct archive_entry
*entry
,
807 archive_mstring_copy_mbs(&entry
->ae_fflags_text
, flags
);
808 return (ae_strtofflags(flags
,
809 &entry
->ae_fflags_set
, &entry
->ae_fflags_clear
));
813 archive_entry_copy_fflags_text_w(struct archive_entry
*entry
,
814 const wchar_t *flags
)
816 archive_mstring_copy_wcs(&entry
->ae_fflags_text
, flags
);
817 return (ae_wcstofflags(flags
,
818 &entry
->ae_fflags_set
, &entry
->ae_fflags_clear
));
822 archive_entry_set_gid(struct archive_entry
*entry
, int64_t g
)
824 entry
->stat_valid
= 0;
825 entry
->ae_stat
.aest_gid
= g
;
829 archive_entry_set_gname(struct archive_entry
*entry
, const char *name
)
831 archive_mstring_copy_mbs(&entry
->ae_gname
, name
);
835 archive_entry_set_gname_utf8(struct archive_entry
*entry
, const char *name
)
837 archive_mstring_copy_utf8(&entry
->ae_gname
, name
);
841 archive_entry_copy_gname(struct archive_entry
*entry
, const char *name
)
843 archive_mstring_copy_mbs(&entry
->ae_gname
, name
);
847 archive_entry_copy_gname_w(struct archive_entry
*entry
, const wchar_t *name
)
849 archive_mstring_copy_wcs(&entry
->ae_gname
, name
);
853 archive_entry_update_gname_utf8(struct archive_entry
*entry
, const char *name
)
855 if (archive_mstring_update_utf8(entry
->archive
,
856 &entry
->ae_gname
, name
) == 0)
859 __archive_errx(1, "No memory");
864 _archive_entry_copy_gname_l(struct archive_entry
*entry
,
865 const char *name
, size_t len
, struct archive_string_conv
*sc
)
867 return (archive_mstring_copy_mbs_len_l(&entry
->ae_gname
, name
, len
, sc
));
871 archive_entry_set_ino(struct archive_entry
*entry
, int64_t ino
)
873 entry
->stat_valid
= 0;
874 entry
->ae_set
|= AE_SET_INO
;
875 entry
->ae_stat
.aest_ino
= ino
;
879 archive_entry_set_ino64(struct archive_entry
*entry
, int64_t ino
)
881 entry
->stat_valid
= 0;
882 entry
->ae_set
|= AE_SET_INO
;
883 entry
->ae_stat
.aest_ino
= ino
;
887 archive_entry_set_hardlink(struct archive_entry
*entry
, const char *target
)
889 archive_mstring_copy_mbs(&entry
->ae_hardlink
, target
);
891 entry
->ae_set
|= AE_SET_HARDLINK
;
893 entry
->ae_set
&= ~AE_SET_HARDLINK
;
897 archive_entry_set_hardlink_utf8(struct archive_entry
*entry
, const char *target
)
899 archive_mstring_copy_utf8(&entry
->ae_hardlink
, target
);
901 entry
->ae_set
|= AE_SET_HARDLINK
;
903 entry
->ae_set
&= ~AE_SET_HARDLINK
;
907 archive_entry_copy_hardlink(struct archive_entry
*entry
, const char *target
)
909 archive_mstring_copy_mbs(&entry
->ae_hardlink
, target
);
911 entry
->ae_set
|= AE_SET_HARDLINK
;
913 entry
->ae_set
&= ~AE_SET_HARDLINK
;
917 archive_entry_copy_hardlink_w(struct archive_entry
*entry
, const wchar_t *target
)
919 archive_mstring_copy_wcs(&entry
->ae_hardlink
, target
);
921 entry
->ae_set
|= AE_SET_HARDLINK
;
923 entry
->ae_set
&= ~AE_SET_HARDLINK
;
927 archive_entry_update_hardlink_utf8(struct archive_entry
*entry
, const char *target
)
930 entry
->ae_set
|= AE_SET_HARDLINK
;
932 entry
->ae_set
&= ~AE_SET_HARDLINK
;
933 if (archive_mstring_update_utf8(entry
->archive
,
934 &entry
->ae_hardlink
, target
) == 0)
937 __archive_errx(1, "No memory");
942 _archive_entry_copy_hardlink_l(struct archive_entry
*entry
,
943 const char *target
, size_t len
, struct archive_string_conv
*sc
)
947 r
= archive_mstring_copy_mbs_len_l(&entry
->ae_hardlink
,
949 if (target
!= NULL
&& r
== 0)
950 entry
->ae_set
|= AE_SET_HARDLINK
;
952 entry
->ae_set
&= ~AE_SET_HARDLINK
;
957 archive_entry_set_atime(struct archive_entry
*entry
, time_t t
, long ns
)
960 entry
->stat_valid
= 0;
961 entry
->ae_set
|= AE_SET_ATIME
;
962 entry
->ae_stat
.aest_atime
= t
;
963 entry
->ae_stat
.aest_atime_nsec
= ns
;
967 archive_entry_unset_atime(struct archive_entry
*entry
)
969 archive_entry_set_atime(entry
, 0, 0);
970 entry
->ae_set
&= ~AE_SET_ATIME
;
974 archive_entry_set_birthtime(struct archive_entry
*entry
, time_t t
, long ns
)
977 entry
->stat_valid
= 0;
978 entry
->ae_set
|= AE_SET_BIRTHTIME
;
979 entry
->ae_stat
.aest_birthtime
= t
;
980 entry
->ae_stat
.aest_birthtime_nsec
= ns
;
984 archive_entry_unset_birthtime(struct archive_entry
*entry
)
986 archive_entry_set_birthtime(entry
, 0, 0);
987 entry
->ae_set
&= ~AE_SET_BIRTHTIME
;
991 archive_entry_set_ctime(struct archive_entry
*entry
, time_t t
, long ns
)
994 entry
->stat_valid
= 0;
995 entry
->ae_set
|= AE_SET_CTIME
;
996 entry
->ae_stat
.aest_ctime
= t
;
997 entry
->ae_stat
.aest_ctime_nsec
= ns
;
1001 archive_entry_unset_ctime(struct archive_entry
*entry
)
1003 archive_entry_set_ctime(entry
, 0, 0);
1004 entry
->ae_set
&= ~AE_SET_CTIME
;
1008 archive_entry_set_dev(struct archive_entry
*entry
, dev_t d
)
1010 entry
->stat_valid
= 0;
1011 entry
->ae_set
|= AE_SET_DEV
;
1012 entry
->ae_stat
.aest_dev_is_broken_down
= 0;
1013 entry
->ae_stat
.aest_dev
= d
;
1017 archive_entry_set_devmajor(struct archive_entry
*entry
, dev_t m
)
1019 entry
->stat_valid
= 0;
1020 entry
->ae_set
|= AE_SET_DEV
;
1021 entry
->ae_stat
.aest_dev_is_broken_down
= 1;
1022 entry
->ae_stat
.aest_devmajor
= m
;
1026 archive_entry_set_devminor(struct archive_entry
*entry
, dev_t m
)
1028 entry
->stat_valid
= 0;
1029 entry
->ae_set
|= AE_SET_DEV
;
1030 entry
->ae_stat
.aest_dev_is_broken_down
= 1;
1031 entry
->ae_stat
.aest_devminor
= m
;
1034 /* Set symlink if symlink is already set, else set hardlink. */
1036 archive_entry_set_link(struct archive_entry
*entry
, const char *target
)
1038 if (entry
->ae_set
& AE_SET_SYMLINK
)
1039 archive_mstring_copy_mbs(&entry
->ae_symlink
, target
);
1041 archive_mstring_copy_mbs(&entry
->ae_hardlink
, target
);
1045 archive_entry_set_link_utf8(struct archive_entry
*entry
, const char *target
)
1047 if (entry
->ae_set
& AE_SET_SYMLINK
)
1048 archive_mstring_copy_utf8(&entry
->ae_symlink
, target
);
1050 archive_mstring_copy_utf8(&entry
->ae_hardlink
, target
);
1053 /* Set symlink if symlink is already set, else set hardlink. */
1055 archive_entry_copy_link(struct archive_entry
*entry
, const char *target
)
1057 if (entry
->ae_set
& AE_SET_SYMLINK
)
1058 archive_mstring_copy_mbs(&entry
->ae_symlink
, target
);
1060 archive_mstring_copy_mbs(&entry
->ae_hardlink
, target
);
1063 /* Set symlink if symlink is already set, else set hardlink. */
1065 archive_entry_copy_link_w(struct archive_entry
*entry
, const wchar_t *target
)
1067 if (entry
->ae_set
& AE_SET_SYMLINK
)
1068 archive_mstring_copy_wcs(&entry
->ae_symlink
, target
);
1070 archive_mstring_copy_wcs(&entry
->ae_hardlink
, target
);
1074 archive_entry_update_link_utf8(struct archive_entry
*entry
, const char *target
)
1077 if (entry
->ae_set
& AE_SET_SYMLINK
)
1078 r
= archive_mstring_update_utf8(entry
->archive
,
1079 &entry
->ae_symlink
, target
);
1081 r
= archive_mstring_update_utf8(entry
->archive
,
1082 &entry
->ae_hardlink
, target
);
1085 if (errno
== ENOMEM
)
1086 __archive_errx(1, "No memory");
1091 _archive_entry_copy_link_l(struct archive_entry
*entry
,
1092 const char *target
, size_t len
, struct archive_string_conv
*sc
)
1096 if (entry
->ae_set
& AE_SET_SYMLINK
)
1097 r
= archive_mstring_copy_mbs_len_l(&entry
->ae_symlink
,
1100 r
= archive_mstring_copy_mbs_len_l(&entry
->ae_hardlink
,
1106 archive_entry_set_mode(struct archive_entry
*entry
, mode_t m
)
1108 entry
->stat_valid
= 0;
1109 entry
->acl
.mode
= m
;
1113 archive_entry_set_mtime(struct archive_entry
*entry
, time_t t
, long ns
)
1116 entry
->stat_valid
= 0;
1117 entry
->ae_set
|= AE_SET_MTIME
;
1118 entry
->ae_stat
.aest_mtime
= t
;
1119 entry
->ae_stat
.aest_mtime_nsec
= ns
;
1123 archive_entry_unset_mtime(struct archive_entry
*entry
)
1125 archive_entry_set_mtime(entry
, 0, 0);
1126 entry
->ae_set
&= ~AE_SET_MTIME
;
1130 archive_entry_set_nlink(struct archive_entry
*entry
, unsigned int nlink
)
1132 entry
->stat_valid
= 0;
1133 entry
->ae_stat
.aest_nlink
= nlink
;
1137 archive_entry_set_pathname(struct archive_entry
*entry
, const char *name
)
1139 archive_mstring_copy_mbs(&entry
->ae_pathname
, name
);
1143 archive_entry_set_pathname_utf8(struct archive_entry
*entry
, const char *name
)
1145 archive_mstring_copy_utf8(&entry
->ae_pathname
, name
);
1149 archive_entry_copy_pathname(struct archive_entry
*entry
, const char *name
)
1151 archive_mstring_copy_mbs(&entry
->ae_pathname
, name
);
1155 archive_entry_copy_pathname_w(struct archive_entry
*entry
, const wchar_t *name
)
1157 archive_mstring_copy_wcs(&entry
->ae_pathname
, name
);
1161 archive_entry_update_pathname_utf8(struct archive_entry
*entry
, const char *name
)
1163 if (archive_mstring_update_utf8(entry
->archive
,
1164 &entry
->ae_pathname
, name
) == 0)
1166 if (errno
== ENOMEM
)
1167 __archive_errx(1, "No memory");
1172 _archive_entry_copy_pathname_l(struct archive_entry
*entry
,
1173 const char *name
, size_t len
, struct archive_string_conv
*sc
)
1175 return (archive_mstring_copy_mbs_len_l(&entry
->ae_pathname
,
1180 archive_entry_set_perm(struct archive_entry
*entry
, mode_t p
)
1182 entry
->stat_valid
= 0;
1183 entry
->acl
.mode
&= AE_IFMT
;
1184 entry
->acl
.mode
|= ~AE_IFMT
& p
;
1188 archive_entry_set_rdev(struct archive_entry
*entry
, dev_t m
)
1190 entry
->stat_valid
= 0;
1191 entry
->ae_stat
.aest_rdev
= m
;
1192 entry
->ae_stat
.aest_rdev_is_broken_down
= 0;
1196 archive_entry_set_rdevmajor(struct archive_entry
*entry
, dev_t m
)
1198 entry
->stat_valid
= 0;
1199 entry
->ae_stat
.aest_rdev_is_broken_down
= 1;
1200 entry
->ae_stat
.aest_rdevmajor
= m
;
1204 archive_entry_set_rdevminor(struct archive_entry
*entry
, dev_t m
)
1206 entry
->stat_valid
= 0;
1207 entry
->ae_stat
.aest_rdev_is_broken_down
= 1;
1208 entry
->ae_stat
.aest_rdevminor
= m
;
1212 archive_entry_set_size(struct archive_entry
*entry
, int64_t s
)
1214 entry
->stat_valid
= 0;
1215 entry
->ae_stat
.aest_size
= s
;
1216 entry
->ae_set
|= AE_SET_SIZE
;
1220 archive_entry_unset_size(struct archive_entry
*entry
)
1222 archive_entry_set_size(entry
, 0);
1223 entry
->ae_set
&= ~AE_SET_SIZE
;
1227 archive_entry_copy_sourcepath(struct archive_entry
*entry
, const char *path
)
1229 archive_mstring_copy_mbs(&entry
->ae_sourcepath
, path
);
1233 archive_entry_copy_sourcepath_w(struct archive_entry
*entry
, const wchar_t *path
)
1235 archive_mstring_copy_wcs(&entry
->ae_sourcepath
, path
);
1239 archive_entry_set_symlink(struct archive_entry
*entry
, const char *linkname
)
1241 archive_mstring_copy_mbs(&entry
->ae_symlink
, linkname
);
1242 if (linkname
!= NULL
)
1243 entry
->ae_set
|= AE_SET_SYMLINK
;
1245 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1249 archive_entry_set_symlink_utf8(struct archive_entry
*entry
, const char *linkname
)
1251 archive_mstring_copy_utf8(&entry
->ae_symlink
, linkname
);
1252 if (linkname
!= NULL
)
1253 entry
->ae_set
|= AE_SET_SYMLINK
;
1255 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1259 archive_entry_copy_symlink(struct archive_entry
*entry
, const char *linkname
)
1261 archive_mstring_copy_mbs(&entry
->ae_symlink
, linkname
);
1262 if (linkname
!= NULL
)
1263 entry
->ae_set
|= AE_SET_SYMLINK
;
1265 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1269 archive_entry_copy_symlink_w(struct archive_entry
*entry
, const wchar_t *linkname
)
1271 archive_mstring_copy_wcs(&entry
->ae_symlink
, linkname
);
1272 if (linkname
!= NULL
)
1273 entry
->ae_set
|= AE_SET_SYMLINK
;
1275 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1279 archive_entry_update_symlink_utf8(struct archive_entry
*entry
, const char *linkname
)
1281 if (linkname
!= NULL
)
1282 entry
->ae_set
|= AE_SET_SYMLINK
;
1284 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1285 if (archive_mstring_update_utf8(entry
->archive
,
1286 &entry
->ae_symlink
, linkname
) == 0)
1288 if (errno
== ENOMEM
)
1289 __archive_errx(1, "No memory");
1294 _archive_entry_copy_symlink_l(struct archive_entry
*entry
,
1295 const char *linkname
, size_t len
, struct archive_string_conv
*sc
)
1299 r
= archive_mstring_copy_mbs_len_l(&entry
->ae_symlink
,
1301 if (linkname
!= NULL
&& r
== 0)
1302 entry
->ae_set
|= AE_SET_SYMLINK
;
1304 entry
->ae_set
&= ~AE_SET_SYMLINK
;
1309 archive_entry_set_uid(struct archive_entry
*entry
, int64_t u
)
1311 entry
->stat_valid
= 0;
1312 entry
->ae_stat
.aest_uid
= u
;
1316 archive_entry_set_uname(struct archive_entry
*entry
, const char *name
)
1318 archive_mstring_copy_mbs(&entry
->ae_uname
, name
);
1322 archive_entry_set_uname_utf8(struct archive_entry
*entry
, const char *name
)
1324 archive_mstring_copy_utf8(&entry
->ae_uname
, name
);
1328 archive_entry_copy_uname(struct archive_entry
*entry
, const char *name
)
1330 archive_mstring_copy_mbs(&entry
->ae_uname
, name
);
1334 archive_entry_copy_uname_w(struct archive_entry
*entry
, const wchar_t *name
)
1336 archive_mstring_copy_wcs(&entry
->ae_uname
, name
);
1340 archive_entry_update_uname_utf8(struct archive_entry
*entry
, const char *name
)
1342 if (archive_mstring_update_utf8(entry
->archive
,
1343 &entry
->ae_uname
, name
) == 0)
1345 if (errno
== ENOMEM
)
1346 __archive_errx(1, "No memory");
1351 archive_entry_set_is_data_encrypted(struct archive_entry
*entry
, char is_encrypted
)
1354 entry
->encryption
|= AE_ENCRYPTION_DATA
;
1356 entry
->encryption
&= ~AE_ENCRYPTION_DATA
;
1361 archive_entry_set_is_metadata_encrypted(struct archive_entry
*entry
, char is_encrypted
)
1364 entry
->encryption
|= AE_ENCRYPTION_METADATA
;
1366 entry
->encryption
&= ~AE_ENCRYPTION_METADATA
;
1371 _archive_entry_copy_uname_l(struct archive_entry
*entry
,
1372 const char *name
, size_t len
, struct archive_string_conv
*sc
)
1374 return (archive_mstring_copy_mbs_len_l(&entry
->ae_uname
,
1379 archive_entry_mac_metadata(struct archive_entry
*entry
, size_t *s
)
1381 *s
= entry
->mac_metadata_size
;
1382 return entry
->mac_metadata
;
1386 archive_entry_copy_mac_metadata(struct archive_entry
*entry
,
1387 const void *p
, size_t s
)
1389 free(entry
->mac_metadata
);
1390 if (p
== NULL
|| s
== 0) {
1391 entry
->mac_metadata
= NULL
;
1392 entry
->mac_metadata_size
= 0;
1394 entry
->mac_metadata_size
= s
;
1395 entry
->mac_metadata
= malloc(s
);
1396 if (entry
->mac_metadata
== NULL
)
1398 memcpy(entry
->mac_metadata
, p
, s
);
1403 * ACL management. The following would, of course, be a lot simpler
1404 * if: 1) the last draft of POSIX.1e were a really thorough and
1405 * complete standard that addressed the needs of ACL archiving and 2)
1406 * everyone followed it faithfully. Alas, neither is true, so the
1407 * following is a lot more complex than might seem necessary to the
1411 struct archive_acl
*
1412 archive_entry_acl(struct archive_entry
*entry
)
1418 archive_entry_acl_clear(struct archive_entry
*entry
)
1420 archive_acl_clear(&entry
->acl
);
1424 * Add a single ACL entry to the internal list of ACL data.
1427 archive_entry_acl_add_entry(struct archive_entry
*entry
,
1428 int type
, int permset
, int tag
, int id
, const char *name
)
1430 return archive_acl_add_entry(&entry
->acl
, type
, permset
, tag
, id
, name
);
1434 * As above, but with a wide-character name.
1437 archive_entry_acl_add_entry_w(struct archive_entry
*entry
,
1438 int type
, int permset
, int tag
, int id
, const wchar_t *name
)
1440 return archive_acl_add_entry_w_len(&entry
->acl
,
1441 type
, permset
, tag
, id
, name
, wcslen(name
));
1445 * Return a count of entries matching "want_type".
1448 archive_entry_acl_count(struct archive_entry
*entry
, int want_type
)
1450 return archive_acl_count(&entry
->acl
, want_type
);
1454 * Prepare for reading entries from the ACL data. Returns a count
1455 * of entries matching "want_type", or zero if there are no
1456 * non-extended ACL entries of that type.
1459 archive_entry_acl_reset(struct archive_entry
*entry
, int want_type
)
1461 return archive_acl_reset(&entry
->acl
, want_type
);
1465 * Return the next ACL entry in the list. Fake entries for the
1466 * standard permissions and include them in the returned list.
1469 archive_entry_acl_next(struct archive_entry
*entry
, int want_type
, int *type
,
1470 int *permset
, int *tag
, int *id
, const char **name
)
1473 r
= archive_acl_next(entry
->archive
, &entry
->acl
, want_type
, type
,
1474 permset
, tag
, id
, name
);
1475 if (r
== ARCHIVE_FATAL
&& errno
== ENOMEM
)
1476 __archive_errx(1, "No memory");
1481 * Generate a text version of the ACL. The flags parameter controls
1482 * the style of the generated ACL.
1485 archive_entry_acl_text_w(struct archive_entry
*entry
, int flags
)
1488 r
= archive_acl_text_w(entry
->archive
, &entry
->acl
, flags
);
1489 if (r
== NULL
&& errno
== ENOMEM
)
1490 __archive_errx(1, "No memory");
1495 archive_entry_acl_text(struct archive_entry
*entry
, int flags
)
1498 if (archive_acl_text_l(&entry
->acl
, flags
, &p
, NULL
, NULL
) != 0
1500 __archive_errx(1, "No memory");
1505 _archive_entry_acl_text_l(struct archive_entry
*entry
, int flags
,
1506 const char **acl_text
, size_t *len
, struct archive_string_conv
*sc
)
1508 return (archive_acl_text_l(&entry
->acl
, flags
, acl_text
, len
, sc
));
1512 * Following code is modified from UC Berkeley sources, and
1513 * is subject to the following copyright notice.
1517 * Copyright (c) 1993
1518 * The Regents of the University of California. All rights reserved.
1520 * Redistribution and use in source and binary forms, with or without
1521 * modification, are permitted provided that the following conditions
1523 * 1. Redistributions of source code must retain the above copyright
1524 * notice, this list of conditions and the following disclaimer.
1525 * 2. Redistributions in binary form must reproduce the above copyright
1526 * notice, this list of conditions and the following disclaimer in the
1527 * documentation and/or other materials provided with the distribution.
1528 * 4. Neither the name of the University nor the names of its contributors
1529 * may be used to endorse or promote products derived from this software
1530 * without specific prior written permission.
1532 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1533 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1534 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1535 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1536 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1537 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1538 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1539 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1540 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1541 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1545 static struct flag
{
1547 const wchar_t *wname
;
1549 unsigned long clear
;
1551 /* Preferred (shorter) names per flag first, all prefixed by "no" */
1553 { "nosappnd", L
"nosappnd", SF_APPEND
, 0 },
1554 { "nosappend", L
"nosappend", SF_APPEND
, 0 },
1556 #ifdef EXT2_APPEND_FL /* 'a' */
1557 { "nosappnd", L
"nosappnd", EXT2_APPEND_FL
, 0 },
1558 { "nosappend", L
"nosappend", EXT2_APPEND_FL
, 0 },
1561 { "noarch", L
"noarch", SF_ARCHIVED
, 0 },
1562 { "noarchived", L
"noarchived", SF_ARCHIVED
, 0 },
1565 { "noschg", L
"noschg", SF_IMMUTABLE
, 0 },
1566 { "noschange", L
"noschange", SF_IMMUTABLE
, 0 },
1567 { "nosimmutable", L
"nosimmutable", SF_IMMUTABLE
, 0 },
1569 #ifdef EXT2_IMMUTABLE_FL /* 'i' */
1570 { "noschg", L
"noschg", EXT2_IMMUTABLE_FL
, 0 },
1571 { "noschange", L
"noschange", EXT2_IMMUTABLE_FL
, 0 },
1572 { "nosimmutable", L
"nosimmutable", EXT2_IMMUTABLE_FL
, 0 },
1575 { "nosunlnk", L
"nosunlnk", SF_NOUNLINK
, 0 },
1576 { "nosunlink", L
"nosunlink", SF_NOUNLINK
, 0 },
1579 { "nosnapshot", L
"nosnapshot", SF_SNAPSHOT
, 0 },
1582 { "nouappnd", L
"nouappnd", UF_APPEND
, 0 },
1583 { "nouappend", L
"nouappend", UF_APPEND
, 0 },
1586 { "nouchg", L
"nouchg", UF_IMMUTABLE
, 0 },
1587 { "nouchange", L
"nouchange", UF_IMMUTABLE
, 0 },
1588 { "nouimmutable", L
"nouimmutable", UF_IMMUTABLE
, 0 },
1591 { "nodump", L
"nodump", 0, UF_NODUMP
},
1593 #ifdef EXT2_NODUMP_FL /* 'd' */
1594 { "nodump", L
"nodump", 0, EXT2_NODUMP_FL
},
1597 { "noopaque", L
"noopaque", UF_OPAQUE
, 0 },
1600 { "nouunlnk", L
"nouunlnk", UF_NOUNLINK
, 0 },
1601 { "nouunlink", L
"nouunlink", UF_NOUNLINK
, 0 },
1603 #ifdef UF_COMPRESSED
1604 { "nocompressed",L
"nocompressed", UF_COMPRESSED
, 0 },
1607 { "nouunlink", L
"nouunlink", EXT2_UNRM_FL
, 0},
1610 #ifdef EXT2_BTREE_FL
1611 { "nobtree", L
"nobtree", EXT2_BTREE_FL
, 0 },
1614 #ifdef EXT2_ECOMPR_FL
1615 { "nocomperr", L
"nocomperr", EXT2_ECOMPR_FL
, 0 },
1618 #ifdef EXT2_COMPR_FL /* 'c' */
1619 { "nocompress", L
"nocompress", EXT2_COMPR_FL
, 0 },
1622 #ifdef EXT2_NOATIME_FL /* 'A' */
1623 { "noatime", L
"noatime", 0, EXT2_NOATIME_FL
},
1626 #ifdef EXT2_DIRTY_FL
1627 { "nocompdirty",L
"nocompdirty", EXT2_DIRTY_FL
, 0},
1630 #ifdef EXT2_COMPRBLK_FL
1631 #ifdef EXT2_NOCOMPR_FL
1632 { "nocomprblk", L
"nocomprblk", EXT2_COMPRBLK_FL
, EXT2_NOCOMPR_FL
},
1634 { "nocomprblk", L
"nocomprblk", EXT2_COMPRBLK_FL
, 0},
1637 #ifdef EXT2_DIRSYNC_FL
1638 { "nodirsync", L
"nodirsync", EXT2_DIRSYNC_FL
, 0},
1640 #ifdef EXT2_INDEX_FL
1641 { "nohashidx", L
"nohashidx", EXT2_INDEX_FL
, 0},
1643 #ifdef EXT2_IMAGIC_FL
1644 { "noimagic", L
"noimagic", EXT2_IMAGIC_FL
, 0},
1646 #ifdef EXT3_JOURNAL_DATA_FL
1647 { "nojournal", L
"nojournal", EXT3_JOURNAL_DATA_FL
, 0},
1649 #ifdef EXT2_SECRM_FL
1650 { "nosecuredeletion",L
"nosecuredeletion",EXT2_SECRM_FL
, 0},
1653 { "nosync", L
"nosync", EXT2_SYNC_FL
, 0},
1655 #ifdef EXT2_NOTAIL_FL
1656 { "notail", L
"notail", 0, EXT2_NOTAIL_FL
},
1658 #ifdef EXT2_TOPDIR_FL
1659 { "notopdir", L
"notopdir", EXT2_TOPDIR_FL
, 0},
1661 #ifdef EXT2_RESERVED_FL
1662 { "noreserved", L
"noreserved", EXT2_RESERVED_FL
, 0},
1665 { NULL
, NULL
, 0, 0 }
1670 * Convert file flags to a comma-separated string. If no flags
1671 * are set, return the empty string.
1674 ae_fflagstostr(unsigned long bitset
, unsigned long bitclear
)
1682 bits
= bitset
| bitclear
;
1684 for (flag
= flags
; flag
->name
!= NULL
; flag
++)
1685 if (bits
& (flag
->set
| flag
->clear
)) {
1686 length
+= strlen(flag
->name
) + 1;
1687 bits
&= ~(flag
->set
| flag
->clear
);
1692 string
= (char *)malloc(length
);
1697 for (flag
= flags
; flag
->name
!= NULL
; flag
++) {
1698 if (bitset
& flag
->set
|| bitclear
& flag
->clear
) {
1699 sp
= flag
->name
+ 2;
1700 } else if (bitset
& flag
->clear
|| bitclear
& flag
->set
) {
1704 bitset
&= ~(flag
->set
| flag
->clear
);
1705 bitclear
&= ~(flag
->set
| flag
->clear
);
1708 while ((*dp
++ = *sp
++) != '\0')
1719 * Take string of arguments and return file flags. This
1720 * version works a little differently than strtofflags(3).
1721 * In particular, it always tests every token, skipping any
1722 * unrecognized tokens. It returns a pointer to the first
1723 * unrecognized token, or NULL if every token was recognized.
1724 * This version is also const-correct and does not modify the
1728 ae_strtofflags(const char *s
, unsigned long *setp
, unsigned long *clrp
)
1730 const char *start
, *end
;
1732 unsigned long set
, clear
;
1738 /* Find start of first token. */
1739 while (*start
== '\t' || *start
== ' ' || *start
== ',')
1741 while (*start
!= '\0') {
1743 /* Locate end of token. */
1745 while (*end
!= '\0' && *end
!= '\t' &&
1746 *end
!= ' ' && *end
!= ',')
1748 length
= end
- start
;
1749 for (flag
= flags
; flag
->name
!= NULL
; flag
++) {
1750 size_t flag_length
= strlen(flag
->name
);
1751 if (length
== flag_length
1752 && memcmp(start
, flag
->name
, length
) == 0) {
1753 /* Matched "noXXXX", so reverse the sense. */
1757 } else if (length
== flag_length
- 2
1758 && memcmp(start
, flag
->name
+ 2, length
) == 0) {
1759 /* Matched "XXXX", so don't reverse. */
1761 clear
|= flag
->clear
;
1765 /* Ignore unknown flag names. */
1766 if (flag
->name
== NULL
&& failed
== NULL
)
1769 /* Find start of next token. */
1771 while (*start
== '\t' || *start
== ' ' || *start
== ',')
1781 /* Return location of first failure. */
1787 * Take string of arguments and return file flags. This
1788 * version works a little differently than strtofflags(3).
1789 * In particular, it always tests every token, skipping any
1790 * unrecognized tokens. It returns a pointer to the first
1791 * unrecognized token, or NULL if every token was recognized.
1792 * This version is also const-correct and does not modify the
1795 static const wchar_t *
1796 ae_wcstofflags(const wchar_t *s
, unsigned long *setp
, unsigned long *clrp
)
1798 const wchar_t *start
, *end
;
1800 unsigned long set
, clear
;
1801 const wchar_t *failed
;
1806 /* Find start of first token. */
1807 while (*start
== L
'\t' || *start
== L
' ' || *start
== L
',')
1809 while (*start
!= L
'\0') {
1811 /* Locate end of token. */
1813 while (*end
!= L
'\0' && *end
!= L
'\t' &&
1814 *end
!= L
' ' && *end
!= L
',')
1816 length
= end
- start
;
1817 for (flag
= flags
; flag
->wname
!= NULL
; flag
++) {
1818 size_t flag_length
= wcslen(flag
->wname
);
1819 if (length
== flag_length
1820 && wmemcmp(start
, flag
->wname
, length
) == 0) {
1821 /* Matched "noXXXX", so reverse the sense. */
1825 } else if (length
== flag_length
- 2
1826 && wmemcmp(start
, flag
->wname
+ 2, length
) == 0) {
1827 /* Matched "XXXX", so don't reverse. */
1829 clear
|= flag
->clear
;
1833 /* Ignore unknown flag names. */
1834 if (flag
->wname
== NULL
&& failed
== NULL
)
1837 /* Find start of next token. */
1839 while (*start
== L
'\t' || *start
== L
' ' || *start
== L
',')
1849 /* Return location of first failure. */
1857 main(int argc
, char **argv
)
1859 struct archive_entry
*entry
= archive_entry_new();
1860 unsigned long set
, clear
;
1861 const wchar_t *remainder
;
1863 remainder
= archive_entry_copy_fflags_text_w(entry
, L
"nosappnd dump archive,,,,,,,");
1864 archive_entry_fflags(entry
, &set
, &clear
);
1866 wprintf(L
"set=0x%lX clear=0x%lX remainder='%ls'\n", set
, clear
, remainder
);
1868 wprintf(L
"new flags='%s'\n", archive_entry_fflags_text(entry
));