1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27228763Smm__FBSDID("$FreeBSD$"); 28228753Smm 29228753Smm#ifdef HAVE_SYS_STAT_H 30228753Smm#include <sys/stat.h> 31228753Smm#endif 32228753Smm#ifdef HAVE_SYS_TYPES_H 33228753Smm#include <sys/types.h> 34228753Smm#endif 35228753Smm#if MAJOR_IN_MKDEV 36228753Smm#include <sys/mkdev.h> 37228753Smm#define HAVE_MAJOR 38228753Smm#elif MAJOR_IN_SYSMACROS 39228753Smm#include <sys/sysmacros.h> 40228753Smm#define HAVE_MAJOR 41228753Smm#endif 42232153Smm#ifdef HAVE_ERRNO_H 43232153Smm#include <errno.h> 44232153Smm#endif 45228753Smm#ifdef HAVE_LIMITS_H 46228753Smm#include <limits.h> 47228753Smm#endif 48228753Smm#ifdef HAVE_LINUX_FS_H 49228753Smm#include <linux/fs.h> /* for Linux file flags */ 50228753Smm#endif 51228753Smm/* 52228753Smm * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. 53228753Smm * As the include guards don't agree, the order of include is important. 54228753Smm */ 55228753Smm#ifdef HAVE_LINUX_EXT2_FS_H 56228753Smm#include <linux/ext2_fs.h> /* for Linux file flags */ 57228753Smm#endif 58228753Smm#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) 59228753Smm#include <ext2fs/ext2_fs.h> /* for Linux file flags */ 60228753Smm#endif 61228753Smm#include <stddef.h> 62228753Smm#include <stdio.h> 63228753Smm#ifdef HAVE_STDLIB_H 64228753Smm#include <stdlib.h> 65228753Smm#endif 66228753Smm#ifdef HAVE_STRING_H 67228753Smm#include <string.h> 68228753Smm#endif 69228753Smm#ifdef HAVE_WCHAR_H 70228753Smm#include <wchar.h> 71228753Smm#endif 72228753Smm 73228753Smm#include "archive.h" 74232153Smm#include "archive_acl_private.h" 75228753Smm#include "archive_entry.h" 76232153Smm#include "archive_entry_locale.h" 77228753Smm#include "archive_private.h" 78228753Smm#include "archive_entry_private.h" 79228753Smm 80228753Smm#if !defined(HAVE_MAJOR) && !defined(major) 81228753Smm/* Replacement for major/minor/makedev. */ 82228753Smm#define major(x) ((int)(0x00ff & ((x) >> 8))) 83228753Smm#define minor(x) ((int)(0xffff00ff & (x))) 84228753Smm#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) 85228753Smm#endif 86228753Smm 87228753Smm/* Play games to come up with a suitable makedev() definition. */ 88228753Smm#ifdef __QNXNTO__ 89228753Smm/* QNX. <sigh> */ 90228753Smm#include <sys/netmgr.h> 91228753Smm#define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) 92228753Smm#elif defined makedev 93228753Smm/* There's a "makedev" macro. */ 94228753Smm#define ae_makedev(maj, min) makedev((maj), (min)) 95228753Smm#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) 96228753Smm/* Windows. <sigh> */ 97228753Smm#define ae_makedev(maj, min) mkdev((maj), (min)) 98228753Smm#else 99228753Smm/* There's a "makedev" function. */ 100228753Smm#define ae_makedev(maj, min) makedev((maj), (min)) 101228753Smm#endif 102228753Smm 103232153Smm/* 104232153Smm * This adjustment is needed to support the following idiom for adding 105232153Smm * 1000ns to the stored time: 106232153Smm * archive_entry_set_atime(archive_entry_atime(), 107232153Smm * archive_entry_atime_nsec() + 1000) 108232153Smm * The additional if() here compensates for ambiguity in the C standard, 109232153Smm * which permits two possible interpretations of a % b when a is negative. 110232153Smm */ 111232153Smm#define FIX_NS(t,ns) \ 112232153Smm do { \ 113232153Smm t += ns / 1000000000; \ 114232153Smm ns %= 1000000000; \ 115232153Smm if (ns < 0) { --t; ns += 1000000000; } \ 116232153Smm } while (0) 117228753Smm 118228753Smmstatic char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear); 119228753Smmstatic const wchar_t *ae_wcstofflags(const wchar_t *stringp, 120228753Smm unsigned long *setp, unsigned long *clrp); 121228753Smmstatic const char *ae_strtofflags(const char *stringp, 122228753Smm unsigned long *setp, unsigned long *clrp); 123228753Smm 124228753Smm#ifndef HAVE_WCSCPY 125228753Smmstatic wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) 126228753Smm{ 127228753Smm wchar_t *dest = s1; 128228753Smm while ((*s1 = *s2) != L'\0') 129228753Smm ++s1, ++s2; 130228753Smm return dest; 131228753Smm} 132228753Smm#endif 133228753Smm#ifndef HAVE_WCSLEN 134228753Smmstatic size_t wcslen(const wchar_t *s) 135228753Smm{ 136228753Smm const wchar_t *p = s; 137228753Smm while (*p != L'\0') 138228753Smm ++p; 139228753Smm return p - s; 140228753Smm} 141228753Smm#endif 142228753Smm#ifndef HAVE_WMEMCMP 143228753Smm/* Good enough for simple equality testing, but not for sorting. */ 144228753Smm#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) 145228753Smm#endif 146228753Smm 147228753Smm/**************************************************************************** 148228753Smm * 149228753Smm * Public Interface 150228753Smm * 151228753Smm ****************************************************************************/ 152228753Smm 153228753Smmstruct archive_entry * 154228753Smmarchive_entry_clear(struct archive_entry *entry) 155228753Smm{ 156228753Smm if (entry == NULL) 157228753Smm return (NULL); 158232153Smm archive_mstring_clean(&entry->ae_fflags_text); 159232153Smm archive_mstring_clean(&entry->ae_gname); 160232153Smm archive_mstring_clean(&entry->ae_hardlink); 161232153Smm archive_mstring_clean(&entry->ae_pathname); 162232153Smm archive_mstring_clean(&entry->ae_sourcepath); 163232153Smm archive_mstring_clean(&entry->ae_symlink); 164232153Smm archive_mstring_clean(&entry->ae_uname); 165232153Smm archive_entry_copy_mac_metadata(entry, NULL, 0); 166232153Smm archive_acl_clear(&entry->acl); 167228753Smm archive_entry_xattr_clear(entry); 168232153Smm archive_entry_sparse_clear(entry); 169228753Smm free(entry->stat); 170228753Smm memset(entry, 0, sizeof(*entry)); 171228753Smm return entry; 172228753Smm} 173228753Smm 174228753Smmstruct archive_entry * 175228753Smmarchive_entry_clone(struct archive_entry *entry) 176228753Smm{ 177228753Smm struct archive_entry *entry2; 178228753Smm struct ae_xattr *xp; 179232153Smm struct ae_sparse *sp; 180232153Smm size_t s; 181232153Smm const void *p; 182228753Smm 183228753Smm /* Allocate new structure and copy over all of the fields. */ 184232153Smm /* TODO: Should we copy the archive over? Or require a new archive 185232153Smm * as an argument? */ 186232153Smm entry2 = archive_entry_new2(entry->archive); 187228753Smm if (entry2 == NULL) 188228753Smm return (NULL); 189228753Smm entry2->ae_stat = entry->ae_stat; 190228753Smm entry2->ae_fflags_set = entry->ae_fflags_set; 191228753Smm entry2->ae_fflags_clear = entry->ae_fflags_clear; 192228753Smm 193232153Smm /* TODO: XXX If clone can have a different archive, what do we do here if 194232153Smm * character sets are different? XXX */ 195232153Smm archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text); 196232153Smm archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname); 197232153Smm archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink); 198232153Smm archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname); 199232153Smm archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath); 200232153Smm archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink); 201228753Smm entry2->ae_set = entry->ae_set; 202232153Smm archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname); 203228753Smm 204228753Smm /* Copy ACL data over. */ 205232153Smm archive_acl_copy(&entry2->acl, &entry->acl); 206228753Smm 207232153Smm /* Copy Mac OS metadata. */ 208232153Smm p = archive_entry_mac_metadata(entry, &s); 209232153Smm archive_entry_copy_mac_metadata(entry2, p, s); 210232153Smm 211228753Smm /* Copy xattr data over. */ 212228753Smm xp = entry->xattr_head; 213228753Smm while (xp != NULL) { 214228753Smm archive_entry_xattr_add_entry(entry2, 215228753Smm xp->name, xp->value, xp->size); 216228753Smm xp = xp->next; 217228753Smm } 218228753Smm 219232153Smm /* Copy sparse data over. */ 220232153Smm sp = entry->sparse_head; 221232153Smm while (sp != NULL) { 222232153Smm archive_entry_sparse_add_entry(entry2, 223232153Smm sp->offset, sp->length); 224232153Smm sp = sp->next; 225232153Smm } 226232153Smm 227228753Smm return (entry2); 228228753Smm} 229228753Smm 230228753Smmvoid 231228753Smmarchive_entry_free(struct archive_entry *entry) 232228753Smm{ 233228753Smm archive_entry_clear(entry); 234228753Smm free(entry); 235228753Smm} 236228753Smm 237228753Smmstruct archive_entry * 238228753Smmarchive_entry_new(void) 239228753Smm{ 240232153Smm return archive_entry_new2(NULL); 241232153Smm} 242232153Smm 243232153Smmstruct archive_entry * 244232153Smmarchive_entry_new2(struct archive *a) 245232153Smm{ 246228753Smm struct archive_entry *entry; 247228753Smm 248228753Smm entry = (struct archive_entry *)malloc(sizeof(*entry)); 249228753Smm if (entry == NULL) 250228753Smm return (NULL); 251228753Smm memset(entry, 0, sizeof(*entry)); 252232153Smm entry->archive = a; 253228753Smm return (entry); 254228753Smm} 255228753Smm 256228753Smm/* 257228753Smm * Functions for reading fields from an archive_entry. 258228753Smm */ 259228753Smm 260228753Smmtime_t 261228753Smmarchive_entry_atime(struct archive_entry *entry) 262228753Smm{ 263228753Smm return (entry->ae_stat.aest_atime); 264228753Smm} 265228753Smm 266228753Smmlong 267228753Smmarchive_entry_atime_nsec(struct archive_entry *entry) 268228753Smm{ 269228753Smm return (entry->ae_stat.aest_atime_nsec); 270228753Smm} 271228753Smm 272228753Smmint 273228753Smmarchive_entry_atime_is_set(struct archive_entry *entry) 274228753Smm{ 275228753Smm return (entry->ae_set & AE_SET_ATIME); 276228753Smm} 277228753Smm 278228753Smmtime_t 279228753Smmarchive_entry_birthtime(struct archive_entry *entry) 280228753Smm{ 281228753Smm return (entry->ae_stat.aest_birthtime); 282228753Smm} 283228753Smm 284228753Smmlong 285228753Smmarchive_entry_birthtime_nsec(struct archive_entry *entry) 286228753Smm{ 287228753Smm return (entry->ae_stat.aest_birthtime_nsec); 288228753Smm} 289228753Smm 290228753Smmint 291228753Smmarchive_entry_birthtime_is_set(struct archive_entry *entry) 292228753Smm{ 293228753Smm return (entry->ae_set & AE_SET_BIRTHTIME); 294228753Smm} 295228753Smm 296228753Smmtime_t 297228753Smmarchive_entry_ctime(struct archive_entry *entry) 298228753Smm{ 299228753Smm return (entry->ae_stat.aest_ctime); 300228753Smm} 301228753Smm 302228753Smmint 303228753Smmarchive_entry_ctime_is_set(struct archive_entry *entry) 304228753Smm{ 305228753Smm return (entry->ae_set & AE_SET_CTIME); 306228753Smm} 307228753Smm 308228753Smmlong 309228753Smmarchive_entry_ctime_nsec(struct archive_entry *entry) 310228753Smm{ 311228753Smm return (entry->ae_stat.aest_ctime_nsec); 312228753Smm} 313228753Smm 314228753Smmdev_t 315228753Smmarchive_entry_dev(struct archive_entry *entry) 316228753Smm{ 317228753Smm if (entry->ae_stat.aest_dev_is_broken_down) 318228753Smm return ae_makedev(entry->ae_stat.aest_devmajor, 319228753Smm entry->ae_stat.aest_devminor); 320228753Smm else 321228753Smm return (entry->ae_stat.aest_dev); 322228753Smm} 323228753Smm 324232153Smmint 325232153Smmarchive_entry_dev_is_set(struct archive_entry *entry) 326232153Smm{ 327232153Smm return (entry->ae_set & AE_SET_DEV); 328232153Smm} 329232153Smm 330228753Smmdev_t 331228753Smmarchive_entry_devmajor(struct archive_entry *entry) 332228753Smm{ 333228753Smm if (entry->ae_stat.aest_dev_is_broken_down) 334228753Smm return (entry->ae_stat.aest_devmajor); 335228753Smm else 336228753Smm return major(entry->ae_stat.aest_dev); 337228753Smm} 338228753Smm 339228753Smmdev_t 340228753Smmarchive_entry_devminor(struct archive_entry *entry) 341228753Smm{ 342228753Smm if (entry->ae_stat.aest_dev_is_broken_down) 343228753Smm return (entry->ae_stat.aest_devminor); 344228753Smm else 345228753Smm return minor(entry->ae_stat.aest_dev); 346228753Smm} 347228753Smm 348228753Smmmode_t 349228753Smmarchive_entry_filetype(struct archive_entry *entry) 350228753Smm{ 351232153Smm return (AE_IFMT & entry->acl.mode); 352228753Smm} 353228753Smm 354228753Smmvoid 355228753Smmarchive_entry_fflags(struct archive_entry *entry, 356228753Smm unsigned long *set, unsigned long *clear) 357228753Smm{ 358228753Smm *set = entry->ae_fflags_set; 359228753Smm *clear = entry->ae_fflags_clear; 360228753Smm} 361228753Smm 362228753Smm/* 363228753Smm * Note: if text was provided, this just returns that text. If you 364228753Smm * really need the text to be rebuilt in a canonical form, set the 365228753Smm * text, ask for the bitmaps, then set the bitmaps. (Setting the 366228753Smm * bitmaps clears any stored text.) This design is deliberate: if 367228753Smm * we're editing archives, we don't want to discard flags just because 368228753Smm * they aren't supported on the current system. The bitmap<->text 369228753Smm * conversions are platform-specific (see below). 370228753Smm */ 371228753Smmconst char * 372228753Smmarchive_entry_fflags_text(struct archive_entry *entry) 373228753Smm{ 374228753Smm const char *f; 375228753Smm char *p; 376228753Smm 377232153Smm if (archive_mstring_get_mbs(entry->archive, 378238856Smm &entry->ae_fflags_text, &f) == 0) { 379238856Smm if (f != NULL) 380238856Smm return (f); 381238856Smm } else if (errno == ENOMEM) 382238856Smm __archive_errx(1, "No memory"); 383228753Smm 384228753Smm if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) 385228753Smm return (NULL); 386228753Smm 387228753Smm p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); 388228753Smm if (p == NULL) 389228753Smm return (NULL); 390228753Smm 391232153Smm archive_mstring_copy_mbs(&entry->ae_fflags_text, p); 392228753Smm free(p); 393232153Smm if (archive_mstring_get_mbs(entry->archive, 394232153Smm &entry->ae_fflags_text, &f) == 0) 395232153Smm return (f); 396238856Smm if (errno == ENOMEM) 397238856Smm __archive_errx(1, "No memory"); 398232153Smm return (NULL); 399228753Smm} 400228753Smm 401232153Smmint64_t 402228753Smmarchive_entry_gid(struct archive_entry *entry) 403228753Smm{ 404228753Smm return (entry->ae_stat.aest_gid); 405228753Smm} 406228753Smm 407228753Smmconst char * 408228753Smmarchive_entry_gname(struct archive_entry *entry) 409228753Smm{ 410232153Smm const char *p; 411232153Smm if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0) 412232153Smm return (p); 413238856Smm if (errno == ENOMEM) 414238856Smm __archive_errx(1, "No memory"); 415232153Smm return (NULL); 416228753Smm} 417228753Smm 418228753Smmconst wchar_t * 419228753Smmarchive_entry_gname_w(struct archive_entry *entry) 420228753Smm{ 421232153Smm const wchar_t *p; 422232153Smm if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0) 423232153Smm return (p); 424238856Smm if (errno == ENOMEM) 425238856Smm __archive_errx(1, "No memory"); 426232153Smm return (NULL); 427228753Smm} 428228753Smm 429232153Smmint 430232153Smm_archive_entry_gname_l(struct archive_entry *entry, 431232153Smm const char **p, size_t *len, struct archive_string_conv *sc) 432232153Smm{ 433232153Smm return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc)); 434232153Smm} 435232153Smm 436228753Smmconst char * 437228753Smmarchive_entry_hardlink(struct archive_entry *entry) 438228753Smm{ 439232153Smm const char *p; 440238856Smm if ((entry->ae_set & AE_SET_HARDLINK) == 0) 441238856Smm return (NULL); 442238856Smm if (archive_mstring_get_mbs( 443232153Smm entry->archive, &entry->ae_hardlink, &p) == 0) 444232153Smm return (p); 445238856Smm if (errno == ENOMEM) 446238856Smm __archive_errx(1, "No memory"); 447228753Smm return (NULL); 448228753Smm} 449228753Smm 450228753Smmconst wchar_t * 451228753Smmarchive_entry_hardlink_w(struct archive_entry *entry) 452228753Smm{ 453232153Smm const wchar_t *p; 454238856Smm if ((entry->ae_set & AE_SET_HARDLINK) == 0) 455238856Smm return (NULL); 456238856Smm if (archive_mstring_get_wcs( 457232153Smm entry->archive, &entry->ae_hardlink, &p) == 0) 458232153Smm return (p); 459238856Smm if (errno == ENOMEM) 460238856Smm __archive_errx(1, "No memory"); 461228753Smm return (NULL); 462228753Smm} 463228753Smm 464232153Smmint 465232153Smm_archive_entry_hardlink_l(struct archive_entry *entry, 466232153Smm const char **p, size_t *len, struct archive_string_conv *sc) 467232153Smm{ 468232153Smm if ((entry->ae_set & AE_SET_HARDLINK) == 0) { 469232153Smm *p = NULL; 470232153Smm *len = 0; 471232153Smm return (0); 472232153Smm } 473232153Smm return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); 474232153Smm} 475232153Smm 476232153Smmint64_t 477228753Smmarchive_entry_ino(struct archive_entry *entry) 478228753Smm{ 479228753Smm return (entry->ae_stat.aest_ino); 480228753Smm} 481228753Smm 482232153Smmint 483232153Smmarchive_entry_ino_is_set(struct archive_entry *entry) 484232153Smm{ 485232153Smm return (entry->ae_set & AE_SET_INO); 486232153Smm} 487232153Smm 488228753Smmint64_t 489228753Smmarchive_entry_ino64(struct archive_entry *entry) 490228753Smm{ 491228753Smm return (entry->ae_stat.aest_ino); 492228753Smm} 493228753Smm 494228753Smmmode_t 495228753Smmarchive_entry_mode(struct archive_entry *entry) 496228753Smm{ 497232153Smm return (entry->acl.mode); 498228753Smm} 499228753Smm 500228753Smmtime_t 501228753Smmarchive_entry_mtime(struct archive_entry *entry) 502228753Smm{ 503228753Smm return (entry->ae_stat.aest_mtime); 504228753Smm} 505228753Smm 506228753Smmlong 507228753Smmarchive_entry_mtime_nsec(struct archive_entry *entry) 508228753Smm{ 509228753Smm return (entry->ae_stat.aest_mtime_nsec); 510228753Smm} 511228753Smm 512228753Smmint 513228753Smmarchive_entry_mtime_is_set(struct archive_entry *entry) 514228753Smm{ 515228753Smm return (entry->ae_set & AE_SET_MTIME); 516228753Smm} 517228753Smm 518228753Smmunsigned int 519228753Smmarchive_entry_nlink(struct archive_entry *entry) 520228753Smm{ 521228753Smm return (entry->ae_stat.aest_nlink); 522228753Smm} 523228753Smm 524228753Smmconst char * 525228753Smmarchive_entry_pathname(struct archive_entry *entry) 526228753Smm{ 527232153Smm const char *p; 528232153Smm if (archive_mstring_get_mbs( 529232153Smm entry->archive, &entry->ae_pathname, &p) == 0) 530232153Smm return (p); 531238856Smm if (errno == ENOMEM) 532238856Smm __archive_errx(1, "No memory"); 533232153Smm return (NULL); 534228753Smm} 535228753Smm 536228753Smmconst wchar_t * 537228753Smmarchive_entry_pathname_w(struct archive_entry *entry) 538228753Smm{ 539232153Smm const wchar_t *p; 540232153Smm if (archive_mstring_get_wcs( 541232153Smm entry->archive, &entry->ae_pathname, &p) == 0) 542232153Smm return (p); 543238856Smm if (errno == ENOMEM) 544238856Smm __archive_errx(1, "No memory"); 545232153Smm return (NULL); 546228753Smm} 547228753Smm 548232153Smmint 549232153Smm_archive_entry_pathname_l(struct archive_entry *entry, 550232153Smm const char **p, size_t *len, struct archive_string_conv *sc) 551232153Smm{ 552232153Smm return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc)); 553232153Smm} 554232153Smm 555232153Smmmode_t 556232153Smmarchive_entry_perm(struct archive_entry *entry) 557232153Smm{ 558232153Smm return (~AE_IFMT & entry->acl.mode); 559232153Smm} 560232153Smm 561228753Smmdev_t 562228753Smmarchive_entry_rdev(struct archive_entry *entry) 563228753Smm{ 564228753Smm if (entry->ae_stat.aest_rdev_is_broken_down) 565228753Smm return ae_makedev(entry->ae_stat.aest_rdevmajor, 566228753Smm entry->ae_stat.aest_rdevminor); 567228753Smm else 568228753Smm return (entry->ae_stat.aest_rdev); 569228753Smm} 570228753Smm 571228753Smmdev_t 572228753Smmarchive_entry_rdevmajor(struct archive_entry *entry) 573228753Smm{ 574228753Smm if (entry->ae_stat.aest_rdev_is_broken_down) 575228753Smm return (entry->ae_stat.aest_rdevmajor); 576228753Smm else 577228753Smm return major(entry->ae_stat.aest_rdev); 578228753Smm} 579228753Smm 580228753Smmdev_t 581228753Smmarchive_entry_rdevminor(struct archive_entry *entry) 582228753Smm{ 583228753Smm if (entry->ae_stat.aest_rdev_is_broken_down) 584228753Smm return (entry->ae_stat.aest_rdevminor); 585228753Smm else 586228753Smm return minor(entry->ae_stat.aest_rdev); 587228753Smm} 588228753Smm 589228753Smmint64_t 590228753Smmarchive_entry_size(struct archive_entry *entry) 591228753Smm{ 592228753Smm return (entry->ae_stat.aest_size); 593228753Smm} 594228753Smm 595228753Smmint 596228753Smmarchive_entry_size_is_set(struct archive_entry *entry) 597228753Smm{ 598228753Smm return (entry->ae_set & AE_SET_SIZE); 599228753Smm} 600228753Smm 601228753Smmconst char * 602228753Smmarchive_entry_sourcepath(struct archive_entry *entry) 603228753Smm{ 604232153Smm const char *p; 605232153Smm if (archive_mstring_get_mbs( 606232153Smm entry->archive, &entry->ae_sourcepath, &p) == 0) 607232153Smm return (p); 608238856Smm if (errno == ENOMEM) 609238856Smm __archive_errx(1, "No memory"); 610232153Smm return (NULL); 611228753Smm} 612228753Smm 613232153Smmconst wchar_t * 614232153Smmarchive_entry_sourcepath_w(struct archive_entry *entry) 615232153Smm{ 616232153Smm const wchar_t *p; 617232153Smm if (archive_mstring_get_wcs( 618232153Smm entry->archive, &entry->ae_sourcepath, &p) == 0) 619232153Smm return (p); 620232153Smm return (NULL); 621232153Smm} 622232153Smm 623228753Smmconst char * 624228753Smmarchive_entry_symlink(struct archive_entry *entry) 625228753Smm{ 626232153Smm const char *p; 627238856Smm if ((entry->ae_set & AE_SET_SYMLINK) == 0) 628238856Smm return (NULL); 629238856Smm if (archive_mstring_get_mbs( 630232153Smm entry->archive, &entry->ae_symlink, &p) == 0) 631232153Smm return (p); 632238856Smm if (errno == ENOMEM) 633238856Smm __archive_errx(1, "No memory"); 634228753Smm return (NULL); 635228753Smm} 636228753Smm 637228753Smmconst wchar_t * 638228753Smmarchive_entry_symlink_w(struct archive_entry *entry) 639228753Smm{ 640232153Smm const wchar_t *p; 641238856Smm if ((entry->ae_set & AE_SET_SYMLINK) == 0) 642238856Smm return (NULL); 643238856Smm if (archive_mstring_get_wcs( 644232153Smm entry->archive, &entry->ae_symlink, &p) == 0) 645232153Smm return (p); 646238856Smm if (errno == ENOMEM) 647238856Smm __archive_errx(1, "No memory"); 648228753Smm return (NULL); 649228753Smm} 650228753Smm 651232153Smmint 652232153Smm_archive_entry_symlink_l(struct archive_entry *entry, 653232153Smm const char **p, size_t *len, struct archive_string_conv *sc) 654232153Smm{ 655232153Smm if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 656232153Smm *p = NULL; 657232153Smm *len = 0; 658232153Smm return (0); 659232153Smm } 660232153Smm return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); 661232153Smm} 662232153Smm 663232153Smmint64_t 664228753Smmarchive_entry_uid(struct archive_entry *entry) 665228753Smm{ 666228753Smm return (entry->ae_stat.aest_uid); 667228753Smm} 668228753Smm 669228753Smmconst char * 670228753Smmarchive_entry_uname(struct archive_entry *entry) 671228753Smm{ 672232153Smm const char *p; 673232153Smm if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) 674232153Smm return (p); 675238856Smm if (errno == ENOMEM) 676238856Smm __archive_errx(1, "No memory"); 677232153Smm return (NULL); 678228753Smm} 679228753Smm 680228753Smmconst wchar_t * 681228753Smmarchive_entry_uname_w(struct archive_entry *entry) 682228753Smm{ 683232153Smm const wchar_t *p; 684232153Smm if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) 685232153Smm return (p); 686238856Smm if (errno == ENOMEM) 687238856Smm __archive_errx(1, "No memory"); 688232153Smm return (NULL); 689228753Smm} 690228753Smm 691232153Smmint 692232153Smm_archive_entry_uname_l(struct archive_entry *entry, 693232153Smm const char **p, size_t *len, struct archive_string_conv *sc) 694232153Smm{ 695232153Smm return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc)); 696232153Smm} 697232153Smm 698228753Smm/* 699228753Smm * Functions to set archive_entry properties. 700228753Smm */ 701228753Smm 702228753Smmvoid 703228753Smmarchive_entry_set_filetype(struct archive_entry *entry, unsigned int type) 704228753Smm{ 705228753Smm entry->stat_valid = 0; 706232153Smm entry->acl.mode &= ~AE_IFMT; 707232153Smm entry->acl.mode |= AE_IFMT & type; 708228753Smm} 709228753Smm 710228753Smmvoid 711228753Smmarchive_entry_set_fflags(struct archive_entry *entry, 712228753Smm unsigned long set, unsigned long clear) 713228753Smm{ 714232153Smm archive_mstring_clean(&entry->ae_fflags_text); 715228753Smm entry->ae_fflags_set = set; 716228753Smm entry->ae_fflags_clear = clear; 717228753Smm} 718228753Smm 719228753Smmconst char * 720228753Smmarchive_entry_copy_fflags_text(struct archive_entry *entry, 721228753Smm const char *flags) 722228753Smm{ 723232153Smm archive_mstring_copy_mbs(&entry->ae_fflags_text, flags); 724228753Smm return (ae_strtofflags(flags, 725228753Smm &entry->ae_fflags_set, &entry->ae_fflags_clear)); 726228753Smm} 727228753Smm 728228753Smmconst wchar_t * 729228753Smmarchive_entry_copy_fflags_text_w(struct archive_entry *entry, 730228753Smm const wchar_t *flags) 731228753Smm{ 732232153Smm archive_mstring_copy_wcs(&entry->ae_fflags_text, flags); 733228753Smm return (ae_wcstofflags(flags, 734228753Smm &entry->ae_fflags_set, &entry->ae_fflags_clear)); 735228753Smm} 736228753Smm 737228753Smmvoid 738232153Smmarchive_entry_set_gid(struct archive_entry *entry, int64_t g) 739228753Smm{ 740228753Smm entry->stat_valid = 0; 741228753Smm entry->ae_stat.aest_gid = g; 742228753Smm} 743228753Smm 744228753Smmvoid 745228753Smmarchive_entry_set_gname(struct archive_entry *entry, const char *name) 746228753Smm{ 747232153Smm archive_mstring_copy_mbs(&entry->ae_gname, name); 748228753Smm} 749228753Smm 750228753Smmvoid 751228753Smmarchive_entry_copy_gname(struct archive_entry *entry, const char *name) 752228753Smm{ 753232153Smm archive_mstring_copy_mbs(&entry->ae_gname, name); 754228753Smm} 755228753Smm 756228753Smmvoid 757228753Smmarchive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) 758228753Smm{ 759232153Smm archive_mstring_copy_wcs(&entry->ae_gname, name); 760228753Smm} 761228753Smm 762228753Smmint 763228753Smmarchive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) 764228753Smm{ 765232153Smm if (archive_mstring_update_utf8(entry->archive, 766232153Smm &entry->ae_gname, name) == 0) 767232153Smm return (1); 768238856Smm if (errno == ENOMEM) 769238856Smm __archive_errx(1, "No memory"); 770232153Smm return (0); 771228753Smm} 772228753Smm 773232153Smmint 774232153Smm_archive_entry_copy_gname_l(struct archive_entry *entry, 775232153Smm const char *name, size_t len, struct archive_string_conv *sc) 776232153Smm{ 777232153Smm return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc)); 778232153Smm} 779232153Smm 780228753Smmvoid 781232153Smmarchive_entry_set_ino(struct archive_entry *entry, int64_t ino) 782228753Smm{ 783228753Smm entry->stat_valid = 0; 784232153Smm entry->ae_set |= AE_SET_INO; 785228753Smm entry->ae_stat.aest_ino = ino; 786228753Smm} 787228753Smm 788228753Smmvoid 789228753Smmarchive_entry_set_ino64(struct archive_entry *entry, int64_t ino) 790228753Smm{ 791228753Smm entry->stat_valid = 0; 792232153Smm entry->ae_set |= AE_SET_INO; 793228753Smm entry->ae_stat.aest_ino = ino; 794228753Smm} 795228753Smm 796228753Smmvoid 797228753Smmarchive_entry_set_hardlink(struct archive_entry *entry, const char *target) 798228753Smm{ 799232153Smm archive_mstring_copy_mbs(&entry->ae_hardlink, target); 800228753Smm if (target != NULL) 801228753Smm entry->ae_set |= AE_SET_HARDLINK; 802228753Smm else 803228753Smm entry->ae_set &= ~AE_SET_HARDLINK; 804228753Smm} 805228753Smm 806228753Smmvoid 807228753Smmarchive_entry_copy_hardlink(struct archive_entry *entry, const char *target) 808228753Smm{ 809232153Smm archive_mstring_copy_mbs(&entry->ae_hardlink, target); 810228753Smm if (target != NULL) 811228753Smm entry->ae_set |= AE_SET_HARDLINK; 812228753Smm else 813228753Smm entry->ae_set &= ~AE_SET_HARDLINK; 814228753Smm} 815228753Smm 816228753Smmvoid 817228753Smmarchive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) 818228753Smm{ 819232153Smm archive_mstring_copy_wcs(&entry->ae_hardlink, target); 820228753Smm if (target != NULL) 821228753Smm entry->ae_set |= AE_SET_HARDLINK; 822228753Smm else 823228753Smm entry->ae_set &= ~AE_SET_HARDLINK; 824228753Smm} 825228753Smm 826228753Smmint 827228753Smmarchive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) 828228753Smm{ 829228753Smm if (target != NULL) 830228753Smm entry->ae_set |= AE_SET_HARDLINK; 831228753Smm else 832228753Smm entry->ae_set &= ~AE_SET_HARDLINK; 833232153Smm if (archive_mstring_update_utf8(entry->archive, 834232153Smm &entry->ae_hardlink, target) == 0) 835232153Smm return (1); 836238856Smm if (errno == ENOMEM) 837238856Smm __archive_errx(1, "No memory"); 838232153Smm return (0); 839228753Smm} 840228753Smm 841232153Smmint 842232153Smm_archive_entry_copy_hardlink_l(struct archive_entry *entry, 843232153Smm const char *target, size_t len, struct archive_string_conv *sc) 844232153Smm{ 845232153Smm int r; 846232153Smm 847232153Smm r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, 848232153Smm target, len, sc); 849232153Smm if (target != NULL && r == 0) 850232153Smm entry->ae_set |= AE_SET_HARDLINK; 851232153Smm else 852232153Smm entry->ae_set &= ~AE_SET_HARDLINK; 853232153Smm return (r); 854232153Smm} 855232153Smm 856228753Smmvoid 857228753Smmarchive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) 858228753Smm{ 859232153Smm FIX_NS(t, ns); 860228753Smm entry->stat_valid = 0; 861228753Smm entry->ae_set |= AE_SET_ATIME; 862228753Smm entry->ae_stat.aest_atime = t; 863228753Smm entry->ae_stat.aest_atime_nsec = ns; 864228753Smm} 865228753Smm 866228753Smmvoid 867228753Smmarchive_entry_unset_atime(struct archive_entry *entry) 868228753Smm{ 869228753Smm archive_entry_set_atime(entry, 0, 0); 870228753Smm entry->ae_set &= ~AE_SET_ATIME; 871228753Smm} 872228753Smm 873228753Smmvoid 874232153Smmarchive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) 875228753Smm{ 876232153Smm FIX_NS(t, ns); 877228753Smm entry->stat_valid = 0; 878228753Smm entry->ae_set |= AE_SET_BIRTHTIME; 879232153Smm entry->ae_stat.aest_birthtime = t; 880228753Smm entry->ae_stat.aest_birthtime_nsec = ns; 881228753Smm} 882228753Smm 883228753Smmvoid 884228753Smmarchive_entry_unset_birthtime(struct archive_entry *entry) 885228753Smm{ 886228753Smm archive_entry_set_birthtime(entry, 0, 0); 887228753Smm entry->ae_set &= ~AE_SET_BIRTHTIME; 888228753Smm} 889228753Smm 890228753Smmvoid 891228753Smmarchive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) 892228753Smm{ 893232153Smm FIX_NS(t, ns); 894228753Smm entry->stat_valid = 0; 895228753Smm entry->ae_set |= AE_SET_CTIME; 896228753Smm entry->ae_stat.aest_ctime = t; 897228753Smm entry->ae_stat.aest_ctime_nsec = ns; 898228753Smm} 899228753Smm 900228753Smmvoid 901228753Smmarchive_entry_unset_ctime(struct archive_entry *entry) 902228753Smm{ 903228753Smm archive_entry_set_ctime(entry, 0, 0); 904228753Smm entry->ae_set &= ~AE_SET_CTIME; 905228753Smm} 906228753Smm 907228753Smmvoid 908228753Smmarchive_entry_set_dev(struct archive_entry *entry, dev_t d) 909228753Smm{ 910228753Smm entry->stat_valid = 0; 911232153Smm entry->ae_set |= AE_SET_DEV; 912228753Smm entry->ae_stat.aest_dev_is_broken_down = 0; 913228753Smm entry->ae_stat.aest_dev = d; 914228753Smm} 915228753Smm 916228753Smmvoid 917228753Smmarchive_entry_set_devmajor(struct archive_entry *entry, dev_t m) 918228753Smm{ 919228753Smm entry->stat_valid = 0; 920232153Smm entry->ae_set |= AE_SET_DEV; 921228753Smm entry->ae_stat.aest_dev_is_broken_down = 1; 922228753Smm entry->ae_stat.aest_devmajor = m; 923228753Smm} 924228753Smm 925228753Smmvoid 926228753Smmarchive_entry_set_devminor(struct archive_entry *entry, dev_t m) 927228753Smm{ 928228753Smm entry->stat_valid = 0; 929232153Smm entry->ae_set |= AE_SET_DEV; 930228753Smm entry->ae_stat.aest_dev_is_broken_down = 1; 931228753Smm entry->ae_stat.aest_devminor = m; 932228753Smm} 933228753Smm 934228753Smm/* Set symlink if symlink is already set, else set hardlink. */ 935228753Smmvoid 936228753Smmarchive_entry_set_link(struct archive_entry *entry, const char *target) 937228753Smm{ 938228753Smm if (entry->ae_set & AE_SET_SYMLINK) 939232153Smm archive_mstring_copy_mbs(&entry->ae_symlink, target); 940228753Smm else 941232153Smm archive_mstring_copy_mbs(&entry->ae_hardlink, target); 942228753Smm} 943228753Smm 944228753Smm/* Set symlink if symlink is already set, else set hardlink. */ 945228753Smmvoid 946228753Smmarchive_entry_copy_link(struct archive_entry *entry, const char *target) 947228753Smm{ 948228753Smm if (entry->ae_set & AE_SET_SYMLINK) 949232153Smm archive_mstring_copy_mbs(&entry->ae_symlink, target); 950228753Smm else 951232153Smm archive_mstring_copy_mbs(&entry->ae_hardlink, target); 952228753Smm} 953228753Smm 954228753Smm/* Set symlink if symlink is already set, else set hardlink. */ 955228753Smmvoid 956228753Smmarchive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target) 957228753Smm{ 958228753Smm if (entry->ae_set & AE_SET_SYMLINK) 959232153Smm archive_mstring_copy_wcs(&entry->ae_symlink, target); 960228753Smm else 961232153Smm archive_mstring_copy_wcs(&entry->ae_hardlink, target); 962228753Smm} 963228753Smm 964228753Smmint 965228753Smmarchive_entry_update_link_utf8(struct archive_entry *entry, const char *target) 966228753Smm{ 967232153Smm int r; 968228753Smm if (entry->ae_set & AE_SET_SYMLINK) 969232153Smm r = archive_mstring_update_utf8(entry->archive, 970232153Smm &entry->ae_symlink, target); 971228753Smm else 972232153Smm r = archive_mstring_update_utf8(entry->archive, 973232153Smm &entry->ae_hardlink, target); 974238856Smm if (r == 0) 975238856Smm return (1); 976238856Smm if (errno == ENOMEM) 977238856Smm __archive_errx(1, "No memory"); 978238856Smm return (0); 979228753Smm} 980228753Smm 981232153Smmint 982232153Smm_archive_entry_copy_link_l(struct archive_entry *entry, 983232153Smm const char *target, size_t len, struct archive_string_conv *sc) 984232153Smm{ 985232153Smm int r; 986232153Smm 987232153Smm if (entry->ae_set & AE_SET_SYMLINK) 988232153Smm r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, 989232153Smm target, len, sc); 990232153Smm else 991232153Smm r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, 992232153Smm target, len, sc); 993232153Smm return (r); 994232153Smm} 995232153Smm 996228753Smmvoid 997228753Smmarchive_entry_set_mode(struct archive_entry *entry, mode_t m) 998228753Smm{ 999228753Smm entry->stat_valid = 0; 1000232153Smm entry->acl.mode = m; 1001228753Smm} 1002228753Smm 1003228753Smmvoid 1004232153Smmarchive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) 1005228753Smm{ 1006232153Smm FIX_NS(t, ns); 1007228753Smm entry->stat_valid = 0; 1008228753Smm entry->ae_set |= AE_SET_MTIME; 1009232153Smm entry->ae_stat.aest_mtime = t; 1010228753Smm entry->ae_stat.aest_mtime_nsec = ns; 1011228753Smm} 1012228753Smm 1013228753Smmvoid 1014228753Smmarchive_entry_unset_mtime(struct archive_entry *entry) 1015228753Smm{ 1016228753Smm archive_entry_set_mtime(entry, 0, 0); 1017228753Smm entry->ae_set &= ~AE_SET_MTIME; 1018228753Smm} 1019228753Smm 1020228753Smmvoid 1021228753Smmarchive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink) 1022228753Smm{ 1023228753Smm entry->stat_valid = 0; 1024228753Smm entry->ae_stat.aest_nlink = nlink; 1025228753Smm} 1026228753Smm 1027228753Smmvoid 1028228753Smmarchive_entry_set_pathname(struct archive_entry *entry, const char *name) 1029228753Smm{ 1030232153Smm archive_mstring_copy_mbs(&entry->ae_pathname, name); 1031228753Smm} 1032228753Smm 1033228753Smmvoid 1034228753Smmarchive_entry_copy_pathname(struct archive_entry *entry, const char *name) 1035228753Smm{ 1036232153Smm archive_mstring_copy_mbs(&entry->ae_pathname, name); 1037228753Smm} 1038228753Smm 1039228753Smmvoid 1040228753Smmarchive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) 1041228753Smm{ 1042232153Smm archive_mstring_copy_wcs(&entry->ae_pathname, name); 1043228753Smm} 1044228753Smm 1045228753Smmint 1046228753Smmarchive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name) 1047228753Smm{ 1048232153Smm if (archive_mstring_update_utf8(entry->archive, 1049232153Smm &entry->ae_pathname, name) == 0) 1050232153Smm return (1); 1051238856Smm if (errno == ENOMEM) 1052238856Smm __archive_errx(1, "No memory"); 1053232153Smm return (0); 1054228753Smm} 1055228753Smm 1056232153Smmint 1057232153Smm_archive_entry_copy_pathname_l(struct archive_entry *entry, 1058232153Smm const char *name, size_t len, struct archive_string_conv *sc) 1059232153Smm{ 1060232153Smm return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname, 1061232153Smm name, len, sc)); 1062232153Smm} 1063232153Smm 1064228753Smmvoid 1065228753Smmarchive_entry_set_perm(struct archive_entry *entry, mode_t p) 1066228753Smm{ 1067228753Smm entry->stat_valid = 0; 1068232153Smm entry->acl.mode &= AE_IFMT; 1069232153Smm entry->acl.mode |= ~AE_IFMT & p; 1070228753Smm} 1071228753Smm 1072228753Smmvoid 1073228753Smmarchive_entry_set_rdev(struct archive_entry *entry, dev_t m) 1074228753Smm{ 1075228753Smm entry->stat_valid = 0; 1076228753Smm entry->ae_stat.aest_rdev = m; 1077228753Smm entry->ae_stat.aest_rdev_is_broken_down = 0; 1078228753Smm} 1079228753Smm 1080228753Smmvoid 1081228753Smmarchive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) 1082228753Smm{ 1083228753Smm entry->stat_valid = 0; 1084228753Smm entry->ae_stat.aest_rdev_is_broken_down = 1; 1085228753Smm entry->ae_stat.aest_rdevmajor = m; 1086228753Smm} 1087228753Smm 1088228753Smmvoid 1089228753Smmarchive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) 1090228753Smm{ 1091228753Smm entry->stat_valid = 0; 1092228753Smm entry->ae_stat.aest_rdev_is_broken_down = 1; 1093228753Smm entry->ae_stat.aest_rdevminor = m; 1094228753Smm} 1095228753Smm 1096228753Smmvoid 1097228753Smmarchive_entry_set_size(struct archive_entry *entry, int64_t s) 1098228753Smm{ 1099228753Smm entry->stat_valid = 0; 1100228753Smm entry->ae_stat.aest_size = s; 1101228753Smm entry->ae_set |= AE_SET_SIZE; 1102228753Smm} 1103228753Smm 1104228753Smmvoid 1105228753Smmarchive_entry_unset_size(struct archive_entry *entry) 1106228753Smm{ 1107228753Smm archive_entry_set_size(entry, 0); 1108228753Smm entry->ae_set &= ~AE_SET_SIZE; 1109228753Smm} 1110228753Smm 1111228753Smmvoid 1112228753Smmarchive_entry_copy_sourcepath(struct archive_entry *entry, const char *path) 1113228753Smm{ 1114232153Smm archive_mstring_copy_mbs(&entry->ae_sourcepath, path); 1115228753Smm} 1116228753Smm 1117228753Smmvoid 1118232153Smmarchive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path) 1119232153Smm{ 1120232153Smm archive_mstring_copy_wcs(&entry->ae_sourcepath, path); 1121232153Smm} 1122232153Smm 1123232153Smmvoid 1124228753Smmarchive_entry_set_symlink(struct archive_entry *entry, const char *linkname) 1125228753Smm{ 1126232153Smm archive_mstring_copy_mbs(&entry->ae_symlink, linkname); 1127228753Smm if (linkname != NULL) 1128228753Smm entry->ae_set |= AE_SET_SYMLINK; 1129228753Smm else 1130228753Smm entry->ae_set &= ~AE_SET_SYMLINK; 1131228753Smm} 1132228753Smm 1133228753Smmvoid 1134228753Smmarchive_entry_copy_symlink(struct archive_entry *entry, const char *linkname) 1135228753Smm{ 1136232153Smm archive_mstring_copy_mbs(&entry->ae_symlink, linkname); 1137228753Smm if (linkname != NULL) 1138228753Smm entry->ae_set |= AE_SET_SYMLINK; 1139228753Smm else 1140228753Smm entry->ae_set &= ~AE_SET_SYMLINK; 1141228753Smm} 1142228753Smm 1143228753Smmvoid 1144228753Smmarchive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) 1145228753Smm{ 1146232153Smm archive_mstring_copy_wcs(&entry->ae_symlink, linkname); 1147228753Smm if (linkname != NULL) 1148228753Smm entry->ae_set |= AE_SET_SYMLINK; 1149228753Smm else 1150228753Smm entry->ae_set &= ~AE_SET_SYMLINK; 1151228753Smm} 1152228753Smm 1153228753Smmint 1154228753Smmarchive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) 1155228753Smm{ 1156228753Smm if (linkname != NULL) 1157228753Smm entry->ae_set |= AE_SET_SYMLINK; 1158228753Smm else 1159228753Smm entry->ae_set &= ~AE_SET_SYMLINK; 1160232153Smm if (archive_mstring_update_utf8(entry->archive, 1161232153Smm &entry->ae_symlink, linkname) == 0) 1162232153Smm return (1); 1163238856Smm if (errno == ENOMEM) 1164238856Smm __archive_errx(1, "No memory"); 1165232153Smm return (0); 1166228753Smm} 1167228753Smm 1168232153Smmint 1169232153Smm_archive_entry_copy_symlink_l(struct archive_entry *entry, 1170232153Smm const char *linkname, size_t len, struct archive_string_conv *sc) 1171232153Smm{ 1172232153Smm int r; 1173232153Smm 1174232153Smm r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, 1175232153Smm linkname, len, sc); 1176232153Smm if (linkname != NULL && r == 0) 1177232153Smm entry->ae_set |= AE_SET_SYMLINK; 1178232153Smm else 1179232153Smm entry->ae_set &= ~AE_SET_SYMLINK; 1180232153Smm return (r); 1181232153Smm} 1182232153Smm 1183228753Smmvoid 1184232153Smmarchive_entry_set_uid(struct archive_entry *entry, int64_t u) 1185228753Smm{ 1186228753Smm entry->stat_valid = 0; 1187228753Smm entry->ae_stat.aest_uid = u; 1188228753Smm} 1189228753Smm 1190228753Smmvoid 1191228753Smmarchive_entry_set_uname(struct archive_entry *entry, const char *name) 1192228753Smm{ 1193232153Smm archive_mstring_copy_mbs(&entry->ae_uname, name); 1194228753Smm} 1195228753Smm 1196228753Smmvoid 1197228753Smmarchive_entry_copy_uname(struct archive_entry *entry, const char *name) 1198228753Smm{ 1199232153Smm archive_mstring_copy_mbs(&entry->ae_uname, name); 1200228753Smm} 1201228753Smm 1202228753Smmvoid 1203228753Smmarchive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) 1204228753Smm{ 1205232153Smm archive_mstring_copy_wcs(&entry->ae_uname, name); 1206228753Smm} 1207228753Smm 1208228753Smmint 1209228753Smmarchive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) 1210228753Smm{ 1211232153Smm if (archive_mstring_update_utf8(entry->archive, 1212232153Smm &entry->ae_uname, name) == 0) 1213232153Smm return (1); 1214238856Smm if (errno == ENOMEM) 1215238856Smm __archive_errx(1, "No memory"); 1216232153Smm return (0); 1217228753Smm} 1218228753Smm 1219232153Smmint 1220232153Smm_archive_entry_copy_uname_l(struct archive_entry *entry, 1221232153Smm const char *name, size_t len, struct archive_string_conv *sc) 1222232153Smm{ 1223232153Smm return (archive_mstring_copy_mbs_len_l(&entry->ae_uname, 1224232153Smm name, len, sc)); 1225232153Smm} 1226232153Smm 1227232153Smmconst void * 1228232153Smmarchive_entry_mac_metadata(struct archive_entry *entry, size_t *s) 1229232153Smm{ 1230232153Smm *s = entry->mac_metadata_size; 1231232153Smm return entry->mac_metadata; 1232232153Smm} 1233232153Smm 1234232153Smmvoid 1235232153Smmarchive_entry_copy_mac_metadata(struct archive_entry *entry, 1236232153Smm const void *p, size_t s) 1237232153Smm{ 1238232153Smm free(entry->mac_metadata); 1239232153Smm if (p == NULL || s == 0) { 1240232153Smm entry->mac_metadata = NULL; 1241232153Smm entry->mac_metadata_size = 0; 1242232153Smm } else { 1243232153Smm entry->mac_metadata_size = s; 1244232153Smm entry->mac_metadata = malloc(s); 1245232153Smm if (entry->mac_metadata == NULL) 1246232153Smm abort(); 1247232153Smm memcpy(entry->mac_metadata, p, s); 1248232153Smm } 1249232153Smm} 1250232153Smm 1251228753Smm/* 1252228753Smm * ACL management. The following would, of course, be a lot simpler 1253228753Smm * if: 1) the last draft of POSIX.1e were a really thorough and 1254228753Smm * complete standard that addressed the needs of ACL archiving and 2) 1255228753Smm * everyone followed it faithfully. Alas, neither is true, so the 1256228753Smm * following is a lot more complex than might seem necessary to the 1257228753Smm * uninitiated. 1258228753Smm */ 1259228753Smm 1260232153Smmstruct archive_acl * 1261232153Smmarchive_entry_acl(struct archive_entry *entry) 1262232153Smm{ 1263232153Smm return &entry->acl; 1264232153Smm} 1265232153Smm 1266228753Smmvoid 1267228753Smmarchive_entry_acl_clear(struct archive_entry *entry) 1268228753Smm{ 1269232153Smm archive_acl_clear(&entry->acl); 1270228753Smm} 1271228753Smm 1272228753Smm/* 1273228753Smm * Add a single ACL entry to the internal list of ACL data. 1274228753Smm */ 1275232153Smmint 1276228753Smmarchive_entry_acl_add_entry(struct archive_entry *entry, 1277228753Smm int type, int permset, int tag, int id, const char *name) 1278228753Smm{ 1279232153Smm return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name); 1280228753Smm} 1281228753Smm 1282228753Smm/* 1283228753Smm * As above, but with a wide-character name. 1284228753Smm */ 1285232153Smmint 1286228753Smmarchive_entry_acl_add_entry_w(struct archive_entry *entry, 1287228753Smm int type, int permset, int tag, int id, const wchar_t *name) 1288228753Smm{ 1289232153Smm return archive_acl_add_entry_w_len(&entry->acl, 1290232153Smm type, permset, tag, id, name, wcslen(name)); 1291228753Smm} 1292228753Smm 1293228753Smm/* 1294228753Smm * Return a count of entries matching "want_type". 1295228753Smm */ 1296228753Smmint 1297228753Smmarchive_entry_acl_count(struct archive_entry *entry, int want_type) 1298228753Smm{ 1299232153Smm return archive_acl_count(&entry->acl, want_type); 1300228753Smm} 1301228753Smm 1302228753Smm/* 1303228753Smm * Prepare for reading entries from the ACL data. Returns a count 1304228753Smm * of entries matching "want_type", or zero if there are no 1305228753Smm * non-extended ACL entries of that type. 1306228753Smm */ 1307228753Smmint 1308228753Smmarchive_entry_acl_reset(struct archive_entry *entry, int want_type) 1309228753Smm{ 1310232153Smm return archive_acl_reset(&entry->acl, want_type); 1311228753Smm} 1312228753Smm 1313228753Smm/* 1314228753Smm * Return the next ACL entry in the list. Fake entries for the 1315228753Smm * standard permissions and include them in the returned list. 1316228753Smm */ 1317228753Smmint 1318228753Smmarchive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, 1319228753Smm int *permset, int *tag, int *id, const char **name) 1320228753Smm{ 1321238856Smm int r; 1322238856Smm r = archive_acl_next(entry->archive, &entry->acl, want_type, type, 1323238856Smm permset, tag, id, name); 1324238856Smm if (r == ARCHIVE_FATAL && errno == ENOMEM) 1325238856Smm __archive_errx(1, "No memory"); 1326238856Smm return (r); 1327228753Smm} 1328228753Smm 1329228753Smm/* 1330228753Smm * Generate a text version of the ACL. The flags parameter controls 1331228753Smm * the style of the generated ACL. 1332228753Smm */ 1333228753Smmconst wchar_t * 1334228753Smmarchive_entry_acl_text_w(struct archive_entry *entry, int flags) 1335228753Smm{ 1336238856Smm const wchar_t *r; 1337238856Smm r = archive_acl_text_w(entry->archive, &entry->acl, flags); 1338238856Smm if (r == NULL && errno == ENOMEM) 1339238856Smm __archive_errx(1, "No memory"); 1340238856Smm return (r); 1341228753Smm} 1342228753Smm 1343232153Smmconst char * 1344232153Smmarchive_entry_acl_text(struct archive_entry *entry, int flags) 1345228753Smm{ 1346232153Smm const char *p; 1347232153Smm if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0 1348232153Smm && errno == ENOMEM) 1349238856Smm __archive_errx(1, "No memory"); 1350232153Smm return (p); 1351228753Smm} 1352228753Smm 1353228753Smmint 1354232153Smm_archive_entry_acl_text_l(struct archive_entry *entry, int flags, 1355232153Smm const char **acl_text, size_t *len, struct archive_string_conv *sc) 1356228753Smm{ 1357232153Smm return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc)); 1358228753Smm} 1359228753Smm 1360228753Smm/* 1361228753Smm * Following code is modified from UC Berkeley sources, and 1362228753Smm * is subject to the following copyright notice. 1363228753Smm */ 1364228753Smm 1365228753Smm/*- 1366228753Smm * Copyright (c) 1993 1367228753Smm * The Regents of the University of California. All rights reserved. 1368228753Smm * 1369228753Smm * Redistribution and use in source and binary forms, with or without 1370228753Smm * modification, are permitted provided that the following conditions 1371228753Smm * are met: 1372228753Smm * 1. Redistributions of source code must retain the above copyright 1373228753Smm * notice, this list of conditions and the following disclaimer. 1374228753Smm * 2. Redistributions in binary form must reproduce the above copyright 1375228753Smm * notice, this list of conditions and the following disclaimer in the 1376228753Smm * documentation and/or other materials provided with the distribution. 1377228753Smm * 4. Neither the name of the University nor the names of its contributors 1378228753Smm * may be used to endorse or promote products derived from this software 1379228753Smm * without specific prior written permission. 1380228753Smm * 1381228753Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1382228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1383228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1384228753Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1385228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1386228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1387228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1388228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1389228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1390228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1391228753Smm * SUCH DAMAGE. 1392228753Smm */ 1393228753Smm 1394228753Smmstatic struct flag { 1395228753Smm const char *name; 1396228753Smm const wchar_t *wname; 1397228753Smm unsigned long set; 1398228753Smm unsigned long clear; 1399228753Smm} flags[] = { 1400228753Smm /* Preferred (shorter) names per flag first, all prefixed by "no" */ 1401228753Smm#ifdef SF_APPEND 1402228753Smm { "nosappnd", L"nosappnd", SF_APPEND, 0 }, 1403228753Smm { "nosappend", L"nosappend", SF_APPEND, 0 }, 1404228753Smm#endif 1405228753Smm#ifdef EXT2_APPEND_FL /* 'a' */ 1406228753Smm { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 }, 1407228753Smm { "nosappend", L"nosappend", EXT2_APPEND_FL, 0 }, 1408228753Smm#endif 1409228753Smm#ifdef SF_ARCHIVED 1410228753Smm { "noarch", L"noarch", SF_ARCHIVED, 0 }, 1411228753Smm { "noarchived", L"noarchived", SF_ARCHIVED, 0 }, 1412228753Smm#endif 1413228753Smm#ifdef SF_IMMUTABLE 1414228753Smm { "noschg", L"noschg", SF_IMMUTABLE, 0 }, 1415228753Smm { "noschange", L"noschange", SF_IMMUTABLE, 0 }, 1416228753Smm { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 }, 1417228753Smm#endif 1418228753Smm#ifdef EXT2_IMMUTABLE_FL /* 'i' */ 1419228753Smm { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 }, 1420228753Smm { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 }, 1421228753Smm { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 }, 1422228753Smm#endif 1423228753Smm#ifdef SF_NOUNLINK 1424228753Smm { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0 }, 1425228753Smm { "nosunlink", L"nosunlink", SF_NOUNLINK, 0 }, 1426228753Smm#endif 1427228753Smm#ifdef SF_SNAPSHOT 1428228753Smm { "nosnapshot", L"nosnapshot", SF_SNAPSHOT, 0 }, 1429228753Smm#endif 1430228753Smm#ifdef UF_APPEND 1431228753Smm { "nouappnd", L"nouappnd", UF_APPEND, 0 }, 1432228753Smm { "nouappend", L"nouappend", UF_APPEND, 0 }, 1433228753Smm#endif 1434228753Smm#ifdef UF_IMMUTABLE 1435228753Smm { "nouchg", L"nouchg", UF_IMMUTABLE, 0 }, 1436228753Smm { "nouchange", L"nouchange", UF_IMMUTABLE, 0 }, 1437228753Smm { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0 }, 1438228753Smm#endif 1439228753Smm#ifdef UF_NODUMP 1440228753Smm { "nodump", L"nodump", 0, UF_NODUMP}, 1441228753Smm#endif 1442228753Smm#ifdef EXT2_NODUMP_FL /* 'd' */ 1443228753Smm { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, 1444228753Smm#endif 1445228753Smm#ifdef UF_OPAQUE 1446228753Smm { "noopaque", L"noopaque", UF_OPAQUE, 0 }, 1447228753Smm#endif 1448228753Smm#ifdef UF_NOUNLINK 1449228753Smm { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 }, 1450228753Smm { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 }, 1451228753Smm#endif 1452248616Smm#ifdef UF_COMPRESSED 1453248616Smm { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, 1454248616Smm#endif 1455228753Smm#ifdef EXT2_UNRM_FL 1456228753Smm { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0}, 1457228753Smm#endif 1458228753Smm 1459228753Smm#ifdef EXT2_BTREE_FL 1460228753Smm { "nobtree", L"nobtree", EXT2_BTREE_FL, 0 }, 1461228753Smm#endif 1462228753Smm 1463228753Smm#ifdef EXT2_ECOMPR_FL 1464228753Smm { "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 }, 1465228753Smm#endif 1466228753Smm 1467228753Smm#ifdef EXT2_COMPR_FL /* 'c' */ 1468228753Smm { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 }, 1469228753Smm#endif 1470228753Smm 1471228753Smm#ifdef EXT2_NOATIME_FL /* 'A' */ 1472228753Smm { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, 1473228753Smm#endif 1474228753Smm 1475228753Smm#ifdef EXT2_DIRTY_FL 1476228753Smm { "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0}, 1477228753Smm#endif 1478228753Smm 1479228753Smm#ifdef EXT2_COMPRBLK_FL 1480228753Smm#ifdef EXT2_NOCOMPR_FL 1481228753Smm { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL}, 1482228753Smm#else 1483228753Smm { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0}, 1484228753Smm#endif 1485228753Smm#endif 1486228753Smm#ifdef EXT2_DIRSYNC_FL 1487228753Smm { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, 1488228753Smm#endif 1489228753Smm#ifdef EXT2_INDEX_FL 1490228753Smm { "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0}, 1491228753Smm#endif 1492228753Smm#ifdef EXT2_IMAGIC_FL 1493228753Smm { "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0}, 1494228753Smm#endif 1495228753Smm#ifdef EXT3_JOURNAL_DATA_FL 1496228753Smm { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, 1497228753Smm#endif 1498228753Smm#ifdef EXT2_SECRM_FL 1499228753Smm { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, 1500228753Smm#endif 1501228753Smm#ifdef EXT2_SYNC_FL 1502228753Smm { "nosync", L"nosync", EXT2_SYNC_FL, 0}, 1503228753Smm#endif 1504228753Smm#ifdef EXT2_NOTAIL_FL 1505228753Smm { "notail", L"notail", 0, EXT2_NOTAIL_FL}, 1506228753Smm#endif 1507228753Smm#ifdef EXT2_TOPDIR_FL 1508228753Smm { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, 1509228753Smm#endif 1510228753Smm#ifdef EXT2_RESERVED_FL 1511228753Smm { "noreserved", L"noreserved", EXT2_RESERVED_FL, 0}, 1512228753Smm#endif 1513228753Smm 1514228753Smm { NULL, NULL, 0, 0 } 1515228753Smm}; 1516228753Smm 1517228753Smm/* 1518228753Smm * fflagstostr -- 1519228753Smm * Convert file flags to a comma-separated string. If no flags 1520228753Smm * are set, return the empty string. 1521228753Smm */ 1522228753Smmstatic char * 1523228753Smmae_fflagstostr(unsigned long bitset, unsigned long bitclear) 1524228753Smm{ 1525228753Smm char *string, *dp; 1526228753Smm const char *sp; 1527228753Smm unsigned long bits; 1528228753Smm struct flag *flag; 1529228753Smm size_t length; 1530228753Smm 1531228753Smm bits = bitset | bitclear; 1532228753Smm length = 0; 1533228753Smm for (flag = flags; flag->name != NULL; flag++) 1534228753Smm if (bits & (flag->set | flag->clear)) { 1535228753Smm length += strlen(flag->name) + 1; 1536228753Smm bits &= ~(flag->set | flag->clear); 1537228753Smm } 1538228753Smm 1539228753Smm if (length == 0) 1540228753Smm return (NULL); 1541228753Smm string = (char *)malloc(length); 1542228753Smm if (string == NULL) 1543228753Smm return (NULL); 1544228753Smm 1545228753Smm dp = string; 1546228753Smm for (flag = flags; flag->name != NULL; flag++) { 1547228753Smm if (bitset & flag->set || bitclear & flag->clear) { 1548228753Smm sp = flag->name + 2; 1549228753Smm } else if (bitset & flag->clear || bitclear & flag->set) { 1550228753Smm sp = flag->name; 1551228753Smm } else 1552228753Smm continue; 1553228753Smm bitset &= ~(flag->set | flag->clear); 1554228753Smm bitclear &= ~(flag->set | flag->clear); 1555228753Smm if (dp > string) 1556228753Smm *dp++ = ','; 1557228753Smm while ((*dp++ = *sp++) != '\0') 1558228753Smm ; 1559228753Smm dp--; 1560228753Smm } 1561228753Smm 1562228753Smm *dp = '\0'; 1563228753Smm return (string); 1564228753Smm} 1565228753Smm 1566228753Smm/* 1567228753Smm * strtofflags -- 1568228753Smm * Take string of arguments and return file flags. This 1569228753Smm * version works a little differently than strtofflags(3). 1570228753Smm * In particular, it always tests every token, skipping any 1571228753Smm * unrecognized tokens. It returns a pointer to the first 1572228753Smm * unrecognized token, or NULL if every token was recognized. 1573228753Smm * This version is also const-correct and does not modify the 1574228753Smm * provided string. 1575228753Smm */ 1576228753Smmstatic const char * 1577228753Smmae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp) 1578228753Smm{ 1579228753Smm const char *start, *end; 1580228753Smm struct flag *flag; 1581228753Smm unsigned long set, clear; 1582228753Smm const char *failed; 1583228753Smm 1584228753Smm set = clear = 0; 1585228753Smm start = s; 1586228753Smm failed = NULL; 1587228753Smm /* Find start of first token. */ 1588228753Smm while (*start == '\t' || *start == ' ' || *start == ',') 1589228753Smm start++; 1590228753Smm while (*start != '\0') { 1591228753Smm /* Locate end of token. */ 1592228753Smm end = start; 1593228753Smm while (*end != '\0' && *end != '\t' && 1594228753Smm *end != ' ' && *end != ',') 1595228753Smm end++; 1596228753Smm for (flag = flags; flag->name != NULL; flag++) { 1597228753Smm if (memcmp(start, flag->name, end - start) == 0) { 1598228753Smm /* Matched "noXXXX", so reverse the sense. */ 1599228753Smm clear |= flag->set; 1600228753Smm set |= flag->clear; 1601228753Smm break; 1602228753Smm } else if (memcmp(start, flag->name + 2, end - start) 1603228753Smm == 0) { 1604228753Smm /* Matched "XXXX", so don't reverse. */ 1605228753Smm set |= flag->set; 1606228753Smm clear |= flag->clear; 1607228753Smm break; 1608228753Smm } 1609228753Smm } 1610228753Smm /* Ignore unknown flag names. */ 1611228753Smm if (flag->name == NULL && failed == NULL) 1612228753Smm failed = start; 1613228753Smm 1614228753Smm /* Find start of next token. */ 1615228753Smm start = end; 1616228753Smm while (*start == '\t' || *start == ' ' || *start == ',') 1617228753Smm start++; 1618228753Smm 1619228753Smm } 1620228753Smm 1621228753Smm if (setp) 1622228753Smm *setp = set; 1623228753Smm if (clrp) 1624228753Smm *clrp = clear; 1625228753Smm 1626228753Smm /* Return location of first failure. */ 1627228753Smm return (failed); 1628228753Smm} 1629228753Smm 1630228753Smm/* 1631228753Smm * wcstofflags -- 1632228753Smm * Take string of arguments and return file flags. This 1633228753Smm * version works a little differently than strtofflags(3). 1634228753Smm * In particular, it always tests every token, skipping any 1635228753Smm * unrecognized tokens. It returns a pointer to the first 1636228753Smm * unrecognized token, or NULL if every token was recognized. 1637228753Smm * This version is also const-correct and does not modify the 1638228753Smm * provided string. 1639228753Smm */ 1640228753Smmstatic const wchar_t * 1641228753Smmae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) 1642228753Smm{ 1643228753Smm const wchar_t *start, *end; 1644228753Smm struct flag *flag; 1645228753Smm unsigned long set, clear; 1646228753Smm const wchar_t *failed; 1647228753Smm 1648228753Smm set = clear = 0; 1649228753Smm start = s; 1650228753Smm failed = NULL; 1651228753Smm /* Find start of first token. */ 1652228753Smm while (*start == L'\t' || *start == L' ' || *start == L',') 1653228753Smm start++; 1654228753Smm while (*start != L'\0') { 1655228753Smm /* Locate end of token. */ 1656228753Smm end = start; 1657228753Smm while (*end != L'\0' && *end != L'\t' && 1658228753Smm *end != L' ' && *end != L',') 1659228753Smm end++; 1660228753Smm for (flag = flags; flag->wname != NULL; flag++) { 1661228753Smm if (wmemcmp(start, flag->wname, end - start) == 0) { 1662228753Smm /* Matched "noXXXX", so reverse the sense. */ 1663228753Smm clear |= flag->set; 1664228753Smm set |= flag->clear; 1665228753Smm break; 1666228753Smm } else if (wmemcmp(start, flag->wname + 2, end - start) 1667228753Smm == 0) { 1668228753Smm /* Matched "XXXX", so don't reverse. */ 1669228753Smm set |= flag->set; 1670228753Smm clear |= flag->clear; 1671228753Smm break; 1672228753Smm } 1673228753Smm } 1674228753Smm /* Ignore unknown flag names. */ 1675228753Smm if (flag->wname == NULL && failed == NULL) 1676228753Smm failed = start; 1677228753Smm 1678228753Smm /* Find start of next token. */ 1679228753Smm start = end; 1680228753Smm while (*start == L'\t' || *start == L' ' || *start == L',') 1681228753Smm start++; 1682228753Smm 1683228753Smm } 1684228753Smm 1685228753Smm if (setp) 1686228753Smm *setp = set; 1687228753Smm if (clrp) 1688228753Smm *clrp = clear; 1689228753Smm 1690228753Smm /* Return location of first failure. */ 1691228753Smm return (failed); 1692228753Smm} 1693228753Smm 1694228753Smm 1695228753Smm#ifdef TEST 1696228753Smm#include <stdio.h> 1697228753Smmint 1698228753Smmmain(int argc, char **argv) 1699228753Smm{ 1700228753Smm struct archive_entry *entry = archive_entry_new(); 1701228753Smm unsigned long set, clear; 1702228753Smm const wchar_t *remainder; 1703228753Smm 1704228753Smm remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); 1705228753Smm archive_entry_fflags(entry, &set, &clear); 1706228753Smm 1707228753Smm wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); 1708228753Smm 1709228753Smm wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); 1710228753Smm return (0); 1711228753Smm} 1712228753Smm#endif 1713