diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 807d9ab6a..485d23066 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ set(CSYNC_LINK_LIBRARIES set(csync_SRCS csync.c csync_config.c + csync_exclude.c csync_journal.c csync_lock.c csync_util.c diff --git a/src/csync_exclude.c b/src/csync_exclude.c new file mode 100644 index 000000000..e08ba506a --- /dev/null +++ b/src/csync_exclude.c @@ -0,0 +1,116 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008 by Andreas Schneider + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * vim: ts=2 sw=2 et cindent + */ + +#include +#include +#include +#include +#include + +#include "c_lib.h" + +#include "csync_private.h" +#include "csync_exclude.h" + +#define CSYNC_LOG_CATEGORY_NAME "csync.exclude" +#include "csync_log.h" + +static void csync_exclude_add(CSYNC *ctx, const char *string) { + if (ctx->excludes == NULL) { + ctx->excludes = c_strlist_new(32); + } + + if (ctx->excludes->count == ctx->excludes->size) { + ctx->excludes = c_strlist_expand(ctx->excludes, 2 * ctx->excludes->size); + } + + c_strlist_add(ctx->excludes, string); +} + +int csync_exclude_load(CSYNC *ctx, const char *fname) { + int fd = -1; + int i, rc; + off_t size; + char *buf, *entry; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + return -1; + } + + size = lseek(fd, 0, SEEK_END); + if (size < 0) { + rc = -1; + goto out; + } + lseek(fd, 0, SEEK_SET); + if (size == 0) { + rc = 0; + goto out; + } + buf = c_malloc(size); + if (read(fd, buf, size) != size) { + rc = -1; + goto out; + } + close(fd); + + entry = buf; + for (i = 0; i < size; i++) { + if (buf[i] == '\n') { + if (entry != buf + i) { + buf[i] = '\0'; + if (*entry != '#' || *entry == '\n') { + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry); + printf("Adding entry: %s\n", entry); + csync_exclude_add(ctx, entry); + } + } + entry = buf + i + 1; + } + } + SAFE_FREE(buf); + + rc = 0; +out: + SAFE_FREE(buf); + close(fd); + return rc; +} + +void csync_exclude_destroy(CSYNC *ctx) { + c_strlist_destroy(ctx->excludes); +} + +int csync_excluded(CSYNC *ctx, const char *path) { + size_t i; + + if (ctx->excludes->count) { + for (i = 0; i < ctx->excludes->count; i++) { + if (fnmatch(ctx->excludes->vector[i], path, 0) == 0) { + return 1; + } + } + } + return 0; +} + diff --git a/src/csync_exclude.h b/src/csync_exclude.h new file mode 100644 index 000000000..4108b6e52 --- /dev/null +++ b/src/csync_exclude.h @@ -0,0 +1,53 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008 by Andreas Schneider + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * vim: ft=c.doxygen ts=2 sw=2 et cindent + */ + +#ifndef _CSYNC_EXCLUDE_H +#define _CSYNC_EXCLUDE_H + +/** + * @brief Load exclude list + * + * @param ctx The context of the synchronizer. + * @param fname The filename to load. + * + * @return 0 on success, -1 if an error occured with errno set. + */ +int csync_exclude_load(CSYNC *ctx, const char *fname); + +/** + * @brief Destroy the exclude list in memory. + * + * @param ctx The synchronizer context. + */ +void csync_exclude_destroy(CSYNC *ctx); + +/** + * @brief Check if the given path should be excluded. + * + * @param ctx The synchronizer context. + * @param path The patch to check. + * + * @return 1 if excluded, 0 if not. + */ +int csync_excluded(CSYNC *ctx, const char *path); + +#endif /* _CSYNC_EXCLUDE_H */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8f06421a8..132224855 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,5 +33,6 @@ macro_add_check_test(check_logger log_tests/check_log.c ${TEST_TARGET_LIBRARIES} macro_add_check_test(check_csync csync_tests/check_csync.c ${TEST_TARGET_LIBRARIES}) macro_add_check_test(check_csync_lock csync_tests/check_csync_lock.c ${TEST_TARGET_LIBRARIES}) macro_add_check_test(check_csync_config csync_tests/check_csync_config.c ${TEST_TARGET_LIBRARIES}) +macro_add_check_test(check_csync_exclude csync_tests/check_csync_exclude.c ${TEST_TARGET_LIBRARIES}) macro_add_check_test(check_csync_journal csync_tests/check_csync_journal.c ${TEST_TARGET_LIBRARIES}) diff --git a/tests/csync_tests/check_csync_exclude.c b/tests/csync_tests/check_csync_exclude.c new file mode 100644 index 000000000..1ea71a352 --- /dev/null +++ b/tests/csync_tests/check_csync_exclude.c @@ -0,0 +1,77 @@ +#define _GNU_SOURCE /* asprintf */ +#include + +#include "support.h" + +#include "csync_exclude.c" + +CSYNC *csync; + +static void setup(void) { + csync_create(&csync); + SAFE_FREE(csync->options.config_dir); + csync->options.config_dir = c_strdup("/tmp/check_csync/"); +} + +static void setup_init(void) { + csync_create(&csync); + SAFE_FREE(csync->options.config_dir); + csync->options.config_dir = c_strdup("/tmp/check_csync/"); + csync_exclude_load(csync, SYSCONFDIR "/config/" CSYNC_EXCLUDE_FILE); +} + +static void teardown(void) { + csync_exclude_destroy(csync); + csync_destroy(csync); + system("rm -rf /tmp/check_csync"); +} + +START_TEST (check_csync_exclude_add) +{ + csync_exclude_add(csync, (const char *) "/tmp/check_csync/*"); + fail_unless(strcmp(csync->excludes->vector[0], (const char *) "/tmp/check_csync/*") == 0, NULL); +} +END_TEST + +START_TEST (check_csync_exclude_load) +{ + fail_unless(csync_exclude_load(csync, SYSCONFDIR "/config/" CSYNC_EXCLUDE_FILE) == 0, NULL); + fail_unless(strcmp(csync->excludes->vector[0], (const char *) "/home/*/.kde?/cache-*") == 0, NULL); +} +END_TEST + +START_TEST (check_csync_excluded) +{ + fail_unless(csync_excluded(csync, "/home/user/.kde4/cache-maximegalon/") == 1, NULL); + fail_unless(csync_excluded(csync, "/home/user/.mozilla/plugins/foo.so") == 1, NULL); +} +END_TEST + + +static Suite *csync_suite(void) { + Suite *s = suite_create("csync_exclude"); + + create_case_fixture(s, "check_csync_exclude_add", check_csync_exclude_add, setup, teardown); + create_case_fixture(s, "check_csync_exclude_load", check_csync_exclude_load, setup, teardown); + create_case_fixture(s, "check_csync_excluded", check_csync_excluded, setup_init, teardown); + + return s; +} + +int main(void) { + int nf; + + Suite *s = csync_suite(); + + SRunner *sr; + sr = srunner_create(s); +#if 0 + srunner_set_fork_status(sr, CK_NOFORK); +#endif + srunner_run_all(sr, CK_VERBOSE); + nf = srunner_ntests_failed(sr); + srunner_free(sr); + + return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} +