From: Michihiro NAKAJIMA Date: Thu, 19 Jan 2012 03:13:43 +0000 (-0500) Subject: Cast away archive_read_disk_set_name_filter_callback and add archive_read_disk_set_ma... X-Git-Tag: v3.0.4~2^2~174 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4fd30257d3f552ff83632c9f8af6695b8e941428;p=thirdparty%2Flibarchive.git Cast away archive_read_disk_set_name_filter_callback and add archive_read_disk_set_matching instead to effectively call archive_matching_*_excluded_ae function in archive_read_disk. SVN-Revision: 4175 --- diff --git a/libarchive/archive.h b/libarchive/archive.h index 7d7c493ba..44d53c5f4 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -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); diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index f73a3c093..68ee9aa6d 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -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); } diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h index c6af738ea..c0367e5de 100644 --- a/libarchive/archive_read_disk_private.h +++ b/libarchive/archive_read_disk_private.h @@ -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 diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index b96bfe1c7..814d4bec8 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -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); } diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c index 8a805f10d..3f9a8a7ea 100644 --- a/libarchive/test/test_read_disk_directory_traversals.c +++ b/libarchive/test/test_read_disk_directory_traversals.c @@ -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); } diff --git a/tar/write.c b/tar/write.c index c3a701618..817d5a4be 100644 --- a/tar/write.c +++ b/tar/write.c @@ -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 =