]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Implement optional behavior of archive_read_disk that do not traverse mount points...
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Jan 2012 11:51:43 +0000 (06:51 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Jan 2012 11:51:43 +0000 (06:51 -0500)
SVN-Revision: 4186

libarchive/archive_read_disk_posix.c
libarchive/archive_read_disk_private.h
libarchive/archive_read_disk_windows.c
tar/bsdtar.c
tar/bsdtar.h
tar/write.c

index ddf39d1c699807cfe255d51f9f32fb19dda80f31..7ebe10acfa6373a7114e55605412f739c708b913 100644 (file)
@@ -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);
index ff50ebdcd8f8a93e6591b873387c6d160051b45e..59b0fe22b510f312b32ae099d044ae68ba8f28b0 100644 (file)
@@ -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;
 
index cad57a1eb5c538b5abe9e665acb9d04b2ed42c36..3d9669f71a8fd76d7ff7010bd7315f8a88bbdfef 100644 (file)
@@ -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);
index 9ed1d6f8915d7abbad8236529b7ca2a36cdcc33b..c1e71f1a8099e09638cb981685be08a106b8d970 100644 (file)
@@ -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");
index c9bf9544bc8b261ede8e5029500492df5a9bc188..1f7dd74accf7d0f62242c6865ee7013d0a91fbcc 100644 (file)
@@ -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 */
index b3b8355ba1cfe20b28ab52bf7332e04e4973af91..d6ba06a24da0d01eebdfadf7c738da1b41274b68 100644 (file)
@@ -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.