diff options
author | Uri Simchoni <uri@samba.org> | 2017-03-21 23:13:07 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2017-03-28 17:45:19 +0200 |
commit | 200dbca238772b64e7c055d82d985045f92f6bcb (patch) | |
tree | e3e5a21fed08cfdd1d89d88898199152348e13de | |
parent | a67802fad505738a10f3c73392db9e6235f13b62 (diff) | |
download | samba-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>
-rw-r--r-- | source3/client/client.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 15 | ||||
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 10 | ||||
-rw-r--r-- | source3/libsmb/proto.h | 5 | ||||
-rw-r--r-- | source3/torture/nbio.c | 2 | ||||
-rw-r--r-- | source3/torture/torture.c | 14 |
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)); |