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