From: Michihiro NAKAJIMA Date: Thu, 19 Jan 2012 11:51:43 +0000 (-0500) Subject: Implement optional behavior of archive_read_disk that do not traverse mount points... X-Git-Tag: v3.0.4~2^2~167 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffa08263e3add5f077e444cde2b1488be2984360;p=thirdparty%2Flibarchive.git Implement optional behavior of archive_read_disk that do not traverse mount points if user requests. SVN-Revision: 4186 --- diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index ddf39d1c6..7ebe10acf 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -235,6 +235,7 @@ struct tree { char symlink_mode; struct filesystem *current_filesystem; struct filesystem *filesystem_table; + int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; int allocated_filesytem; @@ -452,7 +453,7 @@ archive_read_disk_new(void) a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; a->enable_copyfile = 1; - a->traversal_mount_points = 1; + a->traverse_mount_points = 1; a->entry_wd_fd = -1; return (&a->archive); } @@ -594,9 +595,9 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) else a->enable_copyfile = 0; if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traversal_mount_points = 0; + a->traverse_mount_points = 0; else - a->traversal_mount_points = 1; + a->traverse_mount_points = 1; return (r); } @@ -979,6 +980,14 @@ next_entry: tree_enter_initial_dir(t); return (ARCHIVE_FATAL); } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (!a->traverse_mount_points) { + if (t->initial_filesystem_id != t->current_filesystem_id) { + archive_entry_clear(entry); + goto next_entry; + } + } t->descend = descend; /* @@ -2015,6 +2024,7 @@ tree_reopen(struct tree *t, const char *path, int restore_time) t->entry_fd = -1; t->entry_eof = 0; t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; /* First item is set up a lot like a symlink traversal. */ tree_push(t, path, 0, 0, 0, NULL); diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h index ff50ebdcd..59b0fe22b 100644 --- a/libarchive/archive_read_disk_private.h +++ b/libarchive/archive_read_disk_private.h @@ -63,8 +63,8 @@ struct archive_read_disk { int honor_nodump; /* Set 1 if users request to enable mac copyfile. */ int enable_copyfile; - /* Set 1 if users request to traversal mount points. */ - int traversal_mount_points; + /* Set 1 if users request to traverse mount points. */ + int traverse_mount_points; int entry_wd_fd; diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index cad57a1eb..3d9669f71 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -165,6 +165,7 @@ struct tree { char symlink_mode; struct filesystem *current_filesystem; struct filesystem *filesystem_table; + int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; int allocated_filesytem; @@ -395,7 +396,7 @@ archive_read_disk_new(void) a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; a->enable_copyfile = 1; - a->traversal_mount_points = 1; + a->traverse_mount_points = 1; a->entry_wd_fd = -1; return (&a->archive); } @@ -522,9 +523,9 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) else a->enable_copyfile = 0; if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traversal_mount_points = 0; + a->traverse_mount_points = 0; else - a->traversal_mount_points = 1; + a->traverse_mount_points = 1; return (r); } @@ -860,6 +861,14 @@ next_entry: a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (!a->traverse_mount_points) { + if (t->initial_filesystem_id != t->current_filesystem_id) { + archive_entry_clear(entry); + goto next_entry; + } + } t->descend = descend; tree_archive_entry_copy_bhfi(entry, t, st); @@ -1505,6 +1514,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) t->entry_fh = INVALID_HANDLE_VALUE; t->entry_eof = 0; t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; /* Get wchar_t strings from char strings. */ archive_string_init(&ws); diff --git a/tar/bsdtar.c b/tar/bsdtar.c index 9ed1d6f89..c1e71f1a8 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -451,7 +451,8 @@ main(int argc, char **argv) option_o = 1; /* Record it and resolve it later. */ break; case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ - bsdtar->option_dont_traverse_mounts = 1; + bsdtar->readdisk_flags |= + ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS; break; case OPTION_OPTIONS: bsdtar->option_options = bsdtar->argument; @@ -610,7 +611,7 @@ main(int argc, char **argv) "Must specify one of -c, -r, -t, -u, -x"); /* Check boolean options only permitted in certain modes. */ - if (bsdtar->option_dont_traverse_mounts) + if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) only_mode(bsdtar, "--one-file-system", "cru"); if (bsdtar->option_fast_read) only_mode(bsdtar, "--fast-read", "xt"); diff --git a/tar/bsdtar.h b/tar/bsdtar.h index c9bf9544b..1f7dd74ac 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -62,7 +62,6 @@ struct bsdtar { const char *compress_program; char option_absolute_paths; /* -P */ char option_chroot; /* --chroot */ - char option_dont_traverse_mounts; /* --one-file-system */ char option_fast_read; /* --fast-read */ const char *option_options; /* --options */ char option_interactive; /* -w */ diff --git a/tar/write.c b/tar/write.c index b3b8355ba..d6ba06a24 100644 --- a/tar/write.c +++ b/tar/write.c @@ -711,14 +711,6 @@ excluded_callback(struct archive *a, void *_data, struct archive_entry *entry) return; if (!archive_read_disk_can_descend(a)) return; - if (bsdtar->option_dont_traverse_mounts) { - if (bsdtar->first_fs == -1) - bsdtar->first_fs = - archive_read_disk_current_filesystem(a); - else if (bsdtar->first_fs != - archive_read_disk_current_filesystem(a)) - return; - } if (bsdtar->option_interactive && !yes("add '%s'", archive_entry_pathname(entry))) return; @@ -730,27 +722,19 @@ metadata_filter(struct archive *a, void *_data, struct archive_entry *entry) { struct bsdtar *bsdtar = (struct bsdtar *)_data; - if (bsdtar->option_dont_traverse_mounts) { - if (bsdtar->first_fs == -1) - bsdtar->first_fs = - archive_read_disk_current_filesystem(a); - else if (bsdtar->first_fs != - archive_read_disk_current_filesystem(a)) - return (0); - /* XXX TODO: check whether this filesystem is - * synthetic and/or local. Add a new - * --local-only option to skip non-local - * filesystems. Skip synthetic filesystems - * regardless. - * - * The results should be cached, since - * tree.c doesn't usually visit a directory - * and the directory contents together. A simple - * move-to-front list should perform quite well. - * - * Use archive_read_disk_current_filesystem_is_remote(). - */ - } + /* XXX TODO: check whether this filesystem is + * synthetic and/or local. Add a new + * --local-only option to skip non-local + * filesystems. Skip synthetic filesystems + * regardless. + * + * The results should be cached, since + * tree.c doesn't usually visit a directory + * and the directory contents together. A simple + * move-to-front list should perform quite well. + * + * Use archive_read_disk_current_filesystem_is_remote(). + */ /* * If the user vetoes this file/directory, skip it.