s3: libsmb: add replace support to cli_rename()
authorUri Simchoni <uri@samba.org>
Tue, 21 Mar 2017 21:13:07 +0000 (23:13 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 28 Mar 2017 15:45:19 +0000 (17:45 +0200)
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>
source3/client/client.c
source3/libsmb/clifile.c
source3/libsmb/libsmb_dir.c
source3/libsmb/proto.h
source3/torture/nbio.c
source3/torture/torture.c

index 226eb2775730601638e75c88fac5f1fbeb1fc5f0..78945f92c2b3715d95ae062f7a6cf42ec7cdca32 100644 (file)
@@ -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),
index e6bc40cf5cb6c77d3cdc10fc3e3a12fe229ed8a7..8f96e043d5698018e0f9e86cf74e82edd3af220b 100644 (file)
@@ -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;
index 8bf3c6b8efc25d688c8de54c67ad348bd83010e2..4a4e08412bc293360272872913775508bef99126 100644 (file)
@@ -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);
index 764f3fc1b12d68b88d0ec33356173fc975e6767a..57a45e3f3633c814d2595398d1cdf5ccb268c8e8 100644 (file)
@@ -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,
index 6c87f9ab8c8e994f7393fd25ace7ece94cd07339..861f8741c9661779c2499158e39acc15a5903413 100644 (file)
@@ -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));
index dbbd072c679756389ca23184de481c82c224721f..0d9a653cf20d5b52e46f0cfd02f9ee37365c66ab 100644 (file)
@@ -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));