~ubuntu-branches/ubuntu/utopic/cmake/utopic

« back to all changes in this revision

Viewing changes to Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-10-10 12:54:39 UTC
  • mfrom: (1.14.7)
  • Revision ID: package-import@ubuntu.com-20131010125439-h0ahaj004on6oj92
Tags: 2.8.12-0ubuntu1
New upstream release LP: #1246701

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*-
2
2
 * Copyright (c) 2003-2009 Tim Kientzle
3
 
 * Copyright (c) 2010 Michihiro NAKAJIMA
 
3
 * Copyright (c) 2010-2012 Michihiro NAKAJIMA
4
4
 * All rights reserved.
5
5
 *
6
6
 * Redistribution and use in source and binary forms, with or without
49
49
#ifdef HAVE_SYS_STAT_H
50
50
#include <sys/stat.h>
51
51
#endif
52
 
#ifdef HAVE_SYS_XATTR_H
 
52
#if defined(HAVE_SYS_XATTR_H)
53
53
#include <sys/xattr.h>
 
54
#elif defined(HAVE_ATTR_XATTR_H)
 
55
#include <attr/xattr.h>
54
56
#endif
55
57
#ifdef HAVE_SYS_EA_H
56
58
#include <sys/ea.h>
58
60
#ifdef HAVE_ACL_LIBACL_H
59
61
#include <acl/libacl.h>
60
62
#endif
61
 
#ifdef HAVE_ATTR_XATTR_H
62
 
#include <attr/xattr.h>
63
 
#endif
64
63
#ifdef HAVE_COPYFILE_H
65
64
#include <copyfile.h>
66
65
#endif
104
103
#include "archive_private.h"
105
104
#include "archive_read_disk_private.h"
106
105
 
 
106
#ifndef O_CLOEXEC
 
107
#define O_CLOEXEC       0
 
108
#endif
 
109
 
107
110
/*
108
111
 * Linux and FreeBSD plug this obvious hole in POSIX.1e in
109
112
 * different ways.
114
117
#define ACL_GET_PERM acl_get_perm_np
115
118
#endif
116
119
 
117
 
static int setup_acls_posix1e(struct archive_read_disk *,
118
 
    struct archive_entry *, int fd);
 
120
static int setup_acls(struct archive_read_disk *,
 
121
    struct archive_entry *, int *fd);
119
122
static int setup_mac_metadata(struct archive_read_disk *,
120
 
    struct archive_entry *, int fd);
 
123
    struct archive_entry *, int *fd);
121
124
static int setup_xattrs(struct archive_read_disk *,
122
 
    struct archive_entry *, int fd);
 
125
    struct archive_entry *, int *fd);
123
126
static int setup_sparse(struct archive_read_disk *,
124
 
    struct archive_entry *, int fd);
 
127
    struct archive_entry *, int *fd);
125
128
 
126
129
int
127
130
archive_read_disk_entry_from_file(struct archive *_a,
190
193
         * this is an extra step, it has a nice side-effect: We get an
191
194
         * open file descriptor which we can use in the subsequent lookups. */
192
195
        if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
193
 
                if (fd < 0)
194
 
                        fd = open(path, O_RDONLY | O_NONBLOCK);
 
196
                if (fd < 0) {
 
197
                        if (a->tree != NULL)
 
198
                                fd = a->open_on_current_dir(a->tree, path,
 
199
                                        O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 
200
                        else
 
201
                                fd = open(path, O_RDONLY | O_NONBLOCK |
 
202
                                                O_CLOEXEC);
 
203
                        __archive_ensure_cloexec_flag(fd);
 
204
                }
195
205
                if (fd >= 0) {
196
 
                        unsigned long stflags;
197
 
                        int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
 
206
                        int stflags;
 
207
                        r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
198
208
                        if (r == 0 && stflags != 0)
199
209
                                archive_entry_set_fflags(entry, stflags, 0);
200
210
                }
213
223
                            "Couldn't read link data");
214
224
                        return (ARCHIVE_FAILED);
215
225
                }
 
226
                if (a->tree != NULL) {
216
227
#ifdef HAVE_READLINKAT
217
 
                if (a->entry_wd_fd >= 0)
218
 
                        lnklen = readlinkat(a->entry_wd_fd, path,
219
 
                            linkbuffer, linkbuffer_len);
220
 
                else
 
228
                        lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
 
229
                            path, linkbuffer, linkbuffer_len);
 
230
#else
 
231
                        if (a->tree_enter_working_dir(a->tree) != 0) {
 
232
                                archive_set_error(&a->archive, errno,
 
233
                                    "Couldn't read link data");
 
234
                                free(linkbuffer);
 
235
                                return (ARCHIVE_FAILED);
 
236
                        }
 
237
                        lnklen = readlink(path, linkbuffer, linkbuffer_len);
221
238
#endif /* HAVE_READLINKAT */
222
 
                lnklen = readlink(path, linkbuffer, linkbuffer_len);
 
239
                } else
 
240
                        lnklen = readlink(path, linkbuffer, linkbuffer_len);
223
241
                if (lnklen < 0) {
224
242
                        archive_set_error(&a->archive, errno,
225
243
                            "Couldn't read link data");
232
250
        }
233
251
#endif /* HAVE_READLINK || HAVE_READLINKAT */
234
252
 
235
 
        r = setup_acls_posix1e(a, entry, fd);
236
 
        r1 = setup_xattrs(a, entry, fd);
237
 
        if (r1 < r)
238
 
                r = r1;
239
 
        r1 = setup_mac_metadata(a, entry, fd);
240
 
        if (r1 < r)
241
 
                r = r1;
242
 
        r1 = setup_sparse(a, entry, fd);
 
253
        r = setup_acls(a, entry, &fd);
 
254
        r1 = setup_xattrs(a, entry, &fd);
 
255
        if (r1 < r)
 
256
                r = r1;
 
257
        if (a->enable_copyfile) {
 
258
                r1 = setup_mac_metadata(a, entry, &fd);
 
259
                if (r1 < r)
 
260
                        r = r1;
 
261
        }
 
262
        r1 = setup_sparse(a, entry, &fd);
243
263
        if (r1 < r)
244
264
                r = r1;
245
265
 
265
285
 */
266
286
static int
267
287
setup_mac_metadata(struct archive_read_disk *a,
268
 
    struct archive_entry *entry, int fd)
 
288
    struct archive_entry *entry, int *fd)
269
289
{
270
290
        int tempfd = -1;
271
291
        int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
272
292
        struct stat copyfile_stat;
273
293
        int ret = ARCHIVE_OK;
274
 
        void *buff;
 
294
        void *buff = NULL;
275
295
        int have_attrs;
276
 
        const char *name, *tempdir, *tempfile = NULL;
 
296
        const char *name, *tempdir;
 
297
        struct archive_string tempfile;
277
298
 
 
299
        (void)fd; /* UNUSED */
278
300
        name = archive_entry_sourcepath(entry);
279
301
        if (name == NULL)
280
302
                name = archive_entry_pathname(entry);
284
306
                return (ARCHIVE_WARN);
285
307
        }
286
308
 
 
309
        if (a->tree != NULL) {
 
310
                if (a->tree_enter_working_dir(a->tree) != 0) {
 
311
                        archive_set_error(&a->archive, errno,
 
312
                                    "Couldn't change dir");
 
313
                                return (ARCHIVE_FAILED);
 
314
                }
 
315
        }
 
316
 
287
317
        /* Short-circuit if there's nothing to do. */
288
318
        have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
289
319
        if (have_attrs == -1) {
299
329
                tempdir = getenv("TMPDIR");
300
330
        if (tempdir == NULL)
301
331
                tempdir = _PATH_TMP;
302
 
        tempfile = tempnam(tempdir, "tar.md.");
 
332
        archive_string_init(&tempfile);
 
333
        archive_strcpy(&tempfile, tempdir);
 
334
        archive_strcat(&tempfile, "tar.md.XXXXXX");
 
335
        tempfd = mkstemp(tempfile.s);
 
336
        if (tempfd < 0) {
 
337
                archive_set_error(&a->archive, errno,
 
338
                    "Could not open extended attribute file");
 
339
                ret = ARCHIVE_WARN;
 
340
                goto cleanup;
 
341
        }
 
342
        __archive_ensure_cloexec_flag(tempfd);
303
343
 
304
344
        /* XXX I wish copyfile() could pack directly to a memory
305
345
         * buffer; that would avoid the temp file here.  For that
306
346
         * matter, it would be nice if fcopyfile() actually worked,
307
347
         * that would reduce the many open/close races here. */
308
 
        if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
 
348
        if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
309
349
                archive_set_error(&a->archive, errno,
310
350
                    "Could not pack extended attributes");
311
351
                ret = ARCHIVE_WARN;
312
352
                goto cleanup;
313
353
        }
314
 
        tempfd = open(tempfile, O_RDONLY);
315
 
        if (tempfd < 0) {
316
 
                archive_set_error(&a->archive, errno,
317
 
                    "Could not open extended attribute file");
318
 
                ret = ARCHIVE_WARN;
319
 
                goto cleanup;
320
 
        }
321
354
        if (fstat(tempfd, &copyfile_stat)) {
322
355
                archive_set_error(&a->archive, errno,
323
356
                    "Could not check size of extended attributes");
340
373
        archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
341
374
 
342
375
cleanup:
343
 
        if (tempfd >= 0)
 
376
        if (tempfd >= 0) {
344
377
                close(tempfd);
345
 
        if (tempfile != NULL)
346
 
                unlink(tempfile);
 
378
                unlink(tempfile.s);
 
379
        }
 
380
        archive_string_free(&tempfile);
 
381
        free(buff);
347
382
        return (ret);
348
383
}
349
384
 
354
389
 */
355
390
static int
356
391
setup_mac_metadata(struct archive_read_disk *a,
357
 
    struct archive_entry *entry, int fd)
 
392
    struct archive_entry *entry, int *fd)
358
393
{
359
394
        (void)a; /* UNUSED */
360
395
        (void)entry; /* UNUSED */
364
399
#endif
365
400
 
366
401
 
367
 
#ifdef HAVE_POSIX_ACL
368
 
static void setup_acl_posix1e(struct archive_read_disk *a,
 
402
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
 
403
static int translate_acl(struct archive_read_disk *a,
369
404
    struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
370
405
 
371
406
static int
372
 
setup_acls_posix1e(struct archive_read_disk *a,
373
 
    struct archive_entry *entry, int fd)
 
407
setup_acls(struct archive_read_disk *a,
 
408
    struct archive_entry *entry, int *fd)
374
409
{
375
410
        const char      *accpath;
376
411
        acl_t            acl;
 
412
#if HAVE_ACL_IS_TRIVIAL_NP
 
413
        int             r;
 
414
#endif
377
415
 
378
416
        accpath = archive_entry_sourcepath(entry);
379
417
        if (accpath == NULL)
381
419
 
382
420
        archive_entry_acl_clear(entry);
383
421
 
 
422
        /* Try NFS4 ACL first. */
 
423
        if (*fd >= 0)
 
424
                acl = acl_get_fd(*fd);
 
425
#if HAVE_ACL_GET_LINK_NP
 
426
        else if (!a->follow_symlinks)
 
427
                acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
 
428
#else
 
429
        else if ((!a->follow_symlinks)
 
430
            && (archive_entry_filetype(entry) == AE_IFLNK))
 
431
                /* We can't get the ACL of a symlink, so we assume it can't
 
432
                   have one. */
 
433
                acl = NULL;
 
434
#endif
 
435
        else
 
436
                acl = acl_get_file(accpath, ACL_TYPE_NFS4);
 
437
#if HAVE_ACL_IS_TRIVIAL_NP
 
438
        /* Ignore "trivial" ACLs that just mirror the file mode. */
 
439
        acl_is_trivial_np(acl, &r);
 
440
        if (r) {
 
441
                acl_free(acl);
 
442
                acl = NULL;
 
443
        }
 
444
#endif
 
445
        if (acl != NULL) {
 
446
                translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
 
447
                acl_free(acl);
 
448
                return (ARCHIVE_OK);
 
449
        }
 
450
 
384
451
        /* Retrieve access ACL from file. */
385
 
        if (fd >= 0)
386
 
                acl = acl_get_fd(fd);
 
452
        if (*fd >= 0)
 
453
                acl = acl_get_fd(*fd);
387
454
#if HAVE_ACL_GET_LINK_NP
388
455
        else if (!a->follow_symlinks)
389
456
                acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
397
464
        else
398
465
                acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
399
466
        if (acl != NULL) {
400
 
                setup_acl_posix1e(a, entry, acl,
 
467
                translate_acl(a, entry, acl,
401
468
                    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
402
469
                acl_free(acl);
403
470
        }
406
473
        if (S_ISDIR(archive_entry_mode(entry))) {
407
474
                acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
408
475
                if (acl != NULL) {
409
 
                        setup_acl_posix1e(a, entry, acl,
 
476
                        translate_acl(a, entry, acl,
410
477
                            ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
411
478
                        acl_free(acl);
412
479
                }
415
482
}
416
483
 
417
484
/*
418
 
 * Translate POSIX.1e ACL into libarchive internal structure.
 
485
 * Translate system ACL into libarchive internal structure.
419
486
 */
420
 
static void
421
 
setup_acl_posix1e(struct archive_read_disk *a,
422
 
    struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
 
487
 
 
488
static struct {
 
489
        int archive_perm;
 
490
        int platform_perm;
 
491
} acl_perm_map[] = {
 
492
        {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
 
493
        {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
 
494
        {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
 
495
        {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
 
496
        {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
 
497
        {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
 
498
        {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
 
499
        {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
 
500
        {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
 
501
        {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
 
502
        {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
 
503
        {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
 
504
        {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
 
505
        {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
 
506
        {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
 
507
        {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
 
508
        {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
 
509
        {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
 
510
        {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
 
511
};
 
512
 
 
513
static struct {
 
514
        int archive_inherit;
 
515
        int platform_inherit;
 
516
} acl_inherit_map[] = {
 
517
        {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
 
518
        {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
 
519
        {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
 
520
        {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
 
521
};
 
522
 
 
523
static int
 
524
translate_acl(struct archive_read_disk *a,
 
525
    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
423
526
{
424
527
        acl_tag_t        acl_tag;
 
528
        acl_entry_type_t acl_type;
 
529
        acl_flagset_t    acl_flagset;
425
530
        acl_entry_t      acl_entry;
426
531
        acl_permset_t    acl_permset;
 
532
        int              brand, i, r, entry_acl_type;
427
533
        int              s, ae_id, ae_tag, ae_perm;
428
534
        const char      *ae_name;
429
535
 
 
536
 
 
537
        // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
 
538
        // Make sure the "brand" on this ACL is consistent
 
539
        // with the default_entry_acl_type bits provided.
 
540
        acl_get_brand_np(acl, &brand);
 
541
        switch (brand) {
 
542
        case ACL_BRAND_POSIX:
 
543
                switch (default_entry_acl_type) {
 
544
                case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
 
545
                case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
 
546
                        break;
 
547
                default:
 
548
                        // XXX set warning message?
 
549
                        return ARCHIVE_FAILED;
 
550
                }
 
551
                break;
 
552
        case ACL_BRAND_NFS4:
 
553
                if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
 
554
                        // XXX set warning message?
 
555
                        return ARCHIVE_FAILED;
 
556
                }
 
557
                break;
 
558
        default:
 
559
                // XXX set warning message?
 
560
                return ARCHIVE_FAILED;
 
561
                break;
 
562
        }
 
563
 
 
564
 
430
565
        s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
431
566
        while (s == 1) {
432
567
                ae_id = -1;
433
568
                ae_name = NULL;
 
569
                ae_perm = 0;
434
570
 
435
571
                acl_get_tag_type(acl_entry, &acl_tag);
436
 
                if (acl_tag == ACL_USER) {
 
572
                switch (acl_tag) {
 
573
                case ACL_USER:
437
574
                        ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
438
575
                        ae_name = archive_read_disk_uname(&a->archive, ae_id);
439
576
                        ae_tag = ARCHIVE_ENTRY_ACL_USER;
440
 
                } else if (acl_tag == ACL_GROUP) {
 
577
                        break;
 
578
                case ACL_GROUP:
441
579
                        ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
442
580
                        ae_name = archive_read_disk_gname(&a->archive, ae_id);
443
581
                        ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
444
 
                } else if (acl_tag == ACL_MASK) {
 
582
                        break;
 
583
                case ACL_MASK:
445
584
                        ae_tag = ARCHIVE_ENTRY_ACL_MASK;
446
 
                } else if (acl_tag == ACL_USER_OBJ) {
 
585
                        break;
 
586
                case ACL_USER_OBJ:
447
587
                        ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
448
 
                } else if (acl_tag == ACL_GROUP_OBJ) {
 
588
                        break;
 
589
                case ACL_GROUP_OBJ:
449
590
                        ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
450
 
                } else if (acl_tag == ACL_OTHER) {
 
591
                        break;
 
592
                case ACL_OTHER:
451
593
                        ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
452
 
                } else {
 
594
                        break;
 
595
                case ACL_EVERYONE:
 
596
                        ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
 
597
                        break;
 
598
                default:
453
599
                        /* Skip types that libarchive can't support. */
 
600
                        s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
454
601
                        continue;
455
602
                }
456
603
 
457
 
                acl_get_permset(acl_entry, &acl_permset);
458
 
                ae_perm = 0;
 
604
                // XXX acl type maps to allow/deny/audit/YYYY bits
 
605
                // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
 
606
                // non-NFSv4 ACLs
 
607
                entry_acl_type = default_entry_acl_type;
 
608
                r = acl_get_entry_type_np(acl_entry, &acl_type);
 
609
                if (r == 0) {
 
610
                        switch (acl_type) {
 
611
                        case ACL_ENTRY_TYPE_ALLOW:
 
612
                                entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
 
613
                                break;
 
614
                        case ACL_ENTRY_TYPE_DENY:
 
615
                                entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
 
616
                                break;
 
617
                        case ACL_ENTRY_TYPE_AUDIT:
 
618
                                entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
 
619
                                break;
 
620
                        case ACL_ENTRY_TYPE_ALARM:
 
621
                                entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
 
622
                                break;
 
623
                        }
 
624
                }
 
625
 
459
626
                /*
460
 
                 * acl_get_perm() is spelled differently on different
461
 
                 * platforms; see above.
 
627
                 * Libarchive stores "flag" (NFSv4 inheritance bits)
 
628
                 * in the ae_perm bitmap.
462
629
                 */
463
 
                if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
464
 
                        ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
465
 
                if (ACL_GET_PERM(acl_permset, ACL_READ))
466
 
                        ae_perm |= ARCHIVE_ENTRY_ACL_READ;
467
 
                if (ACL_GET_PERM(acl_permset, ACL_WRITE))
468
 
                        ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
469
 
 
470
 
                archive_entry_acl_add_entry(entry,
471
 
                    archive_entry_acl_type, ae_perm, ae_tag,
472
 
                    ae_id, ae_name);
 
630
                acl_get_flagset_np(acl_entry, &acl_flagset);
 
631
                for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
 
632
                        if (acl_get_flag_np(acl_flagset,
 
633
                                            acl_inherit_map[i].platform_inherit))
 
634
                                ae_perm |= acl_inherit_map[i].archive_inherit;
 
635
 
 
636
                }
 
637
 
 
638
                acl_get_permset(acl_entry, &acl_permset);
 
639
                for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
 
640
                        /*
 
641
                         * acl_get_perm() is spelled differently on different
 
642
                         * platforms; see above.
 
643
                         */
 
644
                        if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
 
645
                                ae_perm |= acl_perm_map[i].archive_perm;
 
646
                }
 
647
 
 
648
                archive_entry_acl_add_entry(entry, entry_acl_type,
 
649
                                            ae_perm, ae_tag,
 
650
                                            ae_id, ae_name);
473
651
 
474
652
                s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
475
653
        }
 
654
        return (ARCHIVE_OK);
476
655
}
477
656
#else
478
657
static int
479
 
setup_acls_posix1e(struct archive_read_disk *a,
480
 
    struct archive_entry *entry, int fd)
 
658
setup_acls(struct archive_read_disk *a,
 
659
    struct archive_entry *entry, int *fd)
481
660
{
482
661
        (void)a;      /* UNUSED */
483
662
        (void)entry;  /* UNUSED */
571
750
 
572
751
static int
573
752
setup_xattrs(struct archive_read_disk *a,
574
 
    struct archive_entry *entry, int fd)
 
753
    struct archive_entry *entry, int *fd)
575
754
{
576
755
        char *list, *p;
577
756
        const char *path;
581
760
        if (path == NULL)
582
761
                path = archive_entry_pathname(entry);
583
762
 
 
763
        if (*fd < 0 && a->tree != NULL) {
 
764
                if (a->follow_symlinks ||
 
765
                    archive_entry_filetype(entry) != AE_IFLNK)
 
766
                        *fd = a->open_on_current_dir(a->tree, path,
 
767
                                O_RDONLY | O_NONBLOCK);
 
768
                if (*fd < 0) {
 
769
                        if (a->tree_enter_working_dir(a->tree) != 0) {
 
770
                                archive_set_error(&a->archive, errno,
 
771
                                    "Couldn't access %s", path);
 
772
                                return (ARCHIVE_FAILED);
 
773
                        }
 
774
                }
 
775
        }
 
776
 
584
777
#if HAVE_FLISTXATTR
585
 
        if (fd >= 0)
586
 
                list_size = flistxattr(fd, NULL, 0);
 
778
        if (*fd >= 0)
 
779
                list_size = flistxattr(*fd, NULL, 0);
587
780
        else if (!a->follow_symlinks)
588
781
                list_size = llistxattr(path, NULL, 0);
589
782
        else
590
783
                list_size = listxattr(path, NULL, 0);
591
784
#elif HAVE_FLISTEA
592
 
        if (fd >= 0)
593
 
                list_size = flistea(fd, NULL, 0);
 
785
        if (*fd >= 0)
 
786
                list_size = flistea(*fd, NULL, 0);
594
787
        else if (!a->follow_symlinks)
595
788
                list_size = llistea(path, NULL, 0);
596
789
        else
614
807
        }
615
808
 
616
809
#if HAVE_FLISTXATTR
617
 
        if (fd >= 0)
618
 
                list_size = flistxattr(fd, list, list_size);
 
810
        if (*fd >= 0)
 
811
                list_size = flistxattr(*fd, list, list_size);
619
812
        else if (!a->follow_symlinks)
620
813
                list_size = llistxattr(path, list, list_size);
621
814
        else
622
815
                list_size = listxattr(path, list, list_size);
623
816
#elif HAVE_FLISTEA
624
 
        if (fd >= 0)
625
 
                list_size = flistea(fd, list, list_size);
 
817
        if (*fd >= 0)
 
818
                list_size = flistea(*fd, list, list_size);
626
819
        else if (!a->follow_symlinks)
627
820
                list_size = llistea(path, list, list_size);
628
821
        else
640
833
                if (strncmp(p, "system.", 7) == 0 ||
641
834
                                strncmp(p, "xfsroot.", 8) == 0)
642
835
                        continue;
643
 
                setup_xattr(a, entry, p, fd);
 
836
                setup_xattr(a, entry, p, *fd);
644
837
        }
645
838
 
646
839
        free(list);
701
894
                size = extattr_get_file(accpath, namespace, name, value, size);
702
895
 
703
896
        if (size == -1) {
 
897
                free(value);
704
898
                archive_set_error(&a->archive, errno,
705
899
                    "Couldn't read extended attribute");
706
900
                return (ARCHIVE_WARN);
714
908
 
715
909
static int
716
910
setup_xattrs(struct archive_read_disk *a,
717
 
    struct archive_entry *entry, int fd)
 
911
    struct archive_entry *entry, int *fd)
718
912
{
719
913
        char buff[512];
720
914
        char *list, *p;
726
920
        if (path == NULL)
727
921
                path = archive_entry_pathname(entry);
728
922
 
729
 
        if (fd >= 0)
730
 
                list_size = extattr_list_fd(fd, namespace, NULL, 0);
 
923
        if (*fd < 0 && a->tree != NULL) {
 
924
                if (a->follow_symlinks ||
 
925
                    archive_entry_filetype(entry) != AE_IFLNK)
 
926
                        *fd = a->open_on_current_dir(a->tree, path,
 
927
                                O_RDONLY | O_NONBLOCK);
 
928
                if (*fd < 0) {
 
929
                        if (a->tree_enter_working_dir(a->tree) != 0) {
 
930
                                archive_set_error(&a->archive, errno,
 
931
                                    "Couldn't access %s", path);
 
932
                                return (ARCHIVE_FAILED);
 
933
                        }
 
934
                }
 
935
        }
 
936
 
 
937
        if (*fd >= 0)
 
938
                list_size = extattr_list_fd(*fd, namespace, NULL, 0);
731
939
        else if (!a->follow_symlinks)
732
940
                list_size = extattr_list_link(path, namespace, NULL, 0);
733
941
        else
749
957
                return (ARCHIVE_FATAL);
750
958
        }
751
959
 
752
 
        if (fd >= 0)
753
 
                list_size = extattr_list_fd(fd, namespace, list, list_size);
 
960
        if (*fd >= 0)
 
961
                list_size = extattr_list_fd(*fd, namespace, list, list_size);
754
962
        else if (!a->follow_symlinks)
755
963
                list_size = extattr_list_link(path, namespace, list, list_size);
756
964
        else
772
980
                name = buff + strlen(buff);
773
981
                memcpy(name, p + 1, len);
774
982
                name[len] = '\0';
775
 
                setup_xattr(a, entry, namespace, name, buff, fd);
 
983
                setup_xattr(a, entry, namespace, name, buff, *fd);
776
984
                p += 1 + len;
777
985
        }
778
986
 
787
995
 */
788
996
static int
789
997
setup_xattrs(struct archive_read_disk *a,
790
 
    struct archive_entry *entry, int fd)
 
998
    struct archive_entry *entry, int *fd)
791
999
{
792
1000
        (void)a;     /* UNUSED */
793
1001
        (void)entry; /* UNUSED */
816
1024
 
817
1025
static int
818
1026
setup_sparse(struct archive_read_disk *a,
819
 
    struct archive_entry *entry, int fd)
 
1027
    struct archive_entry *entry, int *fd)
820
1028
{
821
1029
        char buff[4096];
822
1030
        struct fiemap *fm;
823
1031
        struct fiemap_extent *fe;
824
1032
        int64_t size;
825
1033
        int count, do_fiemap;
826
 
        int initial_fd = fd;
827
1034
        int exit_sts = ARCHIVE_OK;
828
1035
 
829
1036
        if (archive_entry_filetype(entry) != AE_IFREG
831
1038
            || archive_entry_hardlink(entry) != NULL)
832
1039
                return (ARCHIVE_OK);
833
1040
 
834
 
        if (fd < 0) {
 
1041
        if (*fd < 0) {
835
1042
                const char *path;
836
1043
 
837
1044
                path = archive_entry_sourcepath(entry);
838
1045
                if (path == NULL)
839
1046
                        path = archive_entry_pathname(entry);
840
 
                fd = open(path, O_RDONLY | O_NONBLOCK);
841
 
                if (fd < 0) {
 
1047
                if (a->tree != NULL)
 
1048
                        *fd = a->open_on_current_dir(a->tree, path,
 
1049
                                O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 
1050
                else
 
1051
                        *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 
1052
                if (*fd < 0) {
842
1053
                        archive_set_error(&a->archive, errno,
843
1054
                            "Can't open `%s'", path);
844
1055
                        return (ARCHIVE_FAILED);
845
1056
                }
 
1057
                __archive_ensure_cloexec_flag(*fd);
846
1058
        }
847
1059
 
 
1060
        /* Initialize buffer to avoid the error valgrind complains about. */
 
1061
        memset(buff, 0, sizeof(buff));
848
1062
        count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
849
1063
        fm = (struct fiemap *)buff;
850
1064
        fm->fm_start = 0;
856
1070
        for (;;) {
857
1071
                int i, r;
858
1072
 
859
 
                r = ioctl(fd, FS_IOC_FIEMAP, fm); 
 
1073
                r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
860
1074
                if (r < 0) {
861
 
                        /* When errno is ENOTTY, it is better we should
862
 
                         * return ARCHIVE_OK because an earlier version
863
 
                         *(<2.6.28) cannot perfom FS_IOC_FIEMAP.
864
 
                         * We should also check if errno is EOPNOTSUPP,
865
 
                         * it means "Operation not supported". */
866
 
                        if (errno != ENOTTY && errno != EOPNOTSUPP) {
867
 
                                archive_set_error(&a->archive, errno,
868
 
                                    "FIEMAP failed");
869
 
                                exit_sts = ARCHIVE_FAILED;
870
 
                        }
 
1075
                        /* When something error happens, it is better we
 
1076
                         * should return ARCHIVE_OK because an earlier
 
1077
                         * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
871
1078
                        goto exit_setup_sparse;
872
1079
                }
873
1080
                if (fm->fm_mapped_extents == 0)
874
1081
                        break;
875
1082
                fe = fm->fm_extents;
876
 
                for (i = 0; i < fm->fm_mapped_extents; i++, fe++) {
 
1083
                for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
877
1084
                        if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
878
1085
                                /* The fe_length of the last block does not
879
1086
                                 * adjust itself to its size files. */
880
1087
                                int64_t length = fe->fe_length;
881
 
                                if (fe->fe_logical + length > size)
 
1088
                                if (fe->fe_logical + length > (uint64_t)size)
882
1089
                                        length -= fe->fe_logical + length - size;
883
1090
                                if (fe->fe_logical == 0 && length == size) {
884
1091
                                        /* This is not sparse. */
899
1106
                        break;
900
1107
        }
901
1108
exit_setup_sparse:
902
 
        if (initial_fd != fd)
903
 
                close(fd);
904
1109
        return (exit_sts);
905
1110
}
906
1111
 
912
1117
 
913
1118
static int
914
1119
setup_sparse(struct archive_read_disk *a,
915
 
    struct archive_entry *entry, int fd)
 
1120
    struct archive_entry *entry, int *fd)
916
1121
{
917
1122
        int64_t size;
918
 
        int initial_fd = fd;
919
1123
        off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
920
1124
        off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
921
1125
        int exit_sts = ARCHIVE_OK;
926
1130
                return (ARCHIVE_OK);
927
1131
 
928
1132
        /* Does filesystem support the reporting of hole ? */
929
 
        if (fd >= 0) {
930
 
                if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0)
 
1133
        if (*fd < 0 && a->tree != NULL) {
 
1134
                const char *path;
 
1135
 
 
1136
                path = archive_entry_sourcepath(entry);
 
1137
                if (path == NULL)
 
1138
                        path = archive_entry_pathname(entry);
 
1139
                *fd = a->open_on_current_dir(a->tree, path,
 
1140
                                O_RDONLY | O_NONBLOCK);
 
1141
                if (*fd < 0) {
 
1142
                        archive_set_error(&a->archive, errno,
 
1143
                            "Can't open `%s'", path);
 
1144
                        return (ARCHIVE_FAILED);
 
1145
                }
 
1146
        }
 
1147
 
 
1148
        if (*fd >= 0) {
 
1149
                if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
931
1150
                        return (ARCHIVE_OK);
932
 
                initial_off = lseek(fd, 0, SEEK_CUR);
 
1151
                initial_off = lseek(*fd, 0, SEEK_CUR);
933
1152
                if (initial_off != 0)
934
 
                        lseek(fd, 0, SEEK_SET);
 
1153
                        lseek(*fd, 0, SEEK_SET);
935
1154
        } else {
936
1155
                const char *path;
937
1156
 
938
1157
                path = archive_entry_sourcepath(entry);
939
1158
                if (path == NULL)
940
1159
                        path = archive_entry_pathname(entry);
 
1160
                        
941
1161
                if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
942
1162
                        return (ARCHIVE_OK);
943
 
                fd = open(path, O_RDONLY | O_NONBLOCK);
944
 
                if (fd < 0) {
 
1163
                *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 
1164
                if (*fd < 0) {
945
1165
                        archive_set_error(&a->archive, errno,
946
1166
                            "Can't open `%s'", path);
947
1167
                        return (ARCHIVE_FAILED);
948
1168
                }
 
1169
                __archive_ensure_cloexec_flag(*fd);
949
1170
                initial_off = 0;
950
1171
        }
951
1172
 
952
1173
        off_s = 0;
953
1174
        size = archive_entry_size(entry);
954
1175
        while (off_s < size) {
955
 
                off_s = lseek(fd, off_s, SEEK_DATA);
 
1176
                off_s = lseek(*fd, off_s, SEEK_DATA);
956
1177
                if (off_s == (off_t)-1) {
957
1178
                        if (errno == ENXIO)
958
1179
                                break;/* no more hole */
961
1182
                        exit_sts = ARCHIVE_FAILED;
962
1183
                        goto exit_setup_sparse;
963
1184
                }
964
 
                off_e = lseek(fd, off_s, SEEK_HOLE);
965
 
                if (off_s == (off_t)-1) {
 
1185
                off_e = lseek(*fd, off_s, SEEK_HOLE);
 
1186
                if (off_e == (off_t)-1) {
966
1187
                        if (errno == ENXIO) {
967
 
                                off_e = lseek(fd, 0, SEEK_END);
 
1188
                                off_e = lseek(*fd, 0, SEEK_END);
968
1189
                                if (off_e != (off_t)-1)
969
1190
                                        break;/* no more data */
970
1191
                        }
980
1201
                off_s = off_e;
981
1202
        }
982
1203
exit_setup_sparse:
983
 
        if (initial_fd != fd)
984
 
                close(fd);
985
 
        else
986
 
                lseek(fd, initial_off, SEEK_SET);
 
1204
        lseek(*fd, initial_off, SEEK_SET);
987
1205
        return (exit_sts);
988
1206
}
989
1207
 
994
1212
 */
995
1213
static int
996
1214
setup_sparse(struct archive_read_disk *a,
997
 
    struct archive_entry *entry, int fd)
 
1215
    struct archive_entry *entry, int *fd)
998
1216
{
999
1217
        (void)a;     /* UNUSED */
1000
1218
        (void)entry; /* UNUSED */