summaryrefslogtreecommitdiffstats
path: root/source3/client
diff options
context:
space:
mode:
authorAurélien Aptel <aurelien.aptel@gmail.com>2013-07-10 13:16:08 +0200
committerAndreas Schneider <asn@samba.org>2014-02-19 18:22:27 +0100
commitb7f6fd26b6346eac7ec37cf6742d49cd179df960 (patch)
treea2ac0c61bcf60b85a04253c0d6484d58db190b04 /source3/client
parentc9e23fd1a6c7595413dc0ea93db2c9936051b51d (diff)
downloadsamba-b7f6fd26b6346eac7ec37cf6742d49cd179df960.tar.gz
samba-b7f6fd26b6346eac7ec37cf6742d49cd179df960.tar.xz
samba-b7f6fd26b6346eac7ec37cf6742d49cd179df960.zip
clitar.c: implement basic full extraction
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')
-rw-r--r--source3/client/clitar.c121
1 files changed, 119 insertions, 2 deletions
diff --git a/source3/client/clitar.c b/source3/client/clitar.c
index ecf5700d35c..7af0ca96e7e 100644
--- a/source3/client/clitar.c
+++ b/source3/client/clitar.c
@@ -429,7 +429,119 @@ int cmd_setmode(void)
return 0;
}
-/* static int send_file(struct archive_entry *entry, */
+static int make_remote_path(const char *full_path)
+{
+ /*
+ a. strrchr() to get last occ of \\ => NULL to get path without
+ filename
+ b. strtok to split on \\
+ c. accumulate each token to concat the whole path little by little
+ d. use cli_chkpath + cli_mkdir
+ */
+ extern struct cli_state *cli;
+ TALLOC_CTX *ctx = talloc_tos();
+ char *path;
+ char *subpath;
+ char *state;
+ char *last_backslash;
+ char *p;
+ int len;
+ NTSTATUS status;
+
+ subpath = talloc_strdup(ctx, full_path);
+ path = talloc_strdup(ctx, full_path);
+ len = talloc_get_size(path) - 1;
+
+ last_backslash = strrchr_m(path, '\\');
+
+ if (!last_backslash) {
+ return 0;
+ }
+
+ *last_backslash = 0;
+
+ subpath[0] = 0;
+ p = strtok_r(path, "\\", &state);
+
+ while (p) {
+ strlcat(subpath, p, len);
+ status = cli_chkpath(cli, subpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ status = cli_mkdir(cli, subpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Can't mkdir %s: %s\n", subpath, nt_errstr(status)) );
+ return 1;
+ }
+ DEBUG(3, ("mkdir %s\n", subpath));
+ }
+
+ strlcat(subpath, "\\", len);
+ p = strtok_r(NULL, "/\\", &state);
+
+ }
+
+ return 0;
+}
+
+static int tar_send_file(struct tar *t, struct archive_entry *entry)
+{
+ extern struct cli_state *cli;
+ TALLOC_CTX *ctx = talloc_tos();
+ char *dos_path;
+ char *full_path;
+ const void *buf;
+ size_t len;
+ off_t off;
+ int r;
+ NTSTATUS status;
+ uint16_t remote_fd = (uint16_t) -1;
+ int err = 0;
+
+ dos_path = talloc_strdup(ctx, archive_entry_pathname(entry));
+ fix_unix_path(dos_path, true);
+
+ full_path = talloc_strdup(ctx, client_get_cur_dir());
+ full_path = talloc_strdup_append(full_path, dos_path);
+
+ make_remote_path(full_path);
+
+ status = cli_open(cli, full_path, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &remote_fd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("abandoning restore\n"));
+ return False;
+ }
+
+ for (;;) {
+ r = archive_read_data_block(t->archive, &buf, &len, &off);
+ if (r == ARCHIVE_EOF) {
+ break;
+ }
+ if (r == ARCHIVE_WARN) {
+ DEBUG(0, ("Warning: %s\n", archive_error_string(t->archive)));
+ }
+ if (r == ARCHIVE_FATAL) {
+ DEBUG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
+ err = 1;
+ goto out;
+ }
+
+ status = cli_writeall(cli, remote_fd, 0, buf, off, len, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Error writing remote file %s: %s\n",
+ full_path, nt_errstr(status)));
+ }
+ }
+
+ out:
+ status = cli_close(cli, remote_fd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Error losing remote file %s: %s\n",
+ full_path, nt_errstr(status)));
+ err = 1;
+ }
+
+ return err;
+}
/**
* cmd_tar - interactive command to start a tar backup/restoration
@@ -461,7 +573,8 @@ static int tar_extract(struct tar *t)
if (r != ARCHIVE_OK) {
DEBUG(0, ("Can't open %s : %s\n", t->tar_path,
archive_error_string(t->archive)));
- return 1;
+ err = 1;
+ goto out;
}
for (;;) {
@@ -479,6 +592,10 @@ static int tar_extract(struct tar *t)
}
DEBUG(0, ("Processing %s...\n", archive_entry_pathname(entry)));
+ if (tar_send_file(t, entry)) {
+ err = 1;
+ goto out;
+ }
}
out: