Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibarchive/libarchive/archive_entry.c
Line
Count
Source
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
0
#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
12.9k
  do { \
113
12.9k
    t += ns / 1000000000; \
114
12.9k
    ns %= 1000000000; \
115
12.9k
    if (ns < 0) { --t; ns += 1000000000; } \
116
12.9k
  } 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
73.9k
{
156
73.9k
  if (entry == NULL)
157
28.5k
    return (NULL);
158
45.4k
  archive_mstring_clean(&entry->ae_fflags_text);
159
45.4k
  archive_mstring_clean(&entry->ae_gname);
160
45.4k
  archive_mstring_clean(&entry->ae_linkname);
161
45.4k
  archive_mstring_clean(&entry->ae_pathname);
162
45.4k
  archive_mstring_clean(&entry->ae_sourcepath);
163
45.4k
  archive_mstring_clean(&entry->ae_uname);
164
45.4k
  archive_entry_copy_mac_metadata(entry, NULL, 0);
165
45.4k
  archive_acl_clear(&entry->acl);
166
45.4k
  archive_entry_xattr_clear(entry);
167
45.4k
  archive_entry_sparse_clear(entry);
168
45.4k
  free(entry->stat);
169
45.4k
  entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
170
45.4k
  memset(entry, 0, sizeof(*entry));
171
45.4k
  return entry;
172
73.9k
}
173
174
struct archive_entry *
175
archive_entry_clone(struct archive_entry *entry)
176
4.65k
{
177
4.65k
  struct archive_entry *entry2;
178
4.65k
  struct ae_xattr *xp;
179
4.65k
  struct ae_sparse *sp;
180
4.65k
  size_t s;
181
4.65k
  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
4.65k
  entry2 = archive_entry_new2(entry->archive);
187
4.65k
  if (entry2 == NULL)
188
0
    return (NULL);
189
4.65k
  entry2->ae_stat = entry->ae_stat;
190
4.65k
  entry2->ae_fflags_set = entry->ae_fflags_set;
191
4.65k
  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
4.65k
  archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
196
4.65k
  archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
197
4.65k
  archive_mstring_copy(&entry2->ae_linkname, &entry->ae_linkname);
198
4.65k
  archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
199
4.65k
  archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
200
4.65k
  entry2->ae_set = entry->ae_set;
201
4.65k
  archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
202
203
  /* Copy symlink type */
204
4.65k
  entry2->ae_symlink_type = entry->ae_symlink_type;
205
206
  /* Copy encryption status */
207
4.65k
  entry2->encryption = entry->encryption;
208
209
  /* Copy digests */
210
4.65k
#define copy_digest(_e2, _e, _t) \
211
27.9k
  memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t))
212
213
4.65k
  copy_digest(entry2, entry, md5);
214
4.65k
  copy_digest(entry2, entry, rmd160);
215
4.65k
  copy_digest(entry2, entry, sha1);
216
4.65k
  copy_digest(entry2, entry, sha256);
217
4.65k
  copy_digest(entry2, entry, sha384);
218
4.65k
  copy_digest(entry2, entry, sha512);
219
220
4.65k
#undef copy_digest
221
  
222
  /* Copy ACL data over. */
223
4.65k
  archive_acl_copy(&entry2->acl, &entry->acl);
224
225
  /* Copy Mac OS metadata. */
226
4.65k
  p = archive_entry_mac_metadata(entry, &s);
227
4.65k
  archive_entry_copy_mac_metadata(entry2, p, s);
228
229
  /* Copy xattr data over. */
230
4.65k
  xp = entry->xattr_head;
231
4.65k
  while (xp != NULL) {
232
0
    archive_entry_xattr_add_entry(entry2,
233
0
        xp->name, xp->value, xp->size);
234
0
    xp = xp->next;
235
0
  }
236
237
  /* Copy sparse data over. */
238
4.65k
  sp = entry->sparse_head;
239
4.65k
  while (sp != NULL) {
240
0
    archive_entry_sparse_add_entry(entry2,
241
0
        sp->offset, sp->length);
242
0
    sp = sp->next;
243
0
  }
244
245
4.65k
  return (entry2);
246
4.65k
}
247
248
void
249
archive_entry_free(struct archive_entry *entry)
250
62.2k
{
251
62.2k
  archive_entry_clear(entry);
252
62.2k
  free(entry);
253
62.2k
}
254
255
struct archive_entry *
256
archive_entry_new(void)
257
0
{
258
0
  return archive_entry_new2(NULL);
259
0
}
260
261
struct archive_entry *
262
archive_entry_new2(struct archive *a)
263
33.7k
{
264
33.7k
  struct archive_entry *entry;
265
266
33.7k
  entry = calloc(1, sizeof(*entry));
267
33.7k
  if (entry == NULL)
268
0
    return (NULL);
269
33.7k
  entry->archive = a;
270
33.7k
  entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
271
33.7k
  return (entry);
272
33.7k
}
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
1.63k
{
281
1.63k
  return (entry->ae_stat.aest_atime);
282
1.63k
}
283
284
long
285
archive_entry_atime_nsec(struct archive_entry *entry)
286
1.63k
{
287
1.63k
  return (entry->ae_stat.aest_atime_nsec);
288
1.63k
}
289
290
int
291
archive_entry_atime_is_set(struct archive_entry *entry)
292
3.95k
{
293
3.95k
  return (entry->ae_set & AE_SET_ATIME);
294
3.95k
}
295
296
__LA_TIME_T
297
archive_entry_birthtime(struct archive_entry *entry)
298
0
{
299
0
  return (entry->ae_stat.aest_birthtime);
300
0
}
301
302
long
303
archive_entry_birthtime_nsec(struct archive_entry *entry)
304
0
{
305
0
  return (entry->ae_stat.aest_birthtime_nsec);
306
0
}
307
308
int
309
archive_entry_birthtime_is_set(struct archive_entry *entry)
310
2.05k
{
311
2.05k
  return (entry->ae_set & AE_SET_BIRTHTIME);
312
2.05k
}
313
314
__LA_TIME_T
315
archive_entry_ctime(struct archive_entry *entry)
316
1.53k
{
317
1.53k
  return (entry->ae_stat.aest_ctime);
318
1.53k
}
319
320
int
321
archive_entry_ctime_is_set(struct archive_entry *entry)
322
1.90k
{
323
1.90k
  return (entry->ae_set & AE_SET_CTIME);
324
1.90k
}
325
326
long
327
archive_entry_ctime_nsec(struct archive_entry *entry)
328
1.53k
{
329
1.53k
  return (entry->ae_stat.aest_ctime_nsec);
330
1.53k
}
331
332
__LA_DEV_T
333
archive_entry_dev(struct archive_entry *entry)
334
458
{
335
458
  if (entry->ae_stat.aest_dev_is_broken_down)
336
0
    return ae_makedev(entry->ae_stat.aest_devmajor,
337
458
        entry->ae_stat.aest_devminor);
338
458
  else
339
458
    return (entry->ae_stat.aest_dev);
340
458
}
341
342
int
343
archive_entry_dev_is_set(struct archive_entry *entry)
344
0
{
345
0
  return (entry->ae_set & AE_SET_DEV);
346
0
}
347
348
__LA_DEV_T
349
archive_entry_devmajor(struct archive_entry *entry)
350
0
{
351
0
  if (entry->ae_stat.aest_dev_is_broken_down)
352
0
    return (entry->ae_stat.aest_devmajor);
353
0
  else
354
0
    return major(entry->ae_stat.aest_dev);
355
0
}
356
357
__LA_DEV_T
358
archive_entry_devminor(struct archive_entry *entry)
359
0
{
360
0
  if (entry->ae_stat.aest_dev_is_broken_down)
361
0
    return (entry->ae_stat.aest_devminor);
362
0
  else
363
0
    return minor(entry->ae_stat.aest_dev);
364
0
}
365
366
__LA_MODE_T
367
archive_entry_filetype(struct archive_entry *entry)
368
1.71k
{
369
1.71k
  return (AE_IFMT & entry->acl.mode);
370
1.71k
}
371
372
int
373
archive_entry_filetype_is_set(struct archive_entry *entry)
374
0
{
375
0
  return (entry->ae_set & AE_SET_FILETYPE);
376
0
}
377
378
void
379
archive_entry_fflags(struct archive_entry *entry,
380
    unsigned long *set, unsigned long *clear)
381
0
{
382
0
  *set = entry->ae_fflags_set;
383
0
  *clear = entry->ae_fflags_clear;
384
0
}
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
0
{
398
0
  const char *f;
399
0
  char *p;
400
401
0
  if (archive_mstring_get_mbs(entry->archive,
402
0
      &entry->ae_fflags_text, &f) == 0) {
403
0
    if (f != NULL)
404
0
      return (f);
405
0
  } else if (errno == ENOMEM)
406
0
    __archive_errx(1, "No memory");
407
408
0
  if (entry->ae_fflags_set == 0  &&  entry->ae_fflags_clear == 0)
409
0
    return (NULL);
410
411
0
  p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);
412
0
  if (p == NULL)
413
0
    return (NULL);
414
415
0
  archive_mstring_copy_mbs(&entry->ae_fflags_text, p);
416
0
  free(p);
417
0
  if (archive_mstring_get_mbs(entry->archive,
418
0
      &entry->ae_fflags_text, &f) == 0)
419
0
    return (f);
420
0
  if (errno == ENOMEM)
421
0
    __archive_errx(1, "No memory");
422
0
  return (NULL);
423
0
}
424
425
la_int64_t
426
archive_entry_gid(struct archive_entry *entry)
427
0
{
428
0
  return (entry->ae_stat.aest_gid);
429
0
}
430
431
int
432
archive_entry_gid_is_set(struct archive_entry *entry)
433
0
{
434
0
  return (entry->ae_set & AE_SET_GID);
435
0
}
436
437
const char *
438
archive_entry_gname(struct archive_entry *entry)
439
0
{
440
0
  const char *p;
441
0
  if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
442
0
    return (p);
443
0
  if (errno == ENOMEM)
444
0
    __archive_errx(1, "No memory");
445
0
  return (NULL);
446
0
}
447
448
const char *
449
archive_entry_gname_utf8(struct archive_entry *entry)
450
0
{
451
0
  const char *p;
452
0
  if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)
453
0
    return (p);
454
0
  if (errno == ENOMEM)
455
0
    __archive_errx(1, "No memory");
456
0
  return (NULL);
457
0
}
458
459
460
const wchar_t *
461
archive_entry_gname_w(struct archive_entry *entry)
462
0
{
463
0
  const wchar_t *p;
464
0
  if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
465
0
    return (p);
466
0
  if (errno == ENOMEM)
467
0
    __archive_errx(1, "No memory");
468
0
  return (NULL);
469
0
}
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
0
{
475
0
  return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc));
476
0
}
477
478
void
479
archive_entry_set_link_to_hardlink(struct archive_entry *entry)
480
0
{
481
0
  if ((entry->ae_set & AE_SET_SYMLINK) != 0) {
482
0
    entry->ae_set &= ~AE_SET_SYMLINK;
483
0
  }
484
0
  entry->ae_set |= AE_SET_HARDLINK;
485
0
}
486
487
const char *
488
archive_entry_hardlink(struct archive_entry *entry)
489
11.4k
{
490
11.4k
  const char *p;
491
11.4k
  if ((entry->ae_set & AE_SET_HARDLINK) == 0)
492
11.4k
    return (NULL);
493
57
  if (archive_mstring_get_mbs(
494
57
      entry->archive, &entry->ae_linkname, &p) == 0)
495
57
    return (p);
496
0
  if (errno == ENOMEM)
497
0
    __archive_errx(1, "No memory");
498
0
  return (NULL);
499
0
}
500
501
const char *
502
archive_entry_hardlink_utf8(struct archive_entry *entry)
503
0
{
504
0
  const char *p;
505
0
  if ((entry->ae_set & AE_SET_HARDLINK) == 0)
506
0
    return (NULL);
507
0
  if (archive_mstring_get_utf8(
508
0
      entry->archive, &entry->ae_linkname, &p) == 0)
509
0
    return (p);
510
0
  if (errno == ENOMEM)
511
0
    __archive_errx(1, "No memory");
512
0
  return (NULL);
513
0
}
514
515
const wchar_t *
516
archive_entry_hardlink_w(struct archive_entry *entry)
517
0
{
518
0
  const wchar_t *p;
519
0
  if ((entry->ae_set & AE_SET_HARDLINK) == 0)
520
0
    return (NULL);
521
0
  if (archive_mstring_get_wcs(
522
0
      entry->archive, &entry->ae_linkname, &p) == 0)
523
0
    return (p);
524
0
  if (errno == ENOMEM)
525
0
    __archive_errx(1, "No memory");
526
0
  return (NULL);
527
0
}
528
529
int
530
archive_entry_hardlink_is_set(struct archive_entry *entry)
531
0
{
532
0
  return (entry->ae_set & AE_SET_HARDLINK) != 0;
533
0
}
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
0
{
539
0
  if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
540
0
    *p = NULL;
541
0
    *len = 0;
542
0
    return (0);
543
0
  }
544
0
  return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc));
545
0
}
546
547
la_int64_t
548
archive_entry_ino(struct archive_entry *entry)
549
0
{
550
0
  return (entry->ae_stat.aest_ino);
551
0
}
552
553
int
554
archive_entry_ino_is_set(struct archive_entry *entry)
555
0
{
556
0
  return (entry->ae_set & AE_SET_INO);
557
0
}
558
559
la_int64_t
560
archive_entry_ino64(struct archive_entry *entry)
561
458
{
562
458
  return (entry->ae_stat.aest_ino);
563
458
}
564
565
__LA_MODE_T
566
archive_entry_mode(struct archive_entry *entry)
567
4.65k
{
568
4.65k
  return (entry->acl.mode);
569
4.65k
}
570
571
__LA_TIME_T
572
archive_entry_mtime(struct archive_entry *entry)
573
2.05k
{
574
2.05k
  return (entry->ae_stat.aest_mtime);
575
2.05k
}
576
577
long
578
archive_entry_mtime_nsec(struct archive_entry *entry)
579
2.05k
{
580
2.05k
  return (entry->ae_stat.aest_mtime_nsec);
581
2.05k
}
582
583
int
584
archive_entry_mtime_is_set(struct archive_entry *entry)
585
2.57k
{
586
2.57k
  return (entry->ae_set & AE_SET_MTIME);
587
2.57k
}
588
589
unsigned int
590
archive_entry_nlink(struct archive_entry *entry)
591
958
{
592
958
  return (entry->ae_stat.aest_nlink);
593
958
}
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
18.2k
{
605
18.2k
  const char *p;
606
18.2k
  if (archive_mstring_get_mbs(
607
18.2k
      entry->archive, &entry->ae_pathname, &p) == 0)
608
18.2k
    return (p);
609
#if HAVE_EILSEQ  /*{*/
610
0
    if (errno == EILSEQ) {
611
0
      if (archive_mstring_get_utf8(
612
0
          entry->archive, &entry->ae_pathname, &p) == 0)
613
0
        return (p);
614
0
    }
615
0
#endif  /*}*/
616
0
  if (errno == ENOMEM)
617
0
    __archive_errx(1, "No memory");
618
0
  return (NULL);
619
0
}
620
621
const char *
622
archive_entry_pathname_utf8(struct archive_entry *entry)
623
0
{
624
0
  const char *p;
625
0
  if (archive_mstring_get_utf8(
626
0
      entry->archive, &entry->ae_pathname, &p) == 0)
627
0
    return (p);
628
0
  if (errno == ENOMEM)
629
0
    __archive_errx(1, "No memory");
630
0
  return (NULL);
631
0
}
632
633
const wchar_t *
634
archive_entry_pathname_w(struct archive_entry *entry)
635
5.66k
{
636
5.66k
  const wchar_t *p;
637
5.66k
  if (archive_mstring_get_wcs(
638
5.66k
      entry->archive, &entry->ae_pathname, &p) == 0)
639
4.67k
    return (p);
640
994
  if (errno == ENOMEM)
641
0
    __archive_errx(1, "No memory");
642
994
  return (NULL);
643
994
}
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
0
{
649
0
  return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc));
650
0
}
651
652
__LA_MODE_T
653
archive_entry_perm(struct archive_entry *entry)
654
0
{
655
0
  return (~AE_IFMT & entry->acl.mode);
656
0
}
657
658
int
659
archive_entry_perm_is_set(struct archive_entry *entry)
660
0
{
661
0
  return (entry->ae_set & AE_SET_PERM);
662
0
}
663
664
int
665
archive_entry_rdev_is_set(struct archive_entry *entry)
666
73
{
667
73
  return (entry->ae_set & AE_SET_RDEV);
668
73
}
669
670
__LA_DEV_T
671
archive_entry_rdev(struct archive_entry *entry)
672
73
{
673
73
  if (archive_entry_rdev_is_set(entry)) {
674
73
    if (entry->ae_stat.aest_rdev_is_broken_down)
675
0
      return ae_makedev(entry->ae_stat.aest_rdevmajor,
676
73
          entry->ae_stat.aest_rdevminor);
677
73
    else
678
73
      return (entry->ae_stat.aest_rdev);
679
73
  } else {
680
0
    return 0;
681
0
  }
682
73
}
683
684
__LA_DEV_T
685
archive_entry_rdevmajor(struct archive_entry *entry)
686
0
{
687
0
  if (archive_entry_rdev_is_set(entry)) {
688
0
    if (entry->ae_stat.aest_rdev_is_broken_down)
689
0
      return (entry->ae_stat.aest_rdevmajor);
690
0
    else
691
0
      return major(entry->ae_stat.aest_rdev);
692
0
  } else {
693
0
    return 0;
694
0
  }
695
0
}
696
697
__LA_DEV_T
698
archive_entry_rdevminor(struct archive_entry *entry)
699
0
{
700
0
  if (archive_entry_rdev_is_set(entry)) {
701
0
    if (entry->ae_stat.aest_rdev_is_broken_down)
702
0
      return (entry->ae_stat.aest_rdevminor);
703
0
    else
704
0
      return minor(entry->ae_stat.aest_rdev);
705
0
  } else {
706
0
    return 0;
707
0
  }
708
0
}
709
710
la_int64_t
711
archive_entry_size(struct archive_entry *entry)
712
6.68k
{
713
6.68k
  return (entry->ae_stat.aest_size);
714
6.68k
}
715
716
int
717
archive_entry_size_is_set(struct archive_entry *entry)
718
4.65k
{
719
4.65k
  return (entry->ae_set & AE_SET_SIZE);
720
4.65k
}
721
722
const char *
723
archive_entry_sourcepath(struct archive_entry *entry)
724
0
{
725
0
  const char *p;
726
0
  if (archive_mstring_get_mbs(
727
0
      entry->archive, &entry->ae_sourcepath, &p) == 0)
728
0
    return (p);
729
0
  if (errno == ENOMEM)
730
0
    __archive_errx(1, "No memory");
731
0
  return (NULL);
732
0
}
733
734
const wchar_t *
735
archive_entry_sourcepath_w(struct archive_entry *entry)
736
0
{
737
0
  const wchar_t *p;
738
0
  if (archive_mstring_get_wcs(
739
0
      entry->archive, &entry->ae_sourcepath, &p) == 0)
740
0
    return (p);
741
0
  return (NULL);
742
0
}
743
744
const char *
745
archive_entry_symlink(struct archive_entry *entry)
746
7.16k
{
747
7.16k
  const char *p;
748
7.16k
  if ((entry->ae_set & AE_SET_SYMLINK) == 0)
749
7.14k
    return (NULL);
750
16
  if (archive_mstring_get_mbs(
751
16
      entry->archive, &entry->ae_linkname, &p) == 0)
752
16
    return (p);
753
0
  if (errno == ENOMEM)
754
0
    __archive_errx(1, "No memory");
755
0
  return (NULL);
756
0
}
757
758
void
759
archive_entry_set_link_to_symlink(struct archive_entry *entry)
760
0
{
761
0
  if ((entry->ae_set & AE_SET_HARDLINK) != 0) {
762
0
    entry->ae_set &= ~AE_SET_HARDLINK;
763
0
  }
764
0
  entry->ae_set |= AE_SET_SYMLINK;
765
0
}
766
767
int
768
archive_entry_symlink_type(struct archive_entry *entry)
769
0
{
770
0
  return (entry->ae_symlink_type);
771
0
}
772
773
const char *
774
archive_entry_symlink_utf8(struct archive_entry *entry)
775
0
{
776
0
  const char *p;
777
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0)
778
0
    return (NULL);
779
0
  if (archive_mstring_get_utf8(
780
0
      entry->archive, &entry->ae_linkname, &p) == 0)
781
0
    return (p);
782
0
  if (errno == ENOMEM)
783
0
    __archive_errx(1, "No memory");
784
0
  return (NULL);
785
0
}
786
787
const wchar_t *
788
archive_entry_symlink_w(struct archive_entry *entry)
789
22
{
790
22
  const wchar_t *p;
791
22
  if ((entry->ae_set & AE_SET_SYMLINK) == 0)
792
22
    return (NULL);
793
0
  if (archive_mstring_get_wcs(
794
0
      entry->archive, &entry->ae_linkname, &p) == 0)
795
0
    return (p);
796
0
  if (errno == ENOMEM)
797
0
    __archive_errx(1, "No memory");
798
0
  return (NULL);
799
0
}
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
0
{
805
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
806
0
    *p = NULL;
807
0
    *len = 0;
808
0
    return (0);
809
0
  }
810
0
  return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc));
811
0
}
812
813
la_int64_t
814
archive_entry_uid(struct archive_entry *entry)
815
0
{
816
0
  return (entry->ae_stat.aest_uid);
817
0
}
818
819
int
820
archive_entry_uid_is_set(struct archive_entry *entry)
821
0
{
822
0
  return (entry->ae_set & AE_SET_UID);
823
0
}
824
825
const char *
826
archive_entry_uname(struct archive_entry *entry)
827
0
{
828
0
  const char *p;
829
0
  if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
830
0
    return (p);
831
0
  if (errno == ENOMEM)
832
0
    __archive_errx(1, "No memory");
833
0
  return (NULL);
834
0
}
835
836
const char *
837
archive_entry_uname_utf8(struct archive_entry *entry)
838
0
{
839
0
  const char *p;
840
0
  if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)
841
0
    return (p);
842
0
  if (errno == ENOMEM)
843
0
    __archive_errx(1, "No memory");
844
0
  return (NULL);
845
0
}
846
847
const wchar_t *
848
archive_entry_uname_w(struct archive_entry *entry)
849
0
{
850
0
  const wchar_t *p;
851
0
  if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
852
0
    return (p);
853
0
  if (errno == ENOMEM)
854
0
    __archive_errx(1, "No memory");
855
0
  return (NULL);
856
0
}
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
0
{
862
0
  return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc));
863
0
}
864
865
int
866
archive_entry_is_data_encrypted(struct archive_entry *entry)
867
0
{
868
0
  return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
869
0
}
870
871
int
872
archive_entry_is_metadata_encrypted(struct archive_entry *entry)
873
0
{
874
0
  return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
875
0
}
876
877
int
878
archive_entry_is_encrypted(struct archive_entry *entry)
879
0
{
880
0
  return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
881
0
}
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
2.70k
{
890
2.70k
  entry->stat_valid = 0;
891
2.70k
  entry->acl.mode &= ~AE_IFMT;
892
2.70k
  entry->acl.mode |= AE_IFMT & type;
893
2.70k
  entry->ae_set |= AE_SET_FILETYPE;
894
2.70k
}
895
896
void
897
archive_entry_set_fflags(struct archive_entry *entry,
898
    unsigned long set, unsigned long clear)
899
0
{
900
0
  archive_mstring_clean(&entry->ae_fflags_text);
901
0
  entry->ae_fflags_set = set;
902
0
  entry->ae_fflags_clear = clear;
903
0
}
904
905
const char *
906
archive_entry_copy_fflags_text(struct archive_entry *entry,
907
  const char *flags)
908
0
{
909
0
  return archive_entry_copy_fflags_text_len(entry, flags, strlen(flags));
910
0
}
911
912
const char *
913
archive_entry_copy_fflags_text_len(struct archive_entry *entry,
914
    const char *flags, size_t flags_length)
915
0
{
916
0
  archive_mstring_copy_mbs_len(&entry->ae_fflags_text, flags, flags_length);
917
0
  return (ae_strtofflags(flags, flags_length,
918
0
        &entry->ae_fflags_set, &entry->ae_fflags_clear));
919
0
}
920
921
const wchar_t *
922
archive_entry_copy_fflags_text_w(struct archive_entry *entry,
923
    const wchar_t *flags)
924
0
{
925
0
  archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);
926
0
  return (ae_wcstofflags(flags,
927
0
        &entry->ae_fflags_set, &entry->ae_fflags_clear));
928
0
}
929
930
void
931
archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
932
5.00k
{
933
5.00k
  if (g < 0) {
934
0
    g = 0;
935
0
  }
936
5.00k
  entry->stat_valid = 0;
937
5.00k
  entry->ae_stat.aest_gid = g;
938
5.00k
  entry->ae_set |= AE_SET_GID;
939
5.00k
}
940
941
void
942
archive_entry_set_gname(struct archive_entry *entry, const char *name)
943
0
{
944
0
  archive_mstring_copy_mbs(&entry->ae_gname, name);
945
0
}
946
947
void
948
archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)
949
0
{
950
0
  archive_mstring_copy_utf8(&entry->ae_gname, name);
951
0
}
952
953
void
954
archive_entry_copy_gname(struct archive_entry *entry, const char *name)
955
0
{
956
0
  archive_mstring_copy_mbs(&entry->ae_gname, name);
957
0
}
958
959
void
960
archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
961
0
{
962
0
  archive_mstring_copy_wcs(&entry->ae_gname, name);
963
0
}
964
965
int
966
archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
967
0
{
968
0
  if (archive_mstring_update_utf8(entry->archive,
969
0
      &entry->ae_gname, name) == 0)
970
0
    return (1);
971
0
  if (errno == ENOMEM)
972
0
    __archive_errx(1, "No memory");
973
0
  return (0);
974
0
}
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
0
{
980
0
  return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
981
0
}
982
983
void
984
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
985
654
{
986
654
  if (ino < 0) {
987
0
    entry->stat_valid = 0;
988
0
    entry->ae_set &= ~AE_SET_INO;
989
0
    return;
990
0
  }
991
654
  entry->stat_valid = 0;
992
654
  entry->ae_set |= AE_SET_INO;
993
654
  entry->ae_stat.aest_ino = ino;
994
654
}
995
996
void
997
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
998
0
{
999
0
  if (ino < 0) {
1000
0
    entry->stat_valid = 0;
1001
0
    entry->ae_set &= ~AE_SET_INO;
1002
0
    return;
1003
0
  }
1004
0
  entry->stat_valid = 0;
1005
0
  entry->ae_set |= AE_SET_INO;
1006
0
  entry->ae_stat.aest_ino = ino;
1007
0
}
1008
1009
void
1010
archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
1011
0
{
1012
0
  if (target == NULL) {
1013
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1014
0
    if (entry->ae_set & AE_SET_SYMLINK) {
1015
0
      return;
1016
0
    }
1017
0
  } else {
1018
0
    entry->ae_set |= AE_SET_HARDLINK;
1019
0
  }
1020
0
  entry->ae_set &= ~AE_SET_SYMLINK;
1021
0
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1022
0
}
1023
1024
void
1025
archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
1026
0
{
1027
0
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1028
0
    return;
1029
0
  archive_mstring_copy_utf8(&entry->ae_linkname, target);
1030
0
  if (target != NULL)
1031
0
    entry->ae_set |= AE_SET_HARDLINK;
1032
0
  else
1033
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1034
0
}
1035
1036
void
1037
archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
1038
24
{
1039
24
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1040
0
    return;
1041
24
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1042
24
  if (target != NULL)
1043
24
    entry->ae_set |= AE_SET_HARDLINK;
1044
0
  else
1045
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1046
24
}
1047
1048
void
1049
archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
1050
0
{
1051
0
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1052
0
    return;
1053
0
  archive_mstring_copy_wcs(&entry->ae_linkname, target);
1054
0
  if (target != NULL)
1055
0
    entry->ae_set |= AE_SET_HARDLINK;
1056
0
  else
1057
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1058
0
}
1059
1060
int
1061
archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
1062
0
{
1063
0
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1064
0
    return (0);
1065
0
  if (target != NULL)
1066
0
    entry->ae_set |= AE_SET_HARDLINK;
1067
0
  else
1068
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1069
0
  if (archive_mstring_update_utf8(entry->archive,
1070
0
      &entry->ae_linkname, target) == 0)
1071
0
    return (1);
1072
0
  if (errno == ENOMEM)
1073
0
    __archive_errx(1, "No memory");
1074
0
  return (0);
1075
0
}
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
0
{
1081
0
  int r;
1082
1083
0
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1084
0
    return (0);
1085
0
  r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1086
0
      target, len, sc);
1087
0
  if (target != NULL && r == 0)
1088
0
    entry->ae_set |= AE_SET_HARDLINK;
1089
0
  else
1090
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1091
0
  return (r);
1092
0
}
1093
1094
void
1095
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1096
3.87k
{
1097
3.87k
  FIX_NS(t, ns);
1098
3.87k
  entry->stat_valid = 0;
1099
3.87k
  entry->ae_set |= AE_SET_ATIME;
1100
3.87k
  entry->ae_stat.aest_atime = t;
1101
3.87k
  entry->ae_stat.aest_atime_nsec = ns;
1102
3.87k
}
1103
1104
void
1105
archive_entry_unset_atime(struct archive_entry *entry)
1106
22
{
1107
22
  archive_entry_set_atime(entry, 0, 0);
1108
22
  entry->ae_set &= ~AE_SET_ATIME;
1109
22
}
1110
1111
void
1112
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1113
22
{
1114
22
  FIX_NS(t, ns);
1115
22
  entry->stat_valid = 0;
1116
22
  entry->ae_set |= AE_SET_BIRTHTIME;
1117
22
  entry->ae_stat.aest_birthtime = t;
1118
22
  entry->ae_stat.aest_birthtime_nsec = ns;
1119
22
}
1120
1121
void
1122
archive_entry_unset_birthtime(struct archive_entry *entry)
1123
22
{
1124
22
  archive_entry_set_birthtime(entry, 0, 0);
1125
22
  entry->ae_set &= ~AE_SET_BIRTHTIME;
1126
22
}
1127
1128
void
1129
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1130
3.87k
{
1131
3.87k
  FIX_NS(t, ns);
1132
3.87k
  entry->stat_valid = 0;
1133
3.87k
  entry->ae_set |= AE_SET_CTIME;
1134
3.87k
  entry->ae_stat.aest_ctime = t;
1135
3.87k
  entry->ae_stat.aest_ctime_nsec = ns;
1136
3.87k
}
1137
1138
void
1139
archive_entry_unset_ctime(struct archive_entry *entry)
1140
22
{
1141
22
  archive_entry_set_ctime(entry, 0, 0);
1142
22
  entry->ae_set &= ~AE_SET_CTIME;
1143
22
}
1144
1145
void
1146
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
1147
654
{
1148
654
  entry->stat_valid = 0;
1149
654
  entry->ae_set |= AE_SET_DEV;
1150
654
  entry->ae_stat.aest_dev_is_broken_down = 0;
1151
654
  entry->ae_stat.aest_dev = d;
1152
654
}
1153
1154
void
1155
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
1156
0
{
1157
0
  entry->stat_valid = 0;
1158
0
  entry->ae_set |= AE_SET_DEV;
1159
0
  entry->ae_stat.aest_dev_is_broken_down = 1;
1160
0
  entry->ae_stat.aest_devmajor = m;
1161
0
}
1162
1163
void
1164
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
1165
0
{
1166
0
  entry->stat_valid = 0;
1167
0
  entry->ae_set |= AE_SET_DEV;
1168
0
  entry->ae_stat.aest_dev_is_broken_down = 1;
1169
0
  entry->ae_stat.aest_devminor = m;
1170
0
}
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
0
{
1176
0
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1177
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1178
0
    entry->ae_set |= AE_SET_HARDLINK;
1179
0
  }
1180
0
}
1181
1182
void
1183
archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
1184
0
{
1185
0
  archive_mstring_copy_utf8(&entry->ae_linkname, target);
1186
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1187
0
    entry->ae_set |= AE_SET_HARDLINK;
1188
0
  }
1189
0
}
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
0
{
1195
0
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1196
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1197
0
    entry->ae_set |= AE_SET_HARDLINK;
1198
0
  }
1199
0
}
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
0
{
1205
0
  archive_mstring_copy_wcs(&entry->ae_linkname, target);
1206
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1207
0
    entry->ae_set |= AE_SET_HARDLINK;
1208
0
  }
1209
0
}
1210
1211
int
1212
archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
1213
0
{
1214
0
  int r;
1215
0
  r = archive_mstring_update_utf8(entry->archive,
1216
0
        &entry->ae_linkname, target);
1217
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1218
0
    entry->ae_set |= AE_SET_HARDLINK;
1219
0
  }
1220
0
  if (r == 0)
1221
0
    return (1);
1222
0
  if (errno == ENOMEM)
1223
0
    __archive_errx(1, "No memory");
1224
0
  return (0);
1225
0
}
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
0
{
1231
0
  int r;
1232
1233
0
  r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1234
0
        target, len, sc);
1235
0
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1236
0
    entry->ae_set |= AE_SET_HARDLINK;
1237
0
  }
1238
0
  return (r);
1239
0
}
1240
1241
void
1242
archive_entry_set_mode(struct archive_entry *entry, mode_t m)
1243
5.11k
{
1244
5.11k
  entry->stat_valid = 0;
1245
5.11k
  entry->acl.mode = m;
1246
5.11k
  entry->ae_set |= AE_SET_PERM | AE_SET_FILETYPE;
1247
5.11k
}
1248
1249
void
1250
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1251
5.18k
{
1252
5.18k
  FIX_NS(t, ns);
1253
5.18k
  entry->stat_valid = 0;
1254
5.18k
  entry->ae_set |= AE_SET_MTIME;
1255
5.18k
  entry->ae_stat.aest_mtime = t;
1256
5.18k
  entry->ae_stat.aest_mtime_nsec = ns;
1257
5.18k
}
1258
1259
void
1260
archive_entry_unset_mtime(struct archive_entry *entry)
1261
0
{
1262
0
  archive_entry_set_mtime(entry, 0, 0);
1263
0
  entry->ae_set &= ~AE_SET_MTIME;
1264
0
}
1265
1266
void
1267
archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
1268
622
{
1269
622
  entry->stat_valid = 0;
1270
622
  entry->ae_stat.aest_nlink = nlink;
1271
622
}
1272
1273
void
1274
archive_entry_set_pathname(struct archive_entry *entry, const char *name)
1275
0
{
1276
0
  archive_mstring_copy_mbs(&entry->ae_pathname, name);
1277
0
}
1278
1279
void
1280
archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
1281
0
{
1282
0
  archive_mstring_copy_utf8(&entry->ae_pathname, name);
1283
0
}
1284
1285
void
1286
archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
1287
2.63k
{
1288
2.63k
  archive_mstring_copy_mbs(&entry->ae_pathname, name);
1289
2.63k
}
1290
1291
void
1292
archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
1293
210
{
1294
210
  archive_mstring_copy_wcs(&entry->ae_pathname, name);
1295
210
}
1296
1297
int
1298
archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
1299
0
{
1300
0
  if (archive_mstring_update_utf8(entry->archive,
1301
0
      &entry->ae_pathname, name) == 0)
1302
0
    return (1);
1303
0
  if (errno == ENOMEM)
1304
0
    __archive_errx(1, "No memory");
1305
0
  return (0);
1306
0
}
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
5.41k
{
1312
5.41k
  return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
1313
5.41k
      name, len, sc));
1314
5.41k
}
1315
1316
void
1317
archive_entry_set_perm(struct archive_entry *entry, mode_t p)
1318
0
{
1319
0
  entry->stat_valid = 0;
1320
0
  entry->acl.mode &= AE_IFMT;
1321
0
  entry->acl.mode |= ~AE_IFMT & p;
1322
0
  entry->ae_set |= AE_SET_PERM;
1323
0
}
1324
1325
void
1326
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
1327
622
{
1328
622
  entry->stat_valid = 0;
1329
622
  entry->ae_stat.aest_rdev = m;
1330
622
  entry->ae_stat.aest_rdev_is_broken_down = 0;
1331
622
  entry->ae_stat.aest_rdevmajor = 0;
1332
622
  entry->ae_stat.aest_rdevminor = 0;
1333
622
  entry->ae_set |= AE_SET_RDEV;
1334
622
}
1335
1336
void
1337
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
1338
0
{
1339
0
  entry->stat_valid = 0;
1340
0
  entry->ae_stat.aest_rdev_is_broken_down = 1;
1341
0
  entry->ae_stat.aest_rdev = 0;
1342
0
  entry->ae_stat.aest_rdevmajor = m;
1343
0
  entry->ae_set |= AE_SET_RDEV;
1344
0
}
1345
1346
void
1347
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
1348
0
{
1349
0
  entry->stat_valid = 0;
1350
0
  entry->ae_stat.aest_rdev_is_broken_down = 1;
1351
0
  entry->ae_stat.aest_rdev = 0;
1352
0
  entry->ae_stat.aest_rdevminor = m;
1353
0
  entry->ae_set |= AE_SET_RDEV;
1354
0
}
1355
1356
void
1357
archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
1358
7.67k
{
1359
7.67k
  if (s < 0) {
1360
0
    s = 0;
1361
0
  }
1362
7.67k
  entry->stat_valid = 0;
1363
7.67k
  entry->ae_stat.aest_size = s;
1364
7.67k
  entry->ae_set |= AE_SET_SIZE;
1365
7.67k
}
1366
1367
void
1368
archive_entry_unset_size(struct archive_entry *entry)
1369
2
{
1370
2
  archive_entry_set_size(entry, 0);
1371
2
  entry->ae_set &= ~AE_SET_SIZE;
1372
2
}
1373
1374
void
1375
archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
1376
0
{
1377
0
  archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
1378
0
}
1379
1380
void
1381
archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
1382
0
{
1383
0
  archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
1384
0
}
1385
1386
void
1387
archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
1388
22
{
1389
22
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1390
0
    return;
1391
22
  archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1392
22
  entry->ae_set &= ~AE_SET_HARDLINK;
1393
22
  if (linkname == NULL)
1394
22
    entry->ae_set &= ~AE_SET_SYMLINK;
1395
0
  else
1396
0
    entry->ae_set |= AE_SET_SYMLINK;
1397
22
}
1398
1399
void
1400
archive_entry_set_symlink_type(struct archive_entry *entry, int type)
1401
0
{
1402
0
  entry->ae_symlink_type = type;
1403
0
}
1404
1405
void
1406
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
1407
0
{
1408
0
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1409
0
    return;
1410
0
  archive_mstring_copy_utf8(&entry->ae_linkname, linkname);
1411
0
  entry->ae_set &= ~AE_SET_HARDLINK;
1412
0
  if (linkname == NULL)
1413
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1414
0
  else
1415
0
    entry->ae_set |= AE_SET_SYMLINK;
1416
0
}
1417
1418
void
1419
archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
1420
0
{
1421
0
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1422
0
    return;
1423
0
  archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1424
0
  entry->ae_set &= ~AE_SET_HARDLINK;
1425
0
  if (linkname == NULL)
1426
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1427
0
  else
1428
0
    entry->ae_set |= AE_SET_SYMLINK;
1429
0
}
1430
1431
void
1432
archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
1433
0
{
1434
0
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1435
0
    return;
1436
0
  archive_mstring_copy_wcs(&entry->ae_linkname, linkname);
1437
0
  entry->ae_set &= ~AE_SET_HARDLINK;
1438
0
  if (linkname == NULL)
1439
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1440
0
  else
1441
0
    entry->ae_set |= AE_SET_SYMLINK;
1442
0
}
1443
1444
int
1445
archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
1446
0
{
1447
0
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1448
0
    return (0);
1449
0
  entry->ae_set &= ~AE_SET_HARDLINK;
1450
0
  if (linkname == NULL)
1451
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1452
0
  else
1453
0
    entry->ae_set |= AE_SET_SYMLINK;
1454
0
  if (archive_mstring_update_utf8(entry->archive,
1455
0
      &entry->ae_linkname, linkname) == 0)
1456
0
    return (1);
1457
0
  if (errno == ENOMEM)
1458
0
    __archive_errx(1, "No memory");
1459
0
  return (0);
1460
0
}
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
16
{
1466
16
  int r;
1467
1468
16
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1469
0
    return (0);
1470
16
  entry->ae_set &= ~AE_SET_HARDLINK;
1471
16
  r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1472
16
      linkname, len, sc);
1473
16
  if (linkname == NULL || r != 0)
1474
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1475
16
  else
1476
16
    entry->ae_set |= AE_SET_SYMLINK;
1477
16
  return (r);
1478
16
}
1479
1480
void
1481
archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
1482
4.99k
{
1483
4.99k
  if (u < 0) {
1484
0
    u = 0;
1485
0
  }
1486
4.99k
  entry->stat_valid = 0;
1487
4.99k
  entry->ae_stat.aest_uid = u;
1488
4.99k
  entry->ae_set |= AE_SET_UID;
1489
4.99k
}
1490
1491
void
1492
archive_entry_set_uname(struct archive_entry *entry, const char *name)
1493
0
{
1494
0
  archive_mstring_copy_mbs(&entry->ae_uname, name);
1495
0
}
1496
1497
void
1498
archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
1499
0
{
1500
0
  archive_mstring_copy_utf8(&entry->ae_uname, name);
1501
0
}
1502
1503
void
1504
archive_entry_copy_uname(struct archive_entry *entry, const char *name)
1505
0
{
1506
0
  archive_mstring_copy_mbs(&entry->ae_uname, name);
1507
0
}
1508
1509
void
1510
archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
1511
0
{
1512
0
  archive_mstring_copy_wcs(&entry->ae_uname, name);
1513
0
}
1514
1515
int
1516
archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
1517
0
{
1518
0
  if (archive_mstring_update_utf8(entry->archive,
1519
0
      &entry->ae_uname, name) == 0)
1520
0
    return (1);
1521
0
  if (errno == ENOMEM)
1522
0
    __archive_errx(1, "No memory");
1523
0
  return (0);
1524
0
}
1525
1526
void
1527
archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
1528
2.39k
{
1529
2.39k
  if (is_encrypted) {
1530
2.39k
    entry->encryption |= AE_ENCRYPTION_DATA;
1531
2.39k
  } else {
1532
0
    entry->encryption &= ~AE_ENCRYPTION_DATA;
1533
0
  }
1534
2.39k
}
1535
1536
void
1537
archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
1538
6
{
1539
6
  if (is_encrypted) {
1540
6
    entry->encryption |= AE_ENCRYPTION_METADATA;
1541
6
  } else {
1542
0
    entry->encryption &= ~AE_ENCRYPTION_METADATA;
1543
0
  }
1544
6
}
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
0
{
1550
0
  return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
1551
0
      name, len, sc));
1552
0
}
1553
1554
const void *
1555
archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
1556
4.65k
{
1557
4.65k
  *s = entry->mac_metadata_size;
1558
4.65k
  return entry->mac_metadata;
1559
4.65k
}
1560
1561
void
1562
archive_entry_copy_mac_metadata(struct archive_entry *entry,
1563
    const void *p, size_t s)
1564
50.0k
{
1565
50.0k
  free(entry->mac_metadata);
1566
50.0k
  if (p == NULL || s == 0) {
1567
50.0k
    entry->mac_metadata = NULL;
1568
50.0k
    entry->mac_metadata_size = 0;
1569
50.0k
  } else {
1570
0
    entry->mac_metadata_size = s;
1571
0
    entry->mac_metadata = malloc(s);
1572
0
    if (entry->mac_metadata == NULL)
1573
0
      abort();
1574
0
    memcpy(entry->mac_metadata, p, s);
1575
0
  }
1576
50.0k
}
1577
1578
/* Digest handling */
1579
const unsigned char *
1580
archive_entry_digest(struct archive_entry *entry, int type)
1581
0
{
1582
0
  switch (type) {
1583
0
  case ARCHIVE_ENTRY_DIGEST_MD5:
1584
0
    return entry->digest.md5;
1585
0
  case ARCHIVE_ENTRY_DIGEST_RMD160:
1586
0
    return entry->digest.rmd160;
1587
0
  case ARCHIVE_ENTRY_DIGEST_SHA1:
1588
0
    return entry->digest.sha1;
1589
0
  case ARCHIVE_ENTRY_DIGEST_SHA256:
1590
0
    return entry->digest.sha256;
1591
0
  case ARCHIVE_ENTRY_DIGEST_SHA384:
1592
0
    return entry->digest.sha384;
1593
0
  case ARCHIVE_ENTRY_DIGEST_SHA512:
1594
0
    return entry->digest.sha512;
1595
0
  default:
1596
0
    return NULL;
1597
0
  }
1598
0
}
1599
1600
int
1601
archive_entry_set_digest(struct archive_entry *entry, int type,
1602
    const unsigned char *digest)
1603
0
{
1604
0
#define copy_digest(_e, _t, _d)\
1605
0
  memcpy(_e->digest._t, _d, sizeof(_e->digest._t))
1606
1607
0
  switch (type) {
1608
0
  case ARCHIVE_ENTRY_DIGEST_MD5:
1609
0
    copy_digest(entry, md5, digest);
1610
0
    entry->mset_digest |= AE_MSET_DIGEST_MD5;
1611
0
    break;
1612
0
  case ARCHIVE_ENTRY_DIGEST_RMD160:
1613
0
    copy_digest(entry, rmd160, digest);
1614
0
    entry->mset_digest |= AE_MSET_DIGEST_RMD160;
1615
0
    break;
1616
0
  case ARCHIVE_ENTRY_DIGEST_SHA1:
1617
0
    copy_digest(entry, sha1, digest);
1618
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA1;
1619
0
    break;
1620
0
  case ARCHIVE_ENTRY_DIGEST_SHA256:
1621
0
    copy_digest(entry, sha256, digest);
1622
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA256;
1623
0
    break;
1624
0
  case ARCHIVE_ENTRY_DIGEST_SHA384:
1625
0
    copy_digest(entry, sha384, digest);
1626
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA384;
1627
0
    break;
1628
0
  case ARCHIVE_ENTRY_DIGEST_SHA512:
1629
0
    copy_digest(entry, sha512, digest);
1630
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA512;
1631
0
    break;
1632
0
  default:
1633
0
    return ARCHIVE_WARN;
1634
0
  }
1635
1636
0
  return ARCHIVE_OK;
1637
0
#undef copy_digest
1638
0
}
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
0
{
1652
0
  return &entry->acl;
1653
0
}
1654
1655
void
1656
archive_entry_acl_clear(struct archive_entry *entry)
1657
0
{
1658
0
  archive_acl_clear(&entry->acl);
1659
0
}
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
0
{
1668
0
  return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
1669
0
}
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
0
{
1678
0
  return archive_acl_add_entry_w_len(&entry->acl,
1679
0
      type, permset, tag, id, name, wcslen(name));
1680
0
}
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
0
{
1688
0
  return (archive_acl_types(&entry->acl));
1689
0
}
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
0
{
1697
0
  return archive_acl_count(&entry->acl, want_type);
1698
0
}
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
0
{
1708
0
  return archive_acl_reset(&entry->acl, want_type);
1709
0
}
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
0
{
1719
0
  int r;
1720
0
  r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
1721
0
    permset, tag, id, name);
1722
0
  if (r == ARCHIVE_FATAL && errno == ENOMEM)
1723
0
    __archive_errx(1, "No memory");
1724
0
  return (r);
1725
0
}
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
0
{
1735
0
  return (archive_acl_to_text_w(&entry->acl, len, flags,
1736
0
      entry->archive));
1737
0
}
1738
1739
char *
1740
archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
1741
    int flags)
1742
0
{
1743
0
  return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
1744
0
}
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
0
{
1750
0
  return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
1751
0
}
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
0
{
1760
0
  return (archive_acl_from_text_w(&entry->acl, wtext, type));
1761
0
}
1762
1763
int
1764
archive_entry_acl_from_text(struct archive_entry *entry,
1765
    const char *text, int type)
1766
0
{
1767
0
  return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
1768
0
}
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
0
{
1774
0
  return (archive_acl_from_text_l(&entry->acl, text, type, sc));
1775
0
}
1776
1777
/* Deprecated */
1778
static int
1779
archive_entry_acl_text_compat(int *flags)
1780
0
{
1781
0
  if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
1782
0
    return (1);
1783
1784
  /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
1785
0
  if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
1786
0
    *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
1787
1788
  /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
1789
0
  if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
1790
0
    *flags |=  ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
1791
1792
0
  *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
1793
1794
0
  return (0);
1795
0
}
1796
1797
/* Deprecated */
1798
const wchar_t *
1799
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1800
0
{
1801
0
  free(entry->acl.acl_text_w);
1802
0
  entry->acl.acl_text_w = NULL;
1803
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1804
0
    entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
1805
0
        NULL, flags, entry->archive);
1806
0
  return (entry->acl.acl_text_w);
1807
0
}
1808
1809
/* Deprecated */
1810
const char *
1811
archive_entry_acl_text(struct archive_entry *entry, int flags)
1812
0
{
1813
0
  free(entry->acl.acl_text);
1814
0
  entry->acl.acl_text = NULL;
1815
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1816
0
    entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
1817
0
        flags, NULL);
1818
1819
0
  return (entry->acl.acl_text);
1820
0
}
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
0
{
1827
0
  free(entry->acl.acl_text);
1828
0
  entry->acl.acl_text = NULL;
1829
1830
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1831
0
    entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
1832
0
        (ssize_t *)len, flags, sc);
1833
1834
0
  *acl_text = entry->acl.acl_text;
1835
1836
0
  return (0);
1837
0
}
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
0
{
2092
0
  char *string, *dp;
2093
0
  const char *sp;
2094
0
  unsigned long bits;
2095
0
  const struct flag *flag;
2096
0
  size_t  length;
2097
2098
0
  bits = bitset | bitclear;
2099
0
  length = 0;
2100
0
  for (flag = fileflags; flag->name != NULL; flag++)
2101
0
    if (bits & (flag->set | flag->clear)) {
2102
0
      length += strlen(flag->name) + 1;
2103
0
      bits &= ~(flag->set | flag->clear);
2104
0
    }
2105
2106
0
  if (length == 0)
2107
0
    return (NULL);
2108
0
  string = malloc(length);
2109
0
  if (string == NULL)
2110
0
    return (NULL);
2111
2112
0
  dp = string;
2113
0
  for (flag = fileflags; flag->name != NULL; flag++) {
2114
0
    if (bitset & flag->set || bitclear & flag->clear) {
2115
0
      sp = flag->name + 2;
2116
0
    } else if (bitset & flag->clear  ||  bitclear & flag->set) {
2117
0
      sp = flag->name;
2118
0
    } else
2119
0
      continue;
2120
0
    bitset &= ~(flag->set | flag->clear);
2121
0
    bitclear &= ~(flag->set | flag->clear);
2122
0
    if (dp > string)
2123
0
      *dp++ = ',';
2124
0
    while ((*dp++ = *sp++) != '\0')
2125
0
      ;
2126
0
    dp--;
2127
0
  }
2128
2129
0
  *dp = '\0';
2130
0
  return (string);
2131
0
}
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
0
{
2146
0
  const char *start, *end;
2147
0
  const struct flag *flag;
2148
0
  unsigned long set, clear;
2149
0
  const char *failed;
2150
2151
0
  set = clear = 0;
2152
0
  start = s;
2153
0
  failed = NULL;
2154
  /* Find start of first token. */
2155
0
  while (l > 0 && (*start == '\t'  ||  *start == ' '  ||  *start == ',')) {
2156
0
    start++;
2157
0
    l--;
2158
0
  }
2159
0
  while (l > 0) {
2160
0
    size_t length;
2161
    /* Locate end of token. */
2162
0
    end = start;
2163
0
    while (l > 0 && *end != '\t'  &&
2164
0
        *end != ' '  &&  *end != ',') {
2165
0
      end++;
2166
0
      l--;
2167
0
    }
2168
0
    length = end - start;
2169
0
    for (flag = fileflags; flag->name != NULL; flag++) {
2170
0
      size_t flag_length = strlen(flag->name);
2171
0
      if (length == flag_length
2172
0
          && memcmp(start, flag->name, length) == 0) {
2173
        /* Matched "noXXXX", so reverse the sense. */
2174
0
        clear |= flag->set;
2175
0
        set |= flag->clear;
2176
0
        break;
2177
0
      } else if (length == flag_length - 2
2178
0
          && memcmp(start, flag->name + 2, length) == 0) {
2179
        /* Matched "XXXX", so don't reverse. */
2180
0
        set |= flag->set;
2181
0
        clear |= flag->clear;
2182
0
        break;
2183
0
      }
2184
0
    }
2185
    /* Ignore unknown flag names. */
2186
0
    if (flag->name == NULL  &&  failed == NULL)
2187
0
      failed = start;
2188
2189
    /* Find start of next token. */
2190
0
    start = end;
2191
0
    while (l > 0 && (*start == '\t'  ||  *start == ' '  ||  *start == ',')) {
2192
0
      start++;
2193
0
      l--;
2194
0
    }
2195
2196
0
  }
2197
2198
0
  if (setp)
2199
0
    *setp = set;
2200
0
  if (clrp)
2201
0
    *clrp = clear;
2202
2203
  /* Return location of first failure. */
2204
0
  return (failed);
2205
0
}
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
0
{
2220
0
  const wchar_t *start, *end;
2221
0
  const struct flag *flag;
2222
0
  unsigned long set, clear;
2223
0
  const wchar_t *failed;
2224
2225
0
  set = clear = 0;
2226
0
  start = s;
2227
0
  failed = NULL;
2228
  /* Find start of first token. */
2229
0
  while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
2230
0
    start++;
2231
0
  while (*start != L'\0') {
2232
0
    size_t length;
2233
    /* Locate end of token. */
2234
0
    end = start;
2235
0
    while (*end != L'\0'  &&  *end != L'\t'  &&
2236
0
        *end != L' '  &&  *end != L',')
2237
0
      end++;
2238
0
    length = end - start;
2239
0
    for (flag = fileflags; flag->wname != NULL; flag++) {
2240
0
      size_t flag_length = wcslen(flag->wname);
2241
0
      if (length == flag_length
2242
0
          && wmemcmp(start, flag->wname, length) == 0) {
2243
        /* Matched "noXXXX", so reverse the sense. */
2244
0
        clear |= flag->set;
2245
0
        set |= flag->clear;
2246
0
        break;
2247
0
      } else if (length == flag_length - 2
2248
0
          && wmemcmp(start, flag->wname + 2, length) == 0) {
2249
        /* Matched "XXXX", so don't reverse. */
2250
0
        set |= flag->set;
2251
0
        clear |= flag->clear;
2252
0
        break;
2253
0
      }
2254
0
    }
2255
    /* Ignore unknown flag names. */
2256
0
    if (flag->wname == NULL  &&  failed == NULL)
2257
0
      failed = start;
2258
2259
    /* Find start of next token. */
2260
0
    start = end;
2261
0
    while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
2262
0
      start++;
2263
2264
0
  }
2265
2266
0
  if (setp)
2267
0
    *setp = set;
2268
0
  if (clrp)
2269
0
    *clrp = clear;
2270
2271
  /* Return location of first failure. */
2272
0
  return (failed);
2273
0
}
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