From 7c973de80218a1f6f45c2aeeec4f485690d163bd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aur=C3=A9lien=20Aptel?= Date: Wed, 17 Jul 2013 16:25:34 +0200 Subject: [PATCH] clitar.c: only list instead of whole share, handle wildcards MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Aurélien Aptel Reviewed-by: David Disseldorp Reviewed-by: Andreas Schneider --- source3/client/clitar.c | 119 +++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 21 deletions(-) diff --git a/source3/client/clitar.c b/source3/client/clitar.c index b3cfc741eb6..b4284eba0ac 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -26,7 +26,7 @@ #include #define LEN(x) (sizeof(x)/sizeof((x)[0])) -#define DBG(a, b) (DEBUG(a, ("tar:%-3d ", __LINE__)), DEBUG(a, b)) +#define DBG(a, b) (DEBUG(a, ("tar:%-4d ", __LINE__)), DEBUG(a, b)) /** * Maximum value for the blocksize field @@ -147,6 +147,27 @@ static char *fix_unix_path (char *path, bool removeprefix) return path; } +static char *path_base_name (const char *path) +{ + TALLOC_CTX *ctx = talloc_tos(); + char *base = NULL; + int last = -1; + int i; + + for (i = 0; path[i]; i++) { + if (path[i] == '\\' || path[i] == '/') { + last = i; + } + } + + if (last >= 0) { + base = talloc_strdup(ctx, path); + base[last] = 0; + } + + return base; +} + #define XSET(v) [v] = #v #define XTABLE(v, t) DBG(2, ("DUMP:%-20.20s = %s\n", #v, t[v])) #define XBOOL(v) DBG(2, ("DUMP:%-20.20s = %d\n", #v, v ? 1 : 0)) @@ -374,16 +395,20 @@ static bool tar_create_skip_path(struct tar *t, /* 3. is it in the selection list? */ - if (t->path_list_size > 0) { - in = tar_path_in_list(t, fullpath, isdir && !exclude); + /* + * tar_create_from_list() use the include list as a starting + * point, no need to check + */ + if (!exclude) { + return !skip; } - /* inverse result if in exclude mode */ - if (exclude) { - in = !in; + /* we are now in exclude mode */ + if (t->path_list_size > 0) { + in = tar_path_in_list(t, fullpath, isdir && !exclude); } - return in ? !skip : skip; + return in ? skip : !skip; } bool tar_to_process (struct tar *t) @@ -568,7 +593,7 @@ int cmd_setmode(void) return 1; } - DBG(2, ("\nperm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET])); + DBG(2, ("perm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET])); set_remote_attr(fname, attr[ATTR_SET], ATTR_SET); set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET); return 0; @@ -856,13 +881,52 @@ static NTSTATUS get_file_callback(struct cli_state *cli, return err; } +static int tar_create_from_list(struct tar *t) +{ + TALLOC_CTX *ctx = talloc_tos(); + int err = 0; + NTSTATUS status; + const char *path, *mask, *base, *start_dir; + int i; + + start_dir = talloc_strdup(ctx, client_get_cur_dir()); + + for (i = 0; i < t->path_list_size; i++) { + path = t->path_list[i]; + base = path_base_name(path); + mask = talloc_asprintf(ctx, "%s\\%s", client_get_cur_dir(), path); + + DBG(5, ("incl. path='%s', base='%s', mask='%s'\n", + path, base ? base : "NULL", mask)); + + if (base) { + base = talloc_asprintf(ctx, "%s%s\\", + client_get_cur_dir(), path_base_name(path)); + DBG(5, ("cd '%s' before do_list\n", base)); + client_set_cur_dir(base); + } + status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); + if (base) { + client_set_cur_dir(start_dir); + } + if (!NT_STATUS_IS_OK(status)) { + DBG(0, ("do_list failed on %s (%s)\n", path, nt_errstr(status))); + err = 1; + goto out; + } + } + + out: + return err; +} + static int tar_create(struct tar* t) { TALLOC_CTX *ctx = talloc_tos(); - char *mask = talloc_asprintf(ctx, "%s\\*", client_get_cur_dir()); int r; int err = 0; NTSTATUS status; + const char *mask; t->archive = archive_write_new(); @@ -887,23 +951,36 @@ static int tar_create(struct tar* t) } } - DBG(5, ("tar_process do_list with mask: %s\n", mask)); - status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); - if (!NT_STATUS_IS_OK(status)) { - DBG(0, ("do_list fail %s\n", nt_errstr(status))); - err = 1; - goto out_close; + /* + * In inclusion mode, iterate on the inclusion list + */ + if (t->mode.selection == TAR_INCLUDE && t->path_list_size > 0) { + if (tar_create_from_list(t)) { + err = 1; + goto out_close; + } + } else { + mask = talloc_asprintf(ctx, "%s\\*", client_get_cur_dir()); + DBG(5, ("tar_process do_list with mask: %s\n", mask)); + status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); + if (!NT_STATUS_IS_OK(status)) { + DBG(0, ("do_list fail %s\n", nt_errstr(status))); + err = 1; + goto out_close; + } } out_close: DBG(0, ("Total bytes received: %" PRIu64 "\n", t->total_size)); - r = archive_write_close(t->archive); - if (r != ARCHIVE_OK) { - DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); - err = 1; - goto out; - } + if (!t->mode.dry) { + r = archive_write_close(t->archive); + if (r != ARCHIVE_OK) { + DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); + err = 1; + goto out; + } + } out: archive_write_free(t->archive); return err; -- 2.34.1