Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibarchive/libarchive/archive_entry.c
5021 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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
__LA_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
entry->stat_valid = 0;
988
entry->ae_set &= ~AE_SET_INO;
989
return;
990
}
991
entry->stat_valid = 0;
992
entry->ae_set |= AE_SET_INO;
993
entry->ae_stat.aest_ino = ino;
994
}
995
996
void
997
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
998
{
999
if (ino < 0) {
1000
entry->stat_valid = 0;
1001
entry->ae_set &= ~AE_SET_INO;
1002
return;
1003
}
1004
entry->stat_valid = 0;
1005
entry->ae_set |= AE_SET_INO;
1006
entry->ae_stat.aest_ino = ino;
1007
}
1008
1009
void
1010
archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
1011
{
1012
if (target == NULL) {
1013
entry->ae_set &= ~AE_SET_HARDLINK;
1014
if (entry->ae_set & AE_SET_SYMLINK) {
1015
return;
1016
}
1017
} else {
1018
entry->ae_set |= AE_SET_HARDLINK;
1019
}
1020
entry->ae_set &= ~AE_SET_SYMLINK;
1021
archive_mstring_copy_mbs(&entry->ae_linkname, target);
1022
}
1023
1024
void
1025
archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
1026
{
1027
if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1028
return;
1029
archive_mstring_copy_utf8(&entry->ae_linkname, target);
1030
if (target != NULL)
1031
entry->ae_set |= AE_SET_HARDLINK;
1032
else
1033
entry->ae_set &= ~AE_SET_HARDLINK;
1034
}
1035
1036
void
1037
archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
1038
{
1039
if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1040
return;
1041
archive_mstring_copy_mbs(&entry->ae_linkname, target);
1042
if (target != NULL)
1043
entry->ae_set |= AE_SET_HARDLINK;
1044
else
1045
entry->ae_set &= ~AE_SET_HARDLINK;
1046
}
1047
1048
void
1049
archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
1050
{
1051
if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1052
return;
1053
archive_mstring_copy_wcs(&entry->ae_linkname, target);
1054
if (target != NULL)
1055
entry->ae_set |= AE_SET_HARDLINK;
1056
else
1057
entry->ae_set &= ~AE_SET_HARDLINK;
1058
}
1059
1060
int
1061
archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
1062
{
1063
if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1064
return (0);
1065
if (target != NULL)
1066
entry->ae_set |= AE_SET_HARDLINK;
1067
else
1068
entry->ae_set &= ~AE_SET_HARDLINK;
1069
if (archive_mstring_update_utf8(entry->archive,
1070
&entry->ae_linkname, target) == 0)
1071
return (1);
1072
if (errno == ENOMEM)
1073
__archive_errx(1, "No memory");
1074
return (0);
1075
}
1076
1077
int
1078
_archive_entry_copy_hardlink_l(struct archive_entry *entry,
1079
const char *target, size_t len, struct archive_string_conv *sc)
1080
{
1081
int r;
1082
1083
if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1084
return (0);
1085
r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1086
target, len, sc);
1087
if (target != NULL && r == 0)
1088
entry->ae_set |= AE_SET_HARDLINK;
1089
else
1090
entry->ae_set &= ~AE_SET_HARDLINK;
1091
return (r);
1092
}
1093
1094
void
1095
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1096
{
1097
FIX_NS(t, ns);
1098
entry->stat_valid = 0;
1099
entry->ae_set |= AE_SET_ATIME;
1100
entry->ae_stat.aest_atime = t;
1101
entry->ae_stat.aest_atime_nsec = ns;
1102
}
1103
1104
void
1105
archive_entry_unset_atime(struct archive_entry *entry)
1106
{
1107
archive_entry_set_atime(entry, 0, 0);
1108
entry->ae_set &= ~AE_SET_ATIME;
1109
}
1110
1111
void
1112
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1113
{
1114
FIX_NS(t, ns);
1115
entry->stat_valid = 0;
1116
entry->ae_set |= AE_SET_BIRTHTIME;
1117
entry->ae_stat.aest_birthtime = t;
1118
entry->ae_stat.aest_birthtime_nsec = ns;
1119
}
1120
1121
void
1122
archive_entry_unset_birthtime(struct archive_entry *entry)
1123
{
1124
archive_entry_set_birthtime(entry, 0, 0);
1125
entry->ae_set &= ~AE_SET_BIRTHTIME;
1126
}
1127
1128
void
1129
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1130
{
1131
FIX_NS(t, ns);
1132
entry->stat_valid = 0;
1133
entry->ae_set |= AE_SET_CTIME;
1134
entry->ae_stat.aest_ctime = t;
1135
entry->ae_stat.aest_ctime_nsec = ns;
1136
}
1137
1138
void
1139
archive_entry_unset_ctime(struct archive_entry *entry)
1140
{
1141
archive_entry_set_ctime(entry, 0, 0);
1142
entry->ae_set &= ~AE_SET_CTIME;
1143
}
1144
1145
void
1146
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
1147
{
1148
entry->stat_valid = 0;
1149
entry->ae_set |= AE_SET_DEV;
1150
entry->ae_stat.aest_dev_is_broken_down = 0;
1151
entry->ae_stat.aest_dev = d;
1152
}
1153
1154
void
1155
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
1156
{
1157
entry->stat_valid = 0;
1158
entry->ae_set |= AE_SET_DEV;
1159
entry->ae_stat.aest_dev_is_broken_down = 1;
1160
entry->ae_stat.aest_devmajor = m;
1161
}
1162
1163
void
1164
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
1165
{
1166
entry->stat_valid = 0;
1167
entry->ae_set |= AE_SET_DEV;
1168
entry->ae_stat.aest_dev_is_broken_down = 1;
1169
entry->ae_stat.aest_devminor = m;
1170
}
1171
1172
/* Set symlink if symlink is already set, else set hardlink. */
1173
void
1174
archive_entry_set_link(struct archive_entry *entry, const char *target)
1175
{
1176
archive_mstring_copy_mbs(&entry->ae_linkname, target);
1177
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1178
entry->ae_set |= AE_SET_HARDLINK;
1179
}
1180
}
1181
1182
void
1183
archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
1184
{
1185
archive_mstring_copy_utf8(&entry->ae_linkname, target);
1186
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1187
entry->ae_set |= AE_SET_HARDLINK;
1188
}
1189
}
1190
1191
/* Set symlink if symlink is already set, else set hardlink. */
1192
void
1193
archive_entry_copy_link(struct archive_entry *entry, const char *target)
1194
{
1195
archive_mstring_copy_mbs(&entry->ae_linkname, target);
1196
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1197
entry->ae_set |= AE_SET_HARDLINK;
1198
}
1199
}
1200
1201
/* Set symlink if symlink is already set, else set hardlink. */
1202
void
1203
archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
1204
{
1205
archive_mstring_copy_wcs(&entry->ae_linkname, target);
1206
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1207
entry->ae_set |= AE_SET_HARDLINK;
1208
}
1209
}
1210
1211
int
1212
archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
1213
{
1214
int r;
1215
r = archive_mstring_update_utf8(entry->archive,
1216
&entry->ae_linkname, target);
1217
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1218
entry->ae_set |= AE_SET_HARDLINK;
1219
}
1220
if (r == 0)
1221
return (1);
1222
if (errno == ENOMEM)
1223
__archive_errx(1, "No memory");
1224
return (0);
1225
}
1226
1227
int
1228
_archive_entry_copy_link_l(struct archive_entry *entry,
1229
const char *target, size_t len, struct archive_string_conv *sc)
1230
{
1231
int r;
1232
1233
r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1234
target, len, sc);
1235
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1236
entry->ae_set |= AE_SET_HARDLINK;
1237
}
1238
return (r);
1239
}
1240
1241
void
1242
archive_entry_set_mode(struct archive_entry *entry, mode_t m)
1243
{
1244
entry->stat_valid = 0;
1245
entry->acl.mode = m;
1246
entry->ae_set |= AE_SET_PERM | AE_SET_FILETYPE;
1247
}
1248
1249
void
1250
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1251
{
1252
FIX_NS(t, ns);
1253
entry->stat_valid = 0;
1254
entry->ae_set |= AE_SET_MTIME;
1255
entry->ae_stat.aest_mtime = t;
1256
entry->ae_stat.aest_mtime_nsec = ns;
1257
}
1258
1259
void
1260
archive_entry_unset_mtime(struct archive_entry *entry)
1261
{
1262
archive_entry_set_mtime(entry, 0, 0);
1263
entry->ae_set &= ~AE_SET_MTIME;
1264
}
1265
1266
void
1267
archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
1268
{
1269
entry->stat_valid = 0;
1270
entry->ae_stat.aest_nlink = nlink;
1271
}
1272
1273
void
1274
archive_entry_set_pathname(struct archive_entry *entry, const char *name)
1275
{
1276
archive_mstring_copy_mbs(&entry->ae_pathname, name);
1277
}
1278
1279
void
1280
archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
1281
{
1282
archive_mstring_copy_utf8(&entry->ae_pathname, name);
1283
}
1284
1285
void
1286
archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
1287
{
1288
archive_mstring_copy_mbs(&entry->ae_pathname, name);
1289
}
1290
1291
void
1292
archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
1293
{
1294
archive_mstring_copy_wcs(&entry->ae_pathname, name);
1295
}
1296
1297
int
1298
archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
1299
{
1300
if (archive_mstring_update_utf8(entry->archive,
1301
&entry->ae_pathname, name) == 0)
1302
return (1);
1303
if (errno == ENOMEM)
1304
__archive_errx(1, "No memory");
1305
return (0);
1306
}
1307
1308
int
1309
_archive_entry_copy_pathname_l(struct archive_entry *entry,
1310
const char *name, size_t len, struct archive_string_conv *sc)
1311
{
1312
return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
1313
name, len, sc));
1314
}
1315
1316
void
1317
archive_entry_set_perm(struct archive_entry *entry, mode_t p)
1318
{
1319
entry->stat_valid = 0;
1320
entry->acl.mode &= AE_IFMT;
1321
entry->acl.mode |= ~AE_IFMT & p;
1322
entry->ae_set |= AE_SET_PERM;
1323
}
1324
1325
void
1326
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
1327
{
1328
entry->stat_valid = 0;
1329
entry->ae_stat.aest_rdev = m;
1330
entry->ae_stat.aest_rdev_is_broken_down = 0;
1331
entry->ae_stat.aest_rdevmajor = 0;
1332
entry->ae_stat.aest_rdevminor = 0;
1333
entry->ae_set |= AE_SET_RDEV;
1334
}
1335
1336
void
1337
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
1338
{
1339
entry->stat_valid = 0;
1340
entry->ae_stat.aest_rdev_is_broken_down = 1;
1341
entry->ae_stat.aest_rdev = 0;
1342
entry->ae_stat.aest_rdevmajor = m;
1343
entry->ae_set |= AE_SET_RDEV;
1344
}
1345
1346
void
1347
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
1348
{
1349
entry->stat_valid = 0;
1350
entry->ae_stat.aest_rdev_is_broken_down = 1;
1351
entry->ae_stat.aest_rdev = 0;
1352
entry->ae_stat.aest_rdevminor = m;
1353
entry->ae_set |= AE_SET_RDEV;
1354
}
1355
1356
void
1357
archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
1358
{
1359
if (s < 0) {
1360
s = 0;
1361
}
1362
entry->stat_valid = 0;
1363
entry->ae_stat.aest_size = s;
1364
entry->ae_set |= AE_SET_SIZE;
1365
}
1366
1367
void
1368
archive_entry_unset_size(struct archive_entry *entry)
1369
{
1370
archive_entry_set_size(entry, 0);
1371
entry->ae_set &= ~AE_SET_SIZE;
1372
}
1373
1374
void
1375
archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
1376
{
1377
archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
1378
}
1379
1380
void
1381
archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
1382
{
1383
archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
1384
}
1385
1386
void
1387
archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
1388
{
1389
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1390
return;
1391
archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1392
entry->ae_set &= ~AE_SET_HARDLINK;
1393
if (linkname == NULL)
1394
entry->ae_set &= ~AE_SET_SYMLINK;
1395
else
1396
entry->ae_set |= AE_SET_SYMLINK;
1397
}
1398
1399
void
1400
archive_entry_set_symlink_type(struct archive_entry *entry, int type)
1401
{
1402
entry->ae_symlink_type = type;
1403
}
1404
1405
void
1406
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
1407
{
1408
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1409
return;
1410
archive_mstring_copy_utf8(&entry->ae_linkname, linkname);
1411
entry->ae_set &= ~AE_SET_HARDLINK;
1412
if (linkname == NULL)
1413
entry->ae_set &= ~AE_SET_SYMLINK;
1414
else
1415
entry->ae_set |= AE_SET_SYMLINK;
1416
}
1417
1418
void
1419
archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
1420
{
1421
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1422
return;
1423
archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1424
entry->ae_set &= ~AE_SET_HARDLINK;
1425
if (linkname == NULL)
1426
entry->ae_set &= ~AE_SET_SYMLINK;
1427
else
1428
entry->ae_set |= AE_SET_SYMLINK;
1429
}
1430
1431
void
1432
archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
1433
{
1434
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1435
return;
1436
archive_mstring_copy_wcs(&entry->ae_linkname, linkname);
1437
entry->ae_set &= ~AE_SET_HARDLINK;
1438
if (linkname == NULL)
1439
entry->ae_set &= ~AE_SET_SYMLINK;
1440
else
1441
entry->ae_set |= AE_SET_SYMLINK;
1442
}
1443
1444
int
1445
archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
1446
{
1447
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1448
return (0);
1449
entry->ae_set &= ~AE_SET_HARDLINK;
1450
if (linkname == NULL)
1451
entry->ae_set &= ~AE_SET_SYMLINK;
1452
else
1453
entry->ae_set |= AE_SET_SYMLINK;
1454
if (archive_mstring_update_utf8(entry->archive,
1455
&entry->ae_linkname, linkname) == 0)
1456
return (1);
1457
if (errno == ENOMEM)
1458
__archive_errx(1, "No memory");
1459
return (0);
1460
}
1461
1462
int
1463
_archive_entry_copy_symlink_l(struct archive_entry *entry,
1464
const char *linkname, size_t len, struct archive_string_conv *sc)
1465
{
1466
int r;
1467
1468
if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1469
return (0);
1470
entry->ae_set &= ~AE_SET_HARDLINK;
1471
r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1472
linkname, len, sc);
1473
if (linkname == NULL || r != 0)
1474
entry->ae_set &= ~AE_SET_SYMLINK;
1475
else
1476
entry->ae_set |= AE_SET_SYMLINK;
1477
return (r);
1478
}
1479
1480
void
1481
archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
1482
{
1483
if (u < 0) {
1484
u = 0;
1485
}
1486
entry->stat_valid = 0;
1487
entry->ae_stat.aest_uid = u;
1488
entry->ae_set |= AE_SET_UID;
1489
}
1490
1491
void
1492
archive_entry_set_uname(struct archive_entry *entry, const char *name)
1493
{
1494
archive_mstring_copy_mbs(&entry->ae_uname, name);
1495
}
1496
1497
void
1498
archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
1499
{
1500
archive_mstring_copy_utf8(&entry->ae_uname, name);
1501
}
1502
1503
void
1504
archive_entry_copy_uname(struct archive_entry *entry, const char *name)
1505
{
1506
archive_mstring_copy_mbs(&entry->ae_uname, name);
1507
}
1508
1509
void
1510
archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
1511
{
1512
archive_mstring_copy_wcs(&entry->ae_uname, name);
1513
}
1514
1515
int
1516
archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
1517
{
1518
if (archive_mstring_update_utf8(entry->archive,
1519
&entry->ae_uname, name) == 0)
1520
return (1);
1521
if (errno == ENOMEM)
1522
__archive_errx(1, "No memory");
1523
return (0);
1524
}
1525
1526
void
1527
archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
1528
{
1529
if (is_encrypted) {
1530
entry->encryption |= AE_ENCRYPTION_DATA;
1531
} else {
1532
entry->encryption &= ~AE_ENCRYPTION_DATA;
1533
}
1534
}
1535
1536
void
1537
archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
1538
{
1539
if (is_encrypted) {
1540
entry->encryption |= AE_ENCRYPTION_METADATA;
1541
} else {
1542
entry->encryption &= ~AE_ENCRYPTION_METADATA;
1543
}
1544
}
1545
1546
int
1547
_archive_entry_copy_uname_l(struct archive_entry *entry,
1548
const char *name, size_t len, struct archive_string_conv *sc)
1549
{
1550
return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
1551
name, len, sc));
1552
}
1553
1554
const void *
1555
archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
1556
{
1557
*s = entry->mac_metadata_size;
1558
return entry->mac_metadata;
1559
}
1560
1561
void
1562
archive_entry_copy_mac_metadata(struct archive_entry *entry,
1563
const void *p, size_t s)
1564
{
1565
free(entry->mac_metadata);
1566
if (p == NULL || s == 0) {
1567
entry->mac_metadata = NULL;
1568
entry->mac_metadata_size = 0;
1569
} else {
1570
entry->mac_metadata_size = s;
1571
entry->mac_metadata = malloc(s);
1572
if (entry->mac_metadata == NULL)
1573
abort();
1574
memcpy(entry->mac_metadata, p, s);
1575
}
1576
}
1577
1578
/* Digest handling */
1579
const unsigned char *
1580
archive_entry_digest(struct archive_entry *entry, int type)
1581
{
1582
switch (type) {
1583
case ARCHIVE_ENTRY_DIGEST_MD5:
1584
return entry->digest.md5;
1585
case ARCHIVE_ENTRY_DIGEST_RMD160:
1586
return entry->digest.rmd160;
1587
case ARCHIVE_ENTRY_DIGEST_SHA1:
1588
return entry->digest.sha1;
1589
case ARCHIVE_ENTRY_DIGEST_SHA256:
1590
return entry->digest.sha256;
1591
case ARCHIVE_ENTRY_DIGEST_SHA384:
1592
return entry->digest.sha384;
1593
case ARCHIVE_ENTRY_DIGEST_SHA512:
1594
return entry->digest.sha512;
1595
default:
1596
return NULL;
1597
}
1598
}
1599
1600
int
1601
archive_entry_set_digest(struct archive_entry *entry, int type,
1602
const unsigned char *digest)
1603
{
1604
#define copy_digest(_e, _t, _d)\
1605
memcpy(_e->digest._t, _d, sizeof(_e->digest._t))
1606
1607
switch (type) {
1608
case ARCHIVE_ENTRY_DIGEST_MD5:
1609
copy_digest(entry, md5, digest);
1610
entry->mset_digest |= AE_MSET_DIGEST_MD5;
1611
break;
1612
case ARCHIVE_ENTRY_DIGEST_RMD160:
1613
copy_digest(entry, rmd160, digest);
1614
entry->mset_digest |= AE_MSET_DIGEST_RMD160;
1615
break;
1616
case ARCHIVE_ENTRY_DIGEST_SHA1:
1617
copy_digest(entry, sha1, digest);
1618
entry->mset_digest |= AE_MSET_DIGEST_SHA1;
1619
break;
1620
case ARCHIVE_ENTRY_DIGEST_SHA256:
1621
copy_digest(entry, sha256, digest);
1622
entry->mset_digest |= AE_MSET_DIGEST_SHA256;
1623
break;
1624
case ARCHIVE_ENTRY_DIGEST_SHA384:
1625
copy_digest(entry, sha384, digest);
1626
entry->mset_digest |= AE_MSET_DIGEST_SHA384;
1627
break;
1628
case ARCHIVE_ENTRY_DIGEST_SHA512:
1629
copy_digest(entry, sha512, digest);
1630
entry->mset_digest |= AE_MSET_DIGEST_SHA512;
1631
break;
1632
default:
1633
return ARCHIVE_WARN;
1634
}
1635
1636
return ARCHIVE_OK;
1637
#undef copy_digest
1638
}
1639
1640
/*
1641
* ACL management. The following would, of course, be a lot simpler
1642
* if: 1) the last draft of POSIX.1e were a really thorough and
1643
* complete standard that addressed the needs of ACL archiving and 2)
1644
* everyone followed it faithfully. Alas, neither is true, so the
1645
* following is a lot more complex than might seem necessary to the
1646
* uninitiated.
1647
*/
1648
1649
struct archive_acl *
1650
archive_entry_acl(struct archive_entry *entry)
1651
{
1652
return &entry->acl;
1653
}
1654
1655
void
1656
archive_entry_acl_clear(struct archive_entry *entry)
1657
{
1658
archive_acl_clear(&entry->acl);
1659
}
1660
1661
/*
1662
* Add a single ACL entry to the internal list of ACL data.
1663
*/
1664
int
1665
archive_entry_acl_add_entry(struct archive_entry *entry,
1666
int type, int permset, int tag, int id, const char *name)
1667
{
1668
return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
1669
}
1670
1671
/*
1672
* As above, but with a wide-character name.
1673
*/
1674
int
1675
archive_entry_acl_add_entry_w(struct archive_entry *entry,
1676
int type, int permset, int tag, int id, const wchar_t *name)
1677
{
1678
return archive_acl_add_entry_w_len(&entry->acl,
1679
type, permset, tag, id, name, wcslen(name));
1680
}
1681
1682
/*
1683
* Return a bitmask of ACL types in an archive entry ACL list
1684
*/
1685
int
1686
archive_entry_acl_types(struct archive_entry *entry)
1687
{
1688
return (archive_acl_types(&entry->acl));
1689
}
1690
1691
/*
1692
* Return a count of entries matching "want_type".
1693
*/
1694
int
1695
archive_entry_acl_count(struct archive_entry *entry, int want_type)
1696
{
1697
return archive_acl_count(&entry->acl, want_type);
1698
}
1699
1700
/*
1701
* Prepare for reading entries from the ACL data. Returns a count
1702
* of entries matching "want_type", or zero if there are no
1703
* non-extended ACL entries of that type.
1704
*/
1705
int
1706
archive_entry_acl_reset(struct archive_entry *entry, int want_type)
1707
{
1708
return archive_acl_reset(&entry->acl, want_type);
1709
}
1710
1711
/*
1712
* Return the next ACL entry in the list. Fake entries for the
1713
* standard permissions and include them in the returned list.
1714
*/
1715
int
1716
archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
1717
int *permset, int *tag, int *id, const char **name)
1718
{
1719
int r;
1720
r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
1721
permset, tag, id, name);
1722
if (r == ARCHIVE_FATAL && errno == ENOMEM)
1723
__archive_errx(1, "No memory");
1724
return (r);
1725
}
1726
1727
/*
1728
* Generate a text version of the ACL. The flags parameter controls
1729
* the style of the generated ACL.
1730
*/
1731
wchar_t *
1732
archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
1733
int flags)
1734
{
1735
return (archive_acl_to_text_w(&entry->acl, len, flags,
1736
entry->archive));
1737
}
1738
1739
char *
1740
archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
1741
int flags)
1742
{
1743
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
1744
}
1745
1746
char *
1747
_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
1748
int flags, struct archive_string_conv *sc)
1749
{
1750
return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
1751
}
1752
1753
/*
1754
* ACL text parser.
1755
*/
1756
int
1757
archive_entry_acl_from_text_w(struct archive_entry *entry,
1758
const wchar_t *wtext, int type)
1759
{
1760
return (archive_acl_from_text_w(&entry->acl, wtext, type));
1761
}
1762
1763
int
1764
archive_entry_acl_from_text(struct archive_entry *entry,
1765
const char *text, int type)
1766
{
1767
return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
1768
}
1769
1770
int
1771
_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
1772
int type, struct archive_string_conv *sc)
1773
{
1774
return (archive_acl_from_text_l(&entry->acl, text, type, sc));
1775
}
1776
1777
/* Deprecated */
1778
static int
1779
archive_entry_acl_text_compat(int *flags)
1780
{
1781
if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
1782
return (1);
1783
1784
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
1785
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
1786
*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
1787
1788
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
1789
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
1790
*flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
1791
1792
*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
1793
1794
return (0);
1795
}
1796
1797
/* Deprecated */
1798
const wchar_t *
1799
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1800
{
1801
free(entry->acl.acl_text_w);
1802
entry->acl.acl_text_w = NULL;
1803
if (archive_entry_acl_text_compat(&flags) == 0)
1804
entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
1805
NULL, flags, entry->archive);
1806
return (entry->acl.acl_text_w);
1807
}
1808
1809
/* Deprecated */
1810
const char *
1811
archive_entry_acl_text(struct archive_entry *entry, int flags)
1812
{
1813
free(entry->acl.acl_text);
1814
entry->acl.acl_text = NULL;
1815
if (archive_entry_acl_text_compat(&flags) == 0)
1816
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
1817
flags, NULL);
1818
1819
return (entry->acl.acl_text);
1820
}
1821
1822
/* Deprecated */
1823
int
1824
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
1825
const char **acl_text, size_t *len, struct archive_string_conv *sc)
1826
{
1827
free(entry->acl.acl_text);
1828
entry->acl.acl_text = NULL;
1829
1830
if (archive_entry_acl_text_compat(&flags) == 0)
1831
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
1832
(ssize_t *)len, flags, sc);
1833
1834
*acl_text = entry->acl.acl_text;
1835
1836
return (0);
1837
}
1838
1839
/*
1840
* Following code is modified from UC Berkeley sources, and
1841
* is subject to the following copyright notice.
1842
*/
1843
1844
/*-
1845
* Copyright (c) 1993
1846
* The Regents of the University of California. All rights reserved.
1847
*
1848
* Redistribution and use in source and binary forms, with or without
1849
* modification, are permitted provided that the following conditions
1850
* are met:
1851
* 1. Redistributions of source code must retain the above copyright
1852
* notice, this list of conditions and the following disclaimer.
1853
* 2. Redistributions in binary form must reproduce the above copyright
1854
* notice, this list of conditions and the following disclaimer in the
1855
* documentation and/or other materials provided with the distribution.
1856
* 4. Neither the name of the University nor the names of its contributors
1857
* may be used to endorse or promote products derived from this software
1858
* without specific prior written permission.
1859
*
1860
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1861
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1862
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1863
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1864
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1865
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1866
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1867
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1868
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1869
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1870
* SUCH DAMAGE.
1871
*/
1872
1873
/*
1874
* Supported file flags on FreeBSD and Mac OS:
1875
* sappnd,sappend SF_APPEND
1876
* arch,archived SF_ARCHIVED
1877
* schg,schange,simmutable SF_IMMUTABLE
1878
* sunlnk,sunlink SF_NOUNLINK (FreeBSD only)
1879
* uappnd,uappend UF_APPEND
1880
* compressed UF_COMPRESSED (Mac OS only)
1881
* hidden,uhidden UF_HIDDEN
1882
* uchg,uchange,uimmutable UF_IMMUTABLE
1883
* nodump UF_NODUMP
1884
* uunlnk,uunlink UF_NOUNLINK (FreeBSD only)
1885
* offline,uoffline UF_OFFLINE (FreeBSD only)
1886
* opaque UF_OPAQUE
1887
* rdonly,urdonly,readonly UF_READONLY (FreeBSD only)
1888
* reparse,ureparse UF_REPARSE (FreeBSD only)
1889
* sparse,usparse UF_SPARSE (FreeBSD only)
1890
* system,usystem UF_SYSTEM (FreeBSD only)
1891
*
1892
* See chflags(2) for more information
1893
*
1894
* Supported file attributes on Linux:
1895
* a append only FS_APPEND_FL sappnd
1896
* A no atime updates FS_NOATIME_FL atime
1897
* c compress FS_COMPR_FL compress
1898
* C no copy on write FS_NOCOW_FL cow
1899
* d no dump FS_NODUMP_FL dump
1900
* D synchronous directory updates FS_DIRSYNC_FL dirsync
1901
* i immutable FS_IMMUTABLE_FL schg
1902
* j data journalling FS_JOURNAL_DATA_FL journal
1903
* P project hierarchy FS_PROJINHERIT_FL projinherit
1904
* s secure deletion FS_SECRM_FL securedeletion
1905
* S synchronous updates FS_SYNC_FL sync
1906
* t no tail-merging FS_NOTAIL_FL tail
1907
* T top of directory hierarchy FS_TOPDIR_FL topdir
1908
* u undeletable FS_UNRM_FL undel
1909
*
1910
* See ioctl_iflags(2) for more information
1911
*
1912
* Equivalent file flags supported on FreeBSD / Mac OS and Linux:
1913
* SF_APPEND FS_APPEND_FL sappnd
1914
* SF_IMMUTABLE FS_IMMUTABLE_FL schg
1915
* UF_NODUMP FS_NODUMP_FL nodump
1916
*/
1917
1918
static const struct flag {
1919
const char *name;
1920
const wchar_t *wname;
1921
unsigned long set;
1922
unsigned long clear;
1923
} fileflags[] = {
1924
/* Preferred (shorter) names per flag first, all prefixed by "no" */
1925
#ifdef SF_APPEND
1926
{ "nosappnd", L"nosappnd", SF_APPEND, 0},
1927
{ "nosappend", L"nosappend", SF_APPEND, 0},
1928
#endif
1929
#if defined(FS_APPEND_FL) /* 'a' */
1930
{ "nosappnd", L"nosappnd", FS_APPEND_FL, 0},
1931
{ "nosappend", L"nosappend", FS_APPEND_FL, 0},
1932
#elif defined(EXT2_APPEND_FL) /* 'a' */
1933
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0},
1934
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0},
1935
#endif
1936
#ifdef SF_ARCHIVED
1937
{ "noarch", L"noarch", SF_ARCHIVED, 0},
1938
{ "noarchived", L"noarchived", SF_ARCHIVED, 0},
1939
#endif
1940
#ifdef SF_IMMUTABLE
1941
{ "noschg", L"noschg", SF_IMMUTABLE, 0},
1942
{ "noschange", L"noschange", SF_IMMUTABLE, 0},
1943
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0},
1944
#endif
1945
#if defined(FS_IMMUTABLE_FL) /* 'i' */
1946
{ "noschg", L"noschg", FS_IMMUTABLE_FL, 0},
1947
{ "noschange", L"noschange", FS_IMMUTABLE_FL, 0},
1948
{ "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0},
1949
#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
1950
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0},
1951
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0},
1952
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0},
1953
#endif
1954
#ifdef SF_NOUNLINK
1955
{ "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0},
1956
{ "nosunlink", L"nosunlink", SF_NOUNLINK, 0},
1957
#endif
1958
#ifdef UF_APPEND
1959
{ "nouappnd", L"nouappnd", UF_APPEND, 0},
1960
{ "nouappend", L"nouappend", UF_APPEND, 0},
1961
#endif
1962
#ifdef UF_IMMUTABLE
1963
{ "nouchg", L"nouchg", UF_IMMUTABLE, 0},
1964
{ "nouchange", L"nouchange", UF_IMMUTABLE, 0},
1965
{ "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0},
1966
#endif
1967
#ifdef UF_NODUMP
1968
{ "nodump", L"nodump", 0, UF_NODUMP},
1969
#endif
1970
#if defined(FS_NODUMP_FL) /* 'd' */
1971
{ "nodump", L"nodump", 0, FS_NODUMP_FL},
1972
#elif defined(EXT2_NODUMP_FL)
1973
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
1974
#endif
1975
#ifdef UF_OPAQUE
1976
{ "noopaque", L"noopaque", UF_OPAQUE, 0},
1977
#endif
1978
#ifdef UF_NOUNLINK
1979
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0},
1980
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0},
1981
#endif
1982
#ifdef UF_COMPRESSED
1983
/* Mac OS */
1984
{ "nocompressed", L"nocompressed", UF_COMPRESSED, 0},
1985
#endif
1986
#ifdef UF_HIDDEN
1987
{ "nohidden", L"nohidden", UF_HIDDEN, 0},
1988
{ "nouhidden", L"nouhidden", UF_HIDDEN, 0},
1989
#endif
1990
#ifdef FILE_ATTRIBUTE_HIDDEN
1991
{ "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0},
1992
{ "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0},
1993
#endif
1994
#ifdef UF_OFFLINE
1995
{ "nooffline", L"nooffline", UF_OFFLINE, 0},
1996
{ "nouoffline", L"nouoffline", UF_OFFLINE, 0},
1997
#endif
1998
#ifdef UF_READONLY
1999
{ "nordonly", L"nordonly", UF_READONLY, 0},
2000
{ "nourdonly", L"nourdonly", UF_READONLY, 0},
2001
{ "noreadonly", L"noreadonly", UF_READONLY, 0},
2002
#endif
2003
#ifdef FILE_ATTRIBUTE_READONLY
2004
{ "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0},
2005
{ "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0},
2006
{ "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0},
2007
#endif
2008
#ifdef UF_SPARSE
2009
{ "nosparse", L"nosparse", UF_SPARSE, 0},
2010
{ "nousparse", L"nousparse", UF_SPARSE, 0},
2011
#endif
2012
#ifdef UF_REPARSE
2013
{ "noreparse", L"noreparse", UF_REPARSE, 0},
2014
{ "noureparse", L"noureparse", UF_REPARSE, 0},
2015
#endif
2016
#ifdef UF_SYSTEM
2017
{ "nosystem", L"nosystem", UF_SYSTEM, 0},
2018
{ "nousystem", L"nousystem", UF_SYSTEM, 0},
2019
#endif
2020
#ifdef FILE_ATTRIBUTE_SYSTEM
2021
{ "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0},
2022
{ "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0},
2023
#endif
2024
#if defined(FS_UNRM_FL) /* 'u' */
2025
{ "noundel", L"noundel", FS_UNRM_FL, 0},
2026
#elif defined(EXT2_UNRM_FL)
2027
{ "noundel", L"noundel", EXT2_UNRM_FL, 0},
2028
#endif
2029
2030
#if defined(FS_COMPR_FL) /* 'c' */
2031
{ "nocompress", L"nocompress", FS_COMPR_FL, 0},
2032
#elif defined(EXT2_COMPR_FL)
2033
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0},
2034
#endif
2035
2036
#if defined(FS_NOATIME_FL) /* 'A' */
2037
{ "noatime", L"noatime", 0, FS_NOATIME_FL},
2038
#elif defined(EXT2_NOATIME_FL)
2039
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
2040
#endif
2041
#if defined(FS_DIRSYNC_FL) /* 'D' */
2042
{ "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
2043
#elif defined(EXT2_DIRSYNC_FL)
2044
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
2045
#endif
2046
#if defined(FS_JOURNAL_DATA_FL) /* 'j' */
2047
{ "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0},
2048
{ "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
2049
#elif defined(EXT3_JOURNAL_DATA_FL)
2050
{ "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0},
2051
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
2052
#endif
2053
#if defined(FS_SECRM_FL) /* 's' */
2054
{ "nosecdel", L"nosecdel", FS_SECRM_FL, 0},
2055
{ "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
2056
#elif defined(EXT2_SECRM_FL)
2057
{ "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0},
2058
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
2059
#endif
2060
#if defined(FS_SYNC_FL) /* 'S' */
2061
{ "nosync", L"nosync", FS_SYNC_FL, 0},
2062
#elif defined(EXT2_SYNC_FL)
2063
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
2064
#endif
2065
#if defined(FS_NOTAIL_FL) /* 't' */
2066
{ "notail", L"notail", 0, FS_NOTAIL_FL},
2067
#elif defined(EXT2_NOTAIL_FL)
2068
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
2069
#endif
2070
#if defined(FS_TOPDIR_FL) /* 'T' */
2071
{ "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
2072
#elif defined(EXT2_TOPDIR_FL)
2073
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
2074
#endif
2075
#ifdef FS_NOCOW_FL /* 'C' */
2076
{ "nocow", L"nocow", 0, FS_NOCOW_FL},
2077
#endif
2078
#ifdef FS_PROJINHERIT_FL /* 'P' */
2079
{ "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
2080
#endif
2081
{ NULL, NULL, 0, 0}
2082
};
2083
2084
/*
2085
* fflagstostr --
2086
* Convert file flags to a comma-separated string. If no flags
2087
* are set, return the empty string.
2088
*/
2089
static char *
2090
ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
2091
{
2092
char *string, *dp;
2093
const char *sp;
2094
unsigned long bits;
2095
const struct flag *flag;
2096
size_t length;
2097
2098
bits = bitset | bitclear;
2099
length = 0;
2100
for (flag = fileflags; flag->name != NULL; flag++)
2101
if (bits & (flag->set | flag->clear)) {
2102
length += strlen(flag->name) + 1;
2103
bits &= ~(flag->set | flag->clear);
2104
}
2105
2106
if (length == 0)
2107
return (NULL);
2108
string = malloc(length);
2109
if (string == NULL)
2110
return (NULL);
2111
2112
dp = string;
2113
for (flag = fileflags; flag->name != NULL; flag++) {
2114
if (bitset & flag->set || bitclear & flag->clear) {
2115
sp = flag->name + 2;
2116
} else if (bitset & flag->clear || bitclear & flag->set) {
2117
sp = flag->name;
2118
} else
2119
continue;
2120
bitset &= ~(flag->set | flag->clear);
2121
bitclear &= ~(flag->set | flag->clear);
2122
if (dp > string)
2123
*dp++ = ',';
2124
while ((*dp++ = *sp++) != '\0')
2125
;
2126
dp--;
2127
}
2128
2129
*dp = '\0';
2130
return (string);
2131
}
2132
2133
/*
2134
* strtofflags --
2135
* Take string of arguments and return file flags. This
2136
* version works a little differently than strtofflags(3).
2137
* In particular, it always tests every token, skipping any
2138
* unrecognized tokens. It returns a pointer to the first
2139
* unrecognized token, or NULL if every token was recognized.
2140
* This version is also const-correct and does not modify the
2141
* provided string.
2142
*/
2143
static const char *
2144
ae_strtofflags(const char *s, size_t l, unsigned long *setp, unsigned long *clrp)
2145
{
2146
const char *start, *end;
2147
const struct flag *flag;
2148
unsigned long set, clear;
2149
const char *failed;
2150
2151
set = clear = 0;
2152
start = s;
2153
failed = NULL;
2154
/* Find start of first token. */
2155
while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) {
2156
start++;
2157
l--;
2158
}
2159
while (l > 0) {
2160
size_t length;
2161
/* Locate end of token. */
2162
end = start;
2163
while (l > 0 && *end != '\t' &&
2164
*end != ' ' && *end != ',') {
2165
end++;
2166
l--;
2167
}
2168
length = end - start;
2169
for (flag = fileflags; flag->name != NULL; flag++) {
2170
size_t flag_length = strlen(flag->name);
2171
if (length == flag_length
2172
&& memcmp(start, flag->name, length) == 0) {
2173
/* Matched "noXXXX", so reverse the sense. */
2174
clear |= flag->set;
2175
set |= flag->clear;
2176
break;
2177
} else if (length == flag_length - 2
2178
&& memcmp(start, flag->name + 2, length) == 0) {
2179
/* Matched "XXXX", so don't reverse. */
2180
set |= flag->set;
2181
clear |= flag->clear;
2182
break;
2183
}
2184
}
2185
/* Ignore unknown flag names. */
2186
if (flag->name == NULL && failed == NULL)
2187
failed = start;
2188
2189
/* Find start of next token. */
2190
start = end;
2191
while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) {
2192
start++;
2193
l--;
2194
}
2195
2196
}
2197
2198
if (setp)
2199
*setp = set;
2200
if (clrp)
2201
*clrp = clear;
2202
2203
/* Return location of first failure. */
2204
return (failed);
2205
}
2206
2207
/*
2208
* wcstofflags --
2209
* Take string of arguments and return file flags. This
2210
* version works a little differently than strtofflags(3).
2211
* In particular, it always tests every token, skipping any
2212
* unrecognized tokens. It returns a pointer to the first
2213
* unrecognized token, or NULL if every token was recognized.
2214
* This version is also const-correct and does not modify the
2215
* provided string.
2216
*/
2217
static const wchar_t *
2218
ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
2219
{
2220
const wchar_t *start, *end;
2221
const struct flag *flag;
2222
unsigned long set, clear;
2223
const wchar_t *failed;
2224
2225
set = clear = 0;
2226
start = s;
2227
failed = NULL;
2228
/* Find start of first token. */
2229
while (*start == L'\t' || *start == L' ' || *start == L',')
2230
start++;
2231
while (*start != L'\0') {
2232
size_t length;
2233
/* Locate end of token. */
2234
end = start;
2235
while (*end != L'\0' && *end != L'\t' &&
2236
*end != L' ' && *end != L',')
2237
end++;
2238
length = end - start;
2239
for (flag = fileflags; flag->wname != NULL; flag++) {
2240
size_t flag_length = wcslen(flag->wname);
2241
if (length == flag_length
2242
&& wmemcmp(start, flag->wname, length) == 0) {
2243
/* Matched "noXXXX", so reverse the sense. */
2244
clear |= flag->set;
2245
set |= flag->clear;
2246
break;
2247
} else if (length == flag_length - 2
2248
&& wmemcmp(start, flag->wname + 2, length) == 0) {
2249
/* Matched "XXXX", so don't reverse. */
2250
set |= flag->set;
2251
clear |= flag->clear;
2252
break;
2253
}
2254
}
2255
/* Ignore unknown flag names. */
2256
if (flag->wname == NULL && failed == NULL)
2257
failed = start;
2258
2259
/* Find start of next token. */
2260
start = end;
2261
while (*start == L'\t' || *start == L' ' || *start == L',')
2262
start++;
2263
2264
}
2265
2266
if (setp)
2267
*setp = set;
2268
if (clrp)
2269
*clrp = clear;
2270
2271
/* Return location of first failure. */
2272
return (failed);
2273
}
2274
2275
2276
#ifdef TEST
2277
#include <stdio.h>
2278
int
2279
main(int argc, char **argv)
2280
{
2281
struct archive_entry *entry = archive_entry_new();
2282
unsigned long set, clear;
2283
const wchar_t *remainder;
2284
2285
remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
2286
archive_entry_fflags(entry, &set, &clear);
2287
2288
wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
2289
2290
wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
2291
return (0);
2292
}
2293
#endif
2294
2295