summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorUri Simchoni <uri@samba.org>2017-03-21 23:13:07 +0200
committerJeremy Allison <jra@samba.org>2017-03-28 17:45:19 +0200
commit200dbca238772b64e7c055d82d985045f92f6bcb (patch)
treee3e5a21fed08cfdd1d89d88898199152348e13de /source3
parenta67802fad505738a10f3c73392db9e6235f13b62 (diff)
downloadsamba-200dbca238772b64e7c055d82d985045f92f6bcb.tar.gz
s3: libsmb: add replace support to cli_rename()
Adds support for replacing the destination file at the higher-level cli_rename(). This is actually supported only by SMB2, and fails with invalid parameter with SMB1. Signed-off-by: Uri Simchoni <uri@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/client/client.c2
-rw-r--r--source3/libsmb/clifile.c15
-rw-r--r--source3/libsmb/libsmb_dir.c10
-rw-r--r--source3/libsmb/proto.h5
-rw-r--r--source3/torture/nbio.c2
-rw-r--r--source3/torture/torture.c14
6 files changed, 33 insertions, 15 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 226eb277573..78945f92c2b 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -3870,7 +3870,7 @@ static int cmd_rename(void)
return 1;
}
- status = cli_rename(targetcli, targetsrc, targetdest);
+ status = cli_rename(targetcli, targetsrc, targetdest, false);
if (!NT_STATUS_IS_OK(status)) {
d_printf("%s renaming files %s -> %s \n",
nt_errstr(status),
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index e6bc40cf5cb..8f96e043d56 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -1074,7 +1074,10 @@ NTSTATUS cli_rename_recv(struct tevent_req *req)
return tevent_req_simple_recv_ntstatus(req);
}
-NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+NTSTATUS cli_rename(struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace)
{
TALLOC_CTX *frame = NULL;
struct tevent_context *ev;
@@ -1082,7 +1085,7 @@ NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fn
NTSTATUS status = NT_STATUS_OK;
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return cli_smb2_rename(cli, fname_src, fname_dst, false);
+ return cli_smb2_rename(cli, fname_src, fname_dst, replace);
}
frame = talloc_stackframe();
@@ -1095,6 +1098,14 @@ NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fn
goto fail;
}
+ if (replace) {
+ /*
+ * SMB1 doesn't support replace
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
ev = samba_tevent_context_init(frame);
if (ev == NULL) {
status = NT_STATUS_NO_MEMORY;
diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index 8bf3c6b8efc..4a4e08412bc 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -2032,12 +2032,16 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
return -1;
}
- if (!NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
+ if (!NT_STATUS_IS_OK(
+ cli_rename(targetcli1, targetpath1, targetpath2, false))) {
int eno = SMBC_errno(ocontext, targetcli1);
if (eno != EEXIST ||
- !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) ||
- !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
+ !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2,
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN)) ||
+ !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1,
+ targetpath2, false))) {
errno = eno;
TALLOC_FREE(frame);
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 764f3fc1b12..57a45e3f363 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -330,7 +330,10 @@ struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
const char *fname_src,
const char *fname_dst);
NTSTATUS cli_rename_recv(struct tevent_req *req);
-NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst);
+NTSTATUS cli_rename(struct cli_state *cli,
+ const char *fname_src,
+ const char *fname_dst,
+ bool replace);
struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct cli_state *cli,
diff --git a/source3/torture/nbio.c b/source3/torture/nbio.c
index 6c87f9ab8c8..861f8741c96 100644
--- a/source3/torture/nbio.c
+++ b/source3/torture/nbio.c
@@ -261,7 +261,7 @@ void nb_rename(const char *oldname, const char *newname)
{
NTSTATUS status;
- status = cli_rename(c, oldname, newname);
+ status = cli_rename(c, oldname, newname, false);
if (!NT_STATUS_IS_OK(status)) {
printf("ERROR: rename %s %s failed (%s)\n",
oldname, newname, nt_errstr(status));
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index dbbd072c679..0d9a653cf20 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -4703,7 +4703,7 @@ static bool run_rename(int dummy)
return False;
}
- status = cli_rename(cli1, fname, fname1);
+ status = cli_rename(cli1, fname, fname1, false);
if (!NT_STATUS_IS_OK(status)) {
printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
} else {
@@ -4731,7 +4731,7 @@ static bool run_rename(int dummy)
return False;
}
- status = cli_rename(cli1, fname, fname1);
+ status = cli_rename(cli1, fname, fname1, false);
if (!NT_STATUS_IS_OK(status)) {
printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
correct = False;
@@ -4778,7 +4778,7 @@ static bool run_rename(int dummy)
}
#endif
- status = cli_rename(cli1, fname, fname1);
+ status = cli_rename(cli1, fname, fname1, false);
if (!NT_STATUS_IS_OK(status)) {
printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
correct = False;
@@ -4806,7 +4806,7 @@ static bool run_rename(int dummy)
return False;
}
- status = cli_rename(cli1, fname, fname1);
+ status = cli_rename(cli1, fname, fname1, false);
if (!NT_STATUS_IS_OK(status)) {
printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
} else {
@@ -4834,7 +4834,7 @@ static bool run_rename(int dummy)
return False;
}
- status = cli_rename(cli1, fname, fname1);
+ status = cli_rename(cli1, fname, fname1, false);
if (!NT_STATUS_IS_OK(status)) {
printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
correct = False;
@@ -5043,13 +5043,13 @@ static bool run_rename_access(int dummy)
* dst directory should fail.
*/
- status = cli_rename(cli, src, dst);
+ status = cli_rename(cli, src, dst, false);
if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
printf("rename of %s -> %s should be ACCESS denied, was %s\n",
src, dst, nt_errstr(status));
goto fail;
}
- status = cli_rename(cli, dsrc, ddst);
+ status = cli_rename(cli, dsrc, ddst, false);
if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
printf("rename of %s -> %s should be ACCESS denied, was %s\n",
src, dst, nt_errstr(status));