]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Cast away archive_read_disk_set_name_filter_callback and add archive_read_disk_set_ma...
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Jan 2012 03:13:43 +0000 (22:13 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Jan 2012 03:13:43 +0000 (22:13 -0500)
to effectively call archive_matching_*_excluded_ae function in archive_read_disk.

SVN-Revision: 4175

libarchive/archive.h
libarchive/archive_read_disk_posix.c
libarchive/archive_read_disk_private.h
libarchive/archive_read_disk_windows.c
libarchive/test/test_read_disk_directory_traversals.c
tar/write.c

index 7d7c493ba1f0377caa8cacd3152a9b9ffec1c2b3..44d53c5f4ef9d678080881ab890c97410bb7c811 100644 (file)
@@ -748,8 +748,8 @@ __LA_DECL int       archive_read_disk_open_w(struct archive *, const wchar_t *);
  * you invoke this on every returned path, you'll get a full logical
  * traversal.
  */
-__LA_DECL int  archive_read_disk_can_descend(struct archive *);
 __LA_DECL int  archive_read_disk_descend(struct archive *);
+__LA_DECL int  archive_read_disk_can_descend(struct archive *);
 __LA_DECL int  archive_read_disk_current_filesystem(struct archive *);
 __LA_DECL int  archive_read_disk_current_filesystem_is_synthetic(struct archive *);
 __LA_DECL int  archive_read_disk_current_filesystem_is_remote(struct archive *);
@@ -757,10 +757,16 @@ __LA_DECL int     archive_read_disk_current_filesystem_is_remote(struct archive *);
 __LA_DECL int  archive_read_disk_set_atime_restored(struct archive *);
 __LA_DECL int  archive_read_disk_honor_nodump(struct archive *);
 __LA_DECL int  archive_read_disk_disable_mac_copyfile(struct archive *);
-
-__LA_DECL int  archive_read_disk_set_name_filter_callback(struct archive *,
-                   int (*_name_filter_func)(struct archive *, void *,
-                       struct archive_entry *), void *_client_data);
+/*
+ * Set archive_matching object that will be used in archive_read_disk to
+ * know whether an entry should be skipped. The callback function
+ * _excluded_func will be invoked when an entry is skipped by the result
+ * of archive_matching.
+ */
+__LA_DECL int  archive_read_disk_set_matching(struct archive *,
+                   struct archive *_matching, void (*_excluded_func)
+                   (struct archive *, void *, struct archive_entry *),
+                   void *_client_data);
 __LA_DECL int  archive_read_disk_set_metadata_filter_callback(struct archive *,
                    int (*_metadata_filter_func)(struct archive *, void *,
                        struct archive_entry *), void *_client_data);
index f73a3c0933fe4f8a1a2a26cb304f1658f4435687..68ee9aa6db2794d0d7a2637dcc3b6fa8c55c4a4b 100644 (file)
@@ -908,14 +908,26 @@ next_entry:
                        goto next_entry;
        }
 #endif
-       archive_entry_copy_pathname(entry, tree_current_path(t));
 
+       archive_entry_copy_pathname(entry, tree_current_path(t));
        /*
-        * Invoke a name filter callback.
+        * Perform path matching.
         */
-       if (a->name_filter_func) {
-               if (!a->name_filter_func(_a, a->name_filter_data, entry))
+       if (a->matching) {
+               r = archive_matching_path_excluded_w(a->matching,
+                       tree_current_path(t));
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
                        goto next_entry;
+               }
        }
 
        /*
@@ -965,10 +977,8 @@ next_entry:
        fd = -1;
        if (a->honor_nodump) {
 #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-               if (st->st_flags & UF_NODUMP) {
-                       archive_entry_clear(entry);
+               if (st->st_flags & UF_NODUMP)
                        goto next_entry;
-               }
 #elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
       defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
                if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
@@ -987,7 +997,6 @@ next_entry:
                                r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
                                if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) {
                                        close(fd);
-                                       archive_entry_clear(entry);
                                        goto next_entry;
                                }
                        }
@@ -996,6 +1005,7 @@ next_entry:
        }
 
        archive_entry_copy_stat(entry, st);
+
        /* Save the times to be restored. This must be in before
         * calling archive_read_disk_descend() or any chance of it,
         * especially, invokng a callback. */
@@ -1006,6 +1016,25 @@ next_entry:
        t->restore_time.filetype = archive_entry_filetype(entry);
        t->restore_time.noatime = t->current_filesystem->noatime;
 
+       /*
+        * Perform time matching.
+        */
+       if (a->matching) {
+               r = archive_matching_time_excluded_ae(a->matching, entry);
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
+                       goto next_entry;
+               }
+       }
+
        /* Lookup uname/gname */
        name = archive_read_disk_uname(_a, archive_entry_uid(entry));
        if (name != NULL)
@@ -1014,6 +1043,25 @@ next_entry:
        if (name != NULL)
                archive_entry_copy_gname(entry, name);
 
+       /*
+        * Perform owner matching.
+        */
+       if (a->matching) {
+               r = archive_matching_owner_excluded_ae(a->matching, entry);
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
+                       goto next_entry;
+               }
+       }
+
        /*
         * Invoke a meta data filter callback.
         */
@@ -1135,17 +1183,16 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
 }
 
 int
-archive_read_disk_set_name_filter_callback(struct archive *_a,
-    int (*_name_filter_func)(struct archive *, void *, struct archive_entry *),
+archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
+    void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
     void *_client_data)
 {
        struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-       archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
-           "archive_read_disk_set_name_filter_callback");
-
-       a->name_filter_func = _name_filter_func;
-       a->name_filter_data = _client_data;
+       archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
+       a->matching = _ma;
+       a->excluded_cb_func = _excluded_func;
+       a->excluded_cb_data = _client_data;
        return (ARCHIVE_OK);
 }
 
index c6af738ea2ed0f3121bdbf0e083d0b78b93d1fcd..c0367e5deb70a797ea08b3294800eb1bf32bb8fa 100644 (file)
@@ -73,13 +73,17 @@ struct archive_read_disk {
        void    (*cleanup_uname)(void *private);
        void     *lookup_uname_data;
 
-       int     (*name_filter_func)(struct archive *, void *,
-                       struct archive_entry *);
-       void    *name_filter_data;
        int     (*metadata_filter_func)(struct archive *, void *,
                        struct archive_entry *);
        void    *metadata_filter_data;
 
+       /* ARCHIVE_MATCHING object. */
+       struct archive  *matching;
+       /* Callback function, this will be invoked when ARCHIVE_MATCHING
+        * archive_matching_*_excluded_ae return true. */
+       void    (*excluded_cb_func)(struct archive *, void *,
+                        struct archive_entry *);
+       void    *excluded_cb_data;
 };
 
 #endif
index b96bfe1c74bc03e23d4681b9db1128f3621945f6..814d4bec8505b8f66f014b23f878e5d03a8fb1a8 100644 (file)
@@ -790,9 +790,25 @@ next_entry:
        } while (lst == NULL);
 
        archive_entry_copy_pathname_w(entry, tree_current_path(t));
-       if (a->name_filter_func) {
-               if (!a->name_filter_func(_a, a->name_filter_data, entry))
+
+       /*
+        * Perform path matching.
+        */
+       if (a->matching) {
+               r = archive_matching_path_excluded_w(a->matching,
+                       tree_current_path(t));
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
                        goto next_entry;
+               }
        }
 
        /*
@@ -835,6 +851,33 @@ next_entry:
        t->descend = descend;
 
        tree_archive_entry_copy_bhfi(entry, t, st);
+
+       /* Save the times to be restored. This must be in before
+        * calling archive_read_disk_descend() or any chance of it,
+        * especially, invokng a callback. */
+       t->restore_time.lastWriteTime = st->ftLastWriteTime;
+       t->restore_time.lastAccessTime = st->ftLastAccessTime;
+       t->restore_time.filetype = archive_entry_filetype(entry);
+
+       /*
+        * Perform time matching.
+        */
+       if (a->matching) {
+               r = archive_matching_time_excluded_ae(a->matching, entry);
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
+                       goto next_entry;
+               }
+       }
+
        /* Lookup uname/gname */
        name = archive_read_disk_uname(_a, archive_entry_uid(entry));
        if (name != NULL)
@@ -842,7 +885,29 @@ next_entry:
        name = archive_read_disk_gname(_a, archive_entry_gid(entry));
        if (name != NULL)
                archive_entry_copy_gname(entry, name);
-       /* Invoke a filter callback. */
+
+       /*
+        * Perform owner matching.
+        */
+       if (a->matching) {
+               r = archive_matching_owner_excluded_ae(a->matching, entry);
+               if (r < 0) {
+                       archive_set_error(&(a->archive), errno,
+                           "Faild : %s", archive_error_string(a->matching));
+                       return (r);
+               }
+               if (r) {
+                       if (a->excluded_cb_func)
+                               a->excluded_cb_func(&(a->archive),
+                                   a->excluded_cb_data, entry);
+                       archive_entry_clear(entry);
+                       goto next_entry;
+               }
+       }
+
+       /*
+        * Invoke a meta data filter callback.
+        */
        if (a->metadata_filter_func) {
                if (!a->metadata_filter_func(_a,
                    a->metadata_filter_data, entry)) {
@@ -852,11 +917,6 @@ next_entry:
        }
        archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t));
 
-       /* Save the times to be restored. */
-       t->restore_time.lastWriteTime = st->ftLastWriteTime;
-       t->restore_time.lastAccessTime = st->ftLastAccessTime;
-       t->restore_time.filetype = archive_entry_filetype(entry);
-
        r = ARCHIVE_OK;
        if (archive_entry_filetype(entry) == AE_IFREG &&
            archive_entry_size(entry) > 0) {
@@ -994,17 +1054,16 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
 }
 
 int
-archive_read_disk_set_name_filter_callback(struct archive *_a,
-    int (*_name_filter_func)(struct archive *, void *, struct archive_entry *),
+archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
+    void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
     void *_client_data)
 {
        struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-       archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
-           "archive_read_disk_set_name_filter_callback");
-
-       a->name_filter_func = _name_filter_func;
-       a->name_filter_data = _client_data;
+       archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
+       a->matching = _ma;
+       a->excluded_cb_func = _excluded_func;
+       a->excluded_cb_data = _client_data;
        return (ARCHIVE_OK);
 }
 
index 8a805f10db929957daeb12d2d881deb1ea095af9..3f9a8a7ea670a9c2f2d2d55575337013ba2d1d62 100644 (file)
@@ -1273,23 +1273,6 @@ test_restore_atime(void)
        archive_entry_free(ae);
 }
 
-static int
-name_filter(struct archive *a, void *data, struct archive_entry *ae)
-{
-       failure("ATime should not be set");
-       assertEqualInt(0, archive_entry_atime_is_set(ae));
-       failure("BirthTime should not be set");
-       assertEqualInt(0, archive_entry_birthtime_is_set(ae));
-       failure("CTime should not be set");
-       assertEqualInt(0, archive_entry_ctime_is_set(ae));
-       failure("MTime should not be set");
-       assertEqualInt(0, archive_entry_mtime_is_set(ae));
-
-       if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0)
-               return (0);
-       return (1);
-}
-
 static int
 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
 {
@@ -1316,6 +1299,7 @@ static void
 test_callbacks(void)
 {
        struct archive *a;
+       struct archive *m;
        struct archive_entry *ae;
        const void *p;
        size_t size;
@@ -1332,14 +1316,24 @@ test_callbacks(void)
        assertUtimes("cb", 886622, 0, 886622, 0);
 
        assert((ae = archive_entry_new()) != NULL);
-       assert((a = archive_read_disk_new()) != NULL);
+       if (assert((a = archive_read_disk_new()) != NULL)) {
+               archive_entry_free(ae);
+               return;
+       }
+       if (assert((m = archive_matching_new()) != NULL)) {
+               archive_entry_free(ae);
+               archive_read_free(a);
+               return;
+       }
 
        /*
         * Test1: Traversals with a name filter.
         */
        file_count = 3;
+       assertEqualIntA(m, ARCHIVE_OK,
+           archive_matching_exclude_pattern(m, "cb/f2"));
        assertEqualIntA(a, ARCHIVE_OK,
-           archive_read_disk_set_name_filter_callback(a, name_filter, NULL));
+           archive_read_disk_set_matching(a, m, NULL, NULL));
        failure("Directory traversals should work as well");
        assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
        while (file_count--) {
@@ -1386,8 +1380,6 @@ test_callbacks(void)
        assertUtimes("cb/fe", 886611, 0, 886611, 0);
        assertUtimes("cb", 886622, 0, 886622, 0);
        file_count = 3;
-       assertEqualIntA(a, ARCHIVE_OK,
-           archive_read_disk_set_name_filter_callback(a, NULL, NULL));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
                    NULL));
@@ -1424,6 +1416,7 @@ test_callbacks(void)
 
        /* Destroy the disk object. */
        assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+       assertEqualInt(ARCHIVE_OK, archive_matching_free(m));
        archive_entry_free(ae);
 }
 
index c3a701618553ffef27ed9d759b0902aab6466608..817d5a4be5e1ae972160c933abe71935197fe1ba 100644 (file)
@@ -102,7 +102,7 @@ static void          archive_names_from_file(struct bsdtar *bsdtar,
 static int              copy_file_data_block(struct bsdtar *,
                             struct archive *a, struct archive *,
                             struct archive_entry *);
-static int              name_filter(struct archive *, void *,
+static void             excluded_callback(struct archive *, void *,
                             struct archive_entry *);
 static void             report_write(struct bsdtar *, struct archive *,
                             struct archive_entry *, int64_t progress);
@@ -426,8 +426,8 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
                break;
        }
        /* Register entry filters. */
-       archive_read_disk_set_name_filter_callback(bsdtar->diskreader,
-           name_filter, bsdtar);
+       archive_read_disk_set_matching(bsdtar->diskreader,
+           bsdtar->matching, excluded_callback, bsdtar);
        archive_read_disk_set_metadata_filter_callback(
            bsdtar->diskreader, metadata_filter, bsdtar);
        /* Skip a file if it has nodump flag. */
@@ -708,18 +708,27 @@ copy_file_data_block(struct bsdtar *bsdtar, struct archive *a,
        return (0);
 }
 
-static int
-name_filter(struct archive *a, void *_data, struct archive_entry *entry)
+static void
+excluded_callback(struct archive *a, void *_data, struct archive_entry *entry)
 {
        struct bsdtar *bsdtar = (struct bsdtar *)_data;
 
-       /*
-        * If this file/dir is excluded by a filename
-        * pattern, skip it.
-        */
-       if (archive_matching_path_excluded_ae(bsdtar->matching, entry))
-               return (0);
-       return (1);
+       if (bsdtar->option_no_subdirs)
+               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;
+       archive_read_disk_descend(a);
 }
 
 static int
@@ -727,22 +736,6 @@ metadata_filter(struct archive *a, void *_data, struct archive_entry *entry)
 {
        struct bsdtar *bsdtar = (struct bsdtar *)_data;
 
-       /*
-        * In -u mode, check that the file is newer than what's
-        * already in the archive; in all modes, obey --newerXXX flags.
-        */
-       if (archive_matching_time_excluded_ae(bsdtar->matching, entry)) {
-               if (bsdtar->option_no_subdirs)
-                       return (0);
-               if (!archive_read_disk_can_descend(a))
-                       return (0);
-               if (bsdtar->option_interactive &&
-                   !yes("add '%s'", archive_entry_pathname(entry)))
-                       return (0);
-               archive_read_disk_descend(a);
-               return (0);
-       }
-
        if (bsdtar->option_dont_traverse_mounts) {
                if (bsdtar->first_fs == -1)
                        bsdtar->first_fs =