1 /*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
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 memset(entry, 0, sizeof(*entry));
171 return entry;
172 }
173
174 struct archive_entry *
archive_entry_clone(struct archive_entry * entry)175 archive_entry_clone(struct archive_entry *entry)
176 {
177 struct archive_entry *entry2;
178 struct ae_xattr *xp;
179 struct ae_sparse *sp;
180 size_t s;
181 const void *p;
182
183 /* Allocate new structure and copy over all of the fields. */
184 /* TODO: Should we copy the archive over? Or require a new archive
185 * as an argument? */
186 entry2 = archive_entry_new2(entry->archive);
187 if (entry2 == NULL)
188 return (NULL);
189 entry2->ae_stat = entry->ae_stat;
190 entry2->ae_fflags_set = entry->ae_fflags_set;
191 entry2->ae_fflags_clear = entry->ae_fflags_clear;
192
193 /* TODO: XXX If clone can have a different archive, what do we do here if
194 * character sets are different? XXX */
195 archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
196 archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
197 archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
198 archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
199 archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
200 archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink);
201 entry2->ae_set = entry->ae_set;
202 archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
203
204 /* Copy ACL data over. */
205 archive_acl_copy(&entry2->acl, &entry->acl);
206
207 /* Copy Mac OS metadata. */
208 p = archive_entry_mac_metadata(entry, &s);
209 archive_entry_copy_mac_metadata(entry2, p, s);
210
211 /* Copy xattr data over. */
212 xp = entry->xattr_head;
213 while (xp != NULL) {
214 archive_entry_xattr_add_entry(entry2,
215 xp->name, xp->value, xp->size);
216 xp = xp->next;
217 }
218
219 /* Copy sparse data over. */
220 sp = entry->sparse_head;
221 while (sp != NULL) {
222 archive_entry_sparse_add_entry(entry2,
223 sp->offset, sp->length);
224 sp = sp->next;
225 }
226
227 return (entry2);
228 }
229
230 void
archive_entry_free(struct archive_entry * entry)231 archive_entry_free(struct archive_entry *entry)
232 {
233 archive_entry_clear(entry);
234 free(entry);
235 }
236
237 struct archive_entry *
archive_entry_new(void)238 archive_entry_new(void)
239 {
240 return archive_entry_new2(NULL);
241 }
242
243 struct archive_entry *
archive_entry_new2(struct archive * a)244 archive_entry_new2(struct archive *a)
245 {
246 struct archive_entry *entry;
247
248 entry = (struct archive_entry *)malloc(sizeof(*entry));
249 if (entry == NULL)
250 return (NULL);
251 memset(entry, 0, sizeof(*entry));
252 entry->archive = a;
253 return (entry);
254 }
255
256 /*
257 * Functions for reading fields from an archive_entry.
258 */
259
260 time_t
archive_entry_atime(struct archive_entry * entry)261 archive_entry_atime(struct archive_entry *entry)
262 {
263 return (entry->ae_stat.aest_atime);
264 }
265
266 long
archive_entry_atime_nsec(struct archive_entry * entry)267 archive_entry_atime_nsec(struct archive_entry *entry)
268 {
269 return (entry->ae_stat.aest_atime_nsec);
270 }
271
272 int
archive_entry_atime_is_set(struct archive_entry * entry)273 archive_entry_atime_is_set(struct archive_entry *entry)
274 {
275 return (entry->ae_set & AE_SET_ATIME);
276 }
277
278 time_t
archive_entry_birthtime(struct archive_entry * entry)279 archive_entry_birthtime(struct archive_entry *entry)
280 {
281 return (entry->ae_stat.aest_birthtime);
282 }
283
284 long
archive_entry_birthtime_nsec(struct archive_entry * entry)285 archive_entry_birthtime_nsec(struct archive_entry *entry)
286 {
287 return (entry->ae_stat.aest_birthtime_nsec);
288 }
289
290 int
archive_entry_birthtime_is_set(struct archive_entry * entry)291 archive_entry_birthtime_is_set(struct archive_entry *entry)
292 {
293 return (entry->ae_set & AE_SET_BIRTHTIME);
294 }
295
296 time_t
archive_entry_ctime(struct archive_entry * entry)297 archive_entry_ctime(struct archive_entry *entry)
298 {
299 return (entry->ae_stat.aest_ctime);
300 }
301
302 int
archive_entry_ctime_is_set(struct archive_entry * entry)303 archive_entry_ctime_is_set(struct archive_entry *entry)
304 {
305 return (entry->ae_set & AE_SET_CTIME);
306 }
307
308 long
archive_entry_ctime_nsec(struct archive_entry * entry)309 archive_entry_ctime_nsec(struct archive_entry *entry)
310 {
311 return (entry->ae_stat.aest_ctime_nsec);
312 }
313
314 dev_t
archive_entry_dev(struct archive_entry * entry)315 archive_entry_dev(struct archive_entry *entry)
316 {
317 if (entry->ae_stat.aest_dev_is_broken_down)
318 return ae_makedev(entry->ae_stat.aest_devmajor,
319 entry->ae_stat.aest_devminor);
320 else
321 return (entry->ae_stat.aest_dev);
322 }
323
324 int
archive_entry_dev_is_set(struct archive_entry * entry)325 archive_entry_dev_is_set(struct archive_entry *entry)
326 {
327 return (entry->ae_set & AE_SET_DEV);
328 }
329
330 dev_t
archive_entry_devmajor(struct archive_entry * entry)331 archive_entry_devmajor(struct archive_entry *entry)
332 {
333 if (entry->ae_stat.aest_dev_is_broken_down)
334 return (entry->ae_stat.aest_devmajor);
335 else
336 return major(entry->ae_stat.aest_dev);
337 }
338
339 dev_t
archive_entry_devminor(struct archive_entry * entry)340 archive_entry_devminor(struct archive_entry *entry)
341 {
342 if (entry->ae_stat.aest_dev_is_broken_down)
343 return (entry->ae_stat.aest_devminor);
344 else
345 return minor(entry->ae_stat.aest_dev);
346 }
347
348 mode_t
archive_entry_filetype(struct archive_entry * entry)349 archive_entry_filetype(struct archive_entry *entry)
350 {
351 return (AE_IFMT & entry->acl.mode);
352 }
353
354 void
archive_entry_fflags(struct archive_entry * entry,unsigned long * set,unsigned long * clear)355 archive_entry_fflags(struct archive_entry *entry,
356 unsigned long *set, unsigned long *clear)
357 {
358 *set = entry->ae_fflags_set;
359 *clear = entry->ae_fflags_clear;
360 }
361
362 /*
363 * Note: if text was provided, this just returns that text. If you
364 * really need the text to be rebuilt in a canonical form, set the
365 * text, ask for the bitmaps, then set the bitmaps. (Setting the
366 * bitmaps clears any stored text.) This design is deliberate: if
367 * we're editing archives, we don't want to discard flags just because
368 * they aren't supported on the current system. The bitmap<->text
369 * conversions are platform-specific (see below).
370 */
371 const char *
archive_entry_fflags_text(struct archive_entry * entry)372 archive_entry_fflags_text(struct archive_entry *entry)
373 {
374 const char *f;
375 char *p;
376
377 if (archive_mstring_get_mbs(entry->archive,
378 &entry->ae_fflags_text, &f) == 0) {
379 if (f != NULL)
380 return (f);
381 } else if (errno == ENOMEM)
382 __archive_errx(1, "No memory");
383
384 if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0)
385 return (NULL);
386
387 p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);
388 if (p == NULL)
389 return (NULL);
390
391 archive_mstring_copy_mbs(&entry->ae_fflags_text, p);
392 free(p);
393 if (archive_mstring_get_mbs(entry->archive,
394 &entry->ae_fflags_text, &f) == 0)
395 return (f);
396 if (errno == ENOMEM)
397 __archive_errx(1, "No memory");
398 return (NULL);
399 }
400
401 int64_t
archive_entry_gid(struct archive_entry * entry)402 archive_entry_gid(struct archive_entry *entry)
403 {
404 return (entry->ae_stat.aest_gid);
405 }
406
407 const char *
archive_entry_gname(struct archive_entry * entry)408 archive_entry_gname(struct archive_entry *entry)
409 {
410 const char *p;
411 if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
412 return (p);
413 if (errno == ENOMEM)
414 __archive_errx(1, "No memory");
415 return (NULL);
416 }
417
418 const wchar_t *
archive_entry_gname_w(struct archive_entry * entry)419 archive_entry_gname_w(struct archive_entry *entry)
420 {
421 const wchar_t *p;
422 if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
423 return (p);
424 if (errno == ENOMEM)
425 __archive_errx(1, "No memory");
426 return (NULL);
427 }
428
429 int
_archive_entry_gname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)430 _archive_entry_gname_l(struct archive_entry *entry,
431 const char **p, size_t *len, struct archive_string_conv *sc)
432 {
433 return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc));
434 }
435
436 const char *
archive_entry_hardlink(struct archive_entry * entry)437 archive_entry_hardlink(struct archive_entry *entry)
438 {
439 const char *p;
440 if ((entry->ae_set & AE_SET_HARDLINK) == 0)
441 return (NULL);
442 if (archive_mstring_get_mbs(
443 entry->archive, &entry->ae_hardlink, &p) == 0)
444 return (p);
445 if (errno == ENOMEM)
446 __archive_errx(1, "No memory");
447 return (NULL);
448 }
449
450 const wchar_t *
archive_entry_hardlink_w(struct archive_entry * entry)451 archive_entry_hardlink_w(struct archive_entry *entry)
452 {
453 const wchar_t *p;
454 if ((entry->ae_set & AE_SET_HARDLINK) == 0)
455 return (NULL);
456 if (archive_mstring_get_wcs(
457 entry->archive, &entry->ae_hardlink, &p) == 0)
458 return (p);
459 if (errno == ENOMEM)
460 __archive_errx(1, "No memory");
461 return (NULL);
462 }
463
464 int
_archive_entry_hardlink_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)465 _archive_entry_hardlink_l(struct archive_entry *entry,
466 const char **p, size_t *len, struct archive_string_conv *sc)
467 {
468 if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
469 *p = NULL;
470 *len = 0;
471 return (0);
472 }
473 return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
474 }
475
476 int64_t
archive_entry_ino(struct archive_entry * entry)477 archive_entry_ino(struct archive_entry *entry)
478 {
479 return (entry->ae_stat.aest_ino);
480 }
481
482 int
archive_entry_ino_is_set(struct archive_entry * entry)483 archive_entry_ino_is_set(struct archive_entry *entry)
484 {
485 return (entry->ae_set & AE_SET_INO);
486 }
487
488 int64_t
archive_entry_ino64(struct archive_entry * entry)489 archive_entry_ino64(struct archive_entry *entry)
490 {
491 return (entry->ae_stat.aest_ino);
492 }
493
494 mode_t
archive_entry_mode(struct archive_entry * entry)495 archive_entry_mode(struct archive_entry *entry)
496 {
497 return (entry->acl.mode);
498 }
499
500 time_t
archive_entry_mtime(struct archive_entry * entry)501 archive_entry_mtime(struct archive_entry *entry)
502 {
503 return (entry->ae_stat.aest_mtime);
504 }
505
506 long
archive_entry_mtime_nsec(struct archive_entry * entry)507 archive_entry_mtime_nsec(struct archive_entry *entry)
508 {
509 return (entry->ae_stat.aest_mtime_nsec);
510 }
511
512 int
archive_entry_mtime_is_set(struct archive_entry * entry)513 archive_entry_mtime_is_set(struct archive_entry *entry)
514 {
515 return (entry->ae_set & AE_SET_MTIME);
516 }
517
518 unsigned int
archive_entry_nlink(struct archive_entry * entry)519 archive_entry_nlink(struct archive_entry *entry)
520 {
521 return (entry->ae_stat.aest_nlink);
522 }
523
524 const char *
archive_entry_pathname(struct archive_entry * entry)525 archive_entry_pathname(struct archive_entry *entry)
526 {
527 const char *p;
528 if (archive_mstring_get_mbs(
529 entry->archive, &entry->ae_pathname, &p) == 0)
530 return (p);
531 if (errno == ENOMEM)
532 __archive_errx(1, "No memory");
533 return (NULL);
534 }
535
536 const wchar_t *
archive_entry_pathname_w(struct archive_entry * entry)537 archive_entry_pathname_w(struct archive_entry *entry)
538 {
539 const wchar_t *p;
540 if (archive_mstring_get_wcs(
541 entry->archive, &entry->ae_pathname, &p) == 0)
542 return (p);
543 if (errno == ENOMEM)
544 __archive_errx(1, "No memory");
545 return (NULL);
546 }
547
548 int
_archive_entry_pathname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)549 _archive_entry_pathname_l(struct archive_entry *entry,
550 const char **p, size_t *len, struct archive_string_conv *sc)
551 {
552 return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc));
553 }
554
555 mode_t
archive_entry_perm(struct archive_entry * entry)556 archive_entry_perm(struct archive_entry *entry)
557 {
558 return (~AE_IFMT & entry->acl.mode);
559 }
560
561 dev_t
archive_entry_rdev(struct archive_entry * entry)562 archive_entry_rdev(struct archive_entry *entry)
563 {
564 if (entry->ae_stat.aest_rdev_is_broken_down)
565 return ae_makedev(entry->ae_stat.aest_rdevmajor,
566 entry->ae_stat.aest_rdevminor);
567 else
568 return (entry->ae_stat.aest_rdev);
569 }
570
571 dev_t
archive_entry_rdevmajor(struct archive_entry * entry)572 archive_entry_rdevmajor(struct archive_entry *entry)
573 {
574 if (entry->ae_stat.aest_rdev_is_broken_down)
575 return (entry->ae_stat.aest_rdevmajor);
576 else
577 return major(entry->ae_stat.aest_rdev);
578 }
579
580 dev_t
archive_entry_rdevminor(struct archive_entry * entry)581 archive_entry_rdevminor(struct archive_entry *entry)
582 {
583 if (entry->ae_stat.aest_rdev_is_broken_down)
584 return (entry->ae_stat.aest_rdevminor);
585 else
586 return minor(entry->ae_stat.aest_rdev);
587 }
588
589 int64_t
archive_entry_size(struct archive_entry * entry)590 archive_entry_size(struct archive_entry *entry)
591 {
592 return (entry->ae_stat.aest_size);
593 }
594
595 int
archive_entry_size_is_set(struct archive_entry * entry)596 archive_entry_size_is_set(struct archive_entry *entry)
597 {
598 return (entry->ae_set & AE_SET_SIZE);
599 }
600
601 const char *
archive_entry_sourcepath(struct archive_entry * entry)602 archive_entry_sourcepath(struct archive_entry *entry)
603 {
604 const char *p;
605 if (archive_mstring_get_mbs(
606 entry->archive, &entry->ae_sourcepath, &p) == 0)
607 return (p);
608 if (errno == ENOMEM)
609 __archive_errx(1, "No memory");
610 return (NULL);
611 }
612
613 const wchar_t *
archive_entry_sourcepath_w(struct archive_entry * entry)614 archive_entry_sourcepath_w(struct archive_entry *entry)
615 {
616 const wchar_t *p;
617 if (archive_mstring_get_wcs(
618 entry->archive, &entry->ae_sourcepath, &p) == 0)
619 return (p);
620 return (NULL);
621 }
622
623 const char *
archive_entry_symlink(struct archive_entry * entry)624 archive_entry_symlink(struct archive_entry *entry)
625 {
626 const char *p;
627 if ((entry->ae_set & AE_SET_SYMLINK) == 0)
628 return (NULL);
629 if (archive_mstring_get_mbs(
630 entry->archive, &entry->ae_symlink, &p) == 0)
631 return (p);
632 if (errno == ENOMEM)
633 __archive_errx(1, "No memory");
634 return (NULL);
635 }
636
637 const wchar_t *
archive_entry_symlink_w(struct archive_entry * entry)638 archive_entry_symlink_w(struct archive_entry *entry)
639 {
640 const wchar_t *p;
641 if ((entry->ae_set & AE_SET_SYMLINK) == 0)
642 return (NULL);
643 if (archive_mstring_get_wcs(
644 entry->archive, &entry->ae_symlink, &p) == 0)
645 return (p);
646 if (errno == ENOMEM)
647 __archive_errx(1, "No memory");
648 return (NULL);
649 }
650
651 int
_archive_entry_symlink_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)652 _archive_entry_symlink_l(struct archive_entry *entry,
653 const char **p, size_t *len, struct archive_string_conv *sc)
654 {
655 if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
656 *p = NULL;
657 *len = 0;
658 return (0);
659 }
660 return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
661 }
662
663 int64_t
archive_entry_uid(struct archive_entry * entry)664 archive_entry_uid(struct archive_entry *entry)
665 {
666 return (entry->ae_stat.aest_uid);
667 }
668
669 const char *
archive_entry_uname(struct archive_entry * entry)670 archive_entry_uname(struct archive_entry *entry)
671 {
672 const char *p;
673 if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
674 return (p);
675 if (errno == ENOMEM)
676 __archive_errx(1, "No memory");
677 return (NULL);
678 }
679
680 const wchar_t *
archive_entry_uname_w(struct archive_entry * entry)681 archive_entry_uname_w(struct archive_entry *entry)
682 {
683 const wchar_t *p;
684 if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
685 return (p);
686 if (errno == ENOMEM)
687 __archive_errx(1, "No memory");
688 return (NULL);
689 }
690
691 int
_archive_entry_uname_l(struct archive_entry * entry,const char ** p,size_t * len,struct archive_string_conv * sc)692 _archive_entry_uname_l(struct archive_entry *entry,
693 const char **p, size_t *len, struct archive_string_conv *sc)
694 {
695 return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
696 }
697
698 /*
699 * Functions to set archive_entry properties.
700 */
701
702 void
archive_entry_set_filetype(struct archive_entry * entry,unsigned int type)703 archive_entry_set_filetype(struct archive_entry *entry, unsigned int type)
704 {
705 entry->stat_valid = 0;
706 entry->acl.mode &= ~AE_IFMT;
707 entry->acl.mode |= AE_IFMT & type;
708 }
709
710 void
archive_entry_set_fflags(struct archive_entry * entry,unsigned long set,unsigned long clear)711 archive_entry_set_fflags(struct archive_entry *entry,
712 unsigned long set, unsigned long clear)
713 {
714 archive_mstring_clean(&entry->ae_fflags_text);
715 entry->ae_fflags_set = set;
716 entry->ae_fflags_clear = clear;
717 }
718
719 const char *
archive_entry_copy_fflags_text(struct archive_entry * entry,const char * flags)720 archive_entry_copy_fflags_text(struct archive_entry *entry,
721 const char *flags)
722 {
723 archive_mstring_copy_mbs(&entry->ae_fflags_text, flags);
724 return (ae_strtofflags(flags,
725 &entry->ae_fflags_set, &entry->ae_fflags_clear));
726 }
727
728 const wchar_t *
archive_entry_copy_fflags_text_w(struct archive_entry * entry,const wchar_t * flags)729 archive_entry_copy_fflags_text_w(struct archive_entry *entry,
730 const wchar_t *flags)
731 {
732 archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);
733 return (ae_wcstofflags(flags,
734 &entry->ae_fflags_set, &entry->ae_fflags_clear));
735 }
736
737 void
archive_entry_set_gid(struct archive_entry * entry,int64_t g)738 archive_entry_set_gid(struct archive_entry *entry, int64_t g)
739 {
740 entry->stat_valid = 0;
741 entry->ae_stat.aest_gid = g;
742 }
743
744 void
archive_entry_set_gname(struct archive_entry * entry,const char * name)745 archive_entry_set_gname(struct archive_entry *entry, const char *name)
746 {
747 archive_mstring_copy_mbs(&entry->ae_gname, name);
748 }
749
750 void
archive_entry_copy_gname(struct archive_entry * entry,const char * name)751 archive_entry_copy_gname(struct archive_entry *entry, const char *name)
752 {
753 archive_mstring_copy_mbs(&entry->ae_gname, name);
754 }
755
756 void
archive_entry_copy_gname_w(struct archive_entry * entry,const wchar_t * name)757 archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
758 {
759 archive_mstring_copy_wcs(&entry->ae_gname, name);
760 }
761
762 int
archive_entry_update_gname_utf8(struct archive_entry * entry,const char * name)763 archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
764 {
765 if (archive_mstring_update_utf8(entry->archive,
766 &entry->ae_gname, name) == 0)
767 return (1);
768 if (errno == ENOMEM)
769 __archive_errx(1, "No memory");
770 return (0);
771 }
772
773 int
_archive_entry_copy_gname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)774 _archive_entry_copy_gname_l(struct archive_entry *entry,
775 const char *name, size_t len, struct archive_string_conv *sc)
776 {
777 return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
778 }
779
780 void
archive_entry_set_ino(struct archive_entry * entry,int64_t ino)781 archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
782 {
783 entry->stat_valid = 0;
784 entry->ae_set |= AE_SET_INO;
785 entry->ae_stat.aest_ino = ino;
786 }
787
788 void
archive_entry_set_ino64(struct archive_entry * entry,int64_t ino)789 archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
790 {
791 entry->stat_valid = 0;
792 entry->ae_set |= AE_SET_INO;
793 entry->ae_stat.aest_ino = ino;
794 }
795
796 void
archive_entry_set_hardlink(struct archive_entry * entry,const char * target)797 archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
798 {
799 archive_mstring_copy_mbs(&entry->ae_hardlink, target);
800 if (target != NULL)
801 entry->ae_set |= AE_SET_HARDLINK;
802 else
803 entry->ae_set &= ~AE_SET_HARDLINK;
804 }
805
806 void
archive_entry_copy_hardlink(struct archive_entry * entry,const char * target)807 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
808 {
809 archive_mstring_copy_mbs(&entry->ae_hardlink, target);
810 if (target != NULL)
811 entry->ae_set |= AE_SET_HARDLINK;
812 else
813 entry->ae_set &= ~AE_SET_HARDLINK;
814 }
815
816 void
archive_entry_copy_hardlink_w(struct archive_entry * entry,const wchar_t * target)817 archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
818 {
819 archive_mstring_copy_wcs(&entry->ae_hardlink, target);
820 if (target != NULL)
821 entry->ae_set |= AE_SET_HARDLINK;
822 else
823 entry->ae_set &= ~AE_SET_HARDLINK;
824 }
825
826 int
archive_entry_update_hardlink_utf8(struct archive_entry * entry,const char * target)827 archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
828 {
829 if (target != NULL)
830 entry->ae_set |= AE_SET_HARDLINK;
831 else
832 entry->ae_set &= ~AE_SET_HARDLINK;
833 if (archive_mstring_update_utf8(entry->archive,
834 &entry->ae_hardlink, target) == 0)
835 return (1);
836 if (errno == ENOMEM)
837 __archive_errx(1, "No memory");
838 return (0);
839 }
840
841 int
_archive_entry_copy_hardlink_l(struct archive_entry * entry,const char * target,size_t len,struct archive_string_conv * sc)842 _archive_entry_copy_hardlink_l(struct archive_entry *entry,
843 const char *target, size_t len, struct archive_string_conv *sc)
844 {
845 int r;
846
847 r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
848 target, len, sc);
849 if (target != NULL && r == 0)
850 entry->ae_set |= AE_SET_HARDLINK;
851 else
852 entry->ae_set &= ~AE_SET_HARDLINK;
853 return (r);
854 }
855
856 void
archive_entry_set_atime(struct archive_entry * entry,time_t t,long ns)857 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
858 {
859 FIX_NS(t, ns);
860 entry->stat_valid = 0;
861 entry->ae_set |= AE_SET_ATIME;
862 entry->ae_stat.aest_atime = t;
863 entry->ae_stat.aest_atime_nsec = ns;
864 }
865
866 void
archive_entry_unset_atime(struct archive_entry * entry)867 archive_entry_unset_atime(struct archive_entry *entry)
868 {
869 archive_entry_set_atime(entry, 0, 0);
870 entry->ae_set &= ~AE_SET_ATIME;
871 }
872
873 void
archive_entry_set_birthtime(struct archive_entry * entry,time_t t,long ns)874 archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
875 {
876 FIX_NS(t, ns);
877 entry->stat_valid = 0;
878 entry->ae_set |= AE_SET_BIRTHTIME;
879 entry->ae_stat.aest_birthtime = t;
880 entry->ae_stat.aest_birthtime_nsec = ns;
881 }
882
883 void
archive_entry_unset_birthtime(struct archive_entry * entry)884 archive_entry_unset_birthtime(struct archive_entry *entry)
885 {
886 archive_entry_set_birthtime(entry, 0, 0);
887 entry->ae_set &= ~AE_SET_BIRTHTIME;
888 }
889
890 void
archive_entry_set_ctime(struct archive_entry * entry,time_t t,long ns)891 archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
892 {
893 FIX_NS(t, ns);
894 entry->stat_valid = 0;
895 entry->ae_set |= AE_SET_CTIME;
896 entry->ae_stat.aest_ctime = t;
897 entry->ae_stat.aest_ctime_nsec = ns;
898 }
899
900 void
archive_entry_unset_ctime(struct archive_entry * entry)901 archive_entry_unset_ctime(struct archive_entry *entry)
902 {
903 archive_entry_set_ctime(entry, 0, 0);
904 entry->ae_set &= ~AE_SET_CTIME;
905 }
906
907 void
archive_entry_set_dev(struct archive_entry * entry,dev_t d)908 archive_entry_set_dev(struct archive_entry *entry, dev_t d)
909 {
910 entry->stat_valid = 0;
911 entry->ae_set |= AE_SET_DEV;
912 entry->ae_stat.aest_dev_is_broken_down = 0;
913 entry->ae_stat.aest_dev = d;
914 }
915
916 void
archive_entry_set_devmajor(struct archive_entry * entry,dev_t m)917 archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
918 {
919 entry->stat_valid = 0;
920 entry->ae_set |= AE_SET_DEV;
921 entry->ae_stat.aest_dev_is_broken_down = 1;
922 entry->ae_stat.aest_devmajor = m;
923 }
924
925 void
archive_entry_set_devminor(struct archive_entry * entry,dev_t m)926 archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
927 {
928 entry->stat_valid = 0;
929 entry->ae_set |= AE_SET_DEV;
930 entry->ae_stat.aest_dev_is_broken_down = 1;
931 entry->ae_stat.aest_devminor = m;
932 }
933
934 /* Set symlink if symlink is already set, else set hardlink. */
935 void
archive_entry_set_link(struct archive_entry * entry,const char * target)936 archive_entry_set_link(struct archive_entry *entry, const char *target)
937 {
938 if (entry->ae_set & AE_SET_SYMLINK)
939 archive_mstring_copy_mbs(&entry->ae_symlink, target);
940 else
941 archive_mstring_copy_mbs(&entry->ae_hardlink, target);
942 }
943
944 /* Set symlink if symlink is already set, else set hardlink. */
945 void
archive_entry_copy_link(struct archive_entry * entry,const char * target)946 archive_entry_copy_link(struct archive_entry *entry, const char *target)
947 {
948 if (entry->ae_set & AE_SET_SYMLINK)
949 archive_mstring_copy_mbs(&entry->ae_symlink, target);
950 else
951 archive_mstring_copy_mbs(&entry->ae_hardlink, target);
952 }
953
954 /* Set symlink if symlink is already set, else set hardlink. */
955 void
archive_entry_copy_link_w(struct archive_entry * entry,const wchar_t * target)956 archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
957 {
958 if (entry->ae_set & AE_SET_SYMLINK)
959 archive_mstring_copy_wcs(&entry->ae_symlink, target);
960 else
961 archive_mstring_copy_wcs(&entry->ae_hardlink, target);
962 }
963
964 int
archive_entry_update_link_utf8(struct archive_entry * entry,const char * target)965 archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
966 {
967 int r;
968 if (entry->ae_set & AE_SET_SYMLINK)
969 r = archive_mstring_update_utf8(entry->archive,
970 &entry->ae_symlink, target);
971 else
972 r = archive_mstring_update_utf8(entry->archive,
973 &entry->ae_hardlink, target);
974 if (r == 0)
975 return (1);
976 if (errno == ENOMEM)
977 __archive_errx(1, "No memory");
978 return (0);
979 }
980
981 int
_archive_entry_copy_link_l(struct archive_entry * entry,const char * target,size_t len,struct archive_string_conv * sc)982 _archive_entry_copy_link_l(struct archive_entry *entry,
983 const char *target, size_t len, struct archive_string_conv *sc)
984 {
985 int r;
986
987 if (entry->ae_set & AE_SET_SYMLINK)
988 r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
989 target, len, sc);
990 else
991 r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
992 target, len, sc);
993 return (r);
994 }
995
996 void
archive_entry_set_mode(struct archive_entry * entry,mode_t m)997 archive_entry_set_mode(struct archive_entry *entry, mode_t m)
998 {
999 entry->stat_valid = 0;
1000 entry->acl.mode = m;
1001 }
1002
1003 void
archive_entry_set_mtime(struct archive_entry * entry,time_t t,long ns)1004 archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
1005 {
1006 FIX_NS(t, ns);
1007 entry->stat_valid = 0;
1008 entry->ae_set |= AE_SET_MTIME;
1009 entry->ae_stat.aest_mtime = t;
1010 entry->ae_stat.aest_mtime_nsec = ns;
1011 }
1012
1013 void
archive_entry_unset_mtime(struct archive_entry * entry)1014 archive_entry_unset_mtime(struct archive_entry *entry)
1015 {
1016 archive_entry_set_mtime(entry, 0, 0);
1017 entry->ae_set &= ~AE_SET_MTIME;
1018 }
1019
1020 void
archive_entry_set_nlink(struct archive_entry * entry,unsigned int nlink)1021 archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
1022 {
1023 entry->stat_valid = 0;
1024 entry->ae_stat.aest_nlink = nlink;
1025 }
1026
1027 void
archive_entry_set_pathname(struct archive_entry * entry,const char * name)1028 archive_entry_set_pathname(struct archive_entry *entry, const char *name)
1029 {
1030 archive_mstring_copy_mbs(&entry->ae_pathname, name);
1031 }
1032
1033 void
archive_entry_copy_pathname(struct archive_entry * entry,const char * name)1034 archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
1035 {
1036 archive_mstring_copy_mbs(&entry->ae_pathname, name);
1037 }
1038
1039 void
archive_entry_copy_pathname_w(struct archive_entry * entry,const wchar_t * name)1040 archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
1041 {
1042 archive_mstring_copy_wcs(&entry->ae_pathname, name);
1043 }
1044
1045 int
archive_entry_update_pathname_utf8(struct archive_entry * entry,const char * name)1046 archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
1047 {
1048 if (archive_mstring_update_utf8(entry->archive,
1049 &entry->ae_pathname, name) == 0)
1050 return (1);
1051 if (errno == ENOMEM)
1052 __archive_errx(1, "No memory");
1053 return (0);
1054 }
1055
1056 int
_archive_entry_copy_pathname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)1057 _archive_entry_copy_pathname_l(struct archive_entry *entry,
1058 const char *name, size_t len, struct archive_string_conv *sc)
1059 {
1060 return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
1061 name, len, sc));
1062 }
1063
1064 void
archive_entry_set_perm(struct archive_entry * entry,mode_t p)1065 archive_entry_set_perm(struct archive_entry *entry, mode_t p)
1066 {
1067 entry->stat_valid = 0;
1068 entry->acl.mode &= AE_IFMT;
1069 entry->acl.mode |= ~AE_IFMT & p;
1070 }
1071
1072 void
archive_entry_set_rdev(struct archive_entry * entry,dev_t m)1073 archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
1074 {
1075 entry->stat_valid = 0;
1076 entry->ae_stat.aest_rdev = m;
1077 entry->ae_stat.aest_rdev_is_broken_down = 0;
1078 }
1079
1080 void
archive_entry_set_rdevmajor(struct archive_entry * entry,dev_t m)1081 archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
1082 {
1083 entry->stat_valid = 0;
1084 entry->ae_stat.aest_rdev_is_broken_down = 1;
1085 entry->ae_stat.aest_rdevmajor = m;
1086 }
1087
1088 void
archive_entry_set_rdevminor(struct archive_entry * entry,dev_t m)1089 archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
1090 {
1091 entry->stat_valid = 0;
1092 entry->ae_stat.aest_rdev_is_broken_down = 1;
1093 entry->ae_stat.aest_rdevminor = m;
1094 }
1095
1096 void
archive_entry_set_size(struct archive_entry * entry,int64_t s)1097 archive_entry_set_size(struct archive_entry *entry, int64_t s)
1098 {
1099 entry->stat_valid = 0;
1100 entry->ae_stat.aest_size = s;
1101 entry->ae_set |= AE_SET_SIZE;
1102 }
1103
1104 void
archive_entry_unset_size(struct archive_entry * entry)1105 archive_entry_unset_size(struct archive_entry *entry)
1106 {
1107 archive_entry_set_size(entry, 0);
1108 entry->ae_set &= ~AE_SET_SIZE;
1109 }
1110
1111 void
archive_entry_copy_sourcepath(struct archive_entry * entry,const char * path)1112 archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
1113 {
1114 archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
1115 }
1116
1117 void
archive_entry_copy_sourcepath_w(struct archive_entry * entry,const wchar_t * path)1118 archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
1119 {
1120 archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
1121 }
1122
1123 void
archive_entry_set_symlink(struct archive_entry * entry,const char * linkname)1124 archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
1125 {
1126 archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
1127 if (linkname != NULL)
1128 entry->ae_set |= AE_SET_SYMLINK;
1129 else
1130 entry->ae_set &= ~AE_SET_SYMLINK;
1131 }
1132
1133 void
archive_entry_copy_symlink(struct archive_entry * entry,const char * linkname)1134 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
1135 {
1136 archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
1137 if (linkname != NULL)
1138 entry->ae_set |= AE_SET_SYMLINK;
1139 else
1140 entry->ae_set &= ~AE_SET_SYMLINK;
1141 }
1142
1143 void
archive_entry_copy_symlink_w(struct archive_entry * entry,const wchar_t * linkname)1144 archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
1145 {
1146 archive_mstring_copy_wcs(&entry->ae_symlink, linkname);
1147 if (linkname != NULL)
1148 entry->ae_set |= AE_SET_SYMLINK;
1149 else
1150 entry->ae_set &= ~AE_SET_SYMLINK;
1151 }
1152
1153 int
archive_entry_update_symlink_utf8(struct archive_entry * entry,const char * linkname)1154 archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
1155 {
1156 if (linkname != NULL)
1157 entry->ae_set |= AE_SET_SYMLINK;
1158 else
1159 entry->ae_set &= ~AE_SET_SYMLINK;
1160 if (archive_mstring_update_utf8(entry->archive,
1161 &entry->ae_symlink, linkname) == 0)
1162 return (1);
1163 if (errno == ENOMEM)
1164 __archive_errx(1, "No memory");
1165 return (0);
1166 }
1167
1168 int
_archive_entry_copy_symlink_l(struct archive_entry * entry,const char * linkname,size_t len,struct archive_string_conv * sc)1169 _archive_entry_copy_symlink_l(struct archive_entry *entry,
1170 const char *linkname, size_t len, struct archive_string_conv *sc)
1171 {
1172 int r;
1173
1174 r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
1175 linkname, len, sc);
1176 if (linkname != NULL && r == 0)
1177 entry->ae_set |= AE_SET_SYMLINK;
1178 else
1179 entry->ae_set &= ~AE_SET_SYMLINK;
1180 return (r);
1181 }
1182
1183 void
archive_entry_set_uid(struct archive_entry * entry,int64_t u)1184 archive_entry_set_uid(struct archive_entry *entry, int64_t u)
1185 {
1186 entry->stat_valid = 0;
1187 entry->ae_stat.aest_uid = u;
1188 }
1189
1190 void
archive_entry_set_uname(struct archive_entry * entry,const char * name)1191 archive_entry_set_uname(struct archive_entry *entry, const char *name)
1192 {
1193 archive_mstring_copy_mbs(&entry->ae_uname, name);
1194 }
1195
1196 void
archive_entry_copy_uname(struct archive_entry * entry,const char * name)1197 archive_entry_copy_uname(struct archive_entry *entry, const char *name)
1198 {
1199 archive_mstring_copy_mbs(&entry->ae_uname, name);
1200 }
1201
1202 void
archive_entry_copy_uname_w(struct archive_entry * entry,const wchar_t * name)1203 archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
1204 {
1205 archive_mstring_copy_wcs(&entry->ae_uname, name);
1206 }
1207
1208 int
archive_entry_update_uname_utf8(struct archive_entry * entry,const char * name)1209 archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
1210 {
1211 if (archive_mstring_update_utf8(entry->archive,
1212 &entry->ae_uname, name) == 0)
1213 return (1);
1214 if (errno == ENOMEM)
1215 __archive_errx(1, "No memory");
1216 return (0);
1217 }
1218
1219 int
_archive_entry_copy_uname_l(struct archive_entry * entry,const char * name,size_t len,struct archive_string_conv * sc)1220 _archive_entry_copy_uname_l(struct archive_entry *entry,
1221 const char *name, size_t len, struct archive_string_conv *sc)
1222 {
1223 return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
1224 name, len, sc));
1225 }
1226
1227 const void *
archive_entry_mac_metadata(struct archive_entry * entry,size_t * s)1228 archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
1229 {
1230 *s = entry->mac_metadata_size;
1231 return entry->mac_metadata;
1232 }
1233
1234 void
archive_entry_copy_mac_metadata(struct archive_entry * entry,const void * p,size_t s)1235 archive_entry_copy_mac_metadata(struct archive_entry *entry,
1236 const void *p, size_t s)
1237 {
1238 free(entry->mac_metadata);
1239 if (p == NULL || s == 0) {
1240 entry->mac_metadata = NULL;
1241 entry->mac_metadata_size = 0;
1242 } else {
1243 entry->mac_metadata_size = s;
1244 entry->mac_metadata = malloc(s);
1245 if (entry->mac_metadata == NULL)
1246 abort();
1247 memcpy(entry->mac_metadata, p, s);
1248 }
1249 }
1250
1251 /*
1252 * ACL management. The following would, of course, be a lot simpler
1253 * if: 1) the last draft of POSIX.1e were a really thorough and
1254 * complete standard that addressed the needs of ACL archiving and 2)
1255 * everyone followed it faithfully. Alas, neither is true, so the
1256 * following is a lot more complex than might seem necessary to the
1257 * uninitiated.
1258 */
1259
1260 struct archive_acl *
archive_entry_acl(struct archive_entry * entry)1261 archive_entry_acl(struct archive_entry *entry)
1262 {
1263 return &entry->acl;
1264 }
1265
1266 void
archive_entry_acl_clear(struct archive_entry * entry)1267 archive_entry_acl_clear(struct archive_entry *entry)
1268 {
1269 archive_acl_clear(&entry->acl);
1270 }
1271
1272 /*
1273 * Add a single ACL entry to the internal list of ACL data.
1274 */
1275 int
archive_entry_acl_add_entry(struct archive_entry * entry,int type,int permset,int tag,int id,const char * name)1276 archive_entry_acl_add_entry(struct archive_entry *entry,
1277 int type, int permset, int tag, int id, const char *name)
1278 {
1279 return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
1280 }
1281
1282 /*
1283 * As above, but with a wide-character name.
1284 */
1285 int
archive_entry_acl_add_entry_w(struct archive_entry * entry,int type,int permset,int tag,int id,const wchar_t * name)1286 archive_entry_acl_add_entry_w(struct archive_entry *entry,
1287 int type, int permset, int tag, int id, const wchar_t *name)
1288 {
1289 return archive_acl_add_entry_w_len(&entry->acl,
1290 type, permset, tag, id, name, wcslen(name));
1291 }
1292
1293 /*
1294 * Return a count of entries matching "want_type".
1295 */
1296 int
archive_entry_acl_count(struct archive_entry * entry,int want_type)1297 archive_entry_acl_count(struct archive_entry *entry, int want_type)
1298 {
1299 return archive_acl_count(&entry->acl, want_type);
1300 }
1301
1302 /*
1303 * Prepare for reading entries from the ACL data. Returns a count
1304 * of entries matching "want_type", or zero if there are no
1305 * non-extended ACL entries of that type.
1306 */
1307 int
archive_entry_acl_reset(struct archive_entry * entry,int want_type)1308 archive_entry_acl_reset(struct archive_entry *entry, int want_type)
1309 {
1310 return archive_acl_reset(&entry->acl, want_type);
1311 }
1312
1313 /*
1314 * Return the next ACL entry in the list. Fake entries for the
1315 * standard permissions and include them in the returned list.
1316 */
1317 int
archive_entry_acl_next(struct archive_entry * entry,int want_type,int * type,int * permset,int * tag,int * id,const char ** name)1318 archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
1319 int *permset, int *tag, int *id, const char **name)
1320 {
1321 int r;
1322 r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
1323 permset, tag, id, name);
1324 if (r == ARCHIVE_FATAL && errno == ENOMEM)
1325 __archive_errx(1, "No memory");
1326 return (r);
1327 }
1328
1329 /*
1330 * Generate a text version of the ACL. The flags parameter controls
1331 * the style of the generated ACL.
1332 */
1333 const wchar_t *
archive_entry_acl_text_w(struct archive_entry * entry,int flags)1334 archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1335 {
1336 const wchar_t *r;
1337 r = archive_acl_text_w(entry->archive, &entry->acl, flags);
1338 if (r == NULL && errno == ENOMEM)
1339 __archive_errx(1, "No memory");
1340 return (r);
1341 }
1342
1343 const char *
archive_entry_acl_text(struct archive_entry * entry,int flags)1344 archive_entry_acl_text(struct archive_entry *entry, int flags)
1345 {
1346 const char *p;
1347 if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
1348 && errno == ENOMEM)
1349 __archive_errx(1, "No memory");
1350 return (p);
1351 }
1352
1353 int
_archive_entry_acl_text_l(struct archive_entry * entry,int flags,const char ** acl_text,size_t * len,struct archive_string_conv * sc)1354 _archive_entry_acl_text_l(struct archive_entry *entry, int flags,
1355 const char **acl_text, size_t *len, struct archive_string_conv *sc)
1356 {
1357 return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
1358 }
1359
1360 /*
1361 * Following code is modified from UC Berkeley sources, and
1362 * is subject to the following copyright notice.
1363 */
1364
1365 /*-
1366 * Copyright (c) 1993
1367 * The Regents of the University of California. All rights reserved.
1368 *
1369 * Redistribution and use in source and binary forms, with or without
1370 * modification, are permitted provided that the following conditions
1371 * are met:
1372 * 1. Redistributions of source code must retain the above copyright
1373 * notice, this list of conditions and the following disclaimer.
1374 * 2. Redistributions in binary form must reproduce the above copyright
1375 * notice, this list of conditions and the following disclaimer in the
1376 * documentation and/or other materials provided with the distribution.
1377 * 4. Neither the name of the University nor the names of its contributors
1378 * may be used to endorse or promote products derived from this software
1379 * without specific prior written permission.
1380 *
1381 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1382 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1383 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1384 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1385 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1386 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1387 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1388 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1389 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1390 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1391 * SUCH DAMAGE.
1392 */
1393
1394 static struct flag {
1395 const char *name;
1396 const wchar_t *wname;
1397 unsigned long set;
1398 unsigned long clear;
1399 } flags[] = {
1400 /* Preferred (shorter) names per flag first, all prefixed by "no" */
1401 #ifdef SF_APPEND
1402 { "nosappnd", L"nosappnd", SF_APPEND, 0 },
1403 { "nosappend", L"nosappend", SF_APPEND, 0 },
1404 #endif
1405 #ifdef EXT2_APPEND_FL /* 'a' */
1406 { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
1407 { "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
1408 #endif
1409 #ifdef SF_ARCHIVED
1410 { "noarch", L"noarch", SF_ARCHIVED, 0 },
1411 { "noarchived", L"noarchived", SF_ARCHIVED, 0 },
1412 #endif
1413 #ifdef SF_IMMUTABLE
1414 { "noschg", L"noschg", SF_IMMUTABLE, 0 },
1415 { "noschange", L"noschange", SF_IMMUTABLE, 0 },
1416 { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
1417 #endif
1418 #ifdef EXT2_IMMUTABLE_FL /* 'i' */
1419 { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
1420 { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
1421 { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
1422 #endif
1423 #ifdef SF_NOUNLINK
1424 { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0 },
1425 { "nosunlink", L"nosunlink", SF_NOUNLINK, 0 },
1426 #endif
1427 #ifdef SF_SNAPSHOT
1428 { "nosnapshot", L"nosnapshot", SF_SNAPSHOT, 0 },
1429 #endif
1430 #ifdef UF_APPEND
1431 { "nouappnd", L"nouappnd", UF_APPEND, 0 },
1432 { "nouappend", L"nouappend", UF_APPEND, 0 },
1433 #endif
1434 #ifdef UF_IMMUTABLE
1435 { "nouchg", L"nouchg", UF_IMMUTABLE, 0 },
1436 { "nouchange", L"nouchange", UF_IMMUTABLE, 0 },
1437 { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0 },
1438 #endif
1439 #ifdef UF_NODUMP
1440 { "nodump", L"nodump", 0, UF_NODUMP},
1441 #endif
1442 #ifdef EXT2_NODUMP_FL /* 'd' */
1443 { "nodump", L"nodump", 0, EXT2_NODUMP_FL},
1444 #endif
1445 #ifdef UF_OPAQUE
1446 { "noopaque", L"noopaque", UF_OPAQUE, 0 },
1447 #endif
1448 #ifdef UF_NOUNLINK
1449 { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
1450 { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
1451 #endif
1452 #ifdef UF_COMPRESSED
1453 { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
1454 #endif
1455 #ifdef EXT2_UNRM_FL
1456 { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
1457 #endif
1458
1459 #ifdef EXT2_BTREE_FL
1460 { "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
1461 #endif
1462
1463 #ifdef EXT2_ECOMPR_FL
1464 { "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
1465 #endif
1466
1467 #ifdef EXT2_COMPR_FL /* 'c' */
1468 { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
1469 #endif
1470
1471 #ifdef EXT2_NOATIME_FL /* 'A' */
1472 { "noatime", L"noatime", 0, EXT2_NOATIME_FL},
1473 #endif
1474
1475 #ifdef EXT2_DIRTY_FL
1476 { "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
1477 #endif
1478
1479 #ifdef EXT2_COMPRBLK_FL
1480 #ifdef EXT2_NOCOMPR_FL
1481 { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
1482 #else
1483 { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
1484 #endif
1485 #endif
1486 #ifdef EXT2_DIRSYNC_FL
1487 { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
1488 #endif
1489 #ifdef EXT2_INDEX_FL
1490 { "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
1491 #endif
1492 #ifdef EXT2_IMAGIC_FL
1493 { "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
1494 #endif
1495 #ifdef EXT3_JOURNAL_DATA_FL
1496 { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
1497 #endif
1498 #ifdef EXT2_SECRM_FL
1499 { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
1500 #endif
1501 #ifdef EXT2_SYNC_FL
1502 { "nosync", L"nosync", EXT2_SYNC_FL, 0},
1503 #endif
1504 #ifdef EXT2_NOTAIL_FL
1505 { "notail", L"notail", 0, EXT2_NOTAIL_FL},
1506 #endif
1507 #ifdef EXT2_TOPDIR_FL
1508 { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
1509 #endif
1510 #ifdef EXT2_RESERVED_FL
1511 { "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
1512 #endif
1513
1514 { NULL, NULL, 0, 0 }
1515 };
1516
1517 /*
1518 * fflagstostr --
1519 * Convert file flags to a comma-separated string. If no flags
1520 * are set, return the empty string.
1521 */
1522 static char *
ae_fflagstostr(unsigned long bitset,unsigned long bitclear)1523 ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
1524 {
1525 char *string, *dp;
1526 const char *sp;
1527 unsigned long bits;
1528 struct flag *flag;
1529 size_t length;
1530
1531 bits = bitset | bitclear;
1532 length = 0;
1533 for (flag = flags; flag->name != NULL; flag++)
1534 if (bits & (flag->set | flag->clear)) {
1535 length += strlen(flag->name) + 1;
1536 bits &= ~(flag->set | flag->clear);
1537 }
1538
1539 if (length == 0)
1540 return (NULL);
1541 string = (char *)malloc(length);
1542 if (string == NULL)
1543 return (NULL);
1544
1545 dp = string;
1546 for (flag = flags; flag->name != NULL; flag++) {
1547 if (bitset & flag->set || bitclear & flag->clear) {
1548 sp = flag->name + 2;
1549 } else if (bitset & flag->clear || bitclear & flag->set) {
1550 sp = flag->name;
1551 } else
1552 continue;
1553 bitset &= ~(flag->set | flag->clear);
1554 bitclear &= ~(flag->set | flag->clear);
1555 if (dp > string)
1556 *dp++ = ',';
1557 while ((*dp++ = *sp++) != '\0')
1558 ;
1559 dp--;
1560 }
1561
1562 *dp = '\0';
1563 return (string);
1564 }
1565
1566 /*
1567 * strtofflags --
1568 * Take string of arguments and return file flags. This
1569 * version works a little differently than strtofflags(3).
1570 * In particular, it always tests every token, skipping any
1571 * unrecognized tokens. It returns a pointer to the first
1572 * unrecognized token, or NULL if every token was recognized.
1573 * This version is also const-correct and does not modify the
1574 * provided string.
1575 */
1576 static const char *
ae_strtofflags(const char * s,unsigned long * setp,unsigned long * clrp)1577 ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
1578 {
1579 const char *start, *end;
1580 struct flag *flag;
1581 unsigned long set, clear;
1582 const char *failed;
1583
1584 set = clear = 0;
1585 start = s;
1586 failed = NULL;
1587 /* Find start of first token. */
1588 while (*start == '\t' || *start == ' ' || *start == ',')
1589 start++;
1590 while (*start != '\0') {
1591 /* Locate end of token. */
1592 end = start;
1593 while (*end != '\0' && *end != '\t' &&
1594 *end != ' ' && *end != ',')
1595 end++;
1596 for (flag = flags; flag->name != NULL; flag++) {
1597 if (memcmp(start, flag->name, end - start) == 0) {
1598 /* Matched "noXXXX", so reverse the sense. */
1599 clear |= flag->set;
1600 set |= flag->clear;
1601 break;
1602 } else if (memcmp(start, flag->name + 2, end - start)
1603 == 0) {
1604 /* Matched "XXXX", so don't reverse. */
1605 set |= flag->set;
1606 clear |= flag->clear;
1607 break;
1608 }
1609 }
1610 /* Ignore unknown flag names. */
1611 if (flag->name == NULL && failed == NULL)
1612 failed = start;
1613
1614 /* Find start of next token. */
1615 start = end;
1616 while (*start == '\t' || *start == ' ' || *start == ',')
1617 start++;
1618
1619 }
1620
1621 if (setp)
1622 *setp = set;
1623 if (clrp)
1624 *clrp = clear;
1625
1626 /* Return location of first failure. */
1627 return (failed);
1628 }
1629
1630 /*
1631 * wcstofflags --
1632 * Take string of arguments and return file flags. This
1633 * version works a little differently than strtofflags(3).
1634 * In particular, it always tests every token, skipping any
1635 * unrecognized tokens. It returns a pointer to the first
1636 * unrecognized token, or NULL if every token was recognized.
1637 * This version is also const-correct and does not modify the
1638 * provided string.
1639 */
1640 static const wchar_t *
ae_wcstofflags(const wchar_t * s,unsigned long * setp,unsigned long * clrp)1641 ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
1642 {
1643 const wchar_t *start, *end;
1644 struct flag *flag;
1645 unsigned long set, clear;
1646 const wchar_t *failed;
1647
1648 set = clear = 0;
1649 start = s;
1650 failed = NULL;
1651 /* Find start of first token. */
1652 while (*start == L'\t' || *start == L' ' || *start == L',')
1653 start++;
1654 while (*start != L'\0') {
1655 /* Locate end of token. */
1656 end = start;
1657 while (*end != L'\0' && *end != L'\t' &&
1658 *end != L' ' && *end != L',')
1659 end++;
1660 for (flag = flags; flag->wname != NULL; flag++) {
1661 if (wmemcmp(start, flag->wname, end - start) == 0) {
1662 /* Matched "noXXXX", so reverse the sense. */
1663 clear |= flag->set;
1664 set |= flag->clear;
1665 break;
1666 } else if (wmemcmp(start, flag->wname + 2, end - start)
1667 == 0) {
1668 /* Matched "XXXX", so don't reverse. */
1669 set |= flag->set;
1670 clear |= flag->clear;
1671 break;
1672 }
1673 }
1674 /* Ignore unknown flag names. */
1675 if (flag->wname == NULL && failed == NULL)
1676 failed = start;
1677
1678 /* Find start of next token. */
1679 start = end;
1680 while (*start == L'\t' || *start == L' ' || *start == L',')
1681 start++;
1682
1683 }
1684
1685 if (setp)
1686 *setp = set;
1687 if (clrp)
1688 *clrp = clear;
1689
1690 /* Return location of first failure. */
1691 return (failed);
1692 }
1693
1694
1695 #ifdef TEST
1696 #include <stdio.h>
1697 int
main(int argc,char ** argv)1698 main(int argc, char **argv)
1699 {
1700 struct archive_entry *entry = archive_entry_new();
1701 unsigned long set, clear;
1702 const wchar_t *remainder;
1703
1704 remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
1705 archive_entry_fflags(entry, &set, &clear);
1706
1707 wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
1708
1709 wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
1710 return (0);
1711 }
1712 #endif
1713