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