]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libsmb: Factor out cli_create_reparse_point() from cli_symlink()
authorVolker Lendecke <vl@samba.org>
Wed, 20 Sep 2023 23:54:40 +0000 (16:54 -0700)
committerJeremy Allison <jra@samba.org>
Mon, 25 Sep 2023 17:09:37 +0000 (17:09 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/libsmb/clisymlink.c
source3/libsmb/proto.h

index 5cf2646961f0e63b6d67d6ee87b7edecef259572..59887d3585ef58e28a7a0ad1696f8e37cb28db01 100644 (file)
 #include "libcli/smb/reparse.h"
 #include "libcli/smb/reparse_symlink.h"
 
-struct cli_symlink_state {
+struct cli_create_reparse_point_state {
        struct tevent_context *ev;
        struct cli_state *cli;
-       const char *link_target;
-       const char *newpath;
-       uint32_t flags;
-
+       DATA_BLOB reparse_blob;
        uint16_t fnum;
-       DATA_BLOB in;
-
        NTSTATUS set_reparse_status;
 };
 
-static void cli_symlink_create_done(struct tevent_req *subreq);
-static void cli_symlink_set_reparse_done(struct tevent_req *subreq);
-static void cli_symlink_delete_on_close_done(struct tevent_req *subreq);
-static void cli_symlink_close_done(struct tevent_req *subreq);
+static void cli_create_reparse_point_opened(struct tevent_req *subreq);
+static void cli_create_reparse_point_done(struct tevent_req *subreq);
+static void cli_create_reparse_point_doc_done(struct tevent_req *subreq);
+static void cli_create_reparse_point_closed(struct tevent_req *subreq);
 
-struct tevent_req *cli_symlink_send(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct cli_state *cli,
-                                   const char *link_target,
-                                   const char *newpath,
-                                   uint32_t flags)
+struct tevent_req *cli_create_reparse_point_send(TALLOC_CTX *mem_ctx,
+                                                struct tevent_context *ev,
+                                                struct cli_state *cli,
+                                                const char *fname,
+                                                DATA_BLOB reparse_blob)
 {
-       struct tevent_req *req, *subreq;
-       struct cli_symlink_state *state;
+       struct tevent_req *req = NULL, *subreq = NULL;
+       struct cli_create_reparse_point_state *state = NULL;
 
-       req = tevent_req_create(mem_ctx, &state, struct cli_symlink_state);
+       req = tevent_req_create(mem_ctx,
+                               &state,
+                               struct cli_create_reparse_point_state);
        if (req == NULL) {
                return NULL;
        }
        state->ev = ev;
        state->cli = cli;
-       state->link_target = link_target;
-       state->newpath = newpath;
-       state->flags = flags;
+       state->reparse_blob = reparse_blob;
 
+       /*
+        * The create arguments were taken from a Windows->Windows
+        * symlink create call.
+        */
        subreq = cli_ntcreate_send(
-               state, ev, cli, state->newpath, 0,
-               SYNCHRONIZE_ACCESS|DELETE_ACCESS|
-               FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
-               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_CREATE,
-               FILE_OPEN_REPARSE_POINT|FILE_SYNCHRONOUS_IO_NONALERT|
-               FILE_NON_DIRECTORY_FILE,
-               SMB2_IMPERSONATION_IMPERSONATION, 0);
+               state,
+               ev,
+               cli,
+               fname,
+               0,
+               SYNCHRONIZE_ACCESS | DELETE_ACCESS | FILE_READ_ATTRIBUTES |
+                       FILE_WRITE_ATTRIBUTES,
+               FILE_ATTRIBUTE_NORMAL,
+               FILE_SHARE_NONE,
+               FILE_CREATE,
+               FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT |
+                       FILE_NON_DIRECTORY_FILE,
+               SMB2_IMPERSONATION_IMPERSONATION,
+               0);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       tevent_req_set_callback(subreq, cli_symlink_create_done, req);
+       tevent_req_set_callback(subreq, cli_create_reparse_point_opened, req);
        return req;
 }
 
-static void cli_symlink_create_done(struct tevent_req *subreq)
+static void cli_create_reparse_point_opened(struct tevent_req *subreq)
 {
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct cli_symlink_state *state = tevent_req_data(
-               req, struct cli_symlink_state);
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq, struct tevent_req);
+       struct cli_create_reparse_point_state *state =
+               tevent_req_data(req, struct cli_create_reparse_point_state);
        NTSTATUS status;
 
        status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
@@ -97,33 +102,25 @@ static void cli_symlink_create_done(struct tevent_req *subreq)
                return;
        }
 
-       if (!symlink_reparse_buffer_marshall(
-                   state->link_target, NULL, 0, state->flags, state,
-                   &state->in.data, &state->in.length)) {
-               tevent_req_oom(req);
-               return;
-       }
-
-       subreq = cli_fsctl_send(
-               state,
-               state->ev,
-               state->cli,
-               state->fnum,
-               FSCTL_SET_REPARSE_POINT,
-               &state->in,
-               0);
+       subreq = cli_fsctl_send(state,
+                               state->ev,
+                               state->cli,
+                               state->fnum,
+                               FSCTL_SET_REPARSE_POINT,
+                               &state->reparse_blob,
+                               0);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cli_symlink_set_reparse_done, req);
+       tevent_req_set_callback(subreq, cli_create_reparse_point_done, req);
 }
 
-static void cli_symlink_set_reparse_done(struct tevent_req *subreq)
+static void cli_create_reparse_point_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       struct cli_symlink_state *state = tevent_req_data(
-               req, struct cli_symlink_state);
+       struct cli_create_reparse_point_state *state =
+               tevent_req_data(req, struct cli_create_reparse_point_state);
 
        state->set_reparse_status = cli_fsctl_recv(subreq, NULL, NULL);
        TALLOC_FREE(subreq);
@@ -134,7 +131,9 @@ static void cli_symlink_set_reparse_done(struct tevent_req *subreq)
                if (tevent_req_nomem(subreq, req)) {
                        return;
                }
-               tevent_req_set_callback(subreq, cli_symlink_close_done, req);
+               tevent_req_set_callback(subreq,
+                                       cli_create_reparse_point_closed,
+                                       req);
                return;
        }
        subreq = cli_nt_delete_on_close_send(
@@ -142,15 +141,17 @@ static void cli_symlink_set_reparse_done(struct tevent_req *subreq)
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cli_symlink_delete_on_close_done, req);
+       tevent_req_set_callback(subreq,
+                               cli_create_reparse_point_doc_done,
+                               req);
 }
 
-static void cli_symlink_delete_on_close_done(struct tevent_req *subreq)
+static void cli_create_reparse_point_doc_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       struct cli_symlink_state *state = tevent_req_data(
-               req, struct cli_symlink_state);
+       struct cli_create_reparse_point_state *state =
+               tevent_req_data(req, struct cli_create_reparse_point_state);
 
        /*
         * Ignore status, we can't do much anyway in case of failure
@@ -163,15 +164,15 @@ static void cli_symlink_delete_on_close_done(struct tevent_req *subreq)
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cli_symlink_close_done, req);
+       tevent_req_set_callback(subreq, cli_create_reparse_point_closed, req);
 }
 
-static void cli_symlink_close_done(struct tevent_req *subreq)
+static void cli_create_reparse_point_closed(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       struct cli_symlink_state *state = tevent_req_data(
-               req, struct cli_symlink_state);
+       struct cli_create_reparse_point_state *state =
+               tevent_req_data(req, struct cli_create_reparse_point_state);
        NTSTATUS status;
 
        status = cli_close_recv(subreq);
@@ -186,6 +187,61 @@ static void cli_symlink_close_done(struct tevent_req *subreq)
        tevent_req_done(req);
 }
 
+NTSTATUS cli_create_reparse_point_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+struct cli_symlink_state {
+       uint8_t dummy;
+};
+
+static void cli_symlink_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_symlink_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct cli_state *cli,
+                                   const char *link_target,
+                                   const char *newpath,
+                                   uint32_t flags)
+{
+       struct tevent_req *req = NULL, *subreq = NULL;
+       struct cli_symlink_state *state = NULL;
+       DATA_BLOB blob = {};
+       bool ok;
+
+       req = tevent_req_create(mem_ctx, &state, struct cli_symlink_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ok = symlink_reparse_buffer_marshall(link_target,
+                                            NULL,
+                                            0,
+                                            flags,
+                                            state,
+                                            &blob.data,
+                                            &blob.length);
+
+       if (!ok) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = cli_create_reparse_point_send(state, ev, cli, newpath, blob);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, cli_symlink_done, req);
+       return req;
+}
+
+static void cli_symlink_done(struct tevent_req *subreq)
+{
+       NTSTATUS status = cli_symlink_recv(subreq);
+       tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
 NTSTATUS cli_symlink_recv(struct tevent_req *req)
 {
        return tevent_req_simple_recv_ntstatus(req);
index a7c58264f0ed4b80facd1392c63c83765a7413f3..0ca6fd01d0132b67bbb42585192d762f2d7fb5b3 100644 (file)
@@ -1024,6 +1024,13 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli,
 
 /* The following definitions come from libsmb/clisymlink.c  */
 
+struct tevent_req *cli_create_reparse_point_send(TALLOC_CTX *mem_ctx,
+                                                struct tevent_context *ev,
+                                                struct cli_state *cli,
+                                                const char *fname,
+                                                DATA_BLOB reparse_blob);
+NTSTATUS cli_create_reparse_point_recv(struct tevent_req *req);
+
 struct tevent_req *cli_symlink_send(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev,
                                    struct cli_state *cli,