1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * Copyright (c) 2016 Martin Matuska
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $");
29 
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
35 #endif
36 #if MAJOR_IN_MKDEV
37 #include <sys/mkdev.h>
38 #define HAVE_MAJOR
39 #elif MAJOR_IN_SYSMACROS
40 #include <sys/sysmacros.h>
41 #define HAVE_MAJOR
42 #endif
43 #ifdef HAVE_ERRNO_H
44 #include <errno.h>
45 #endif
46 #ifdef HAVE_LIMITS_H
47 #include <limits.h>
48 #endif
49 #ifdef HAVE_LINUX_FS_H
50 #include <linux/fs.h>	/* for Linux file flags */
51 #endif
52 /*
53  * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
54  * As the include guards don't agree, the order of include is important.
55  */
56 #ifdef HAVE_LINUX_EXT2_FS_H
57 #include <linux/ext2_fs.h>	/* for Linux file flags */
58 #endif
59 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
60 #include <ext2fs/ext2_fs.h>	/* for Linux file flags */
61 #endif
62 #include <stddef.h>
63 #include <stdio.h>
64 #ifdef HAVE_STDLIB_H
65 #include <stdlib.h>
66 #endif
67 #ifdef HAVE_STRING_H
68 #include <string.h>
69 #endif
70 #ifdef HAVE_WCHAR_H
71 #include <wchar.h>
72 #endif
73 
74 #include "archive.h"
75 #include "archive_acl_private.h"
76 #include "archive_entry.h"
77 #include "archive_entry_locale.h"
78 #include "archive_private.h"
79 #include "archive_entry_private.h"
80 
81 #if !defined(HAVE_MAJOR) && !defined(major)
82 /* Replacement for major/minor/makedev. */
83 #define	major(x) ((int)(0x00ff & ((x) >> 8)))
84 #define	minor(x) ((int)(0xffff00ff & (x)))
85 #define	makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
86 #endif
87 
88 /* Play games to come up with a suitable makedev() definition. */
89 #ifdef __QNXNTO__
90 /* QNX.  <sigh> */
91 #include <sys/netmgr.h>
92 #define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
93 #elif defined makedev
94 /* There's a "makedev" macro. */
95 #define ae_makedev(maj, min) makedev((maj), (min))
96 #elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
97 /* Windows. <sigh> */
98 #define ae_makedev(maj, min) mkdev((maj), (min))
99 #else
100 /* There's a "makedev" function. */
101 #define ae_makedev(maj, min) makedev((maj), (min))
102 #endif
103 
104 /*
105  * This adjustment is needed to support the following idiom for adding
106  * 1000ns to the stored time:
107  * archive_entry_set_atime(archive_entry_atime(),
108  *                         archive_entry_atime_nsec() + 1000)
109  * The additional if() here compensates for ambiguity in the C standard,
110  * which permits two possible interpretations of a % b when a is negative.
111  */
112 #define FIX_NS(t,ns) \
113 	do {	\
114 		t += ns / 1000000000; \
115 		ns %= 1000000000; \
116 		if (ns < 0) { --t; ns += 1000000000; } \
117 	} while (0)
118 
119 static char *	 ae_fflagstostr(unsigned long bitset, unsigned long bitclear);
120 static const wchar_t	*ae_wcstofflags(const wchar_t *stringp,
121 		    unsigned long *setp, unsigned long *clrp);
122 static const char	*ae_strtofflags(const char *stringp,
123 		    unsigned long *setp, unsigned long *clrp);
124 
125 #ifndef HAVE_WCSCPY
wcscpy(wchar_t * s1,const wchar_t * s2)126 static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
127 {
128 	wchar_t *dest = s1;
129 	while ((*s1 = *s2) != L'\0')
130 		++s1, ++s2;
131 	return dest;
132 }
133 #endif
134 #ifndef HAVE_WCSLEN
wcslen(const wchar_t * s)135 static size_t wcslen(const wchar_t *s)
136 {
137 	const wchar_t *p = s;
138 	while (*p != L'\0')
139 		++p;
140 	return p - s;
141 }
142 #endif
143 #ifndef HAVE_WMEMCMP
144 /* Good enough for simple equality testing, but not for sorting. */
145 #define wmemcmp(a,b,i)  memcmp((a), (b), (i) * sizeof(wchar_t))
146 #endif
147 
148 /****************************************************************************
149  *
150  * Public Interface
151  *
152  ****************************************************************************/
153 
154 struct archive_entry *
archive_entry_clear(struct archive_entry * entry)155 archive_entry_clear(struct archive_entry *entry)
156 {
157 	if (entry == NULL)
158 		return (NULL);
159 	archive_mstring_clean(&entry->ae_fflags_text);
160 	archive_mstring_clean(&entry->ae_gname);
161 	archive_mstring_clean(&entry->ae_hardlink);
162 	archive_mstring_clean(&entry->ae_pathname);
163 	archive_mstring_clean(&entry->ae_sourcepath);
164 	archive_mstring_clean(&entry->ae_symlink);
165 	archive_mstring_clean(&entry->ae_uname);
166 	archive_entry_copy_mac_metadata(entry, NULL, 0);
167 	archive_acl_clear(&entry->acl);
168 	archive_entry_xattr_clear(entry);
169 	archive_entry_sparse_clear(entry);
170 	free(entry->stat);
171 	memset(entry, 0, sizeof(*entry));
172 	return entry;
173 }
174 
175 struct archive_entry *
archive_entry_clone(struct archive_entry * entry)176 archive_entry_clone(struct archive_entry *entry)
177 {
178 	struct archive_entry *entry2;
179 	struct ae_xattr *xp;
180 	struct ae_sparse *sp;
181 	size_t s;
182 	const void *p;
183 
184 	/* Allocate new structure and copy over all of the fields. */
185 	/* TODO: Should we copy the archive over?  Or require a new archive
186 	 * as an argument? */
187 	entry2 = archive_entry_new2(entry->archive);
188 	if (entry2 == NULL)
189 		return (NULL);
190 	entry2->ae_stat = entry->ae_stat;
191 	entry2->ae_fflags_set = entry->ae_fflags_set;
192 	entry2->ae_fflags_clear = entry->ae_fflags_clear;
193 
194 	/* TODO: XXX If clone can have a different archive, what do we do here if
195 	 * character sets are different? XXX */
196 	archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
197 	archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
198 	archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
199 	archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
200 	archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
201 	archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink);
202 	entry2->ae_set = entry->ae_set;
203 	archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
204 
205 	/* Copy encryption status */
206 	entry2->encryption = entry->encryption;
207 
208 	/* Copy ACL data over. */
209 	archive_acl_copy(&entry2->acl, &entry->acl);
210 
211 	/* Copy Mac OS metadata. */
212 	p = archive_entry_mac_metadata(entry, &s);
213 	archive_entry_copy_mac_metadata(entry2, p, s);
214 
215 	/* Copy xattr data over. */
216 	xp = entry->xattr_head;
217 	while (xp != NULL) {
218 		archive_entry_xattr_add_entry(entry2,
219 		    xp->name, xp->value, xp->size);
220 		xp = xp->next;
221 	}
222 
223 	/* Copy sparse data over. */
224 	sp = entry->sparse_head;
225 	while (sp != NULL) {
226 		archive_entry_sparse_add_entry(entry2,
227 		    sp->offset, sp->length);
228 		sp = sp->next;
229 	}
230 
231 	return (entry2);
232 }
233 
234 void
archive_entry_free(struct archive_entry * entry)235 archive_entry_free(struct archive_entry *entry)
236 {
237 	archive_entry_clear(entry);
238 	free(entry);
239 }
240 
241 struct archive_entry *
archive_entry_new(void)242 archive_entry_new(void)
243 {
244 	return archive_entry_new2(NULL);
245 }
246 
247 struct archive_entry *
archive_entry_new2(struct archive * a)248 archive_entry_new2(struct archive *a)
249 {
250 	struct archive_entry *entry;
251 
252 	entry = (struct archive_entry *)calloc(1, sizeof(*entry));
253 	if (entry == NULL)
254 		return (NULL);
255 	entry->archive = a;
256 	return (entry);
257 }
258 
259 /*
260  * Functions for reading fields from an archive_entry.
261  */
262 
263 time_t
archive_entry_atime(struct archive_entry * entry)264 archive_entry_atime(struct archive_entry *entry)
265 {
266 	return (entry->ae_stat.aest_atime);
267 }
268 
269 long
archive_entry_atime_nsec(struct archive_entry * entry)270 archive_entry_atime_nsec(struct archive_entry *entry)
271 {
272 	return (entry->ae_stat.aest_atime_nsec);
273 }
274 
275 int
archive_entry_atime_is_set(struct archive_entry * entry)276 archive_entry_atime_is_set(struct archive_entry *entry)
277 {
278 	return (entry->ae_set & AE_SET_ATIME);
279 }
280 
281 time_t
archive_entry_birthtime(struct archive_entry * entry)282 archive_entry_birthtime(struct archive_entry *entry)
283 {
284 	return (entry->ae_stat.aest_birthtime);
285 }
286 
287 long
archive_entry_birthtime_nsec(struct archive_entry * entry)288 archive_entry_birthtime_nsec(struct archive_entry *entry)
289 {
290 	return (entry->ae_stat.aest_birthtime_nsec);
291 }
292 
293 int
archive_entry_birthtime_is_set(struct archive_entry * entry)294 archive_entry_birthtime_is_set(struct archive_entry *entry)
295 {
296 	return (entry->ae_set & AE_SET_BIRTHTIME);
297 }
298 
299 time_t
archive_entry_ctime(struct archive_entry * entry)300 archive_entry_ctime(struct archive_entry *entry)
301 {
302 	return (entry->ae_stat.aest_ctime);
303 }
304 
305 int
archive_entry_ctime_is_set(struct archive_entry * entry)306 archive_entry_ctime_is_set(struct archive_entry *entry)
307 {
308 	return (entry->ae_set & AE_SET_CTIME);
309 }
310 
311 long
archive_entry_ctime_nsec(struct archive_entry * entry)312 archive_entry_ctime_nsec(struct archive_entry *entry)
313 {
314 	return (entry->ae_stat.aest_ctime_nsec);
315 }
316 
317 dev_t
archive_entry_dev(struct archive_entry * entry)318 archive_entry_dev(struct archive_entry *entry)
319 {
320 	if (entry->ae_stat.aest_dev_is_broken_down)
321 		return ae_makedev(entry->ae_stat.aest_devmajor,
322 		    entry->ae_stat.aest_devminor);
323 	else
324 		return (entry->ae_stat.aest_dev);
325 }
326 
327 int
archive_entry_dev_is_set(struct archive_entry * entry)328 archive_entry_dev_is_set(struct archive_entry *entry)
329 {
330 	return (entry->ae_set & AE_SET_DEV);
331 }
332 
333 dev_t
archive_entry_devmajor(struct archive_entry * entry)334 archive_entry_devmajor(struct archive_entry *entry)
335 {
336 	if (entry->ae_stat.aest_dev_is_broken_down)
337 		return (entry->ae_stat.aest_devmajor);
338 	else
339 		return major(entry->ae_stat.aest_dev);
340 }
341 
342 dev_t
archive_entry_devminor(struct archive_entry * entry)343 archive_entry_devminor(struct archive_entry *entry)
344 {
345 	if (entry->ae_stat.aest_dev_is_broken_down)
346 		return (entry->ae_stat.aest_devminor);
347 	else
348 		return minor(entry->ae_stat.aest_dev);
349 }
350 
351 mode_t
archive_entry_filetype(struct archive_entry * entry)352 archive_entry_filetype(struct archive_entry *entry)
353 {
354 	return (AE_IFMT & entry->acl.mode);
355 }
356 
357 void
archive_entry_fflags(struct archive_entry * entry,unsigned long * set,unsigned long * clear)358 archive_entry_fflags(struct archive_entry *entry,
359     unsigned long *set, unsigned long *clear)
360 {
361 	*set = entry->ae_fflags_set;
362 	*clear = entry->ae_fflags_clear;
363 }
364 
365 /*
366  * Note: if text was provided, this just returns that text.  If you
367  * really need the text to be rebuilt in a canonical form, set the
368  * text, ask for the bitmaps, then set the bitmaps.  (Setting the
369  * bitmaps clears any stored text.)  This design is deliberate: if
370  * we're editing archives, we don't want to discard flags just because
371  * they aren't supported on the current system.  The bitmap<->text
372  * conversions are platform-specific (see below).
373  */
374 const char *
archive_entry_fflags_text(struct archive_entry * entry)375 archive_entry_fflags_text(struct archive_entry *entry)
376 {
377 	const char *f;
378 	char *p;
379 
380 	if (archive_mstring_get_mbs(entry->archive,
381 	    &entry->ae_fflags_text, &f) == 0) {
382 		if (f != NULL)
383 			return (f);
384 	} else if (errno == ENOMEM)
385 		__archive_errx(1, "No memory");
386 
387 	if (entry->ae_fflags_set == 0  &&  entry->ae_fflags_clear == 0)
388 		return (NULL);
389 
390 	p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);
391 	if (p == NULL)
392 		return (NULL);
393 
394 	archive_mstring_copy_mbs(&entry->ae_fflags_text, p);
395 	free(p);
396 	if (archive_mstring_get_mbs(entry->archive,
397 	    &entry->ae_fflags_text, &f) == 0)
398 		return (f);
399 	if (errno == ENOMEM)
400 		__archive_errx(1, "No memory");
401 	return (NULL);
402 }
403 
404 int64_t
archive_entry_gid(struct archive_entry * entry)405 archive_entry_gid(struct archive_entry *entry)
406 {
407 	return (entry->ae_stat.aest_gid);
408 }
409 
410 const char *
archive_entry_gname(struct archive_entry * entry)411 archive_entry_gname(struct archive_entry *entry)
412 {
413 	const char *p;
414 	if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
415 		return (p);
416 	if (errno == ENOMEM)
417 		__archive_errx(1, "No memory");
418 	return (NULL);
419 }
420 
421 const char *
archive_entry_gname_utf8(struct archive_entry * entry)422 archive_entry_gname_utf8(struct archive_entry *entry)
423 {
424 	const char *p;
425 	if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)
426 		return (p);
427 	if (errno == ENOMEM)
428 		__archive_errx(1, "No memory");
429 	return (NULL);
430 }
431 
432 
433 const wchar_t *
archive_entry_gname_w(struct archive_entry * entry)434 archive_entry_gname_w(struct archive_entry *entry)
435 {
436 	const wchar_t *p;
437 	if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
438 		return (p);
439 	if (errno == ENOMEM)
440 		__archive_errx(1, "No memory");
441 	return (NULL);
442 }
443 
444 int
_archive_entry_gname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)445 _archive_entry_gname_l(struct archive_entry *entry,
446     const char **p, size_t *len, struct archive_string_conv *sc)
447 {
448 	return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc));
449 }
450 
451 const char *
archive_entry_hardlink(struct archive_entry * entry)452 archive_entry_hardlink(struct archive_entry *entry)
453 {
454 	const char *p;
455 	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
456 		return (NULL);
457 	if (archive_mstring_get_mbs(
458 	    entry->archive, &entry->ae_hardlink, &p) == 0)
459 		return (p);
460 	if (errno == ENOMEM)
461 		__archive_errx(1, "No memory");
462 	return (NULL);
463 }
464 
465 const char *
archive_entry_hardlink_utf8(struct archive_entry * entry)466 archive_entry_hardlink_utf8(struct archive_entry *entry)
467 {
468 	const char *p;
469 	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
470 		return (NULL);
471 	if (archive_mstring_get_utf8(
472 	    entry->archive, &entry->ae_hardlink, &p) == 0)
473 		return (p);
474 	if (errno == ENOMEM)
475 		__archive_errx(1, "No memory");
476 	return (NULL);
477 }
478 
479 const wchar_t *
archive_entry_hardlink_w(struct archive_entry * entry)480 archive_entry_hardlink_w(struct archive_entry *entry)
481 {
482 	const wchar_t *p;
483 	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
484 		return (NULL);
485 	if (archive_mstring_get_wcs(
486 	    entry->archive, &entry->ae_hardlink, &p) == 0)
487 		return (p);
488 	if (errno == ENOMEM)
489 		__archive_errx(1, "No memory");
490 	return (NULL);
491 }
492 
493 int
_archive_entry_hardlink_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)494 _archive_entry_hardlink_l(struct archive_entry *entry,
495     const char **p, size_t *len, struct archive_string_conv *sc)
496 {
497 	if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
498 		*p = NULL;
499 		*len = 0;
500 		return (0);
501 	}
502 	return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
503 }
504 
505 int64_t
archive_entry_ino(struct archive_entry * entry)506 archive_entry_ino(struct archive_entry *entry)
507 {
508 	return (entry->ae_stat.aest_ino);
509 }
510 
511 int
archive_entry_ino_is_set(struct archive_entry * entry)512 archive_entry_ino_is_set(struct archive_entry *entry)
513 {
514 	return (entry->ae_set & AE_SET_INO);
515 }
516 
517 int64_t
archive_entry_ino64(struct archive_entry * entry)518 archive_entry_ino64(struct archive_entry *entry)
519 {
520 	return (entry->ae_stat.aest_ino);
521 }
522 
523 mode_t
archive_entry_mode(struct archive_entry * entry)524 archive_entry_mode(struct archive_entry *entry)
525 {
526 	return (entry->acl.mode);
527 }
528 
529 time_t
archive_entry_mtime(struct archive_entry * entry)530 archive_entry_mtime(struct archive_entry *entry)
531 {
532 	return (entry->ae_stat.aest_mtime);
533 }
534 
535 long
archive_entry_mtime_nsec(struct archive_entry * entry)536 archive_entry_mtime_nsec(struct archive_entry *entry)
537 {
538 	return (entry->ae_stat.aest_mtime_nsec);
539 }
540 
541 int
archive_entry_mtime_is_set(struct archive_entry * entry)542 archive_entry_mtime_is_set(struct archive_entry *entry)
543 {
544 	return (entry->ae_set & AE_SET_MTIME);
545 }
546 
547 unsigned int
archive_entry_nlink(struct archive_entry * entry)548 archive_entry_nlink(struct archive_entry *entry)
549 {
550 	return (entry->ae_stat.aest_nlink);
551 }
552 
553 const char *
archive_entry_pathname(struct archive_entry * entry)554 archive_entry_pathname(struct archive_entry *entry)
555 {
556 	const char *p;
557 	if (archive_mstring_get_mbs(
558 	    entry->archive, &entry->ae_pathname, &p) == 0)
559 		return (p);
560 	if (errno == ENOMEM)
561 		__archive_errx(1, "No memory");
562 	return (NULL);
563 }
564 
565 const char *
archive_entry_pathname_utf8(struct archive_entry * entry)566 archive_entry_pathname_utf8(struct archive_entry *entry)
567 {
568 	const char *p;
569 	if (archive_mstring_get_utf8(
570 	    entry->archive, &entry->ae_pathname, &p) == 0)
571 		return (p);
572 	if (errno == ENOMEM)
573 		__archive_errx(1, "No memory");
574 	return (NULL);
575 }
576 
577 const wchar_t *
archive_entry_pathname_w(struct archive_entry * entry)578 archive_entry_pathname_w(struct archive_entry *entry)
579 {
580 	const wchar_t *p;
581 	if (archive_mstring_get_wcs(
582 	    entry->archive, &entry->ae_pathname, &p) == 0)
583 		return (p);
584 	if (errno == ENOMEM)
585 		__archive_errx(1, "No memory");
586 	return (NULL);
587 }
588 
589 int
_archive_entry_pathname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)590 _archive_entry_pathname_l(struct archive_entry *entry,
591     const char **p, size_t *len, struct archive_string_conv *sc)
592 {
593 	return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc));
594 }
595 
596 mode_t
archive_entry_perm(struct archive_entry * entry)597 archive_entry_perm(struct archive_entry *entry)
598 {
599 	return (~AE_IFMT & entry->acl.mode);
600 }
601 
602 dev_t
archive_entry_rdev(struct archive_entry * entry)603 archive_entry_rdev(struct archive_entry *entry)
604 {
605 	if (entry->ae_stat.aest_rdev_is_broken_down)
606 		return ae_makedev(entry->ae_stat.aest_rdevmajor,
607 		    entry->ae_stat.aest_rdevminor);
608 	else
609 		return (entry->ae_stat.aest_rdev);
610 }
611 
612 dev_t
archive_entry_rdevmajor(struct archive_entry * entry)613 archive_entry_rdevmajor(struct archive_entry *entry)
614 {
615 	if (entry->ae_stat.aest_rdev_is_broken_down)
616 		return (entry->ae_stat.aest_rdevmajor);
617 	else
618 		return major(entry->ae_stat.aest_rdev);
619 }
620 
621 dev_t
archive_entry_rdevminor(struct archive_entry * entry)622 archive_entry_rdevminor(struct archive_entry *entry)
623 {
624 	if (entry->ae_stat.aest_rdev_is_broken_down)
625 		return (entry->ae_stat.aest_rdevminor);
626 	else
627 		return minor(entry->ae_stat.aest_rdev);
628 }
629 
630 int64_t
archive_entry_size(struct archive_entry * entry)631 archive_entry_size(struct archive_entry *entry)
632 {
633 	return (entry->ae_stat.aest_size);
634 }
635 
636 int
archive_entry_size_is_set(struct archive_entry * entry)637 archive_entry_size_is_set(struct archive_entry *entry)
638 {
639 	return (entry->ae_set & AE_SET_SIZE);
640 }
641 
642 const char *
archive_entry_sourcepath(struct archive_entry * entry)643 archive_entry_sourcepath(struct archive_entry *entry)
644 {
645 	const char *p;
646 	if (archive_mstring_get_mbs(
647 	    entry->archive, &entry->ae_sourcepath, &p) == 0)
648 		return (p);
649 	if (errno == ENOMEM)
650 		__archive_errx(1, "No memory");
651 	return (NULL);
652 }
653 
654 const wchar_t *
archive_entry_sourcepath_w(struct archive_entry * entry)655 archive_entry_sourcepath_w(struct archive_entry *entry)
656 {
657 	const wchar_t *p;
658 	if (archive_mstring_get_wcs(
659 	    entry->archive, &entry->ae_sourcepath, &p) == 0)
660 		return (p);
661 	return (NULL);
662 }
663 
664 const char *
archive_entry_symlink(struct archive_entry * entry)665 archive_entry_symlink(struct archive_entry *entry)
666 {
667 	const char *p;
668 	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
669 		return (NULL);
670 	if (archive_mstring_get_mbs(
671 	    entry->archive, &entry->ae_symlink, &p) == 0)
672 		return (p);
673 	if (errno == ENOMEM)
674 		__archive_errx(1, "No memory");
675 	return (NULL);
676 }
677 
678 const char *
archive_entry_symlink_utf8(struct archive_entry * entry)679 archive_entry_symlink_utf8(struct archive_entry *entry)
680 {
681 	const char *p;
682 	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
683 		return (NULL);
684 	if (archive_mstring_get_utf8(
685 	    entry->archive, &entry->ae_symlink, &p) == 0)
686 		return (p);
687 	if (errno == ENOMEM)
688 		__archive_errx(1, "No memory");
689 	return (NULL);
690 }
691 
692 const wchar_t *
archive_entry_symlink_w(struct archive_entry * entry)693 archive_entry_symlink_w(struct archive_entry *entry)
694 {
695 	const wchar_t *p;
696 	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
697 		return (NULL);
698 	if (archive_mstring_get_wcs(
699 	    entry->archive, &entry->ae_symlink, &p) == 0)
700 		return (p);
701 	if (errno == ENOMEM)
702 		__archive_errx(1, "No memory");
703 	return (NULL);
704 }
705 
706 int
_archive_entry_symlink_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)707 _archive_entry_symlink_l(struct archive_entry *entry,
708     const char **p, size_t *len, struct archive_string_conv *sc)
709 {
710 	if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
711 		*p = NULL;
712 		*len = 0;
713 		return (0);
714 	}
715 	return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
716 }
717 
718 int64_t
archive_entry_uid(struct archive_entry * entry)719 archive_entry_uid(struct archive_entry *entry)
720 {
721 	return (entry->ae_stat.aest_uid);
722 }
723 
724 const char *
archive_entry_uname(struct archive_entry * entry)725 archive_entry_uname(struct archive_entry *entry)
726 {
727 	const char *p;
728 	if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
729 		return (p);
730 	if (errno == ENOMEM)
731 		__archive_errx(1, "No memory");
732 	return (NULL);
733 }
734 
735 const char *
archive_entry_uname_utf8(struct archive_entry * entry)736 archive_entry_uname_utf8(struct archive_entry *entry)
737 {
738 	const char *p;
739 	if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)
740 		return (p);
741 	if (errno == ENOMEM)
742 		__archive_errx(1, "No memory");
743 	return (NULL);
744 }
745 
746 const wchar_t *
archive_entry_uname_w(struct archive_entry * entry)747 archive_entry_uname_w(struct archive_entry *entry)
748 {
749 	const wchar_t *p;
750 	if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
751 		return (p);
752 	if (errno == ENOMEM)
753 		__archive_errx(1, "No memory");
754 	return (NULL);
755 }
756 
757 int
_archive_entry_uname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)758 _archive_entry_uname_l(struct archive_entry *entry,
759     const char **p, size_t *len, struct archive_string_conv *sc)
760 {
761 	return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
762 }
763 
764 int
archive_entry_is_data_encrypted(struct archive_entry * entry)765 archive_entry_is_data_encrypted(struct archive_entry *entry)
766 {
767 	return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
768 }
769 
770 int
archive_entry_is_metadata_encrypted(struct archive_entry * entry)771 archive_entry_is_metadata_encrypted(struct archive_entry *entry)
772 {
773 	return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
774 }
775 
776 int
archive_entry_is_encrypted(struct archive_entry * entry)777 archive_entry_is_encrypted(struct archive_entry *entry)
778 {
779 	return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
780 }
781 
782 /*
783  * Functions to set archive_entry properties.
784  */
785 
786 void
archive_entry_set_filetype(struct archive_entry * entry,unsigned int type)787 archive_entry_set_filetype(struct archive_entry *entry, unsigned int type)
788 {
789 	entry->stat_valid = 0;
790 	entry->acl.mode &= ~AE_IFMT;
791 	entry->acl.mode |= AE_IFMT & type;
792 }
793 
794 void
archive_entry_set_fflags(struct archive_entry * entry,unsigned long set,unsigned long clear)795 archive_entry_set_fflags(struct archive_entry *entry,
796     unsigned long set, unsigned long clear)
797 {
798 	archive_mstring_clean(&entry->ae_fflags_text);
799 	entry->ae_fflags_set = set;
800 	entry->ae_fflags_clear = clear;
801 }
802 
803 const char *
archive_entry_copy_fflags_text(struct archive_entry * entry,const char * flags)804 archive_entry_copy_fflags_text(struct archive_entry *entry,
805     const char *flags)
806 {
807 	archive_mstring_copy_mbs(&entry->ae_fflags_text, flags);
808 	return (ae_strtofflags(flags,
809 		    &entry->ae_fflags_set, &entry->ae_fflags_clear));
810 }
811 
812 const wchar_t *
archive_entry_copy_fflags_text_w(struct archive_entry * entry,const wchar_t * flags)813 archive_entry_copy_fflags_text_w(struct archive_entry *entry,
814     const wchar_t *flags)
815 {
816 	archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);
817 	return (ae_wcstofflags(flags,
818 		    &entry->ae_fflags_set, &entry->ae_fflags_clear));
819 }
820 
821 void
archive_entry_set_gid(struct archive_entry * entry,int64_t g)822 archive_entry_set_gid(struct archive_entry *entry, int64_t g)
823 {
824 	entry->stat_valid = 0;
825 	entry->ae_stat.aest_gid = g;
826 }
827 
828 void
archive_entry_set_gname(struct archive_entry * entry,const char * name)829 archive_entry_set_gname(struct archive_entry *entry, const char *name)
830 {
831 	archive_mstring_copy_mbs(&entry->ae_gname, name);
832 }
833 
834 void
archive_entry_set_gname_utf8(struct archive_entry * entry,const char * name)835 archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)
836 {
837 	archive_mstring_copy_utf8(&entry->ae_gname, name);
838 }
839 
840 void
archive_entry_copy_gname(struct archive_entry * entry,const char * name)841 archive_entry_copy_gname(struct archive_entry *entry, const char *name)
842 {
843 	archive_mstring_copy_mbs(&entry->ae_gname, name);
844 }
845 
846 void
archive_entry_copy_gname_w(struct archive_entry * entry,const wchar_t * name)847 archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
848 {
849 	archive_mstring_copy_wcs(&entry->ae_gname, name);
850 }
851 
852 int
archive_entry_update_gname_utf8(struct archive_entry * entry,const char * name)853 archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
854 {
855 	if (archive_mstring_update_utf8(entry->archive,
856 	    &entry->ae_gname, name) == 0)
857 		return (1);
858 	if (errno == ENOMEM)
859 		__archive_errx(1, "No memory");
860 	return (0);
861 }
862 
863 int
_archive_entry_copy_gname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)864 _archive_entry_copy_gname_l(struct archive_entry *entry,
865     const char *name, size_t len, struct archive_string_conv *sc)
866 {
867 	return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
868 }
869 
870 void
archive_entry_set_ino(struct archive_entry * entry,int64_t ino)871 archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
872 {
873 	entry->stat_valid = 0;
874 	entry->ae_set |= AE_SET_INO;
875 	entry->ae_stat.aest_ino = ino;
876 }
877 
878 void
archive_entry_set_ino64(struct archive_entry * entry,int64_t ino)879 archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
880 {
881 	entry->stat_valid = 0;
882 	entry->ae_set |= AE_SET_INO;
883 	entry->ae_stat.aest_ino = ino;
884 }
885 
886 void
archive_entry_set_hardlink(struct archive_entry * entry,const char * target)887 archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
888 {
889 	archive_mstring_copy_mbs(&entry->ae_hardlink, target);
890 	if (target != NULL)
891 		entry->ae_set |= AE_SET_HARDLINK;
892 	else
893 		entry->ae_set &= ~AE_SET_HARDLINK;
894 }
895 
896 void
archive_entry_set_hardlink_utf8(struct archive_entry * entry,const char * target)897 archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
898 {
899 	archive_mstring_copy_utf8(&entry->ae_hardlink, target);
900 	if (target != NULL)
901 		entry->ae_set |= AE_SET_HARDLINK;
902 	else
903 		entry->ae_set &= ~AE_SET_HARDLINK;
904 }
905 
906 void
archive_entry_copy_hardlink(struct archive_entry * entry,const char * target)907 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
908 {
909 	archive_mstring_copy_mbs(&entry->ae_hardlink, target);
910 	if (target != NULL)
911 		entry->ae_set |= AE_SET_HARDLINK;
912 	else
913 		entry->ae_set &= ~AE_SET_HARDLINK;
914 }
915 
916 void
archive_entry_copy_hardlink_w(struct archive_entry * entry,const wchar_t * target)917 archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
918 {
919 	archive_mstring_copy_wcs(&entry->ae_hardlink, target);
920 	if (target != NULL)
921 		entry->ae_set |= AE_SET_HARDLINK;
922 	else
923 		entry->ae_set &= ~AE_SET_HARDLINK;
924 }
925 
926 int
archive_entry_update_hardlink_utf8(struct archive_entry * entry,const char * target)927 archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
928 {
929 	if (target != NULL)
930 		entry->ae_set |= AE_SET_HARDLINK;
931 	else
932 		entry->ae_set &= ~AE_SET_HARDLINK;
933 	if (archive_mstring_update_utf8(entry->archive,
934 	    &entry->ae_hardlink, target) == 0)
935 		return (1);
936 	if (errno == ENOMEM)
937 		__archive_errx(1, "No memory");
938 	return (0);
939 }
940 
941 int
_archive_entry_copy_hardlink_l(struct archive_entry * entry,const char * target,size_t len,struct archive_string_conv * sc)942 _archive_entry_copy_hardlink_l(struct archive_entry *entry,
943     const char *target, size_t len, struct archive_string_conv *sc)
944 {
945 	int r;
946 
947 	r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
948 	    target, len, sc);
949 	if (target != NULL && r == 0)
950 		entry->ae_set |= AE_SET_HARDLINK;
951 	else
952 		entry->ae_set &= ~AE_SET_HARDLINK;
953 	return (r);
954 }
955 
956 void
archive_entry_set_atime(struct archive_entry * entry,time_t t,long ns)957 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
958 {
959 	FIX_NS(t, ns);
960 	entry->stat_valid = 0;
961 	entry->ae_set |= AE_SET_ATIME;
962 	entry->ae_stat.aest_atime = t;
963 	entry->ae_stat.aest_atime_nsec = ns;
964 }
965 
966 void
archive_entry_unset_atime(struct archive_entry * entry)967 archive_entry_unset_atime(struct archive_entry *entry)
968 {
969 	archive_entry_set_atime(entry, 0, 0);
970 	entry->ae_set &= ~AE_SET_ATIME;
971 }
972 
973 void
archive_entry_set_birthtime(struct archive_entry * entry,time_t t,long ns)974 archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
975 {
976 	FIX_NS(t, ns);
977 	entry->stat_valid = 0;
978 	entry->ae_set |= AE_SET_BIRTHTIME;
979 	entry->ae_stat.aest_birthtime = t;
980 	entry->ae_stat.aest_birthtime_nsec = ns;
981 }
982 
983 void
archive_entry_unset_birthtime(struct archive_entry * entry)984 archive_entry_unset_birthtime(struct archive_entry *entry)
985 {
986 	archive_entry_set_birthtime(entry, 0, 0);
987 	entry->ae_set &= ~AE_SET_BIRTHTIME;
988 }
989 
990 void
archive_entry_set_ctime(struct archive_entry * entry,time_t t,long ns)991 archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
992 {
993 	FIX_NS(t, ns);
994 	entry->stat_valid = 0;
995 	entry->ae_set |= AE_SET_CTIME;
996 	entry->ae_stat.aest_ctime = t;
997 	entry->ae_stat.aest_ctime_nsec = ns;
998 }
999 
1000 void
archive_entry_unset_ctime(struct archive_entry * entry)1001 archive_entry_unset_ctime(struct archive_entry *entry)
1002 {
1003 	archive_entry_set_ctime(entry, 0, 0);
1004 	entry->ae_set &= ~AE_SET_CTIME;
1005 }
1006 
1007 void
archive_entry_set_dev(struct archive_entry * entry,dev_t d)1008 archive_entry_set_dev(struct archive_entry *entry, dev_t d)
1009 {
1010 	entry->stat_valid = 0;
1011 	entry->ae_set |= AE_SET_DEV;
1012 	entry->ae_stat.aest_dev_is_broken_down = 0;
1013 	entry->ae_stat.aest_dev = d;
1014 }
1015 
1016 void
archive_entry_set_devmajor(struct archive_entry * entry,dev_t m)1017 archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
1018 {
1019 	entry->stat_valid = 0;
1020 	entry->ae_set |= AE_SET_DEV;
1021 	entry->ae_stat.aest_dev_is_broken_down = 1;
1022 	entry->ae_stat.aest_devmajor = m;
1023 }
1024 
1025 void
archive_entry_set_devminor(struct archive_entry * entry,dev_t m)1026 archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
1027 {
1028 	entry->stat_valid = 0;
1029 	entry->ae_set |= AE_SET_DEV;
1030 	entry->ae_stat.aest_dev_is_broken_down = 1;
1031 	entry->ae_stat.aest_devminor = m;
1032 }
1033 
1034 /* Set symlink if symlink is already set, else set hardlink. */
1035 void
archive_entry_set_link(struct archive_entry * entry,const char * target)1036 archive_entry_set_link(struct archive_entry *entry, const char *target)
1037 {
1038 	if (entry->ae_set & AE_SET_SYMLINK)
1039 		archive_mstring_copy_mbs(&entry->ae_symlink, target);
1040 	else
1041 		archive_mstring_copy_mbs(&entry->ae_hardlink, target);
1042 }
1043 
1044 void
archive_entry_set_link_utf8(struct archive_entry * entry,const char * target)1045 archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
1046 {
1047 	if (entry->ae_set & AE_SET_SYMLINK)
1048 		archive_mstring_copy_utf8(&entry->ae_symlink, target);
1049 	else
1050 		archive_mstring_copy_utf8(&entry->ae_hardlink, target);
1051 }
1052 
1053 /* Set symlink if symlink is already set, else set hardlink. */
1054 void
archive_entry_copy_link(struct archive_entry * entry,const char * target)1055 archive_entry_copy_link(struct archive_entry *entry, const char *target)
1056 {
1057 	if (entry->ae_set & AE_SET_SYMLINK)
1058 		archive_mstring_copy_mbs(&entry->ae_symlink, target);
1059 	else
1060 		archive_mstring_copy_mbs(&entry->ae_hardlink, target);
1061 }
1062 
1063 /* Set symlink if symlink is already set, else set hardlink. */
1064 void
archive_entry_copy_link_w(struct archive_entry * entry,const wchar_t * target)1065 archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
1066 {
1067 	if (entry->ae_set & AE_SET_SYMLINK)
1068 		archive_mstring_copy_wcs(&entry->ae_symlink, target);
1069 	else
1070 		archive_mstring_copy_wcs(&entry->ae_hardlink, target);
1071 }
1072 
1073 int
archive_entry_update_link_utf8(struct archive_entry * entry,const char * target)1074 archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
1075 {
1076 	int r;
1077 	if (entry->ae_set & AE_SET_SYMLINK)
1078 		r = archive_mstring_update_utf8(entry->archive,
1079 		    &entry->ae_symlink, target);
1080 	else
1081 		r = archive_mstring_update_utf8(entry->archive,
1082 		    &entry->ae_hardlink, target);
1083 	if (r == 0)
1084 		return (1);
1085 	if (errno == ENOMEM)
1086 		__archive_errx(1, "No memory");
1087 	return (0);
1088 }
1089 
1090 int
_archive_entry_copy_link_l(struct archive_entry * entry,const char * target,size_t len,struct archive_string_conv * sc)1091 _archive_entry_copy_link_l(struct archive_entry *entry,
1092     const char *target, size_t len, struct archive_string_conv *sc)
1093 {
1094 	int r;
1095 
1096 	if (entry->ae_set & AE_SET_SYMLINK)
1097 		r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
1098 		    target, len, sc);
1099 	else
1100 		r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
1101 		    target, len, sc);
1102 	return (r);
1103 }
1104 
1105 void
archive_entry_set_mode(struct archive_entry * entry,mode_t m)1106 archive_entry_set_mode(struct archive_entry *entry, mode_t m)
1107 {
1108 	entry->stat_valid = 0;
1109 	entry->acl.mode = m;
1110 }
1111 
1112 void
archive_entry_set_mtime(struct archive_entry * entry,time_t t,long ns)1113 archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
1114 {
1115 	FIX_NS(t, ns);
1116 	entry->stat_valid = 0;
1117 	entry->ae_set |= AE_SET_MTIME;
1118 	entry->ae_stat.aest_mtime = t;
1119 	entry->ae_stat.aest_mtime_nsec = ns;
1120 }
1121 
1122 void
archive_entry_unset_mtime(struct archive_entry * entry)1123 archive_entry_unset_mtime(struct archive_entry *entry)
1124 {
1125 	archive_entry_set_mtime(entry, 0, 0);
1126 	entry->ae_set &= ~AE_SET_MTIME;
1127 }
1128 
1129 void
archive_entry_set_nlink(struct archive_entry * entry,unsigned int nlink)1130 archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
1131 {
1132 	entry->stat_valid = 0;
1133 	entry->ae_stat.aest_nlink = nlink;
1134 }
1135 
1136 void
archive_entry_set_pathname(struct archive_entry * entry,const char * name)1137 archive_entry_set_pathname(struct archive_entry *entry, const char *name)
1138 {
1139 	archive_mstring_copy_mbs(&entry->ae_pathname, name);
1140 }
1141 
1142 void
archive_entry_set_pathname_utf8(struct archive_entry * entry,const char * name)1143 archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
1144 {
1145 	archive_mstring_copy_utf8(&entry->ae_pathname, name);
1146 }
1147 
1148 void
archive_entry_copy_pathname(struct archive_entry * entry,const char * name)1149 archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
1150 {
1151 	archive_mstring_copy_mbs(&entry->ae_pathname, name);
1152 }
1153 
1154 void
archive_entry_copy_pathname_w(struct archive_entry * entry,const wchar_t * name)1155 archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
1156 {
1157 	archive_mstring_copy_wcs(&entry->ae_pathname, name);
1158 }
1159 
1160 int
archive_entry_update_pathname_utf8(struct archive_entry * entry,const char * name)1161 archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
1162 {
1163 	if (archive_mstring_update_utf8(entry->archive,
1164 	    &entry->ae_pathname, name) == 0)
1165 		return (1);
1166 	if (errno == ENOMEM)
1167 		__archive_errx(1, "No memory");
1168 	return (0);
1169 }
1170 
1171 int
_archive_entry_copy_pathname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)1172 _archive_entry_copy_pathname_l(struct archive_entry *entry,
1173     const char *name, size_t len, struct archive_string_conv *sc)
1174 {
1175 	return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
1176 	    name, len, sc));
1177 }
1178 
1179 void
archive_entry_set_perm(struct archive_entry * entry,mode_t p)1180 archive_entry_set_perm(struct archive_entry *entry, mode_t p)
1181 {
1182 	entry->stat_valid = 0;
1183 	entry->acl.mode &= AE_IFMT;
1184 	entry->acl.mode |= ~AE_IFMT & p;
1185 }
1186 
1187 void
archive_entry_set_rdev(struct archive_entry * entry,dev_t m)1188 archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
1189 {
1190 	entry->stat_valid = 0;
1191 	entry->ae_stat.aest_rdev = m;
1192 	entry->ae_stat.aest_rdev_is_broken_down = 0;
1193 }
1194 
1195 void
archive_entry_set_rdevmajor(struct archive_entry * entry,dev_t m)1196 archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
1197 {
1198 	entry->stat_valid = 0;
1199 	entry->ae_stat.aest_rdev_is_broken_down = 1;
1200 	entry->ae_stat.aest_rdevmajor = m;
1201 }
1202 
1203 void
archive_entry_set_rdevminor(struct archive_entry * entry,dev_t m)1204 archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
1205 {
1206 	entry->stat_valid = 0;
1207 	entry->ae_stat.aest_rdev_is_broken_down = 1;
1208 	entry->ae_stat.aest_rdevminor = m;
1209 }
1210 
1211 void
archive_entry_set_size(struct archive_entry * entry,int64_t s)1212 archive_entry_set_size(struct archive_entry *entry, int64_t s)
1213 {
1214 	entry->stat_valid = 0;
1215 	entry->ae_stat.aest_size = s;
1216 	entry->ae_set |= AE_SET_SIZE;
1217 }
1218 
1219 void
archive_entry_unset_size(struct archive_entry * entry)1220 archive_entry_unset_size(struct archive_entry *entry)
1221 {
1222 	archive_entry_set_size(entry, 0);
1223 	entry->ae_set &= ~AE_SET_SIZE;
1224 }
1225 
1226 void
archive_entry_copy_sourcepath(struct archive_entry * entry,const char * path)1227 archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
1228 {
1229 	archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
1230 }
1231 
1232 void
archive_entry_copy_sourcepath_w(struct archive_entry * entry,const wchar_t * path)1233 archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
1234 {
1235 	archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
1236 }
1237 
1238 void
archive_entry_set_symlink(struct archive_entry * entry,const char * linkname)1239 archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
1240 {
1241 	archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
1242 	if (linkname != NULL)
1243 		entry->ae_set |= AE_SET_SYMLINK;
1244 	else
1245 		entry->ae_set &= ~AE_SET_SYMLINK;
1246 }
1247 
1248 void
archive_entry_set_symlink_utf8(struct archive_entry * entry,const char * linkname)1249 archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
1250 {
1251 	archive_mstring_copy_utf8(&entry->ae_symlink, linkname);
1252 	if (linkname != NULL)
1253 		entry->ae_set |= AE_SET_SYMLINK;
1254 	else
1255 		entry->ae_set &= ~AE_SET_SYMLINK;
1256 }
1257 
1258 void
archive_entry_copy_symlink(struct archive_entry * entry,const char * linkname)1259 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
1260 {
1261 	archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
1262 	if (linkname != NULL)
1263 		entry->ae_set |= AE_SET_SYMLINK;
1264 	else
1265 		entry->ae_set &= ~AE_SET_SYMLINK;
1266 }
1267 
1268 void
archive_entry_copy_symlink_w(struct archive_entry * entry,const wchar_t * linkname)1269 archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
1270 {
1271 	archive_mstring_copy_wcs(&entry->ae_symlink, linkname);
1272 	if (linkname != NULL)
1273 		entry->ae_set |= AE_SET_SYMLINK;
1274 	else
1275 		entry->ae_set &= ~AE_SET_SYMLINK;
1276 }
1277 
1278 int
archive_entry_update_symlink_utf8(struct archive_entry * entry,const char * linkname)1279 archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
1280 {
1281 	if (linkname != NULL)
1282 		entry->ae_set |= AE_SET_SYMLINK;
1283 	else
1284 		entry->ae_set &= ~AE_SET_SYMLINK;
1285 	if (archive_mstring_update_utf8(entry->archive,
1286 	    &entry->ae_symlink, linkname) == 0)
1287 		return (1);
1288 	if (errno == ENOMEM)
1289 		__archive_errx(1, "No memory");
1290 	return (0);
1291 }
1292 
1293 int
_archive_entry_copy_symlink_l(struct archive_entry * entry,const char * linkname,size_t len,struct archive_string_conv * sc)1294 _archive_entry_copy_symlink_l(struct archive_entry *entry,
1295     const char *linkname, size_t len, struct archive_string_conv *sc)
1296 {
1297 	int r;
1298 
1299 	r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
1300 	    linkname, len, sc);
1301 	if (linkname != NULL && r == 0)
1302 		entry->ae_set |= AE_SET_SYMLINK;
1303 	else
1304 		entry->ae_set &= ~AE_SET_SYMLINK;
1305 	return (r);
1306 }
1307 
1308 void
archive_entry_set_uid(struct archive_entry * entry,int64_t u)1309 archive_entry_set_uid(struct archive_entry *entry, int64_t u)
1310 {
1311 	entry->stat_valid = 0;
1312 	entry->ae_stat.aest_uid = u;
1313 }
1314 
1315 void
archive_entry_set_uname(struct archive_entry * entry,const char * name)1316 archive_entry_set_uname(struct archive_entry *entry, const char *name)
1317 {
1318 	archive_mstring_copy_mbs(&entry->ae_uname, name);
1319 }
1320 
1321 void
archive_entry_set_uname_utf8(struct archive_entry * entry,const char * name)1322 archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
1323 {
1324 	archive_mstring_copy_utf8(&entry->ae_uname, name);
1325 }
1326 
1327 void
archive_entry_copy_uname(struct archive_entry * entry,const char * name)1328 archive_entry_copy_uname(struct archive_entry *entry, const char *name)
1329 {
1330 	archive_mstring_copy_mbs(&entry->ae_uname, name);
1331 }
1332 
1333 void
archive_entry_copy_uname_w(struct archive_entry * entry,const wchar_t * name)1334 archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
1335 {
1336 	archive_mstring_copy_wcs(&entry->ae_uname, name);
1337 }
1338 
1339 int
archive_entry_update_uname_utf8(struct archive_entry * entry,const char * name)1340 archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
1341 {
1342 	if (archive_mstring_update_utf8(entry->archive,
1343 	    &entry->ae_uname, name) == 0)
1344 		return (1);
1345 	if (errno == ENOMEM)
1346 		__archive_errx(1, "No memory");
1347 	return (0);
1348 }
1349 
1350 void
archive_entry_set_is_data_encrypted(struct archive_entry * entry,char is_encrypted)1351 archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
1352 {
1353 	if (is_encrypted) {
1354 		entry->encryption |= AE_ENCRYPTION_DATA;
1355 	} else {
1356 		entry->encryption &= ~AE_ENCRYPTION_DATA;
1357 	}
1358 }
1359 
1360 void
archive_entry_set_is_metadata_encrypted(struct archive_entry * entry,char is_encrypted)1361 archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
1362 {
1363 	if (is_encrypted) {
1364 		entry->encryption |= AE_ENCRYPTION_METADATA;
1365 	} else {
1366 		entry->encryption &= ~AE_ENCRYPTION_METADATA;
1367 	}
1368 }
1369 
1370 int
_archive_entry_copy_uname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)1371 _archive_entry_copy_uname_l(struct archive_entry *entry,
1372     const char *name, size_t len, struct archive_string_conv *sc)
1373 {
1374 	return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
1375 	    name, len, sc));
1376 }
1377 
1378 const void *
archive_entry_mac_metadata(struct archive_entry * entry,size_t * s)1379 archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
1380 {
1381   *s = entry->mac_metadata_size;
1382   return entry->mac_metadata;
1383 }
1384 
1385 void
archive_entry_copy_mac_metadata(struct archive_entry * entry,const void * p,size_t s)1386 archive_entry_copy_mac_metadata(struct archive_entry *entry,
1387     const void *p, size_t s)
1388 {
1389   free(entry->mac_metadata);
1390   if (p == NULL || s == 0) {
1391     entry->mac_metadata = NULL;
1392     entry->mac_metadata_size = 0;
1393   } else {
1394     entry->mac_metadata_size = s;
1395     entry->mac_metadata = malloc(s);
1396     if (entry->mac_metadata == NULL)
1397       abort();
1398     memcpy(entry->mac_metadata, p, s);
1399   }
1400 }
1401 
1402 /*
1403  * ACL management.  The following would, of course, be a lot simpler
1404  * if: 1) the last draft of POSIX.1e were a really thorough and
1405  * complete standard that addressed the needs of ACL archiving and 2)
1406  * everyone followed it faithfully.  Alas, neither is true, so the
1407  * following is a lot more complex than might seem necessary to the
1408  * uninitiated.
1409  */
1410 
1411 struct archive_acl *
archive_entry_acl(struct archive_entry * entry)1412 archive_entry_acl(struct archive_entry *entry)
1413 {
1414 	return &entry->acl;
1415 }
1416 
1417 void
archive_entry_acl_clear(struct archive_entry * entry)1418 archive_entry_acl_clear(struct archive_entry *entry)
1419 {
1420 	archive_acl_clear(&entry->acl);
1421 }
1422 
1423 /*
1424  * Add a single ACL entry to the internal list of ACL data.
1425  */
1426 int
archive_entry_acl_add_entry(struct archive_entry * entry,int type,int permset,int tag,int id,const char * name)1427 archive_entry_acl_add_entry(struct archive_entry *entry,
1428     int type, int permset, int tag, int id, const char *name)
1429 {
1430 	return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
1431 }
1432 
1433 /*
1434  * As above, but with a wide-character name.
1435  */
1436 int
archive_entry_acl_add_entry_w(struct archive_entry * entry,int type,int permset,int tag,int id,const wchar_t * name)1437 archive_entry_acl_add_entry_w(struct archive_entry *entry,
1438     int type, int permset, int tag, int id, const wchar_t *name)
1439 {
1440 	return archive_acl_add_entry_w_len(&entry->acl,
1441 	    type, permset, tag, id, name, wcslen(name));
1442 }
1443 
1444 /*
1445  * Return a bitmask of ACL types in an archive entry ACL list
1446  */
1447 int
archive_entry_acl_types(struct archive_entry * entry)1448 archive_entry_acl_types(struct archive_entry *entry)
1449 {
1450 	return (archive_acl_types(&entry->acl));
1451 }
1452 
1453 /*
1454  * Return a count of entries matching "want_type".
1455  */
1456 int
archive_entry_acl_count(struct archive_entry * entry,int want_type)1457 archive_entry_acl_count(struct archive_entry *entry, int want_type)
1458 {
1459 	return archive_acl_count(&entry->acl, want_type);
1460 }
1461 
1462 /*
1463  * Prepare for reading entries from the ACL data.  Returns a count
1464  * of entries matching "want_type", or zero if there are no
1465  * non-extended ACL entries of that type.
1466  */
1467 int
archive_entry_acl_reset(struct archive_entry * entry,int want_type)1468 archive_entry_acl_reset(struct archive_entry *entry, int want_type)
1469 {
1470 	return archive_acl_reset(&entry->acl, want_type);
1471 }
1472 
1473 /*
1474  * Return the next ACL entry in the list.  Fake entries for the
1475  * standard permissions and include them in the returned list.
1476  */
1477 int
archive_entry_acl_next(struct archive_entry * entry,int want_type,int * type,int * permset,int * tag,int * id,const char ** name)1478 archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
1479     int *permset, int *tag, int *id, const char **name)
1480 {
1481 	int r;
1482 	r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
1483 		permset, tag, id, name);
1484 	if (r == ARCHIVE_FATAL && errno == ENOMEM)
1485 		__archive_errx(1, "No memory");
1486 	return (r);
1487 }
1488 
1489 /*
1490  * Generate a text version of the ACL. The flags parameter controls
1491  * the style of the generated ACL.
1492  */
1493 wchar_t *
archive_entry_acl_to_text_w(struct archive_entry * entry,ssize_t * len,int flags)1494 archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
1495     int flags)
1496 {
1497 	return (archive_acl_to_text_w(&entry->acl, len, flags,
1498 	    entry->archive));
1499 }
1500 
1501 char *
archive_entry_acl_to_text(struct archive_entry * entry,ssize_t * len,int flags)1502 archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
1503     int flags)
1504 {
1505 	return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
1506 }
1507 
1508 char *
_archive_entry_acl_to_text_l(struct archive_entry * entry,ssize_t * len,int flags,struct archive_string_conv * sc)1509 _archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
1510    int flags, struct archive_string_conv *sc)
1511 {
1512 	return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
1513 }
1514 
1515 /*
1516  * ACL text parser.
1517  */
1518 int
archive_entry_acl_from_text_w(struct archive_entry * entry,const wchar_t * wtext,int type)1519 archive_entry_acl_from_text_w(struct archive_entry *entry,
1520     const wchar_t *wtext, int type)
1521 {
1522 	return (archive_acl_from_text_w(&entry->acl, wtext, type));
1523 }
1524 
1525 int
archive_entry_acl_from_text(struct archive_entry * entry,const char * text,int type)1526 archive_entry_acl_from_text(struct archive_entry *entry,
1527     const char *text, int type)
1528 {
1529 	return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
1530 }
1531 
1532 int
_archive_entry_acl_from_text_l(struct archive_entry * entry,const char * text,int type,struct archive_string_conv * sc)1533 _archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
1534     int type, struct archive_string_conv *sc)
1535 {
1536 	return (archive_acl_from_text_l(&entry->acl, text, type, sc));
1537 }
1538 
1539 /* Deprecated */
1540 static int
archive_entry_acl_text_compat(int * flags)1541 archive_entry_acl_text_compat(int *flags)
1542 {
1543 	if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
1544 		return (1);
1545 
1546 	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
1547 	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
1548 		*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
1549 
1550 	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
1551 	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
1552 		*flags |=  ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
1553 
1554 	*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
1555 
1556 	return (0);
1557 }
1558 
1559 /* Deprecated */
1560 const wchar_t *
archive_entry_acl_text_w(struct archive_entry * entry,int flags)1561 archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1562 {
1563 	if (entry->acl.acl_text_w != NULL) {
1564 		free(entry->acl.acl_text_w);
1565 		entry->acl.acl_text_w = NULL;
1566 	}
1567 	if (archive_entry_acl_text_compat(&flags) == 0)
1568 		entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
1569 		    NULL, flags, entry->archive);
1570 	return (entry->acl.acl_text_w);
1571 }
1572 
1573 /* Deprecated */
1574 const char *
archive_entry_acl_text(struct archive_entry * entry,int flags)1575 archive_entry_acl_text(struct archive_entry *entry, int flags)
1576 {
1577 	if (entry->acl.acl_text != NULL) {
1578 		free(entry->acl.acl_text);
1579 		entry->acl.acl_text = NULL;
1580 	}
1581 	if (archive_entry_acl_text_compat(&flags) == 0)
1582 		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
1583 		    flags, NULL);
1584 
1585 	return (entry->acl.acl_text);
1586 }
1587 
1588 /* Deprecated */
1589 int
_archive_entry_acl_text_l(struct archive_entry * entry,int flags,const char ** acl_text,size_t * len,struct archive_string_conv * sc)1590 _archive_entry_acl_text_l(struct archive_entry *entry, int flags,
1591     const char **acl_text, size_t *len, struct archive_string_conv *sc)
1592 {
1593 	if (entry->acl.acl_text != NULL) {
1594 		free(entry->acl.acl_text);
1595 		entry->acl.acl_text = NULL;
1596         }
1597 
1598 	if (archive_entry_acl_text_compat(&flags) == 0)
1599 		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
1600 		    (ssize_t *)len, flags, sc);
1601 
1602 	*acl_text = entry->acl.acl_text;
1603 
1604 	return (0);
1605 }
1606 
1607 /*
1608  * Following code is modified from UC Berkeley sources, and
1609  * is subject to the following copyright notice.
1610  */
1611 
1612 /*-
1613  * Copyright (c) 1993
1614  *	The Regents of the University of California.  All rights reserved.
1615  *
1616  * Redistribution and use in source and binary forms, with or without
1617  * modification, are permitted provided that the following conditions
1618  * are met:
1619  * 1. Redistributions of source code must retain the above copyright
1620  *    notice, this list of conditions and the following disclaimer.
1621  * 2. Redistributions in binary form must reproduce the above copyright
1622  *    notice, this list of conditions and the following disclaimer in the
1623  *    documentation and/or other materials provided with the distribution.
1624  * 4. Neither the name of the University nor the names of its contributors
1625  *    may be used to endorse or promote products derived from this software
1626  *    without specific prior written permission.
1627  *
1628  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1629  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1630  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1631  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1632  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1633  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1634  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1635  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1636  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1637  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1638  * SUCH DAMAGE.
1639  */
1640 
1641 static struct flag {
1642 	const char	*name;
1643 	const wchar_t	*wname;
1644 	unsigned long	 set;
1645 	unsigned long	 clear;
1646 } flags[] = {
1647 	/* Preferred (shorter) names per flag first, all prefixed by "no" */
1648 #ifdef SF_APPEND
1649 	{ "nosappnd",	L"nosappnd",		SF_APPEND,	0 },
1650 	{ "nosappend",	L"nosappend",		SF_APPEND,	0 },
1651 #endif
1652 #if defined(FS_APPEND_FL)			/* 'a' */
1653 	{ "nosappnd",	L"nosappnd",		FS_APPEND_FL,	0 },
1654 	{ "nosappend",	L"nosappend",		FS_APPEND_FL,	0 },
1655 #elif defined(EXT2_APPEND_FL)			/* 'a' */
1656 	{ "nosappnd",	L"nosappnd",		EXT2_APPEND_FL,	0 },
1657 	{ "nosappend",	L"nosappend",		EXT2_APPEND_FL,	0 },
1658 #endif
1659 #ifdef SF_ARCHIVED
1660 	{ "noarch",	L"noarch",		SF_ARCHIVED,	0 },
1661 	{ "noarchived",	L"noarchived",       	SF_ARCHIVED,	0 },
1662 #endif
1663 #ifdef SF_IMMUTABLE
1664 	{ "noschg",	L"noschg",		SF_IMMUTABLE,	0 },
1665 	{ "noschange",	L"noschange",		SF_IMMUTABLE,	0 },
1666 	{ "nosimmutable",	L"nosimmutable",	SF_IMMUTABLE,	0 },
1667 #endif
1668 #if defined(FS_IMMUTABLE_FL)			/* 'i' */
1669 	{ "noschg",	L"noschg",		FS_IMMUTABLE_FL,	0 },
1670 	{ "noschange",	L"noschange",		FS_IMMUTABLE_FL,	0 },
1671 	{ "nosimmutable",	L"nosimmutable",	FS_IMMUTABLE_FL,	0 },
1672 #elif defined(EXT2_IMMUTABLE_FL)		/* 'i' */
1673 	{ "noschg",	L"noschg",		EXT2_IMMUTABLE_FL,	0 },
1674 	{ "noschange",	L"noschange",		EXT2_IMMUTABLE_FL,	0 },
1675 	{ "nosimmutable",	L"nosimmutable",	EXT2_IMMUTABLE_FL,	0 },
1676 #endif
1677 #ifdef SF_NOUNLINK
1678 	{ "nosunlnk",	L"nosunlnk",		SF_NOUNLINK,	0 },
1679 	{ "nosunlink",	L"nosunlink",		SF_NOUNLINK,	0 },
1680 #endif
1681 #ifdef SF_SNAPSHOT
1682 	{ "nosnapshot",	L"nosnapshot",	SF_SNAPSHOT,	0 },
1683 #endif
1684 #ifdef UF_APPEND
1685 	{ "nouappnd",	L"nouappnd",		UF_APPEND,	0 },
1686 	{ "nouappend",	L"nouappend",		UF_APPEND,	0 },
1687 #endif
1688 #ifdef UF_IMMUTABLE
1689 	{ "nouchg",	L"nouchg",		UF_IMMUTABLE,	0 },
1690 	{ "nouchange",	L"nouchange",		UF_IMMUTABLE,	0 },
1691 	{ "nouimmutable",	L"nouimmutable",	UF_IMMUTABLE,	0 },
1692 #endif
1693 #ifdef UF_NODUMP
1694 	{ "nodump",	L"nodump",		0,		UF_NODUMP},
1695 #endif
1696 #if defined(FS_NODUMP_FL)	/* 'd' */
1697 	{ "nodump",	L"nodump",		0,		FS_NODUMP_FL},
1698 #elif defined(EXT2_NODUMP_FL) 	/* 'd' */
1699 	{ "nodump",	L"nodump",		0,		EXT2_NODUMP_FL},
1700 #endif
1701 #ifdef UF_OPAQUE
1702 	{ "noopaque",	L"noopaque",		UF_OPAQUE,	0 },
1703 #endif
1704 #ifdef UF_NOUNLINK
1705 	{ "nouunlnk",	L"nouunlnk",		UF_NOUNLINK,	0 },
1706 	{ "nouunlink",	L"nouunlink",		UF_NOUNLINK,	0 },
1707 #endif
1708 #ifdef UF_COMPRESSED
1709 	{ "nocompressed",L"nocompressed",	UF_COMPRESSED,	0 },
1710 #endif
1711 #if defined(FS_UNRM_FL)
1712         { "nouunlink",	L"nouunlink",		FS_UNRM_FL,	0},
1713 #elif defined(EXT2_UNRM_FL)
1714         { "nouunlink",	L"nouunlink",		EXT2_UNRM_FL,	0},
1715 #endif
1716 
1717 #if defined(FS_BTREE_FL)
1718         { "nobtree",	L"nobtree",       	FS_BTREE_FL,	0 },
1719 #elif defined(EXT2_BTREE_FL)
1720         { "nobtree",	L"nobtree",       	EXT2_BTREE_FL,	0 },
1721 #endif
1722 
1723 #if defined(FS_ECOMPR_FL)
1724         { "nocomperr",	L"nocomperr",       	FS_ECOMPR_FL,	0 },
1725 #elif defined(EXT2_ECOMPR_FL)
1726         { "nocomperr",	L"nocomperr",       	EXT2_ECOMPR_FL,	0 },
1727 #endif
1728 
1729 #if defined(FS_COMPR_FL)			/* 'c' */
1730         { "nocompress",	L"nocompress",       	FS_COMPR_FL,	0 },
1731 #elif defined(EXT2_COMPR_FL)			/* 'c' */
1732         { "nocompress",	L"nocompress",       	EXT2_COMPR_FL,	0 },
1733 #endif
1734 
1735 #if defined(FS_NOATIME_FL)			/* 'A' */
1736         { "noatime",	L"noatime",		0,		FS_NOATIME_FL},
1737 #elif defined(EXT2_NOATIME_FL)			/* 'A' */
1738         { "noatime",	L"noatime",		0,		EXT2_NOATIME_FL},
1739 #endif
1740 
1741 #if defined(FS_DIRTY_FL)
1742         { "nocompdirty",L"nocompdirty",		FS_DIRTY_FL,		0},
1743 #elif defined(EXT2_DIRTY_FL)
1744         { "nocompdirty",L"nocompdirty",		EXT2_DIRTY_FL,		0},
1745 #endif
1746 
1747 #if defined(FS_COMPRBLK_FL)
1748 #if defined(FS_NOCOMPR_FL)
1749         { "nocomprblk",	L"nocomprblk",		FS_COMPRBLK_FL, FS_NOCOMPR_FL},
1750 #else
1751         { "nocomprblk",	L"nocomprblk",		FS_COMPRBLK_FL,	0},
1752 #endif
1753 #elif defined(EXT2_COMPRBLK_FL)
1754 #if defined(EXT2_NOCOMPR_FL)
1755         { "nocomprblk",	L"nocomprblk",		EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
1756 #else
1757         { "nocomprblk",	L"nocomprblk",		EXT2_COMPRBLK_FL,	0},
1758 #endif
1759 #endif
1760 #if defined(FS_DIRSYNC_FL)
1761         { "nodirsync",	L"nodirsync",		FS_DIRSYNC_FL,	0},
1762 #elif defined(EXT2_DIRSYNC_FL)
1763         { "nodirsync",	L"nodirsync",		EXT2_DIRSYNC_FL,	0},
1764 #endif
1765 #if defined(FS_INDEX_FL)
1766         { "nohashidx",	L"nohashidx",		FS_INDEX_FL,		0},
1767 #elif defined(EXT2_INDEX_FL)
1768         { "nohashidx",	L"nohashidx",		EXT2_INDEX_FL,		0},
1769 #endif
1770 #if defined(FS_IMAGIC_FL)
1771         { "noimagic",	L"noimagic",		FS_IMAGIC_FL,		0},
1772 #elif defined(EXT2_IMAGIC_FL)
1773         { "noimagic",	L"noimagic",		EXT2_IMAGIC_FL,		0},
1774 #endif
1775 #if defined(FS_JOURNAL_DATA_FL)
1776         { "nojournal",	L"nojournal",		FS_JOURNAL_DATA_FL,	0},
1777 #elif defined(EXT3_JOURNAL_DATA_FL)
1778         { "nojournal",	L"nojournal",		EXT3_JOURNAL_DATA_FL,	0},
1779 #endif
1780 #if defined(FS_SECRM_FL)
1781         { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL,		0},
1782 #elif defined(EXT2_SECRM_FL)
1783         { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL,		0},
1784 #endif
1785 #if defined(FS_SYNC_FL)
1786         { "nosync",	L"nosync",		FS_SYNC_FL,		0},
1787 #elif defined(EXT2_SYNC_FL)
1788         { "nosync",	L"nosync",		EXT2_SYNC_FL,		0},
1789 #endif
1790 #if defined(FS_NOTAIL_FL)
1791         { "notail",	L"notail",		0,		FS_NOTAIL_FL},
1792 #elif defined(EXT2_NOTAIL_FL)
1793         { "notail",	L"notail",		0,		EXT2_NOTAIL_FL},
1794 #endif
1795 #if defined(FS_TOPDIR_FL)
1796         { "notopdir",	L"notopdir",		FS_TOPDIR_FL,		0},
1797 #elif defined(EXT2_TOPDIR_FL)
1798         { "notopdir",	L"notopdir",		EXT2_TOPDIR_FL,		0},
1799 #endif
1800 #ifdef FS_ENCRYPT_FL
1801         { "noencrypt",	L"noencrypt",		FS_ENCRYPT_FL,	0},
1802 #endif
1803 #ifdef FS_HUGE_FILE_FL
1804         { "nohugefile",	L"nohugefile",		FS_HUGE_FILE_FL,	0},
1805 #endif
1806 #ifdef FS_EXTENT_FL
1807         { "noextent",	L"noextent",		FS_EXTENT_FL,	0},
1808 #endif
1809 #ifdef FS_EA_INODE_FL
1810         { "noeainode",	L"noeainode",		FS_EA_INODE_FL,	0},
1811 #endif
1812 #ifdef FS_EOFBLOCKS_FL
1813         { "noeofblocks",L"noeofblocks",		FS_EOFBLOCKS_FL,	0},
1814 #endif
1815 #ifdef FS_NOCOW_FL
1816         { "nocow",	L"nocow",		FS_NOCOW_FL,	0},
1817 #endif
1818 #ifdef FS_INLINE_DATA_FL
1819         { "noinlinedata",L"noinlinedata",	FS_INLINE_DATA_FL,	0},
1820 #endif
1821 #ifdef FS_PROJINHERIT_FL
1822         { "noprojinherit",L"noprojinherit",	FS_PROJINHERIT_FL,	0},
1823 #endif
1824 #if defined(FS_RESERVED_FL)
1825         { "noreserved",	L"noreserved",		FS_RESERVED_FL,	0},
1826 #elif defined(EXT2_RESERVED_FL)
1827         { "noreserved",	L"noreserved",		EXT2_RESERVED_FL,	0},
1828 #endif
1829 	{ NULL,		NULL,			0,		0 }
1830 };
1831 
1832 /*
1833  * fflagstostr --
1834  *	Convert file flags to a comma-separated string.  If no flags
1835  *	are set, return the empty string.
1836  */
1837 static char *
ae_fflagstostr(unsigned long bitset,unsigned long bitclear)1838 ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
1839 {
1840 	char *string, *dp;
1841 	const char *sp;
1842 	unsigned long bits;
1843 	struct flag *flag;
1844 	size_t	length;
1845 
1846 	bits = bitset | bitclear;
1847 	length = 0;
1848 	for (flag = flags; flag->name != NULL; flag++)
1849 		if (bits & (flag->set | flag->clear)) {
1850 			length += strlen(flag->name) + 1;
1851 			bits &= ~(flag->set | flag->clear);
1852 		}
1853 
1854 	if (length == 0)
1855 		return (NULL);
1856 	string = (char *)malloc(length);
1857 	if (string == NULL)
1858 		return (NULL);
1859 
1860 	dp = string;
1861 	for (flag = flags; flag->name != NULL; flag++) {
1862 		if (bitset & flag->set || bitclear & flag->clear) {
1863 			sp = flag->name + 2;
1864 		} else if (bitset & flag->clear  ||  bitclear & flag->set) {
1865 			sp = flag->name;
1866 		} else
1867 			continue;
1868 		bitset &= ~(flag->set | flag->clear);
1869 		bitclear &= ~(flag->set | flag->clear);
1870 		if (dp > string)
1871 			*dp++ = ',';
1872 		while ((*dp++ = *sp++) != '\0')
1873 			;
1874 		dp--;
1875 	}
1876 
1877 	*dp = '\0';
1878 	return (string);
1879 }
1880 
1881 /*
1882  * strtofflags --
1883  *	Take string of arguments and return file flags.  This
1884  *	version works a little differently than strtofflags(3).
1885  *	In particular, it always tests every token, skipping any
1886  *	unrecognized tokens.  It returns a pointer to the first
1887  *	unrecognized token, or NULL if every token was recognized.
1888  *	This version is also const-correct and does not modify the
1889  *	provided string.
1890  */
1891 static const char *
ae_strtofflags(const char * s,unsigned long * setp,unsigned long * clrp)1892 ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
1893 {
1894 	const char *start, *end;
1895 	struct flag *flag;
1896 	unsigned long set, clear;
1897 	const char *failed;
1898 
1899 	set = clear = 0;
1900 	start = s;
1901 	failed = NULL;
1902 	/* Find start of first token. */
1903 	while (*start == '\t'  ||  *start == ' '  ||  *start == ',')
1904 		start++;
1905 	while (*start != '\0') {
1906 		size_t length;
1907 		/* Locate end of token. */
1908 		end = start;
1909 		while (*end != '\0'  &&  *end != '\t'  &&
1910 		    *end != ' '  &&  *end != ',')
1911 			end++;
1912 		length = end - start;
1913 		for (flag = flags; flag->name != NULL; flag++) {
1914 			size_t flag_length = strlen(flag->name);
1915 			if (length == flag_length
1916 			    && memcmp(start, flag->name, length) == 0) {
1917 				/* Matched "noXXXX", so reverse the sense. */
1918 				clear |= flag->set;
1919 				set |= flag->clear;
1920 				break;
1921 			} else if (length == flag_length - 2
1922 			    && memcmp(start, flag->name + 2, length) == 0) {
1923 				/* Matched "XXXX", so don't reverse. */
1924 				set |= flag->set;
1925 				clear |= flag->clear;
1926 				break;
1927 			}
1928 		}
1929 		/* Ignore unknown flag names. */
1930 		if (flag->name == NULL  &&  failed == NULL)
1931 			failed = start;
1932 
1933 		/* Find start of next token. */
1934 		start = end;
1935 		while (*start == '\t'  ||  *start == ' '  ||  *start == ',')
1936 			start++;
1937 
1938 	}
1939 
1940 	if (setp)
1941 		*setp = set;
1942 	if (clrp)
1943 		*clrp = clear;
1944 
1945 	/* Return location of first failure. */
1946 	return (failed);
1947 }
1948 
1949 /*
1950  * wcstofflags --
1951  *	Take string of arguments and return file flags.  This
1952  *	version works a little differently than strtofflags(3).
1953  *	In particular, it always tests every token, skipping any
1954  *	unrecognized tokens.  It returns a pointer to the first
1955  *	unrecognized token, or NULL if every token was recognized.
1956  *	This version is also const-correct and does not modify the
1957  *	provided string.
1958  */
1959 static const wchar_t *
ae_wcstofflags(const wchar_t * s,unsigned long * setp,unsigned long * clrp)1960 ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
1961 {
1962 	const wchar_t *start, *end;
1963 	struct flag *flag;
1964 	unsigned long set, clear;
1965 	const wchar_t *failed;
1966 
1967 	set = clear = 0;
1968 	start = s;
1969 	failed = NULL;
1970 	/* Find start of first token. */
1971 	while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
1972 		start++;
1973 	while (*start != L'\0') {
1974 		size_t length;
1975 		/* Locate end of token. */
1976 		end = start;
1977 		while (*end != L'\0'  &&  *end != L'\t'  &&
1978 		    *end != L' '  &&  *end != L',')
1979 			end++;
1980 		length = end - start;
1981 		for (flag = flags; flag->wname != NULL; flag++) {
1982 			size_t flag_length = wcslen(flag->wname);
1983 			if (length == flag_length
1984 			    && wmemcmp(start, flag->wname, length) == 0) {
1985 				/* Matched "noXXXX", so reverse the sense. */
1986 				clear |= flag->set;
1987 				set |= flag->clear;
1988 				break;
1989 			} else if (length == flag_length - 2
1990 			    && wmemcmp(start, flag->wname + 2, length) == 0) {
1991 				/* Matched "XXXX", so don't reverse. */
1992 				set |= flag->set;
1993 				clear |= flag->clear;
1994 				break;
1995 			}
1996 		}
1997 		/* Ignore unknown flag names. */
1998 		if (flag->wname == NULL  &&  failed == NULL)
1999 			failed = start;
2000 
2001 		/* Find start of next token. */
2002 		start = end;
2003 		while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
2004 			start++;
2005 
2006 	}
2007 
2008 	if (setp)
2009 		*setp = set;
2010 	if (clrp)
2011 		*clrp = clear;
2012 
2013 	/* Return location of first failure. */
2014 	return (failed);
2015 }
2016 
2017 
2018 #ifdef TEST
2019 #include <stdio.h>
2020 int
main(int argc,char ** argv)2021 main(int argc, char **argv)
2022 {
2023 	struct archive_entry *entry = archive_entry_new();
2024 	unsigned long set, clear;
2025 	const wchar_t *remainder;
2026 
2027 	remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
2028 	archive_entry_fflags(entry, &set, &clear);
2029 
2030 	wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
2031 
2032 	wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
2033 	return (0);
2034 }
2035 #endif
2036