Path: blob/master/Utilities/cmlibarchive/libarchive/archive_entry.c
3153 views
/*-1* Copyright (c) 2003-2007 Tim Kientzle2* Copyright (c) 2016 Martin Matuska3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* 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, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include "archive_platform.h"2728#ifdef HAVE_SYS_STAT_H29#include <sys/stat.h>30#endif31#ifdef HAVE_SYS_TYPES_H32#include <sys/types.h>33#endif34#if MAJOR_IN_MKDEV35#include <sys/mkdev.h>36#define HAVE_MAJOR37#elif MAJOR_IN_SYSMACROS38#include <sys/sysmacros.h>39#define HAVE_MAJOR40#endif41#ifdef HAVE_ERRNO_H42#include <errno.h>43#endif44#ifdef HAVE_LIMITS_H45#include <limits.h>46#endif47#ifdef HAVE_LINUX_FS_H48#include <linux/fs.h> /* for Linux file flags */49#endif50/*51* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.52* As the include guards don't agree, the order of include is important.53*/54#ifdef HAVE_LINUX_EXT2_FS_H55#include <linux/ext2_fs.h> /* for Linux file flags */56#endif57#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)58#include <ext2fs/ext2_fs.h> /* for Linux file flags */59#endif60#include <stddef.h>61#include <stdio.h>62#ifdef HAVE_STDLIB_H63#include <stdlib.h>64#endif65#ifdef HAVE_STRING_H66#include <string.h>67#endif68#ifdef HAVE_WCHAR_H69#include <wchar.h>70#endif7172#include "archive.h"73#include "archive_acl_private.h"74#include "archive_entry.h"75#include "archive_entry_locale.h"76#include "archive_private.h"77#include "archive_entry_private.h"7879#if !defined(HAVE_MAJOR) && !defined(major)80/* Replacement for major/minor/makedev. */81#define major(x) ((int)(0x00ff & ((x) >> 8)))82#define minor(x) ((int)(0xffff00ff & (x)))83#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))84#endif8586/* Play games to come up with a suitable makedev() definition. */87#ifdef __QNXNTO__88/* QNX. <sigh> */89#include <sys/netmgr.h>90#define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))91#elif defined makedev92/* There's a "makedev" macro. */93#define ae_makedev(maj, min) makedev((maj), (min))94#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))95/* Windows. <sigh> */96#define ae_makedev(maj, min) mkdev((maj), (min))97#else98/* There's a "makedev" function. */99#define ae_makedev(maj, min) makedev((maj), (min))100#endif101102/*103* This adjustment is needed to support the following idiom for adding104* 1000ns to the stored time:105* archive_entry_set_atime(archive_entry_atime(),106* archive_entry_atime_nsec() + 1000)107* The additional if() here compensates for ambiguity in the C standard,108* which permits two possible interpretations of a % b when a is negative.109*/110#define FIX_NS(t,ns) \111do { \112t += ns / 1000000000; \113ns %= 1000000000; \114if (ns < 0) { --t; ns += 1000000000; } \115} while (0)116117static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear);118static const wchar_t *ae_wcstofflags(const wchar_t *stringp,119unsigned long *setp, unsigned long *clrp);120static const char *ae_strtofflags(const char *stringp, size_t length,121unsigned long *setp, unsigned long *clrp);122123#ifndef HAVE_WCSCPY124static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)125{126wchar_t *dest = s1;127while ((*s1 = *s2) != L'\0')128++s1, ++s2;129return dest;130}131#endif132#ifndef HAVE_WCSLEN133static size_t wcslen(const wchar_t *s)134{135const wchar_t *p = s;136while (*p != L'\0')137++p;138return p - s;139}140#endif141#ifndef HAVE_WMEMCMP142/* Good enough for simple equality testing, but not for sorting. */143#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))144#endif145146/****************************************************************************147*148* Public Interface149*150****************************************************************************/151152struct archive_entry *153archive_entry_clear(struct archive_entry *entry)154{155if (entry == NULL)156return (NULL);157archive_mstring_clean(&entry->ae_fflags_text);158archive_mstring_clean(&entry->ae_gname);159archive_mstring_clean(&entry->ae_linkname);160archive_mstring_clean(&entry->ae_pathname);161archive_mstring_clean(&entry->ae_sourcepath);162archive_mstring_clean(&entry->ae_uname);163archive_entry_copy_mac_metadata(entry, NULL, 0);164archive_acl_clear(&entry->acl);165archive_entry_xattr_clear(entry);166archive_entry_sparse_clear(entry);167free(entry->stat);168entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;169memset(entry, 0, sizeof(*entry));170return entry;171}172173struct archive_entry *174archive_entry_clone(struct archive_entry *entry)175{176struct archive_entry *entry2;177struct ae_xattr *xp;178struct ae_sparse *sp;179size_t s;180const void *p;181182/* Allocate new structure and copy over all of the fields. */183/* TODO: Should we copy the archive over? Or require a new archive184* as an argument? */185entry2 = archive_entry_new2(entry->archive);186if (entry2 == NULL)187return (NULL);188entry2->ae_stat = entry->ae_stat;189entry2->ae_fflags_set = entry->ae_fflags_set;190entry2->ae_fflags_clear = entry->ae_fflags_clear;191192/* TODO: XXX If clone can have a different archive, what do we do here if193* character sets are different? XXX */194archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);195archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);196archive_mstring_copy(&entry2->ae_linkname, &entry->ae_linkname);197archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);198archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);199entry2->ae_set = entry->ae_set;200archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);201202/* Copy symlink type */203entry2->ae_symlink_type = entry->ae_symlink_type;204205/* Copy encryption status */206entry2->encryption = entry->encryption;207208/* Copy digests */209#define copy_digest(_e2, _e, _t) \210memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t))211212copy_digest(entry2, entry, md5);213copy_digest(entry2, entry, rmd160);214copy_digest(entry2, entry, sha1);215copy_digest(entry2, entry, sha256);216copy_digest(entry2, entry, sha384);217copy_digest(entry2, entry, sha512);218219#undef copy_digest220221/* Copy ACL data over. */222archive_acl_copy(&entry2->acl, &entry->acl);223224/* Copy Mac OS metadata. */225p = archive_entry_mac_metadata(entry, &s);226archive_entry_copy_mac_metadata(entry2, p, s);227228/* Copy xattr data over. */229xp = entry->xattr_head;230while (xp != NULL) {231archive_entry_xattr_add_entry(entry2,232xp->name, xp->value, xp->size);233xp = xp->next;234}235236/* Copy sparse data over. */237sp = entry->sparse_head;238while (sp != NULL) {239archive_entry_sparse_add_entry(entry2,240sp->offset, sp->length);241sp = sp->next;242}243244return (entry2);245}246247void248archive_entry_free(struct archive_entry *entry)249{250archive_entry_clear(entry);251free(entry);252}253254struct archive_entry *255archive_entry_new(void)256{257return archive_entry_new2(NULL);258}259260struct archive_entry *261archive_entry_new2(struct archive *a)262{263struct archive_entry *entry;264265entry = calloc(1, sizeof(*entry));266if (entry == NULL)267return (NULL);268entry->archive = a;269entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;270return (entry);271}272273/*274* Functions for reading fields from an archive_entry.275*/276277time_t278archive_entry_atime(struct archive_entry *entry)279{280return (entry->ae_stat.aest_atime);281}282283long284archive_entry_atime_nsec(struct archive_entry *entry)285{286return (entry->ae_stat.aest_atime_nsec);287}288289int290archive_entry_atime_is_set(struct archive_entry *entry)291{292return (entry->ae_set & AE_SET_ATIME);293}294295time_t296archive_entry_birthtime(struct archive_entry *entry)297{298return (entry->ae_stat.aest_birthtime);299}300301long302archive_entry_birthtime_nsec(struct archive_entry *entry)303{304return (entry->ae_stat.aest_birthtime_nsec);305}306307int308archive_entry_birthtime_is_set(struct archive_entry *entry)309{310return (entry->ae_set & AE_SET_BIRTHTIME);311}312313time_t314archive_entry_ctime(struct archive_entry *entry)315{316return (entry->ae_stat.aest_ctime);317}318319int320archive_entry_ctime_is_set(struct archive_entry *entry)321{322return (entry->ae_set & AE_SET_CTIME);323}324325long326archive_entry_ctime_nsec(struct archive_entry *entry)327{328return (entry->ae_stat.aest_ctime_nsec);329}330331dev_t332archive_entry_dev(struct archive_entry *entry)333{334if (entry->ae_stat.aest_dev_is_broken_down)335return ae_makedev(entry->ae_stat.aest_devmajor,336entry->ae_stat.aest_devminor);337else338return (entry->ae_stat.aest_dev);339}340341int342archive_entry_dev_is_set(struct archive_entry *entry)343{344return (entry->ae_set & AE_SET_DEV);345}346347dev_t348archive_entry_devmajor(struct archive_entry *entry)349{350if (entry->ae_stat.aest_dev_is_broken_down)351return (entry->ae_stat.aest_devmajor);352else353return major(entry->ae_stat.aest_dev);354}355356dev_t357archive_entry_devminor(struct archive_entry *entry)358{359if (entry->ae_stat.aest_dev_is_broken_down)360return (entry->ae_stat.aest_devminor);361else362return minor(entry->ae_stat.aest_dev);363}364365__LA_MODE_T366archive_entry_filetype(struct archive_entry *entry)367{368return (AE_IFMT & entry->acl.mode);369}370371int372archive_entry_filetype_is_set(struct archive_entry *entry)373{374return (entry->ae_set & AE_SET_FILETYPE);375}376377void378archive_entry_fflags(struct archive_entry *entry,379unsigned long *set, unsigned long *clear)380{381*set = entry->ae_fflags_set;382*clear = entry->ae_fflags_clear;383}384385/*386* Note: if text was provided, this just returns that text. If you387* really need the text to be rebuilt in a canonical form, set the388* text, ask for the bitmaps, then set the bitmaps. (Setting the389* bitmaps clears any stored text.) This design is deliberate: if390* we're editing archives, we don't want to discard flags just because391* they aren't supported on the current system. The bitmap<->text392* conversions are platform-specific (see below).393*/394const char *395archive_entry_fflags_text(struct archive_entry *entry)396{397const char *f;398char *p;399400if (archive_mstring_get_mbs(entry->archive,401&entry->ae_fflags_text, &f) == 0) {402if (f != NULL)403return (f);404} else if (errno == ENOMEM)405__archive_errx(1, "No memory");406407if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0)408return (NULL);409410p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);411if (p == NULL)412return (NULL);413414archive_mstring_copy_mbs(&entry->ae_fflags_text, p);415free(p);416if (archive_mstring_get_mbs(entry->archive,417&entry->ae_fflags_text, &f) == 0)418return (f);419if (errno == ENOMEM)420__archive_errx(1, "No memory");421return (NULL);422}423424la_int64_t425archive_entry_gid(struct archive_entry *entry)426{427return (entry->ae_stat.aest_gid);428}429430int431archive_entry_gid_is_set(struct archive_entry *entry)432{433return (entry->ae_set & AE_SET_GID);434}435436const char *437archive_entry_gname(struct archive_entry *entry)438{439const char *p;440if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)441return (p);442if (errno == ENOMEM)443__archive_errx(1, "No memory");444return (NULL);445}446447const char *448archive_entry_gname_utf8(struct archive_entry *entry)449{450const char *p;451if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)452return (p);453if (errno == ENOMEM)454__archive_errx(1, "No memory");455return (NULL);456}457458459const wchar_t *460archive_entry_gname_w(struct archive_entry *entry)461{462const wchar_t *p;463if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)464return (p);465if (errno == ENOMEM)466__archive_errx(1, "No memory");467return (NULL);468}469470int471_archive_entry_gname_l(struct archive_entry *entry,472const char **p, size_t *len, struct archive_string_conv *sc)473{474return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc));475}476477void478archive_entry_set_link_to_hardlink(struct archive_entry *entry)479{480if ((entry->ae_set & AE_SET_SYMLINK) != 0) {481entry->ae_set &= ~AE_SET_SYMLINK;482}483entry->ae_set |= AE_SET_HARDLINK;484}485486const char *487archive_entry_hardlink(struct archive_entry *entry)488{489const char *p;490if ((entry->ae_set & AE_SET_HARDLINK) == 0)491return (NULL);492if (archive_mstring_get_mbs(493entry->archive, &entry->ae_linkname, &p) == 0)494return (p);495if (errno == ENOMEM)496__archive_errx(1, "No memory");497return (NULL);498}499500const char *501archive_entry_hardlink_utf8(struct archive_entry *entry)502{503const char *p;504if ((entry->ae_set & AE_SET_HARDLINK) == 0)505return (NULL);506if (archive_mstring_get_utf8(507entry->archive, &entry->ae_linkname, &p) == 0)508return (p);509if (errno == ENOMEM)510__archive_errx(1, "No memory");511return (NULL);512}513514const wchar_t *515archive_entry_hardlink_w(struct archive_entry *entry)516{517const wchar_t *p;518if ((entry->ae_set & AE_SET_HARDLINK) == 0)519return (NULL);520if (archive_mstring_get_wcs(521entry->archive, &entry->ae_linkname, &p) == 0)522return (p);523if (errno == ENOMEM)524__archive_errx(1, "No memory");525return (NULL);526}527528int529archive_entry_hardlink_is_set(struct archive_entry *entry)530{531return (entry->ae_set & AE_SET_HARDLINK) != 0;532}533534int535_archive_entry_hardlink_l(struct archive_entry *entry,536const char **p, size_t *len, struct archive_string_conv *sc)537{538if ((entry->ae_set & AE_SET_HARDLINK) == 0) {539*p = NULL;540*len = 0;541return (0);542}543return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc));544}545546la_int64_t547archive_entry_ino(struct archive_entry *entry)548{549return (entry->ae_stat.aest_ino);550}551552int553archive_entry_ino_is_set(struct archive_entry *entry)554{555return (entry->ae_set & AE_SET_INO);556}557558la_int64_t559archive_entry_ino64(struct archive_entry *entry)560{561return (entry->ae_stat.aest_ino);562}563564__LA_MODE_T565archive_entry_mode(struct archive_entry *entry)566{567return (entry->acl.mode);568}569570time_t571archive_entry_mtime(struct archive_entry *entry)572{573return (entry->ae_stat.aest_mtime);574}575576long577archive_entry_mtime_nsec(struct archive_entry *entry)578{579return (entry->ae_stat.aest_mtime_nsec);580}581582int583archive_entry_mtime_is_set(struct archive_entry *entry)584{585return (entry->ae_set & AE_SET_MTIME);586}587588unsigned int589archive_entry_nlink(struct archive_entry *entry)590{591return (entry->ae_stat.aest_nlink);592}593594/* Instead, our caller could have chosen a specific encoding595* (archive_mstring_get_mbs, archive_mstring_get_utf8,596* archive_mstring_get_wcs). So we should try multiple597* encodings. Try mbs first because of history, even though598* utf8 might be better for pathname portability.599* Also omit wcs because of type mismatch (char * versus wchar *)600*/601const char *602archive_entry_pathname(struct archive_entry *entry)603{604const char *p;605if (archive_mstring_get_mbs(606entry->archive, &entry->ae_pathname, &p) == 0)607return (p);608#if HAVE_EILSEQ /*{*/609if (errno == EILSEQ) {610if (archive_mstring_get_utf8(611entry->archive, &entry->ae_pathname, &p) == 0)612return (p);613}614#endif /*}*/615if (errno == ENOMEM)616__archive_errx(1, "No memory");617return (NULL);618}619620const char *621archive_entry_pathname_utf8(struct archive_entry *entry)622{623const char *p;624if (archive_mstring_get_utf8(625entry->archive, &entry->ae_pathname, &p) == 0)626return (p);627if (errno == ENOMEM)628__archive_errx(1, "No memory");629return (NULL);630}631632const wchar_t *633archive_entry_pathname_w(struct archive_entry *entry)634{635const wchar_t *p;636if (archive_mstring_get_wcs(637entry->archive, &entry->ae_pathname, &p) == 0)638return (p);639if (errno == ENOMEM)640__archive_errx(1, "No memory");641return (NULL);642}643644int645_archive_entry_pathname_l(struct archive_entry *entry,646const char **p, size_t *len, struct archive_string_conv *sc)647{648return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc));649}650651__LA_MODE_T652archive_entry_perm(struct archive_entry *entry)653{654return (~AE_IFMT & entry->acl.mode);655}656657int658archive_entry_perm_is_set(struct archive_entry *entry)659{660return (entry->ae_set & AE_SET_PERM);661}662663int664archive_entry_rdev_is_set(struct archive_entry *entry)665{666return (entry->ae_set & AE_SET_RDEV);667}668669dev_t670archive_entry_rdev(struct archive_entry *entry)671{672if (archive_entry_rdev_is_set(entry)) {673if (entry->ae_stat.aest_rdev_is_broken_down)674return ae_makedev(entry->ae_stat.aest_rdevmajor,675entry->ae_stat.aest_rdevminor);676else677return (entry->ae_stat.aest_rdev);678} else {679return 0;680}681}682683dev_t684archive_entry_rdevmajor(struct archive_entry *entry)685{686if (archive_entry_rdev_is_set(entry)) {687if (entry->ae_stat.aest_rdev_is_broken_down)688return (entry->ae_stat.aest_rdevmajor);689else690return major(entry->ae_stat.aest_rdev);691} else {692return 0;693}694}695696dev_t697archive_entry_rdevminor(struct archive_entry *entry)698{699if (archive_entry_rdev_is_set(entry)) {700if (entry->ae_stat.aest_rdev_is_broken_down)701return (entry->ae_stat.aest_rdevminor);702else703return minor(entry->ae_stat.aest_rdev);704} else {705return 0;706}707}708709la_int64_t710archive_entry_size(struct archive_entry *entry)711{712return (entry->ae_stat.aest_size);713}714715int716archive_entry_size_is_set(struct archive_entry *entry)717{718return (entry->ae_set & AE_SET_SIZE);719}720721const char *722archive_entry_sourcepath(struct archive_entry *entry)723{724const char *p;725if (archive_mstring_get_mbs(726entry->archive, &entry->ae_sourcepath, &p) == 0)727return (p);728if (errno == ENOMEM)729__archive_errx(1, "No memory");730return (NULL);731}732733const wchar_t *734archive_entry_sourcepath_w(struct archive_entry *entry)735{736const wchar_t *p;737if (archive_mstring_get_wcs(738entry->archive, &entry->ae_sourcepath, &p) == 0)739return (p);740return (NULL);741}742743const char *744archive_entry_symlink(struct archive_entry *entry)745{746const char *p;747if ((entry->ae_set & AE_SET_SYMLINK) == 0)748return (NULL);749if (archive_mstring_get_mbs(750entry->archive, &entry->ae_linkname, &p) == 0)751return (p);752if (errno == ENOMEM)753__archive_errx(1, "No memory");754return (NULL);755}756757void758archive_entry_set_link_to_symlink(struct archive_entry *entry)759{760if ((entry->ae_set & AE_SET_HARDLINK) != 0) {761entry->ae_set &= ~AE_SET_HARDLINK;762}763entry->ae_set |= AE_SET_SYMLINK;764}765766int767archive_entry_symlink_type(struct archive_entry *entry)768{769return (entry->ae_symlink_type);770}771772const char *773archive_entry_symlink_utf8(struct archive_entry *entry)774{775const char *p;776if ((entry->ae_set & AE_SET_SYMLINK) == 0)777return (NULL);778if (archive_mstring_get_utf8(779entry->archive, &entry->ae_linkname, &p) == 0)780return (p);781if (errno == ENOMEM)782__archive_errx(1, "No memory");783return (NULL);784}785786const wchar_t *787archive_entry_symlink_w(struct archive_entry *entry)788{789const wchar_t *p;790if ((entry->ae_set & AE_SET_SYMLINK) == 0)791return (NULL);792if (archive_mstring_get_wcs(793entry->archive, &entry->ae_linkname, &p) == 0)794return (p);795if (errno == ENOMEM)796__archive_errx(1, "No memory");797return (NULL);798}799800int801_archive_entry_symlink_l(struct archive_entry *entry,802const char **p, size_t *len, struct archive_string_conv *sc)803{804if ((entry->ae_set & AE_SET_SYMLINK) == 0) {805*p = NULL;806*len = 0;807return (0);808}809return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc));810}811812la_int64_t813archive_entry_uid(struct archive_entry *entry)814{815return (entry->ae_stat.aest_uid);816}817818int819archive_entry_uid_is_set(struct archive_entry *entry)820{821return (entry->ae_set & AE_SET_UID);822}823824const char *825archive_entry_uname(struct archive_entry *entry)826{827const char *p;828if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)829return (p);830if (errno == ENOMEM)831__archive_errx(1, "No memory");832return (NULL);833}834835const char *836archive_entry_uname_utf8(struct archive_entry *entry)837{838const char *p;839if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)840return (p);841if (errno == ENOMEM)842__archive_errx(1, "No memory");843return (NULL);844}845846const wchar_t *847archive_entry_uname_w(struct archive_entry *entry)848{849const wchar_t *p;850if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)851return (p);852if (errno == ENOMEM)853__archive_errx(1, "No memory");854return (NULL);855}856857int858_archive_entry_uname_l(struct archive_entry *entry,859const char **p, size_t *len, struct archive_string_conv *sc)860{861return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc));862}863864int865archive_entry_is_data_encrypted(struct archive_entry *entry)866{867return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);868}869870int871archive_entry_is_metadata_encrypted(struct archive_entry *entry)872{873return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);874}875876int877archive_entry_is_encrypted(struct archive_entry *entry)878{879return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));880}881882/*883* Functions to set archive_entry properties.884*/885886void887archive_entry_set_filetype(struct archive_entry *entry, unsigned int type)888{889entry->stat_valid = 0;890entry->acl.mode &= ~AE_IFMT;891entry->acl.mode |= AE_IFMT & type;892entry->ae_set |= AE_SET_FILETYPE;893}894895void896archive_entry_set_fflags(struct archive_entry *entry,897unsigned long set, unsigned long clear)898{899archive_mstring_clean(&entry->ae_fflags_text);900entry->ae_fflags_set = set;901entry->ae_fflags_clear = clear;902}903904const char *905archive_entry_copy_fflags_text(struct archive_entry *entry,906const char *flags)907{908return archive_entry_copy_fflags_text_len(entry, flags, strlen(flags));909}910911const char *912archive_entry_copy_fflags_text_len(struct archive_entry *entry,913const char *flags, size_t flags_length)914{915archive_mstring_copy_mbs_len(&entry->ae_fflags_text, flags, flags_length);916return (ae_strtofflags(flags, flags_length,917&entry->ae_fflags_set, &entry->ae_fflags_clear));918}919920const wchar_t *921archive_entry_copy_fflags_text_w(struct archive_entry *entry,922const wchar_t *flags)923{924archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);925return (ae_wcstofflags(flags,926&entry->ae_fflags_set, &entry->ae_fflags_clear));927}928929void930archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)931{932if (g < 0) {933g = 0;934}935entry->stat_valid = 0;936entry->ae_stat.aest_gid = g;937entry->ae_set |= AE_SET_GID;938}939940void941archive_entry_set_gname(struct archive_entry *entry, const char *name)942{943archive_mstring_copy_mbs(&entry->ae_gname, name);944}945946void947archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)948{949archive_mstring_copy_utf8(&entry->ae_gname, name);950}951952void953archive_entry_copy_gname(struct archive_entry *entry, const char *name)954{955archive_mstring_copy_mbs(&entry->ae_gname, name);956}957958void959archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)960{961archive_mstring_copy_wcs(&entry->ae_gname, name);962}963964int965archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)966{967if (archive_mstring_update_utf8(entry->archive,968&entry->ae_gname, name) == 0)969return (1);970if (errno == ENOMEM)971__archive_errx(1, "No memory");972return (0);973}974975int976_archive_entry_copy_gname_l(struct archive_entry *entry,977const char *name, size_t len, struct archive_string_conv *sc)978{979return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));980}981982void983archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)984{985if (ino < 0) {986ino = 0;987}988entry->stat_valid = 0;989entry->ae_set |= AE_SET_INO;990entry->ae_stat.aest_ino = ino;991}992993void994archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)995{996if (ino < 0) {997ino = 0;998}999entry->stat_valid = 0;1000entry->ae_set |= AE_SET_INO;1001entry->ae_stat.aest_ino = ino;1002}10031004void1005archive_entry_set_hardlink(struct archive_entry *entry, const char *target)1006{1007if (target == NULL) {1008entry->ae_set &= ~AE_SET_HARDLINK;1009if (entry->ae_set & AE_SET_SYMLINK) {1010return;1011}1012} else {1013entry->ae_set |= AE_SET_HARDLINK;1014}1015entry->ae_set &= ~AE_SET_SYMLINK;1016archive_mstring_copy_mbs(&entry->ae_linkname, target);1017}10181019void1020archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)1021{1022if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))1023return;1024archive_mstring_copy_utf8(&entry->ae_linkname, target);1025if (target != NULL)1026entry->ae_set |= AE_SET_HARDLINK;1027else1028entry->ae_set &= ~AE_SET_HARDLINK;1029}10301031void1032archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)1033{1034if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))1035return;1036archive_mstring_copy_mbs(&entry->ae_linkname, target);1037if (target != NULL)1038entry->ae_set |= AE_SET_HARDLINK;1039else1040entry->ae_set &= ~AE_SET_HARDLINK;1041}10421043void1044archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)1045{1046if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))1047return;1048archive_mstring_copy_wcs(&entry->ae_linkname, target);1049if (target != NULL)1050entry->ae_set |= AE_SET_HARDLINK;1051else1052entry->ae_set &= ~AE_SET_HARDLINK;1053}10541055int1056archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)1057{1058if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))1059return (0);1060if (target != NULL)1061entry->ae_set |= AE_SET_HARDLINK;1062else1063entry->ae_set &= ~AE_SET_HARDLINK;1064if (archive_mstring_update_utf8(entry->archive,1065&entry->ae_linkname, target) == 0)1066return (1);1067if (errno == ENOMEM)1068__archive_errx(1, "No memory");1069return (0);1070}10711072int1073_archive_entry_copy_hardlink_l(struct archive_entry *entry,1074const char *target, size_t len, struct archive_string_conv *sc)1075{1076int r;10771078if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))1079return (0);1080r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,1081target, len, sc);1082if (target != NULL && r == 0)1083entry->ae_set |= AE_SET_HARDLINK;1084else1085entry->ae_set &= ~AE_SET_HARDLINK;1086return (r);1087}10881089void1090archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)1091{1092FIX_NS(t, ns);1093entry->stat_valid = 0;1094entry->ae_set |= AE_SET_ATIME;1095entry->ae_stat.aest_atime = t;1096entry->ae_stat.aest_atime_nsec = ns;1097}10981099void1100archive_entry_unset_atime(struct archive_entry *entry)1101{1102archive_entry_set_atime(entry, 0, 0);1103entry->ae_set &= ~AE_SET_ATIME;1104}11051106void1107archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)1108{1109FIX_NS(t, ns);1110entry->stat_valid = 0;1111entry->ae_set |= AE_SET_BIRTHTIME;1112entry->ae_stat.aest_birthtime = t;1113entry->ae_stat.aest_birthtime_nsec = ns;1114}11151116void1117archive_entry_unset_birthtime(struct archive_entry *entry)1118{1119archive_entry_set_birthtime(entry, 0, 0);1120entry->ae_set &= ~AE_SET_BIRTHTIME;1121}11221123void1124archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)1125{1126FIX_NS(t, ns);1127entry->stat_valid = 0;1128entry->ae_set |= AE_SET_CTIME;1129entry->ae_stat.aest_ctime = t;1130entry->ae_stat.aest_ctime_nsec = ns;1131}11321133void1134archive_entry_unset_ctime(struct archive_entry *entry)1135{1136archive_entry_set_ctime(entry, 0, 0);1137entry->ae_set &= ~AE_SET_CTIME;1138}11391140void1141archive_entry_set_dev(struct archive_entry *entry, dev_t d)1142{1143entry->stat_valid = 0;1144entry->ae_set |= AE_SET_DEV;1145entry->ae_stat.aest_dev_is_broken_down = 0;1146entry->ae_stat.aest_dev = d;1147}11481149void1150archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)1151{1152entry->stat_valid = 0;1153entry->ae_set |= AE_SET_DEV;1154entry->ae_stat.aest_dev_is_broken_down = 1;1155entry->ae_stat.aest_devmajor = m;1156}11571158void1159archive_entry_set_devminor(struct archive_entry *entry, dev_t m)1160{1161entry->stat_valid = 0;1162entry->ae_set |= AE_SET_DEV;1163entry->ae_stat.aest_dev_is_broken_down = 1;1164entry->ae_stat.aest_devminor = m;1165}11661167/* Set symlink if symlink is already set, else set hardlink. */1168void1169archive_entry_set_link(struct archive_entry *entry, const char *target)1170{1171archive_mstring_copy_mbs(&entry->ae_linkname, target);1172if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1173entry->ae_set |= AE_SET_HARDLINK;1174}1175}11761177void1178archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)1179{1180archive_mstring_copy_utf8(&entry->ae_linkname, target);1181if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1182entry->ae_set |= AE_SET_HARDLINK;1183}1184}11851186/* Set symlink if symlink is already set, else set hardlink. */1187void1188archive_entry_copy_link(struct archive_entry *entry, const char *target)1189{1190archive_mstring_copy_mbs(&entry->ae_linkname, target);1191if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1192entry->ae_set |= AE_SET_HARDLINK;1193}1194}11951196/* Set symlink if symlink is already set, else set hardlink. */1197void1198archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)1199{1200archive_mstring_copy_wcs(&entry->ae_linkname, target);1201if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1202entry->ae_set |= AE_SET_HARDLINK;1203}1204}12051206int1207archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)1208{1209int r;1210r = archive_mstring_update_utf8(entry->archive,1211&entry->ae_linkname, target);1212if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1213entry->ae_set |= AE_SET_HARDLINK;1214}1215if (r == 0)1216return (1);1217if (errno == ENOMEM)1218__archive_errx(1, "No memory");1219return (0);1220}12211222int1223_archive_entry_copy_link_l(struct archive_entry *entry,1224const char *target, size_t len, struct archive_string_conv *sc)1225{1226int r;12271228r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,1229target, len, sc);1230if ((entry->ae_set & AE_SET_SYMLINK) == 0) {1231entry->ae_set |= AE_SET_HARDLINK;1232}1233return (r);1234}12351236void1237archive_entry_set_mode(struct archive_entry *entry, mode_t m)1238{1239entry->stat_valid = 0;1240entry->acl.mode = m;1241entry->ae_set |= AE_SET_PERM | AE_SET_FILETYPE;1242}12431244void1245archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)1246{1247FIX_NS(t, ns);1248entry->stat_valid = 0;1249entry->ae_set |= AE_SET_MTIME;1250entry->ae_stat.aest_mtime = t;1251entry->ae_stat.aest_mtime_nsec = ns;1252}12531254void1255archive_entry_unset_mtime(struct archive_entry *entry)1256{1257archive_entry_set_mtime(entry, 0, 0);1258entry->ae_set &= ~AE_SET_MTIME;1259}12601261void1262archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)1263{1264entry->stat_valid = 0;1265entry->ae_stat.aest_nlink = nlink;1266}12671268void1269archive_entry_set_pathname(struct archive_entry *entry, const char *name)1270{1271archive_mstring_copy_mbs(&entry->ae_pathname, name);1272}12731274void1275archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)1276{1277archive_mstring_copy_utf8(&entry->ae_pathname, name);1278}12791280void1281archive_entry_copy_pathname(struct archive_entry *entry, const char *name)1282{1283archive_mstring_copy_mbs(&entry->ae_pathname, name);1284}12851286void1287archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)1288{1289archive_mstring_copy_wcs(&entry->ae_pathname, name);1290}12911292int1293archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)1294{1295if (archive_mstring_update_utf8(entry->archive,1296&entry->ae_pathname, name) == 0)1297return (1);1298if (errno == ENOMEM)1299__archive_errx(1, "No memory");1300return (0);1301}13021303int1304_archive_entry_copy_pathname_l(struct archive_entry *entry,1305const char *name, size_t len, struct archive_string_conv *sc)1306{1307return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,1308name, len, sc));1309}13101311void1312archive_entry_set_perm(struct archive_entry *entry, mode_t p)1313{1314entry->stat_valid = 0;1315entry->acl.mode &= AE_IFMT;1316entry->acl.mode |= ~AE_IFMT & p;1317entry->ae_set |= AE_SET_PERM;1318}13191320void1321archive_entry_set_rdev(struct archive_entry *entry, dev_t m)1322{1323entry->stat_valid = 0;1324entry->ae_stat.aest_rdev = m;1325entry->ae_stat.aest_rdev_is_broken_down = 0;1326entry->ae_stat.aest_rdevmajor = 0;1327entry->ae_stat.aest_rdevminor = 0;1328entry->ae_set |= AE_SET_RDEV;1329}13301331void1332archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)1333{1334entry->stat_valid = 0;1335entry->ae_stat.aest_rdev_is_broken_down = 1;1336entry->ae_stat.aest_rdev = 0;1337entry->ae_stat.aest_rdevmajor = m;1338entry->ae_set |= AE_SET_RDEV;1339}13401341void1342archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)1343{1344entry->stat_valid = 0;1345entry->ae_stat.aest_rdev_is_broken_down = 1;1346entry->ae_stat.aest_rdev = 0;1347entry->ae_stat.aest_rdevminor = m;1348entry->ae_set |= AE_SET_RDEV;1349}13501351void1352archive_entry_set_size(struct archive_entry *entry, la_int64_t s)1353{1354if (s < 0) {1355s = 0;1356}1357entry->stat_valid = 0;1358entry->ae_stat.aest_size = s;1359entry->ae_set |= AE_SET_SIZE;1360}13611362void1363archive_entry_unset_size(struct archive_entry *entry)1364{1365archive_entry_set_size(entry, 0);1366entry->ae_set &= ~AE_SET_SIZE;1367}13681369void1370archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)1371{1372archive_mstring_copy_mbs(&entry->ae_sourcepath, path);1373}13741375void1376archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)1377{1378archive_mstring_copy_wcs(&entry->ae_sourcepath, path);1379}13801381void1382archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)1383{1384if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1385return;1386archive_mstring_copy_mbs(&entry->ae_linkname, linkname);1387entry->ae_set &= ~AE_SET_HARDLINK;1388if (linkname == NULL)1389entry->ae_set &= ~AE_SET_SYMLINK;1390else1391entry->ae_set |= AE_SET_SYMLINK;1392}13931394void1395archive_entry_set_symlink_type(struct archive_entry *entry, int type)1396{1397entry->ae_symlink_type = type;1398}13991400void1401archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)1402{1403if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1404return;1405archive_mstring_copy_utf8(&entry->ae_linkname, linkname);1406entry->ae_set &= ~AE_SET_HARDLINK;1407if (linkname == NULL)1408entry->ae_set &= ~AE_SET_SYMLINK;1409else1410entry->ae_set |= AE_SET_SYMLINK;1411}14121413void1414archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)1415{1416if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1417return;1418archive_mstring_copy_mbs(&entry->ae_linkname, linkname);1419entry->ae_set &= ~AE_SET_HARDLINK;1420if (linkname == NULL)1421entry->ae_set &= ~AE_SET_SYMLINK;1422else1423entry->ae_set |= AE_SET_SYMLINK;1424}14251426void1427archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)1428{1429if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1430return;1431archive_mstring_copy_wcs(&entry->ae_linkname, linkname);1432entry->ae_set &= ~AE_SET_HARDLINK;1433if (linkname == NULL)1434entry->ae_set &= ~AE_SET_SYMLINK;1435else1436entry->ae_set |= AE_SET_SYMLINK;1437}14381439int1440archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)1441{1442if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1443return (0);1444entry->ae_set &= ~AE_SET_HARDLINK;1445if (linkname == NULL)1446entry->ae_set &= ~AE_SET_SYMLINK;1447else1448entry->ae_set |= AE_SET_SYMLINK;1449if (archive_mstring_update_utf8(entry->archive,1450&entry->ae_linkname, linkname) == 0)1451return (1);1452if (errno == ENOMEM)1453__archive_errx(1, "No memory");1454return (0);1455}14561457int1458_archive_entry_copy_symlink_l(struct archive_entry *entry,1459const char *linkname, size_t len, struct archive_string_conv *sc)1460{1461int r;14621463if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))1464return (0);1465entry->ae_set &= ~AE_SET_HARDLINK;1466r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,1467linkname, len, sc);1468if (linkname == NULL || r != 0)1469entry->ae_set &= ~AE_SET_SYMLINK;1470else1471entry->ae_set |= AE_SET_SYMLINK;1472return (r);1473}14741475void1476archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)1477{1478if (u < 0) {1479u = 0;1480}1481entry->stat_valid = 0;1482entry->ae_stat.aest_uid = u;1483entry->ae_set |= AE_SET_UID;1484}14851486void1487archive_entry_set_uname(struct archive_entry *entry, const char *name)1488{1489archive_mstring_copy_mbs(&entry->ae_uname, name);1490}14911492void1493archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)1494{1495archive_mstring_copy_utf8(&entry->ae_uname, name);1496}14971498void1499archive_entry_copy_uname(struct archive_entry *entry, const char *name)1500{1501archive_mstring_copy_mbs(&entry->ae_uname, name);1502}15031504void1505archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)1506{1507archive_mstring_copy_wcs(&entry->ae_uname, name);1508}15091510int1511archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)1512{1513if (archive_mstring_update_utf8(entry->archive,1514&entry->ae_uname, name) == 0)1515return (1);1516if (errno == ENOMEM)1517__archive_errx(1, "No memory");1518return (0);1519}15201521void1522archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)1523{1524if (is_encrypted) {1525entry->encryption |= AE_ENCRYPTION_DATA;1526} else {1527entry->encryption &= ~AE_ENCRYPTION_DATA;1528}1529}15301531void1532archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)1533{1534if (is_encrypted) {1535entry->encryption |= AE_ENCRYPTION_METADATA;1536} else {1537entry->encryption &= ~AE_ENCRYPTION_METADATA;1538}1539}15401541int1542_archive_entry_copy_uname_l(struct archive_entry *entry,1543const char *name, size_t len, struct archive_string_conv *sc)1544{1545return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,1546name, len, sc));1547}15481549const void *1550archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)1551{1552*s = entry->mac_metadata_size;1553return entry->mac_metadata;1554}15551556void1557archive_entry_copy_mac_metadata(struct archive_entry *entry,1558const void *p, size_t s)1559{1560free(entry->mac_metadata);1561if (p == NULL || s == 0) {1562entry->mac_metadata = NULL;1563entry->mac_metadata_size = 0;1564} else {1565entry->mac_metadata_size = s;1566entry->mac_metadata = malloc(s);1567if (entry->mac_metadata == NULL)1568abort();1569memcpy(entry->mac_metadata, p, s);1570}1571}15721573/* Digest handling */1574const unsigned char *1575archive_entry_digest(struct archive_entry *entry, int type)1576{1577switch (type) {1578case ARCHIVE_ENTRY_DIGEST_MD5:1579return entry->digest.md5;1580case ARCHIVE_ENTRY_DIGEST_RMD160:1581return entry->digest.rmd160;1582case ARCHIVE_ENTRY_DIGEST_SHA1:1583return entry->digest.sha1;1584case ARCHIVE_ENTRY_DIGEST_SHA256:1585return entry->digest.sha256;1586case ARCHIVE_ENTRY_DIGEST_SHA384:1587return entry->digest.sha384;1588case ARCHIVE_ENTRY_DIGEST_SHA512:1589return entry->digest.sha512;1590default:1591return NULL;1592}1593}15941595int1596archive_entry_set_digest(struct archive_entry *entry, int type,1597const unsigned char *digest)1598{1599#define copy_digest(_e, _t, _d)\1600memcpy(_e->digest._t, _d, sizeof(_e->digest._t))16011602switch (type) {1603case ARCHIVE_ENTRY_DIGEST_MD5:1604copy_digest(entry, md5, digest);1605break;1606case ARCHIVE_ENTRY_DIGEST_RMD160:1607copy_digest(entry, rmd160, digest);1608break;1609case ARCHIVE_ENTRY_DIGEST_SHA1:1610copy_digest(entry, sha1, digest);1611break;1612case ARCHIVE_ENTRY_DIGEST_SHA256:1613copy_digest(entry, sha256, digest);1614break;1615case ARCHIVE_ENTRY_DIGEST_SHA384:1616copy_digest(entry, sha384, digest);1617break;1618case ARCHIVE_ENTRY_DIGEST_SHA512:1619copy_digest(entry, sha512, digest);1620break;1621default:1622return ARCHIVE_WARN;1623}16241625return ARCHIVE_OK;1626#undef copy_digest1627}16281629/*1630* ACL management. The following would, of course, be a lot simpler1631* if: 1) the last draft of POSIX.1e were a really thorough and1632* complete standard that addressed the needs of ACL archiving and 2)1633* everyone followed it faithfully. Alas, neither is true, so the1634* following is a lot more complex than might seem necessary to the1635* uninitiated.1636*/16371638struct archive_acl *1639archive_entry_acl(struct archive_entry *entry)1640{1641return &entry->acl;1642}16431644void1645archive_entry_acl_clear(struct archive_entry *entry)1646{1647archive_acl_clear(&entry->acl);1648}16491650/*1651* Add a single ACL entry to the internal list of ACL data.1652*/1653int1654archive_entry_acl_add_entry(struct archive_entry *entry,1655int type, int permset, int tag, int id, const char *name)1656{1657return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);1658}16591660/*1661* As above, but with a wide-character name.1662*/1663int1664archive_entry_acl_add_entry_w(struct archive_entry *entry,1665int type, int permset, int tag, int id, const wchar_t *name)1666{1667return archive_acl_add_entry_w_len(&entry->acl,1668type, permset, tag, id, name, wcslen(name));1669}16701671/*1672* Return a bitmask of ACL types in an archive entry ACL list1673*/1674int1675archive_entry_acl_types(struct archive_entry *entry)1676{1677return (archive_acl_types(&entry->acl));1678}16791680/*1681* Return a count of entries matching "want_type".1682*/1683int1684archive_entry_acl_count(struct archive_entry *entry, int want_type)1685{1686return archive_acl_count(&entry->acl, want_type);1687}16881689/*1690* Prepare for reading entries from the ACL data. Returns a count1691* of entries matching "want_type", or zero if there are no1692* non-extended ACL entries of that type.1693*/1694int1695archive_entry_acl_reset(struct archive_entry *entry, int want_type)1696{1697return archive_acl_reset(&entry->acl, want_type);1698}16991700/*1701* Return the next ACL entry in the list. Fake entries for the1702* standard permissions and include them in the returned list.1703*/1704int1705archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,1706int *permset, int *tag, int *id, const char **name)1707{1708int r;1709r = archive_acl_next(entry->archive, &entry->acl, want_type, type,1710permset, tag, id, name);1711if (r == ARCHIVE_FATAL && errno == ENOMEM)1712__archive_errx(1, "No memory");1713return (r);1714}17151716/*1717* Generate a text version of the ACL. The flags parameter controls1718* the style of the generated ACL.1719*/1720wchar_t *1721archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,1722int flags)1723{1724return (archive_acl_to_text_w(&entry->acl, len, flags,1725entry->archive));1726}17271728char *1729archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,1730int flags)1731{1732return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));1733}17341735char *1736_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,1737int flags, struct archive_string_conv *sc)1738{1739return (archive_acl_to_text_l(&entry->acl, len, flags, sc));1740}17411742/*1743* ACL text parser.1744*/1745int1746archive_entry_acl_from_text_w(struct archive_entry *entry,1747const wchar_t *wtext, int type)1748{1749return (archive_acl_from_text_w(&entry->acl, wtext, type));1750}17511752int1753archive_entry_acl_from_text(struct archive_entry *entry,1754const char *text, int type)1755{1756return (archive_acl_from_text_l(&entry->acl, text, type, NULL));1757}17581759int1760_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,1761int type, struct archive_string_conv *sc)1762{1763return (archive_acl_from_text_l(&entry->acl, text, type, sc));1764}17651766/* Deprecated */1767static int1768archive_entry_acl_text_compat(int *flags)1769{1770if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)1771return (1);17721773/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */1774if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)1775*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;17761777/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */1778if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)1779*flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;17801781*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;17821783return (0);1784}17851786/* Deprecated */1787const wchar_t *1788archive_entry_acl_text_w(struct archive_entry *entry, int flags)1789{1790free(entry->acl.acl_text_w);1791entry->acl.acl_text_w = NULL;1792if (archive_entry_acl_text_compat(&flags) == 0)1793entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,1794NULL, flags, entry->archive);1795return (entry->acl.acl_text_w);1796}17971798/* Deprecated */1799const char *1800archive_entry_acl_text(struct archive_entry *entry, int flags)1801{1802free(entry->acl.acl_text);1803entry->acl.acl_text = NULL;1804if (archive_entry_acl_text_compat(&flags) == 0)1805entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,1806flags, NULL);18071808return (entry->acl.acl_text);1809}18101811/* Deprecated */1812int1813_archive_entry_acl_text_l(struct archive_entry *entry, int flags,1814const char **acl_text, size_t *len, struct archive_string_conv *sc)1815{1816free(entry->acl.acl_text);1817entry->acl.acl_text = NULL;18181819if (archive_entry_acl_text_compat(&flags) == 0)1820entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,1821(ssize_t *)len, flags, sc);18221823*acl_text = entry->acl.acl_text;18241825return (0);1826}18271828/*1829* Following code is modified from UC Berkeley sources, and1830* is subject to the following copyright notice.1831*/18321833/*-1834* Copyright (c) 19931835* The Regents of the University of California. All rights reserved.1836*1837* Redistribution and use in source and binary forms, with or without1838* modification, are permitted provided that the following conditions1839* are met:1840* 1. Redistributions of source code must retain the above copyright1841* notice, this list of conditions and the following disclaimer.1842* 2. Redistributions in binary form must reproduce the above copyright1843* notice, this list of conditions and the following disclaimer in the1844* documentation and/or other materials provided with the distribution.1845* 4. Neither the name of the University nor the names of its contributors1846* may be used to endorse or promote products derived from this software1847* without specific prior written permission.1848*1849* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND1850* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE1851* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE1852* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE1853* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL1854* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS1855* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)1856* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT1857* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY1858* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF1859* SUCH DAMAGE.1860*/18611862/*1863* Supported file flags on FreeBSD and Mac OS:1864* sappnd,sappend SF_APPEND1865* arch,archived SF_ARCHIVED1866* schg,schange,simmutable SF_IMMUTABLE1867* sunlnk,sunlink SF_NOUNLINK (FreeBSD only)1868* uappnd,uappend UF_APPEND1869* compressed UF_COMPRESSED (Mac OS only)1870* hidden,uhidden UF_HIDDEN1871* uchg,uchange,uimmutable UF_IMMUTABLE1872* nodump UF_NODUMP1873* uunlnk,uunlink UF_NOUNLINK (FreeBSD only)1874* offline,uoffline UF_OFFLINE (FreeBSD only)1875* opaque UF_OPAQUE1876* rdonly,urdonly,readonly UF_READONLY (FreeBSD only)1877* reparse,ureparse UF_REPARSE (FreeBSD only)1878* sparse,usparse UF_SPARSE (FreeBSD only)1879* system,usystem UF_SYSTEM (FreeBSD only)1880*1881* See chflags(2) for more information1882*1883* Supported file attributes on Linux:1884* a append only FS_APPEND_FL sappnd1885* A no atime updates FS_NOATIME_FL atime1886* c compress FS_COMPR_FL compress1887* C no copy on write FS_NOCOW_FL cow1888* d no dump FS_NODUMP_FL dump1889* D synchronous directory updates FS_DIRSYNC_FL dirsync1890* i immutable FS_IMMUTABLE_FL schg1891* j data journalling FS_JOURNAL_DATA_FL journal1892* P project hierarchy FS_PROJINHERIT_FL projinherit1893* s secure deletion FS_SECRM_FL securedeletion1894* S synchronous updates FS_SYNC_FL sync1895* t no tail-merging FS_NOTAIL_FL tail1896* T top of directory hierarchy FS_TOPDIR_FL topdir1897* u undeletable FS_UNRM_FL undel1898*1899* See ioctl_iflags(2) for more information1900*1901* Equivalent file flags supported on FreeBSD / Mac OS and Linux:1902* SF_APPEND FS_APPEND_FL sappnd1903* SF_IMMUTABLE FS_IMMUTABLE_FL schg1904* UF_NODUMP FS_NODUMP_FL nodump1905*/19061907static const struct flag {1908const char *name;1909const wchar_t *wname;1910unsigned long set;1911unsigned long clear;1912} fileflags[] = {1913/* Preferred (shorter) names per flag first, all prefixed by "no" */1914#ifdef SF_APPEND1915{ "nosappnd", L"nosappnd", SF_APPEND, 0},1916{ "nosappend", L"nosappend", SF_APPEND, 0},1917#endif1918#if defined(FS_APPEND_FL) /* 'a' */1919{ "nosappnd", L"nosappnd", FS_APPEND_FL, 0},1920{ "nosappend", L"nosappend", FS_APPEND_FL, 0},1921#elif defined(EXT2_APPEND_FL) /* 'a' */1922{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0},1923{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0},1924#endif1925#ifdef SF_ARCHIVED1926{ "noarch", L"noarch", SF_ARCHIVED, 0},1927{ "noarchived", L"noarchived", SF_ARCHIVED, 0},1928#endif1929#ifdef SF_IMMUTABLE1930{ "noschg", L"noschg", SF_IMMUTABLE, 0},1931{ "noschange", L"noschange", SF_IMMUTABLE, 0},1932{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0},1933#endif1934#if defined(FS_IMMUTABLE_FL) /* 'i' */1935{ "noschg", L"noschg", FS_IMMUTABLE_FL, 0},1936{ "noschange", L"noschange", FS_IMMUTABLE_FL, 0},1937{ "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0},1938#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */1939{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0},1940{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0},1941{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0},1942#endif1943#ifdef SF_NOUNLINK1944{ "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0},1945{ "nosunlink", L"nosunlink", SF_NOUNLINK, 0},1946#endif1947#ifdef UF_APPEND1948{ "nouappnd", L"nouappnd", UF_APPEND, 0},1949{ "nouappend", L"nouappend", UF_APPEND, 0},1950#endif1951#ifdef UF_IMMUTABLE1952{ "nouchg", L"nouchg", UF_IMMUTABLE, 0},1953{ "nouchange", L"nouchange", UF_IMMUTABLE, 0},1954{ "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0},1955#endif1956#ifdef UF_NODUMP1957{ "nodump", L"nodump", 0, UF_NODUMP},1958#endif1959#if defined(FS_NODUMP_FL) /* 'd' */1960{ "nodump", L"nodump", 0, FS_NODUMP_FL},1961#elif defined(EXT2_NODUMP_FL)1962{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},1963#endif1964#ifdef UF_OPAQUE1965{ "noopaque", L"noopaque", UF_OPAQUE, 0},1966#endif1967#ifdef UF_NOUNLINK1968{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0},1969{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0},1970#endif1971#ifdef UF_COMPRESSED1972/* Mac OS */1973{ "nocompressed", L"nocompressed", UF_COMPRESSED, 0},1974#endif1975#ifdef UF_HIDDEN1976{ "nohidden", L"nohidden", UF_HIDDEN, 0},1977{ "nouhidden", L"nouhidden", UF_HIDDEN, 0},1978#endif1979#ifdef FILE_ATTRIBUTE_HIDDEN1980{ "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0},1981{ "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0},1982#endif1983#ifdef UF_OFFLINE1984{ "nooffline", L"nooffline", UF_OFFLINE, 0},1985{ "nouoffline", L"nouoffline", UF_OFFLINE, 0},1986#endif1987#ifdef UF_READONLY1988{ "nordonly", L"nordonly", UF_READONLY, 0},1989{ "nourdonly", L"nourdonly", UF_READONLY, 0},1990{ "noreadonly", L"noreadonly", UF_READONLY, 0},1991#endif1992#ifdef FILE_ATTRIBUTE_READONLY1993{ "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0},1994{ "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0},1995{ "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0},1996#endif1997#ifdef UF_SPARSE1998{ "nosparse", L"nosparse", UF_SPARSE, 0},1999{ "nousparse", L"nousparse", UF_SPARSE, 0},2000#endif2001#ifdef UF_REPARSE2002{ "noreparse", L"noreparse", UF_REPARSE, 0},2003{ "noureparse", L"noureparse", UF_REPARSE, 0},2004#endif2005#ifdef UF_SYSTEM2006{ "nosystem", L"nosystem", UF_SYSTEM, 0},2007{ "nousystem", L"nousystem", UF_SYSTEM, 0},2008#endif2009#ifdef FILE_ATTRIBUTE_SYSTEM2010{ "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0},2011{ "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0},2012#endif2013#if defined(FS_UNRM_FL) /* 'u' */2014{ "noundel", L"noundel", FS_UNRM_FL, 0},2015#elif defined(EXT2_UNRM_FL)2016{ "noundel", L"noundel", EXT2_UNRM_FL, 0},2017#endif20182019#if defined(FS_COMPR_FL) /* 'c' */2020{ "nocompress", L"nocompress", FS_COMPR_FL, 0},2021#elif defined(EXT2_COMPR_FL)2022{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0},2023#endif20242025#if defined(FS_NOATIME_FL) /* 'A' */2026{ "noatime", L"noatime", 0, FS_NOATIME_FL},2027#elif defined(EXT2_NOATIME_FL)2028{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},2029#endif2030#if defined(FS_DIRSYNC_FL) /* 'D' */2031{ "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},2032#elif defined(EXT2_DIRSYNC_FL)2033{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},2034#endif2035#if defined(FS_JOURNAL_DATA_FL) /* 'j' */2036{ "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0},2037{ "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},2038#elif defined(EXT3_JOURNAL_DATA_FL)2039{ "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0},2040{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},2041#endif2042#if defined(FS_SECRM_FL) /* 's' */2043{ "nosecdel", L"nosecdel", FS_SECRM_FL, 0},2044{ "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},2045#elif defined(EXT2_SECRM_FL)2046{ "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0},2047{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},2048#endif2049#if defined(FS_SYNC_FL) /* 'S' */2050{ "nosync", L"nosync", FS_SYNC_FL, 0},2051#elif defined(EXT2_SYNC_FL)2052{ "nosync", L"nosync", EXT2_SYNC_FL, 0},2053#endif2054#if defined(FS_NOTAIL_FL) /* 't' */2055{ "notail", L"notail", 0, FS_NOTAIL_FL},2056#elif defined(EXT2_NOTAIL_FL)2057{ "notail", L"notail", 0, EXT2_NOTAIL_FL},2058#endif2059#if defined(FS_TOPDIR_FL) /* 'T' */2060{ "notopdir", L"notopdir", FS_TOPDIR_FL, 0},2061#elif defined(EXT2_TOPDIR_FL)2062{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},2063#endif2064#ifdef FS_NOCOW_FL /* 'C' */2065{ "nocow", L"nocow", 0, FS_NOCOW_FL},2066#endif2067#ifdef FS_PROJINHERIT_FL /* 'P' */2068{ "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},2069#endif2070{ NULL, NULL, 0, 0}2071};20722073/*2074* fflagstostr --2075* Convert file flags to a comma-separated string. If no flags2076* are set, return the empty string.2077*/2078static char *2079ae_fflagstostr(unsigned long bitset, unsigned long bitclear)2080{2081char *string, *dp;2082const char *sp;2083unsigned long bits;2084const struct flag *flag;2085size_t length;20862087bits = bitset | bitclear;2088length = 0;2089for (flag = fileflags; flag->name != NULL; flag++)2090if (bits & (flag->set | flag->clear)) {2091length += strlen(flag->name) + 1;2092bits &= ~(flag->set | flag->clear);2093}20942095if (length == 0)2096return (NULL);2097string = malloc(length);2098if (string == NULL)2099return (NULL);21002101dp = string;2102for (flag = fileflags; flag->name != NULL; flag++) {2103if (bitset & flag->set || bitclear & flag->clear) {2104sp = flag->name + 2;2105} else if (bitset & flag->clear || bitclear & flag->set) {2106sp = flag->name;2107} else2108continue;2109bitset &= ~(flag->set | flag->clear);2110bitclear &= ~(flag->set | flag->clear);2111if (dp > string)2112*dp++ = ',';2113while ((*dp++ = *sp++) != '\0')2114;2115dp--;2116}21172118*dp = '\0';2119return (string);2120}21212122/*2123* strtofflags --2124* Take string of arguments and return file flags. This2125* version works a little differently than strtofflags(3).2126* In particular, it always tests every token, skipping any2127* unrecognized tokens. It returns a pointer to the first2128* unrecognized token, or NULL if every token was recognized.2129* This version is also const-correct and does not modify the2130* provided string.2131*/2132static const char *2133ae_strtofflags(const char *s, size_t l, unsigned long *setp, unsigned long *clrp)2134{2135const char *start, *end;2136const struct flag *flag;2137unsigned long set, clear;2138const char *failed;21392140set = clear = 0;2141start = s;2142failed = NULL;2143/* Find start of first token. */2144while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) {2145start++;2146l--;2147}2148while (l > 0) {2149size_t length;2150/* Locate end of token. */2151end = start;2152while (l > 0 && *end != '\t' &&2153*end != ' ' && *end != ',') {2154end++;2155l--;2156}2157length = end - start;2158for (flag = fileflags; flag->name != NULL; flag++) {2159size_t flag_length = strlen(flag->name);2160if (length == flag_length2161&& memcmp(start, flag->name, length) == 0) {2162/* Matched "noXXXX", so reverse the sense. */2163clear |= flag->set;2164set |= flag->clear;2165break;2166} else if (length == flag_length - 22167&& memcmp(start, flag->name + 2, length) == 0) {2168/* Matched "XXXX", so don't reverse. */2169set |= flag->set;2170clear |= flag->clear;2171break;2172}2173}2174/* Ignore unknown flag names. */2175if (flag->name == NULL && failed == NULL)2176failed = start;21772178/* Find start of next token. */2179start = end;2180while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) {2181start++;2182l--;2183}21842185}21862187if (setp)2188*setp = set;2189if (clrp)2190*clrp = clear;21912192/* Return location of first failure. */2193return (failed);2194}21952196/*2197* wcstofflags --2198* Take string of arguments and return file flags. This2199* version works a little differently than strtofflags(3).2200* In particular, it always tests every token, skipping any2201* unrecognized tokens. It returns a pointer to the first2202* unrecognized token, or NULL if every token was recognized.2203* This version is also const-correct and does not modify the2204* provided string.2205*/2206static const wchar_t *2207ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)2208{2209const wchar_t *start, *end;2210const struct flag *flag;2211unsigned long set, clear;2212const wchar_t *failed;22132214set = clear = 0;2215start = s;2216failed = NULL;2217/* Find start of first token. */2218while (*start == L'\t' || *start == L' ' || *start == L',')2219start++;2220while (*start != L'\0') {2221size_t length;2222/* Locate end of token. */2223end = start;2224while (*end != L'\0' && *end != L'\t' &&2225*end != L' ' && *end != L',')2226end++;2227length = end - start;2228for (flag = fileflags; flag->wname != NULL; flag++) {2229size_t flag_length = wcslen(flag->wname);2230if (length == flag_length2231&& wmemcmp(start, flag->wname, length) == 0) {2232/* Matched "noXXXX", so reverse the sense. */2233clear |= flag->set;2234set |= flag->clear;2235break;2236} else if (length == flag_length - 22237&& wmemcmp(start, flag->wname + 2, length) == 0) {2238/* Matched "XXXX", so don't reverse. */2239set |= flag->set;2240clear |= flag->clear;2241break;2242}2243}2244/* Ignore unknown flag names. */2245if (flag->wname == NULL && failed == NULL)2246failed = start;22472248/* Find start of next token. */2249start = end;2250while (*start == L'\t' || *start == L' ' || *start == L',')2251start++;22522253}22542255if (setp)2256*setp = set;2257if (clrp)2258*clrp = clear;22592260/* Return location of first failure. */2261return (failed);2262}226322642265#ifdef TEST2266#include <stdio.h>2267int2268main(int argc, char **argv)2269{2270struct archive_entry *entry = archive_entry_new();2271unsigned long set, clear;2272const wchar_t *remainder;22732274remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");2275archive_entry_fflags(entry, &set, &clear);22762277wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);22782279wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));2280return (0);2281}2282#endif228322842285