diff options
Diffstat (limited to 'libarchive/archive_read_disk_posix.c')
| -rw-r--r-- | libarchive/archive_read_disk_posix.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 1787d864ca92..22a1f14c0e03 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -356,6 +356,8 @@ static int _archive_read_free(struct archive *); static int _archive_read_close(struct archive *); static int _archive_read_data_block(struct archive *, const void **, size_t *, int64_t *); +static int _archive_read_next_header(struct archive *, + struct archive_entry **); static int _archive_read_next_header2(struct archive *, struct archive_entry *); static const char *trivial_lookup_gname(void *, int64_t gid); @@ -377,6 +379,7 @@ archive_read_disk_vtable(void) av.archive_free = _archive_read_free; av.archive_close = _archive_read_close; av.archive_read_data_block = _archive_read_data_block; + av.archive_read_next_header = _archive_read_next_header; av.archive_read_next_header2 = _archive_read_next_header2; inited = 1; } @@ -459,6 +462,7 @@ archive_read_disk_new(void) a->archive.magic = ARCHIVE_READ_DISK_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_read_disk_vtable(); + a->entry = archive_entry_new2(&a->archive); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; a->enable_copyfile = 1; @@ -491,6 +495,7 @@ _archive_read_free(struct archive *_a) if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL) (a->cleanup_uname)(a->lookup_uname_data); archive_string_free(&a->archive.error_string); + archive_entry_free(a->entry); a->archive.magic = 0; __archive_clean(&a->archive); free(a); @@ -609,6 +614,10 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) a->traverse_mount_points = 0; else a->traverse_mount_points = 1; + if (flags & ARCHIVE_READDISK_NO_XATTR) + a->suppress_xattr = 1; + else + a->suppress_xattr = 0; return (r); } @@ -708,6 +717,7 @@ _archive_read_data_block(struct archive *_a, const void **buff, int r; ssize_t bytes; size_t buffbytes; + int empty_sparse_region = 0; archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_block"); @@ -789,6 +799,9 @@ _archive_read_data_block(struct archive *_a, const void **buff, if ((int64_t)buffbytes > t->current_sparse->length) buffbytes = t->current_sparse->length; + if (t->current_sparse->length == 0) + empty_sparse_region = 1; + /* * Skip hole. * TODO: Should we consider t->current_filesystem->xfer_align? @@ -819,7 +832,11 @@ _archive_read_data_block(struct archive *_a, const void **buff, } } else bytes = 0; - if (bytes == 0) { + /* + * Return an EOF unless we've read a leading empty sparse region, which + * is used to represent fully-sparse files. + */ + if (bytes == 0 && !empty_sparse_region) { /* Get EOF */ t->entry_eof = 1; r = ARCHIVE_EOF; @@ -1081,6 +1098,17 @@ next_entry(struct archive_read_disk *a, struct tree *t, } static int +_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) +{ + int ret; + struct archive_read_disk *a = (struct archive_read_disk *)_a; + *entryp = NULL; + ret = _archive_read_next_header2(_a, a->entry); + *entryp = a->entry; + return ret; +} + +static int _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) { struct archive_read_disk *a = (struct archive_read_disk *)_a; @@ -1148,6 +1176,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) break; } + __archive_reset_read_data(&a->archive); return (r); } @@ -1555,6 +1584,7 @@ setup_current_filesystem(struct archive_read_disk *a) #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) t->current_filesystem->name_max = sfs.f_namemax; #else +# if defined(_PC_NAME_MAX) /* Mac OS X does not have f_namemax in struct statfs. */ if (tree_current_is_symblic_link_target(t)) { if (tree_enter_working_dir(t) != 0) { @@ -1564,6 +1594,9 @@ setup_current_filesystem(struct archive_read_disk *a) nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); } else nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); +# else + nm = -1; +# endif if (nm == -1) t->current_filesystem->name_max = NAME_MAX; else @@ -1660,7 +1693,9 @@ setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; struct statfs sfs; +#if defined(HAVE_STATVFS) struct statvfs svfs; +#endif int r, vr = 0, xr = 0; if (tree_current_is_symblic_link_target(t)) { @@ -1677,7 +1712,9 @@ setup_current_filesystem(struct archive_read_disk *a) "openat failed"); return (ARCHIVE_FAILED); } +#if defined(HAVE_FSTATVFS) vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */ +#endif r = fstatfs(fd, &sfs); if (r == 0) xr = get_xfer_size(t, fd, NULL); @@ -1687,14 +1724,18 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "fchdir failed"); return (ARCHIVE_FAILED); } +#if defined(HAVE_STATVFS) vr = statvfs(tree_current_access_path(t), &svfs); +#endif r = statfs(tree_current_access_path(t), &sfs); if (r == 0) xr = get_xfer_size(t, -1, tree_current_access_path(t)); #endif } else { #ifdef HAVE_FSTATFS +#if defined(HAVE_FSTATVFS) vr = fstatvfs(tree_current_dir_fd(t), &svfs); +#endif r = fstatfs(tree_current_dir_fd(t), &sfs); if (r == 0) xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); @@ -1703,7 +1744,9 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "fchdir failed"); return (ARCHIVE_FAILED); } +#if defined(HAVE_STATVFS) vr = statvfs(".", &svfs); +#endif r = statfs(".", &sfs); if (r == 0) xr = get_xfer_size(t, -1, "."); @@ -1716,10 +1759,17 @@ setup_current_filesystem(struct archive_read_disk *a) return (ARCHIVE_FAILED); } else if (xr == 1) { /* pathconf(_PC_REX_*) operations are not supported. */ +#if defined(HAVE_STATVFS) t->current_filesystem->xfer_align = svfs.f_frsize; t->current_filesystem->max_xfer_size = -1; t->current_filesystem->min_xfer_size = svfs.f_bsize; t->current_filesystem->incr_xfer_size = svfs.f_bsize; +#else + t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->max_xfer_size = -1; + t->current_filesystem->min_xfer_size = sfs.f_bsize; + t->current_filesystem->incr_xfer_size = sfs.f_bsize; +#endif } switch (sfs.f_type) { case AFS_SUPER_MAGIC: @@ -1744,7 +1794,11 @@ setup_current_filesystem(struct archive_read_disk *a) } #if defined(ST_NOATIME) +#if defined(HAVE_STATVFS) if (svfs.f_flag & ST_NOATIME) +#else + if (sfs.f_flag & ST_NOATIME) +#endif t->current_filesystem->noatime = 1; else #endif @@ -1973,7 +2027,7 @@ tree_dup(int fd) static volatile int can_dupfd_cloexec = 1; if (can_dupfd_cloexec) { - new_fd = fcntl(fd, F_DUPFD_CLOEXEC); + new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); if (new_fd != -1) return (new_fd); /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, |
