Coverage Report

Created: 2026-09-14 06:43

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
26
#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
153k
  do { \
113
153k
    t += ns / 1000000000; \
114
153k
    ns %= 1000000000; \
115
153k
    if (ns < 0) { --t; ns += 1000000000; } \
116
153k
  } 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
232k
{
156
232k
  if (entry == NULL)
157
84.2k
    return (NULL);
158
148k
  archive_mstring_clean(&entry->ae_fflags_text);
159
148k
  archive_mstring_clean(&entry->ae_gname);
160
148k
  archive_mstring_clean(&entry->ae_linkname);
161
148k
  archive_mstring_clean(&entry->ae_pathname);
162
148k
  archive_mstring_clean(&entry->ae_sourcepath);
163
148k
  archive_mstring_clean(&entry->ae_uname);
164
148k
  archive_entry_copy_mac_metadata(entry, NULL, 0);
165
148k
  archive_acl_clear(&entry->acl);
166
148k
  archive_entry_xattr_clear(entry);
167
148k
  archive_entry_sparse_clear(entry);
168
148k
  free(entry->stat);
169
148k
  entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
170
148k
  memset(entry, 0, sizeof(*entry));
171
148k
  return entry;
172
232k
}
173
174
struct archive_entry *
175
archive_entry_clone(struct archive_entry *entry)
176
51.8k
{
177
51.8k
  struct archive_entry *entry2;
178
51.8k
  struct ae_xattr *xp;
179
51.8k
  struct ae_sparse *sp;
180
51.8k
  size_t s;
181
51.8k
  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
51.8k
  entry2 = archive_entry_new2(entry->archive);
187
51.8k
  if (entry2 == NULL)
188
0
    return (NULL);
189
51.8k
  entry2->ae_stat = entry->ae_stat;
190
51.8k
  entry2->ae_fflags_set = entry->ae_fflags_set;
191
51.8k
  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
51.8k
  archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
196
51.8k
  archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
197
51.8k
  archive_mstring_copy(&entry2->ae_linkname, &entry->ae_linkname);
198
51.8k
  archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
199
51.8k
  archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
200
51.8k
  entry2->ae_set = entry->ae_set;
201
51.8k
  archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
202
203
  /* Copy symlink type */
204
51.8k
  entry2->ae_symlink_type = entry->ae_symlink_type;
205
206
  /* Copy encryption status */
207
51.8k
  entry2->encryption = entry->encryption;
208
209
  /* Copy digests */
210
51.8k
#define copy_digest(_e2, _e, _t) \
211
311k
  memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t))
212
213
51.8k
  copy_digest(entry2, entry, md5);
214
51.8k
  copy_digest(entry2, entry, rmd160);
215
51.8k
  copy_digest(entry2, entry, sha1);
216
51.8k
  copy_digest(entry2, entry, sha256);
217
51.8k
  copy_digest(entry2, entry, sha384);
218
51.8k
  copy_digest(entry2, entry, sha512);
219
220
51.8k
#undef copy_digest
221
  
222
  /* Copy ACL data over. */
223
51.8k
  archive_acl_copy(&entry2->acl, &entry->acl);
224
225
  /* Copy Mac OS metadata. */
226
51.8k
  p = archive_entry_mac_metadata(entry, &s);
227
51.8k
  archive_entry_copy_mac_metadata(entry2, p, s);
228
229
  /* Copy xattr data over. */
230
51.8k
  xp = entry->xattr_head;
231
51.8k
  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
51.8k
  sp = entry->sparse_head;
239
51.8k
  while (sp != NULL) {
240
50
    archive_entry_sparse_add_entry(entry2,
241
50
        sp->offset, sp->length);
242
50
    sp = sp->next;
243
50
  }
244
245
51.8k
  return (entry2);
246
51.8k
}
247
248
void
249
archive_entry_free(struct archive_entry *entry)
250
169k
{
251
169k
  archive_entry_clear(entry);
252
169k
  free(entry);
253
169k
}
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
85.2k
{
264
85.2k
  struct archive_entry *entry;
265
266
85.2k
  entry = calloc(1, sizeof(*entry));
267
85.2k
  if (entry == NULL)
268
0
    return (NULL);
269
85.2k
  entry->archive = a;
270
85.2k
  entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
271
85.2k
  return (entry);
272
85.2k
}
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
22.6k
{
281
22.6k
  return (entry->ae_stat.aest_atime);
282
22.6k
}
283
284
long
285
archive_entry_atime_nsec(struct archive_entry *entry)
286
22.6k
{
287
22.6k
  return (entry->ae_stat.aest_atime_nsec);
288
22.6k
}
289
290
int
291
archive_entry_atime_is_set(struct archive_entry *entry)
292
47.7k
{
293
47.7k
  return (entry->ae_set & AE_SET_ATIME);
294
47.7k
}
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
24.9k
{
311
24.9k
  return (entry->ae_set & AE_SET_BIRTHTIME);
312
24.9k
}
313
314
__LA_TIME_T
315
archive_entry_ctime(struct archive_entry *entry)
316
18.2k
{
317
18.2k
  return (entry->ae_stat.aest_ctime);
318
18.2k
}
319
320
int
321
archive_entry_ctime_is_set(struct archive_entry *entry)
322
22.2k
{
323
22.2k
  return (entry->ae_set & AE_SET_CTIME);
324
22.2k
}
325
326
long
327
archive_entry_ctime_nsec(struct archive_entry *entry)
328
18.2k
{
329
18.2k
  return (entry->ae_stat.aest_ctime_nsec);
330
18.2k
}
331
332
__LA_DEV_T
333
archive_entry_dev(struct archive_entry *entry)
334
614
{
335
614
  if (entry->ae_stat.aest_dev_is_broken_down)
336
16
    return ae_makedev(entry->ae_stat.aest_devmajor,
337
598
        entry->ae_stat.aest_devminor);
338
598
  else
339
598
    return (entry->ae_stat.aest_dev);
340
614
}
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
9.52k
{
369
9.52k
  return (AE_IFMT & entry->acl.mode);
370
9.52k
}
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
2.04k
{
434
2.04k
  return (entry->ae_set & AE_SET_GID);
435
2.04k
}
436
437
const char *
438
archive_entry_gname(struct archive_entry *entry)
439
2.35k
{
440
2.35k
  const char *p;
441
2.35k
  if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
442
2.35k
    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
28
{
481
28
  if ((entry->ae_set & AE_SET_SYMLINK) != 0) {
482
0
    entry->ae_set &= ~AE_SET_SYMLINK;
483
0
  }
484
28
  entry->ae_set |= AE_SET_HARDLINK;
485
28
}
486
487
const char *
488
archive_entry_hardlink(struct archive_entry *entry)
489
136k
{
490
136k
  const char *p;
491
136k
  if ((entry->ae_set & AE_SET_HARDLINK) == 0)
492
136k
    return (NULL);
493
192
  if (archive_mstring_get_mbs(
494
192
      entry->archive, &entry->ae_linkname, &p) == 0)
495
192
    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
28
{
518
28
  const wchar_t *p;
519
28
  if ((entry->ae_set & AE_SET_HARDLINK) == 0)
520
0
    return (NULL);
521
28
  if (archive_mstring_get_wcs(
522
28
      entry->archive, &entry->ae_linkname, &p) == 0)
523
28
    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
614
{
562
614
  return (entry->ae_stat.aest_ino);
563
614
}
564
565
__LA_MODE_T
566
archive_entry_mode(struct archive_entry *entry)
567
51.8k
{
568
51.8k
  return (entry->acl.mode);
569
51.8k
}
570
571
__LA_TIME_T
572
archive_entry_mtime(struct archive_entry *entry)
573
24.9k
{
574
24.9k
  return (entry->ae_stat.aest_mtime);
575
24.9k
}
576
577
long
578
archive_entry_mtime_nsec(struct archive_entry *entry)
579
24.9k
{
580
24.9k
  return (entry->ae_stat.aest_mtime_nsec);
581
24.9k
}
582
583
int
584
archive_entry_mtime_is_set(struct archive_entry *entry)
585
34.1k
{
586
34.1k
  return (entry->ae_set & AE_SET_MTIME);
587
34.1k
}
588
589
unsigned int
590
archive_entry_nlink(struct archive_entry *entry)
591
1.53k
{
592
1.53k
  return (entry->ae_stat.aest_nlink);
593
1.53k
}
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
190k
{
605
190k
  const char *p;
606
190k
  if (archive_mstring_get_mbs(
607
190k
      entry->archive, &entry->ae_pathname, &p) == 0)
608
190k
    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
85.1k
{
636
85.1k
  const wchar_t *p;
637
85.1k
  if (archive_mstring_get_wcs(
638
85.1k
      entry->archive, &entry->ae_pathname, &p) == 0)
639
85.1k
    return (p);
640
0
  if (errno == ENOMEM)
641
0
    __archive_errx(1, "No memory");
642
0
  return (NULL);
643
0
}
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
2.04k
{
661
2.04k
  return (entry->ae_set & AE_SET_PERM);
662
2.04k
}
663
664
int
665
archive_entry_rdev_is_set(struct archive_entry *entry)
666
54
{
667
54
  return (entry->ae_set & AE_SET_RDEV);
668
54
}
669
670
__LA_DEV_T
671
archive_entry_rdev(struct archive_entry *entry)
672
50
{
673
50
  if (archive_entry_rdev_is_set(entry)) {
674
43
    if (entry->ae_stat.aest_rdev_is_broken_down)
675
10
      return ae_makedev(entry->ae_stat.aest_rdevmajor,
676
33
          entry->ae_stat.aest_rdevminor);
677
33
    else
678
33
      return (entry->ae_stat.aest_rdev);
679
43
  } else {
680
7
    return 0;
681
7
  }
682
50
}
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
158k
{
713
158k
  return (entry->ae_stat.aest_size);
714
158k
}
715
716
int
717
archive_entry_size_is_set(struct archive_entry *entry)
718
107k
{
719
107k
  return (entry->ae_set & AE_SET_SIZE);
720
107k
}
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
85.7k
{
747
85.7k
  const char *p;
748
85.7k
  if ((entry->ae_set & AE_SET_SYMLINK) == 0)
749
85.7k
    return (NULL);
750
56
  if (archive_mstring_get_mbs(
751
56
      entry->archive, &entry->ae_linkname, &p) == 0)
752
56
    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
4
{
761
4
  if ((entry->ae_set & AE_SET_HARDLINK) != 0) {
762
0
    entry->ae_set &= ~AE_SET_HARDLINK;
763
0
  }
764
4
  entry->ae_set |= AE_SET_SYMLINK;
765
4
}
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
498
{
790
498
  const wchar_t *p;
791
498
  if ((entry->ae_set & AE_SET_SYMLINK) == 0)
792
494
    return (NULL);
793
4
  if (archive_mstring_get_wcs(
794
4
      entry->archive, &entry->ae_linkname, &p) == 0)
795
4
    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
2.04k
{
822
2.04k
  return (entry->ae_set & AE_SET_UID);
823
2.04k
}
824
825
const char *
826
archive_entry_uname(struct archive_entry *entry)
827
2.35k
{
828
2.35k
  const char *p;
829
2.35k
  if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
830
2.35k
    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
14.7k
{
890
14.7k
  entry->stat_valid = 0;
891
14.7k
  entry->acl.mode &= ~AE_IFMT;
892
14.7k
  entry->acl.mode |= AE_IFMT & type;
893
14.7k
  entry->ae_set |= AE_SET_FILETYPE;
894
14.7k
}
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
3.77k
{
909
3.77k
  return archive_entry_copy_fflags_text_len(entry, flags, strlen(flags));
910
3.77k
}
911
912
const char *
913
archive_entry_copy_fflags_text_len(struct archive_entry *entry,
914
    const char *flags, size_t flags_length)
915
3.77k
{
916
3.77k
  archive_mstring_copy_mbs_len(&entry->ae_fflags_text, flags, flags_length);
917
3.77k
  return (ae_strtofflags(flags, flags_length,
918
3.77k
        &entry->ae_fflags_set, &entry->ae_fflags_clear));
919
3.77k
}
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
51.2k
{
933
51.2k
  if (g < 0) {
934
872
    g = 0;
935
872
  }
936
51.2k
  entry->stat_valid = 0;
937
51.2k
  entry->ae_stat.aest_gid = g;
938
51.2k
  entry->ae_set |= AE_SET_GID;
939
51.2k
}
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
244
{
956
244
  archive_mstring_copy_mbs(&entry->ae_gname, name);
957
244
}
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
2.35k
{
980
2.35k
  return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
981
2.35k
}
982
983
void
984
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
985
3.97k
{
986
3.97k
  if (ino < 0) {
987
0
    entry->stat_valid = 0;
988
0
    entry->ae_set &= ~AE_SET_INO;
989
0
    return;
990
0
  }
991
3.97k
  entry->stat_valid = 0;
992
3.97k
  entry->ae_set |= AE_SET_INO;
993
3.97k
  entry->ae_stat.aest_ino = ino;
994
3.97k
}
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
59
{
1039
59
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1040
0
    return;
1041
59
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1042
59
  if (target != NULL)
1043
59
    entry->ae_set |= AE_SET_HARDLINK;
1044
0
  else
1045
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1046
59
}
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
28
{
1081
28
  int r;
1082
1083
28
  if (target == NULL && (entry->ae_set & AE_SET_SYMLINK))
1084
0
    return (0);
1085
28
  r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1086
28
      target, len, sc);
1087
28
  if (target != NULL && r == 0)
1088
28
    entry->ae_set |= AE_SET_HARDLINK;
1089
0
  else
1090
0
    entry->ae_set &= ~AE_SET_HARDLINK;
1091
28
  return (r);
1092
28
}
1093
1094
void
1095
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1096
46.7k
{
1097
46.7k
  FIX_NS(t, ns);
1098
46.7k
  entry->stat_valid = 0;
1099
46.7k
  entry->ae_set |= AE_SET_ATIME;
1100
46.7k
  entry->ae_stat.aest_atime = t;
1101
46.7k
  entry->ae_stat.aest_atime_nsec = ns;
1102
46.7k
}
1103
1104
void
1105
archive_entry_unset_atime(struct archive_entry *entry)
1106
498
{
1107
498
  archive_entry_set_atime(entry, 0, 0);
1108
498
  entry->ae_set &= ~AE_SET_ATIME;
1109
498
}
1110
1111
void
1112
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1113
498
{
1114
498
  FIX_NS(t, ns);
1115
498
  entry->stat_valid = 0;
1116
498
  entry->ae_set |= AE_SET_BIRTHTIME;
1117
498
  entry->ae_stat.aest_birthtime = t;
1118
498
  entry->ae_stat.aest_birthtime_nsec = ns;
1119
498
}
1120
1121
void
1122
archive_entry_unset_birthtime(struct archive_entry *entry)
1123
498
{
1124
498
  archive_entry_set_birthtime(entry, 0, 0);
1125
498
  entry->ae_set &= ~AE_SET_BIRTHTIME;
1126
498
}
1127
1128
void
1129
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1130
46.6k
{
1131
46.6k
  FIX_NS(t, ns);
1132
46.6k
  entry->stat_valid = 0;
1133
46.6k
  entry->ae_set |= AE_SET_CTIME;
1134
46.6k
  entry->ae_stat.aest_ctime = t;
1135
46.6k
  entry->ae_stat.aest_ctime_nsec = ns;
1136
46.6k
}
1137
1138
void
1139
archive_entry_unset_ctime(struct archive_entry *entry)
1140
498
{
1141
498
  archive_entry_set_ctime(entry, 0, 0);
1142
498
  entry->ae_set &= ~AE_SET_CTIME;
1143
498
}
1144
1145
void
1146
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
1147
4.52k
{
1148
4.52k
  entry->stat_valid = 0;
1149
4.52k
  entry->ae_set |= AE_SET_DEV;
1150
4.52k
  entry->ae_stat.aest_dev_is_broken_down = 0;
1151
4.52k
  entry->ae_stat.aest_dev = d;
1152
4.52k
}
1153
1154
void
1155
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
1156
112
{
1157
112
  entry->stat_valid = 0;
1158
112
  entry->ae_set |= AE_SET_DEV;
1159
112
  entry->ae_stat.aest_dev_is_broken_down = 1;
1160
112
  entry->ae_stat.aest_devmajor = m;
1161
112
}
1162
1163
void
1164
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
1165
112
{
1166
112
  entry->stat_valid = 0;
1167
112
  entry->ae_set |= AE_SET_DEV;
1168
112
  entry->ae_stat.aest_dev_is_broken_down = 1;
1169
112
  entry->ae_stat.aest_devminor = m;
1170
112
}
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
4
{
1176
4
  archive_mstring_copy_mbs(&entry->ae_linkname, target);
1177
4
  if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
1178
4
    entry->ae_set |= AE_SET_HARDLINK;
1179
4
  }
1180
4
}
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, __LA_MODE_T m)
1243
49.9k
{
1244
49.9k
  entry->stat_valid = 0;
1245
49.9k
  entry->acl.mode = m;
1246
49.9k
  entry->ae_set |= AE_SET_PERM | AE_SET_FILETYPE;
1247
49.9k
}
1248
1249
void
1250
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
1251
59.9k
{
1252
59.9k
  FIX_NS(t, ns);
1253
59.9k
  entry->stat_valid = 0;
1254
59.9k
  entry->ae_set |= AE_SET_MTIME;
1255
59.9k
  entry->ae_stat.aest_mtime = t;
1256
59.9k
  entry->ae_stat.aest_mtime_nsec = ns;
1257
59.9k
}
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
3.39k
{
1269
3.39k
  entry->stat_valid = 0;
1270
3.39k
  entry->ae_stat.aest_nlink = nlink;
1271
3.39k
}
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
5.12k
{
1288
5.12k
  archive_mstring_copy_mbs(&entry->ae_pathname, name);
1289
5.12k
}
1290
1291
void
1292
archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
1293
8.23k
{
1294
8.23k
  archive_mstring_copy_wcs(&entry->ae_pathname, name);
1295
8.23k
}
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
51.4k
{
1312
51.4k
  return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
1313
51.4k
      name, len, sc));
1314
51.4k
}
1315
1316
void
1317
archive_entry_set_perm(struct archive_entry *entry, __LA_MODE_T p)
1318
2.76k
{
1319
2.76k
  entry->stat_valid = 0;
1320
2.76k
  entry->acl.mode &= AE_IFMT;
1321
2.76k
  entry->acl.mode |= ~AE_IFMT & p;
1322
2.76k
  entry->ae_set |= AE_SET_PERM;
1323
2.76k
}
1324
1325
void
1326
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
1327
4.49k
{
1328
4.49k
  entry->stat_valid = 0;
1329
4.49k
  entry->ae_stat.aest_rdev = m;
1330
4.49k
  entry->ae_stat.aest_rdev_is_broken_down = 0;
1331
4.49k
  entry->ae_stat.aest_rdevmajor = 0;
1332
4.49k
  entry->ae_stat.aest_rdevminor = 0;
1333
4.49k
  entry->ae_set |= AE_SET_RDEV;
1334
4.49k
}
1335
1336
void
1337
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
1338
116
{
1339
116
  entry->stat_valid = 0;
1340
116
  entry->ae_stat.aest_rdev_is_broken_down = 1;
1341
116
  entry->ae_stat.aest_rdev = 0;
1342
116
  entry->ae_stat.aest_rdevmajor = m;
1343
116
  entry->ae_set |= AE_SET_RDEV;
1344
116
}
1345
1346
void
1347
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
1348
116
{
1349
116
  entry->stat_valid = 0;
1350
116
  entry->ae_stat.aest_rdev_is_broken_down = 1;
1351
116
  entry->ae_stat.aest_rdev = 0;
1352
116
  entry->ae_stat.aest_rdevminor = m;
1353
116
  entry->ae_set |= AE_SET_RDEV;
1354
116
}
1355
1356
void
1357
archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
1358
81.5k
{
1359
81.5k
  if (s < 0) {
1360
0
    s = 0;
1361
0
  }
1362
81.5k
  entry->stat_valid = 0;
1363
81.5k
  entry->ae_stat.aest_size = s;
1364
81.5k
  entry->ae_set |= AE_SET_SIZE;
1365
81.5k
}
1366
1367
void
1368
archive_entry_unset_size(struct archive_entry *entry)
1369
6
{
1370
6
  archive_entry_set_size(entry, 0);
1371
6
  entry->ae_set &= ~AE_SET_SIZE;
1372
6
}
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
498
{
1389
498
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1390
0
    return;
1391
498
  archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1392
498
  entry->ae_set &= ~AE_SET_HARDLINK;
1393
498
  if (linkname == NULL)
1394
498
    entry->ae_set &= ~AE_SET_SYMLINK;
1395
0
  else
1396
0
    entry->ae_set |= AE_SET_SYMLINK;
1397
498
}
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
440
{
1421
440
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1422
0
    return;
1423
440
  archive_mstring_copy_mbs(&entry->ae_linkname, linkname);
1424
440
  entry->ae_set &= ~AE_SET_HARDLINK;
1425
440
  if (linkname == NULL)
1426
0
    entry->ae_set &= ~AE_SET_SYMLINK;
1427
440
  else
1428
440
    entry->ae_set |= AE_SET_SYMLINK;
1429
440
}
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
76
{
1466
76
  int r;
1467
1468
76
  if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK))
1469
0
    return (0);
1470
76
  entry->ae_set &= ~AE_SET_HARDLINK;
1471
76
  r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname,
1472
76
      linkname, len, sc);
1473
76
  if (linkname == NULL || r != 0)
1474
30
    entry->ae_set &= ~AE_SET_SYMLINK;
1475
46
  else
1476
46
    entry->ae_set |= AE_SET_SYMLINK;
1477
76
  return (r);
1478
76
}
1479
1480
void
1481
archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
1482
52.1k
{
1483
52.1k
  if (u < 0) {
1484
2
    u = 0;
1485
2
  }
1486
52.1k
  entry->stat_valid = 0;
1487
52.1k
  entry->ae_stat.aest_uid = u;
1488
52.1k
  entry->ae_set |= AE_SET_UID;
1489
52.1k
}
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
116
{
1506
116
  archive_mstring_copy_mbs(&entry->ae_uname, name);
1507
116
}
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
7.04k
{
1529
7.04k
  if (is_encrypted) {
1530
7.04k
    entry->encryption |= AE_ENCRYPTION_DATA;
1531
7.04k
  } else {
1532
0
    entry->encryption &= ~AE_ENCRYPTION_DATA;
1533
0
  }
1534
7.04k
}
1535
1536
void
1537
archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
1538
8
{
1539
8
  if (is_encrypted) {
1540
8
    entry->encryption |= AE_ENCRYPTION_METADATA;
1541
8
  } else {
1542
0
    entry->encryption &= ~AE_ENCRYPTION_METADATA;
1543
0
  }
1544
8
}
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
2.35k
{
1550
2.35k
  return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
1551
2.35k
      name, len, sc));
1552
2.35k
}
1553
1554
const void *
1555
archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
1556
51.8k
{
1557
51.8k
  *s = entry->mac_metadata_size;
1558
51.8k
  return entry->mac_metadata;
1559
51.8k
}
1560
1561
void
1562
archive_entry_copy_mac_metadata(struct archive_entry *entry,
1563
    const void *p, size_t s)
1564
200k
{
1565
200k
  void *metadata;
1566
1567
200k
  if (p == NULL || s == 0) {
1568
200k
    free(entry->mac_metadata);
1569
200k
    entry->mac_metadata = NULL;
1570
200k
    entry->mac_metadata_size = 0;
1571
200k
  } else {
1572
0
    metadata = malloc(s);
1573
0
    if (metadata == NULL)
1574
0
      abort();
1575
0
    memcpy(metadata, p, s);
1576
0
    free(entry->mac_metadata);
1577
0
    entry->mac_metadata = metadata;
1578
0
    entry->mac_metadata_size = s;
1579
0
  }
1580
200k
}
1581
1582
/* Digest handling */
1583
const unsigned char *
1584
archive_entry_digest(struct archive_entry *entry, int type)
1585
0
{
1586
0
  switch (type) {
1587
0
  case ARCHIVE_ENTRY_DIGEST_MD5:
1588
0
    return entry->digest.md5;
1589
0
  case ARCHIVE_ENTRY_DIGEST_RMD160:
1590
0
    return entry->digest.rmd160;
1591
0
  case ARCHIVE_ENTRY_DIGEST_SHA1:
1592
0
    return entry->digest.sha1;
1593
0
  case ARCHIVE_ENTRY_DIGEST_SHA256:
1594
0
    return entry->digest.sha256;
1595
0
  case ARCHIVE_ENTRY_DIGEST_SHA384:
1596
0
    return entry->digest.sha384;
1597
0
  case ARCHIVE_ENTRY_DIGEST_SHA512:
1598
0
    return entry->digest.sha512;
1599
0
  default:
1600
0
    return NULL;
1601
0
  }
1602
0
}
1603
1604
int
1605
archive_entry_set_digest(struct archive_entry *entry, int type,
1606
    const unsigned char *digest)
1607
446
{
1608
446
#define copy_digest(_e, _t, _d)\
1609
446
  memcpy(_e->digest._t, _d, sizeof(_e->digest._t))
1610
1611
446
  switch (type) {
1612
0
  case ARCHIVE_ENTRY_DIGEST_MD5:
1613
0
    copy_digest(entry, md5, digest);
1614
0
    entry->mset_digest |= AE_MSET_DIGEST_MD5;
1615
0
    break;
1616
446
  case ARCHIVE_ENTRY_DIGEST_RMD160:
1617
446
    copy_digest(entry, rmd160, digest);
1618
446
    entry->mset_digest |= AE_MSET_DIGEST_RMD160;
1619
446
    break;
1620
0
  case ARCHIVE_ENTRY_DIGEST_SHA1:
1621
0
    copy_digest(entry, sha1, digest);
1622
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA1;
1623
0
    break;
1624
0
  case ARCHIVE_ENTRY_DIGEST_SHA256:
1625
0
    copy_digest(entry, sha256, digest);
1626
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA256;
1627
0
    break;
1628
0
  case ARCHIVE_ENTRY_DIGEST_SHA384:
1629
0
    copy_digest(entry, sha384, digest);
1630
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA384;
1631
0
    break;
1632
0
  case ARCHIVE_ENTRY_DIGEST_SHA512:
1633
0
    copy_digest(entry, sha512, digest);
1634
0
    entry->mset_digest |= AE_MSET_DIGEST_SHA512;
1635
0
    break;
1636
0
  default:
1637
0
    return ARCHIVE_WARN;
1638
446
  }
1639
1640
446
  return ARCHIVE_OK;
1641
446
#undef copy_digest
1642
446
}
1643
1644
/*
1645
 * ACL management.  The following would, of course, be a lot simpler
1646
 * if: 1) the last draft of POSIX.1e were a really thorough and
1647
 * complete standard that addressed the needs of ACL archiving and 2)
1648
 * everyone followed it faithfully.  Alas, neither is true, so the
1649
 * following is a lot more complex than might seem necessary to the
1650
 * uninitiated.
1651
 */
1652
1653
struct archive_acl *
1654
archive_entry_acl(struct archive_entry *entry)
1655
0
{
1656
0
  return &entry->acl;
1657
0
}
1658
1659
void
1660
archive_entry_acl_clear(struct archive_entry *entry)
1661
0
{
1662
0
  archive_acl_clear(&entry->acl);
1663
0
}
1664
1665
/*
1666
 * Add a single ACL entry to the internal list of ACL data.
1667
 */
1668
int
1669
archive_entry_acl_add_entry(struct archive_entry *entry,
1670
    int type, int permset, int tag, int id, const char *name)
1671
0
{
1672
0
  return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
1673
0
}
1674
1675
/*
1676
 * As above, but with a wide-character name.
1677
 */
1678
int
1679
archive_entry_acl_add_entry_w(struct archive_entry *entry,
1680
    int type, int permset, int tag, int id, const wchar_t *name)
1681
0
{
1682
0
  return archive_acl_add_entry_w_len(&entry->acl,
1683
0
      type, permset, tag, id, name, wcslen(name));
1684
0
}
1685
1686
/*
1687
 * Return a bitmask of ACL types in an archive entry ACL list
1688
 */
1689
int
1690
archive_entry_acl_types(struct archive_entry *entry)
1691
0
{
1692
0
  return (archive_acl_types(&entry->acl));
1693
0
}
1694
1695
/*
1696
 * Return a count of entries matching "want_type".
1697
 */
1698
int
1699
archive_entry_acl_count(struct archive_entry *entry, int want_type)
1700
0
{
1701
0
  return archive_acl_count(&entry->acl, want_type);
1702
0
}
1703
1704
/*
1705
 * Prepare for reading entries from the ACL data.  Returns a count
1706
 * of entries matching "want_type", or zero if there are no
1707
 * non-extended ACL entries of that type.
1708
 */
1709
int
1710
archive_entry_acl_reset(struct archive_entry *entry, int want_type)
1711
0
{
1712
0
  return archive_acl_reset(&entry->acl, want_type);
1713
0
}
1714
1715
/*
1716
 * Return the next ACL entry in the list.  Fake entries for the
1717
 * standard permissions and include them in the returned list.
1718
 */
1719
int
1720
archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
1721
    int *permset, int *tag, int *id, const char **name)
1722
0
{
1723
0
  int r;
1724
0
  r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
1725
0
    permset, tag, id, name);
1726
0
  if (r == ARCHIVE_FATAL && errno == ENOMEM)
1727
0
    __archive_errx(1, "No memory");
1728
0
  return (r);
1729
0
}
1730
1731
/*
1732
 * Generate a text version of the ACL. The flags parameter controls
1733
 * the style of the generated ACL.
1734
 */
1735
wchar_t *
1736
archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
1737
    int flags)
1738
0
{
1739
0
  return (archive_acl_to_text_w(&entry->acl, len, flags,
1740
0
      entry->archive));
1741
0
}
1742
1743
char *
1744
archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
1745
    int flags)
1746
0
{
1747
0
  return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
1748
0
}
1749
1750
char *
1751
_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
1752
   int flags, struct archive_string_conv *sc)
1753
0
{
1754
0
  return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
1755
0
}
1756
1757
/*
1758
 * ACL text parser.
1759
 */
1760
int
1761
archive_entry_acl_from_text_w(struct archive_entry *entry,
1762
    const wchar_t *wtext, int type)
1763
0
{
1764
0
  return (archive_acl_from_text_w(&entry->acl, wtext, type));
1765
0
}
1766
1767
int
1768
archive_entry_acl_from_text(struct archive_entry *entry,
1769
    const char *text, int type)
1770
0
{
1771
0
  return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
1772
0
}
1773
1774
int
1775
_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
1776
    int type, struct archive_string_conv *sc)
1777
0
{
1778
0
  return (archive_acl_from_text_l(&entry->acl, text, type, sc));
1779
0
}
1780
1781
/* Deprecated */
1782
static int
1783
archive_entry_acl_text_compat(int *flags)
1784
0
{
1785
0
  if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
1786
0
    return (1);
1787
1788
  /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
1789
0
  if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
1790
0
    *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
1791
1792
  /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
1793
0
  if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
1794
0
    *flags |=  ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
1795
1796
0
  *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
1797
1798
0
  return (0);
1799
0
}
1800
1801
/* Deprecated */
1802
const wchar_t *
1803
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
1804
0
{
1805
0
  free(entry->acl.acl_text_w);
1806
0
  entry->acl.acl_text_w = NULL;
1807
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1808
0
    entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
1809
0
        NULL, flags, entry->archive);
1810
0
  return (entry->acl.acl_text_w);
1811
0
}
1812
1813
/* Deprecated */
1814
const char *
1815
archive_entry_acl_text(struct archive_entry *entry, int flags)
1816
0
{
1817
0
  free(entry->acl.acl_text);
1818
0
  entry->acl.acl_text = NULL;
1819
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1820
0
    entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
1821
0
        flags, NULL);
1822
1823
0
  return (entry->acl.acl_text);
1824
0
}
1825
1826
/* Deprecated */
1827
int
1828
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
1829
    const char **acl_text, size_t *len, struct archive_string_conv *sc)
1830
0
{
1831
0
  free(entry->acl.acl_text);
1832
0
  entry->acl.acl_text = NULL;
1833
1834
0
  if (archive_entry_acl_text_compat(&flags) == 0)
1835
0
    entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
1836
0
        (ssize_t *)len, flags, sc);
1837
1838
0
  *acl_text = entry->acl.acl_text;
1839
1840
0
  return (0);
1841
0
}
1842
1843
/*
1844
 * Following code is modified from UC Berkeley sources, and
1845
 * is subject to the following copyright notice.
1846
 */
1847
1848
/*-
1849
 * Copyright (c) 1993
1850
 *  The Regents of the University of California.  All rights reserved.
1851
 *
1852
 * Redistribution and use in source and binary forms, with or without
1853
 * modification, are permitted provided that the following conditions
1854
 * are met:
1855
 * 1. Redistributions of source code must retain the above copyright
1856
 *    notice, this list of conditions and the following disclaimer.
1857
 * 2. Redistributions in binary form must reproduce the above copyright
1858
 *    notice, this list of conditions and the following disclaimer in the
1859
 *    documentation and/or other materials provided with the distribution.
1860
 * 4. Neither the name of the University nor the names of its contributors
1861
 *    may be used to endorse or promote products derived from this software
1862
 *    without specific prior written permission.
1863
 *
1864
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1865
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1866
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1867
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1868
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1869
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1870
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1871
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1872
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1873
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1874
 * SUCH DAMAGE.
1875
 */
1876
1877
/*
1878
 * Supported file flags on FreeBSD and Mac OS:
1879
 * sappnd,sappend   SF_APPEND
1880
 * arch,archived    SF_ARCHIVED
1881
 * schg,schange,simmutable  SF_IMMUTABLE
1882
 * sunlnk,sunlink   SF_NOUNLINK (FreeBSD only)
1883
 * uappnd,uappend   UF_APPEND
1884
 * compressed     UF_COMPRESSED (Mac OS only)
1885
 * hidden,uhidden   UF_HIDDEN
1886
 * uchg,uchange,uimmutable  UF_IMMUTABLE
1887
 * nodump     UF_NODUMP
1888
 * uunlnk,uunlink   UF_NOUNLINK (FreeBSD only)
1889
 * offline,uoffline   UF_OFFLINE  (FreeBSD only)
1890
 * opaque     UF_OPAQUE
1891
 * rdonly,urdonly,readonly  UF_READONLY (FreeBSD only)
1892
 * reparse,ureparse   UF_REPARSE  (FreeBSD only)
1893
 * sparse,usparse   UF_SPARSE (FreeBSD only)
1894
 * system,usystem   UF_SYSTEM (FreeBSD only)
1895
 *
1896
 * See chflags(2) for more information
1897
 *
1898
 * Supported file attributes on Linux:
1899
 * a  append only     FS_APPEND_FL    sappnd
1900
 * A  no atime updates    FS_NOATIME_FL   atime
1901
 * c  compress      FS_COMPR_FL   compress
1902
 * C  no copy on write    FS_NOCOW_FL   cow
1903
 * d  no dump       FS_NODUMP_FL    dump
1904
 * D  synchronous directory updates FS_DIRSYNC_FL   dirsync
1905
 * i  immutable     FS_IMMUTABLE_FL   schg
1906
 * j  data journalling    FS_JOURNAL_DATA_FL  journal
1907
 * P  project hierarchy   FS_PROJINHERIT_FL projinherit
1908
 * s  secure deletion     FS_SECRM_FL   securedeletion
1909
 * S  synchronous updates   FS_SYNC_FL    sync
1910
 * t  no tail-merging     FS_NOTAIL_FL    tail
1911
 * T  top of directory hierarchy  FS_TOPDIR_FL    topdir
1912
 * u  undeletable     FS_UNRM_FL    undel
1913
 *
1914
 * See ioctl_iflags(2) for more information
1915
 *
1916
 * Equivalent file flags supported on FreeBSD / Mac OS and Linux:
1917
 * SF_APPEND    FS_APPEND_FL    sappnd
1918
 * SF_IMMUTABLE   FS_IMMUTABLE_FL   schg
1919
 * UF_NODUMP    FS_NODUMP_FL    nodump
1920
 */
1921
1922
static const struct flag {
1923
  const char  *name;
1924
  const wchar_t *wname;
1925
  unsigned long  set;
1926
  unsigned long  clear;
1927
} fileflags[] = {
1928
  /* Preferred (shorter) names per flag first, all prefixed by "no" */
1929
#ifdef SF_APPEND
1930
  { "nosappnd", L"nosappnd",    SF_APPEND,  0},
1931
  { "nosappend",  L"nosappend",   SF_APPEND,  0},
1932
#endif
1933
#if defined(FS_APPEND_FL)     /* 'a' */
1934
  { "nosappnd", L"nosappnd",    FS_APPEND_FL, 0},
1935
  { "nosappend",  L"nosappend",   FS_APPEND_FL, 0},
1936
#elif defined(EXT2_APPEND_FL)     /* 'a' */
1937
  { "nosappnd", L"nosappnd",    EXT2_APPEND_FL, 0},
1938
  { "nosappend",  L"nosappend",   EXT2_APPEND_FL, 0},
1939
#endif
1940
#ifdef SF_ARCHIVED
1941
  { "noarch", L"noarch",    SF_ARCHIVED,  0},
1942
  { "noarchived", L"noarchived",        SF_ARCHIVED,  0},
1943
#endif
1944
#ifdef SF_IMMUTABLE
1945
  { "noschg", L"noschg",    SF_IMMUTABLE, 0},
1946
  { "noschange",  L"noschange",   SF_IMMUTABLE, 0},
1947
  { "nosimmutable", L"nosimmutable",  SF_IMMUTABLE, 0},
1948
#endif
1949
#if defined(FS_IMMUTABLE_FL)      /* 'i' */
1950
  { "noschg", L"noschg",    FS_IMMUTABLE_FL,  0},
1951
  { "noschange",  L"noschange",   FS_IMMUTABLE_FL,  0},
1952
  { "nosimmutable", L"nosimmutable",  FS_IMMUTABLE_FL,  0},
1953
#elif defined(EXT2_IMMUTABLE_FL)    /* 'i' */
1954
  { "noschg", L"noschg",    EXT2_IMMUTABLE_FL,  0},
1955
  { "noschange",  L"noschange",   EXT2_IMMUTABLE_FL,  0},
1956
  { "nosimmutable", L"nosimmutable",  EXT2_IMMUTABLE_FL,  0},
1957
#endif
1958
#ifdef SF_NOUNLINK
1959
  { "nosunlnk", L"nosunlnk",    SF_NOUNLINK,  0},
1960
  { "nosunlink",  L"nosunlink",   SF_NOUNLINK,  0},
1961
#endif
1962
#ifdef UF_APPEND
1963
  { "nouappnd", L"nouappnd",    UF_APPEND,  0},
1964
  { "nouappend",  L"nouappend",   UF_APPEND,  0},
1965
#endif
1966
#ifdef UF_IMMUTABLE
1967
  { "nouchg", L"nouchg",    UF_IMMUTABLE, 0},
1968
  { "nouchange",  L"nouchange",   UF_IMMUTABLE, 0},
1969
  { "nouimmutable", L"nouimmutable",  UF_IMMUTABLE, 0},
1970
#endif
1971
#ifdef UF_NODUMP
1972
  { "nodump", L"nodump",    0,    UF_NODUMP},
1973
#endif
1974
#if defined(FS_NODUMP_FL) /* 'd' */
1975
  { "nodump", L"nodump",    0,    FS_NODUMP_FL},
1976
#elif defined(EXT2_NODUMP_FL)
1977
  { "nodump", L"nodump",    0,    EXT2_NODUMP_FL},
1978
#endif
1979
#ifdef UF_OPAQUE
1980
  { "noopaque", L"noopaque",    UF_OPAQUE,  0},
1981
#endif
1982
#ifdef UF_NOUNLINK
1983
  { "nouunlnk", L"nouunlnk",    UF_NOUNLINK,  0},
1984
  { "nouunlink",  L"nouunlink",   UF_NOUNLINK,  0},
1985
#endif
1986
#ifdef UF_COMPRESSED
1987
  /* Mac OS */
1988
  { "nocompressed", L"nocompressed",  UF_COMPRESSED,  0},
1989
#endif
1990
#ifdef UF_HIDDEN
1991
  { "nohidden", L"nohidden",    UF_HIDDEN,  0},
1992
  { "nouhidden",  L"nouhidden",   UF_HIDDEN,  0},
1993
#endif
1994
#ifdef FILE_ATTRIBUTE_HIDDEN
1995
  { "nohidden", L"nohidden",  FILE_ATTRIBUTE_HIDDEN,  0},
1996
  { "nouhidden",  L"nouhidden", FILE_ATTRIBUTE_HIDDEN,  0},
1997
#endif
1998
#ifdef UF_OFFLINE
1999
  { "nooffline",  L"nooffline",   UF_OFFLINE, 0},
2000
  { "nouoffline", L"nouoffline",    UF_OFFLINE, 0},
2001
#endif
2002
#ifdef UF_READONLY
2003
  { "nordonly", L"nordonly",    UF_READONLY,  0},
2004
  { "nourdonly",  L"nourdonly",   UF_READONLY,  0},
2005
  { "noreadonly", L"noreadonly",    UF_READONLY,  0},
2006
#endif
2007
#ifdef FILE_ATTRIBUTE_READONLY
2008
  { "nordonly", L"nordonly",  FILE_ATTRIBUTE_READONLY,  0},
2009
  { "nourdonly",  L"nourdonly", FILE_ATTRIBUTE_READONLY,  0},
2010
  { "noreadonly", L"noreadonly",  FILE_ATTRIBUTE_READONLY,  0},
2011
#endif
2012
#ifdef UF_SPARSE
2013
  { "nosparse", L"nosparse",    UF_SPARSE,  0},
2014
  { "nousparse",  L"nousparse",   UF_SPARSE,  0},
2015
#endif
2016
#ifdef UF_REPARSE
2017
  { "noreparse",  L"noreparse",   UF_REPARSE, 0},
2018
  { "noureparse", L"noureparse",    UF_REPARSE, 0},
2019
#endif
2020
#ifdef UF_SYSTEM
2021
  { "nosystem", L"nosystem",    UF_SYSTEM,  0},
2022
  { "nousystem",  L"nousystem",   UF_SYSTEM,  0},
2023
#endif
2024
#ifdef FILE_ATTRIBUTE_SYSTEM
2025
  { "nosystem", L"nosystem",  FILE_ATTRIBUTE_SYSTEM,  0},
2026
  { "nousystem",  L"nousystem", FILE_ATTRIBUTE_SYSTEM,  0},
2027
#endif
2028
#if defined(FS_UNRM_FL)   /* 'u' */
2029
  { "noundel",  L"noundel",   FS_UNRM_FL, 0},
2030
#elif defined(EXT2_UNRM_FL)
2031
  { "noundel",  L"noundel",   EXT2_UNRM_FL, 0},
2032
#endif
2033
2034
#if defined(FS_COMPR_FL)  /* 'c' */
2035
  { "nocompress", L"nocompress",        FS_COMPR_FL,  0},
2036
#elif defined(EXT2_COMPR_FL)
2037
  { "nocompress", L"nocompress",        EXT2_COMPR_FL,  0},
2038
#endif
2039
2040
#if defined(FS_NOATIME_FL)  /* 'A' */
2041
  { "noatime",  L"noatime",   0,    FS_NOATIME_FL},
2042
#elif defined(EXT2_NOATIME_FL)
2043
  { "noatime",  L"noatime",   0,    EXT2_NOATIME_FL},
2044
#endif
2045
#if defined(FS_DIRSYNC_FL)  /* 'D' */
2046
  { "nodirsync",  L"nodirsync",   FS_DIRSYNC_FL,    0},
2047
#elif defined(EXT2_DIRSYNC_FL)
2048
  { "nodirsync",  L"nodirsync",   EXT2_DIRSYNC_FL,  0},
2049
#endif
2050
#if defined(FS_JOURNAL_DATA_FL) /* 'j' */
2051
  { "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0},
2052
  { "nojournal",  L"nojournal",   FS_JOURNAL_DATA_FL, 0},
2053
#elif defined(EXT3_JOURNAL_DATA_FL)
2054
  { "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0},
2055
  { "nojournal",  L"nojournal",   EXT3_JOURNAL_DATA_FL, 0},
2056
#endif
2057
#if defined(FS_SECRM_FL)  /* 's' */
2058
  { "nosecdel", L"nosecdel",    FS_SECRM_FL,    0},
2059
  { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL,   0},
2060
#elif defined(EXT2_SECRM_FL)
2061
  { "nosecdel", L"nosecdel",    EXT2_SECRM_FL,    0},
2062
  { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL,   0},
2063
#endif
2064
#if defined(FS_SYNC_FL)   /* 'S' */
2065
  { "nosync", L"nosync",    FS_SYNC_FL,   0},
2066
#elif defined(EXT2_SYNC_FL)
2067
  { "nosync", L"nosync",    EXT2_SYNC_FL,   0},
2068
#endif
2069
#if defined(FS_NOTAIL_FL) /* 't' */
2070
  { "notail", L"notail",    0,    FS_NOTAIL_FL},
2071
#elif defined(EXT2_NOTAIL_FL)
2072
  { "notail", L"notail",    0,    EXT2_NOTAIL_FL},
2073
#endif
2074
#if defined(FS_TOPDIR_FL) /* 'T' */
2075
  { "notopdir", L"notopdir",    FS_TOPDIR_FL,   0},
2076
#elif defined(EXT2_TOPDIR_FL)
2077
  { "notopdir", L"notopdir",    EXT2_TOPDIR_FL,   0},
2078
#endif
2079
#ifdef FS_NOCOW_FL  /* 'C' */
2080
  { "nocow",  L"nocow",   0,  FS_NOCOW_FL},
2081
#endif
2082
#ifdef FS_PROJINHERIT_FL  /* 'P' */
2083
  { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL,  0},
2084
#endif
2085
  { NULL,   NULL,     0,    0}
2086
};
2087
2088
/*
2089
 * fflagstostr --
2090
 *  Convert file flags to a comma-separated string.  If no flags
2091
 *  are set, return the empty string.
2092
 */
2093
static char *
2094
ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
2095
0
{
2096
0
  char *string, *dp;
2097
0
  const char *sp;
2098
0
  unsigned long bits;
2099
0
  const struct flag *flag;
2100
0
  size_t  length;
2101
2102
0
  bits = bitset | bitclear;
2103
0
  length = 0;
2104
0
  for (flag = fileflags; flag->name != NULL; flag++)
2105
0
    if (bits & (flag->set | flag->clear)) {
2106
0
      length += strlen(flag->name) + 1;
2107
0
      bits &= ~(flag->set | flag->clear);
2108
0
    }
2109
2110
0
  if (length == 0)
2111
0
    return (NULL);
2112
0
  string = malloc(length);
2113
0
  if (string == NULL)
2114
0
    return (NULL);
2115
2116
0
  dp = string;
2117
0
  for (flag = fileflags; flag->name != NULL; flag++) {
2118
0
    if (bitset & flag->set || bitclear & flag->clear) {
2119
0
      sp = flag->name + 2;
2120
0
    } else if (bitset & flag->clear  ||  bitclear & flag->set) {
2121
0
      sp = flag->name;
2122
0
    } else
2123
0
      continue;
2124
0
    bitset &= ~(flag->set | flag->clear);
2125
0
    bitclear &= ~(flag->set | flag->clear);
2126
0
    if (dp > string)
2127
0
      *dp++ = ',';
2128
0
    while ((*dp++ = *sp++) != '\0')
2129
0
      ;
2130
0
    dp--;
2131
0
  }
2132
2133
0
  *dp = '\0';
2134
0
  return (string);
2135
0
}
2136
2137
/*
2138
 * strtofflags --
2139
 *  Take string of arguments and return file flags.  This
2140
 *  version works a little differently than strtofflags(3).
2141
 *  In particular, it always tests every token, skipping any
2142
 *  unrecognized tokens.  It returns a pointer to the first
2143
 *  unrecognized token, or NULL if every token was recognized.
2144
 *  This version is also const-correct and does not modify the
2145
 *  provided string.
2146
 */
2147
static const char *
2148
ae_strtofflags(const char *s, size_t l, unsigned long *setp, unsigned long *clrp)
2149
3.77k
{
2150
3.77k
  const char *start, *end;
2151
3.77k
  const struct flag *flag;
2152
3.77k
  unsigned long set, clear;
2153
3.77k
  const char *failed;
2154
2155
3.77k
  set = clear = 0;
2156
3.77k
  start = s;
2157
3.77k
  failed = NULL;
2158
  /* Find start of first token. */
2159
6.72k
  while (l > 0 && (*start == '\t'  ||  *start == ' '  ||  *start == ',')) {
2160
2.95k
    start++;
2161
2.95k
    l--;
2162
2.95k
  }
2163
10.0k
  while (l > 0) {
2164
6.23k
    size_t length;
2165
    /* Locate end of token. */
2166
6.23k
    end = start;
2167
56.1k
    while (l > 0 && *end != '\t'  &&
2168
53.8k
        *end != ' '  &&  *end != ',') {
2169
49.8k
      end++;
2170
49.8k
      l--;
2171
49.8k
    }
2172
6.23k
    length = end - start;
2173
116k
    for (flag = fileflags; flag->name != NULL; flag++) {
2174
111k
      size_t flag_length = strlen(flag->name);
2175
111k
      if (length == flag_length
2176
6.68k
          && memcmp(start, flag->name, length) == 0) {
2177
        /* Matched "noXXXX", so reverse the sense. */
2178
106
        clear |= flag->set;
2179
106
        set |= flag->clear;
2180
106
        break;
2181
110k
      } else if (length == flag_length - 2
2182
11.3k
          && memcmp(start, flag->name + 2, length) == 0) {
2183
        /* Matched "XXXX", so don't reverse. */
2184
810
        set |= flag->set;
2185
810
        clear |= flag->clear;
2186
810
        break;
2187
810
      }
2188
111k
    }
2189
    /* Ignore unknown flag names. */
2190
6.23k
    if (flag->name == NULL  &&  failed == NULL)
2191
3.07k
      failed = start;
2192
2193
    /* Find start of next token. */
2194
6.23k
    start = end;
2195
10.3k
    while (l > 0 && (*start == '\t'  ||  *start == ' '  ||  *start == ',')) {
2196
4.10k
      start++;
2197
4.10k
      l--;
2198
4.10k
    }
2199
2200
6.23k
  }
2201
2202
3.77k
  if (setp)
2203
3.77k
    *setp = set;
2204
3.77k
  if (clrp)
2205
3.77k
    *clrp = clear;
2206
2207
  /* Return location of first failure. */
2208
3.77k
  return (failed);
2209
3.77k
}
2210
2211
/*
2212
 * wcstofflags --
2213
 *  Take string of arguments and return file flags.  This
2214
 *  version works a little differently than strtofflags(3).
2215
 *  In particular, it always tests every token, skipping any
2216
 *  unrecognized tokens.  It returns a pointer to the first
2217
 *  unrecognized token, or NULL if every token was recognized.
2218
 *  This version is also const-correct and does not modify the
2219
 *  provided string.
2220
 */
2221
static const wchar_t *
2222
ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
2223
0
{
2224
0
  const wchar_t *start, *end;
2225
0
  const struct flag *flag;
2226
0
  unsigned long set, clear;
2227
0
  const wchar_t *failed;
2228
2229
0
  set = clear = 0;
2230
0
  start = s;
2231
0
  failed = NULL;
2232
  /* Find start of first token. */
2233
0
  while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
2234
0
    start++;
2235
0
  while (*start != L'\0') {
2236
0
    size_t length;
2237
    /* Locate end of token. */
2238
0
    end = start;
2239
0
    while (*end != L'\0'  &&  *end != L'\t'  &&
2240
0
        *end != L' '  &&  *end != L',')
2241
0
      end++;
2242
0
    length = end - start;
2243
0
    for (flag = fileflags; flag->wname != NULL; flag++) {
2244
0
      size_t flag_length = wcslen(flag->wname);
2245
0
      if (length == flag_length
2246
0
          && wmemcmp(start, flag->wname, length) == 0) {
2247
        /* Matched "noXXXX", so reverse the sense. */
2248
0
        clear |= flag->set;
2249
0
        set |= flag->clear;
2250
0
        break;
2251
0
      } else if (length == flag_length - 2
2252
0
          && wmemcmp(start, flag->wname + 2, length) == 0) {
2253
        /* Matched "XXXX", so don't reverse. */
2254
0
        set |= flag->set;
2255
0
        clear |= flag->clear;
2256
0
        break;
2257
0
      }
2258
0
    }
2259
    /* Ignore unknown flag names. */
2260
0
    if (flag->wname == NULL  &&  failed == NULL)
2261
0
      failed = start;
2262
2263
    /* Find start of next token. */
2264
0
    start = end;
2265
0
    while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
2266
0
      start++;
2267
2268
0
  }
2269
2270
0
  if (setp)
2271
0
    *setp = set;
2272
0
  if (clrp)
2273
0
    *clrp = clear;
2274
2275
  /* Return location of first failure. */
2276
0
  return (failed);
2277
0
}
2278
2279
2280
#ifdef TEST
2281
#include <stdio.h>
2282
int
2283
main(int argc, char **argv)
2284
{
2285
  struct archive_entry *entry = archive_entry_new();
2286
  unsigned long set, clear;
2287
  const wchar_t *remainder;
2288
2289
  remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
2290
  archive_entry_fflags(entry, &set, &clear);
2291
2292
  wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
2293
2294
  wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
2295
  return (0);
2296
}
2297
#endif