summaryrefslogtreecommitdiffstats
path: root/source3/client/clitar.c
diff options
context:
space:
mode:
authorAurélien Aptel <aurelien.aptel@gmail.com>2013-07-17 16:25:34 +0200
committerAndreas Schneider <asn@samba.org>2014-02-19 18:22:28 +0100
commit7c973de80218a1f6f45c2aeeec4f485690d163bd (patch)
treefcd605f31d9d51cf04545432c1c0852e00b8db81 /source3/client/clitar.c
parent679cd1627021daf96ddc4c1dd8f71a2067dbaa99 (diff)
downloadsamba-7c973de80218a1f6f45c2aeeec4f485690d163bd.tar.gz
samba-7c973de80218a1f6f45c2aeeec4f485690d163bd.tar.xz
samba-7c973de80218a1f6f45c2aeeec4f485690d163bd.zip
clitar.c: only list <include list> instead of whole share, handle wildcards
Signed-off-by: Aurélien Aptel <aurelien.aptel@gmail.com> Reviewed-by: David Disseldorp <ddiss@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3/client/clitar.c')
-rw-r--r--source3/client/clitar.c119
1 files 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 <archive_entry.h>
#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;