]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Simplify openat_pathref_fsp()
authorVolker Lendecke <vl@samba.org>
Mon, 13 Jun 2022 15:50:32 +0000 (17:50 +0200)
committerRalph Boehme <slow@samba.org>
Mon, 25 Jul 2022 12:04:33 +0000 (12:04 +0000)
Remove the implicit recursion

openat_pathref_fsp->openat_pathref_base_fsp->openat_pathref_fsp

by introducing openat_pathref_nostream() and use
open_stream_pathref_fsp() where possible. openat_pathref_nostream()
will change its name in further refactoring patches, but for
understanding this patch I think this name is good :-)

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/smbd/files.c

index d6ce87cc5fb6e6756b7c4a6b8e665c8c4aad6f93..31f0f144d1b16a93c6c037d8c5c946a00fe76738 100644 (file)
@@ -440,55 +440,11 @@ static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
        return 0;
 }
 
-/*
- * For proper streams support, we have to open the base_fsp for pathref
- * fsp's as well.
- */
-static NTSTATUS open_pathref_base_fsp(const struct files_struct *dirfsp,
-                                     struct smb_filename *smb_fname,
-                                     struct files_struct *fsp)
-{
-       struct smb_filename *smb_fname_base = NULL;
-       NTSTATUS status;
-
-       smb_fname_base = synthetic_smb_fname(talloc_tos(),
-                                            smb_fname->base_name,
-                                            NULL,
-                                            NULL,
-                                            smb_fname->twrp,
-                                            smb_fname->flags);
-       if (smb_fname_base == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = openat_pathref_fsp(dirfsp, smb_fname_base);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(smb_fname_base);
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-                       DBG_DEBUG("Opening base file failed: %s\n",
-                                 nt_errstr(status));
-                       return status;
-               }
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       fsp_set_base_fsp(fsp, smb_fname_base->fsp);
-       smb_fname_fsp_unlink(smb_fname_base);
-       TALLOC_FREE(smb_fname_base);
-
-       return NT_STATUS_OK;
-}
-
-/*
- * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
- * available, open O_RDONLY as root. Both is done in fd_open() ->
- * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
- * true.
- */
-NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
-                           struct smb_filename *smb_fname)
+static NTSTATUS openat_pathref_nostream(
+       const struct files_struct *dirfsp,
+       struct smb_filename *smb_fname)
 {
-       connection_struct *conn = dirfsp->conn;
+       struct connection_struct *conn = dirfsp->conn;
        struct smb_filename *full_fname = NULL;
        struct files_struct *fsp = NULL;
        int open_flags = O_RDONLY;
@@ -496,12 +452,8 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 
        DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
 
-       if (smb_fname->fsp != NULL) {
-               /* We already have one for this name. */
-               DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
-                       smb_fname_str_dbg(smb_fname));
-               return NT_STATUS_OK;
-       }
+       SMB_ASSERT(!is_named_stream(smb_fname));
+       SMB_ASSERT(smb_fname->fsp == NULL);
 
        status = fsp_new(conn, conn, &fsp);
        if (!NT_STATUS_IS_OK(status)) {
@@ -514,9 +466,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
 
        fsp->fsp_flags.is_pathref = true;
 
-       full_fname = full_path_from_dirfsp_atname(fsp,
-                                                 dirfsp,
-                                                 smb_fname);
+       full_fname = full_path_from_dirfsp_atname(fsp, dirfsp, smb_fname);
        if (full_fname == NULL) {
                status = NT_STATUS_NO_MEMORY;
                goto fail;
@@ -527,21 +477,6 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
                goto fail;
        }
 
-       if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
-           && is_named_stream(smb_fname))
-       {
-               /*
-                * We must use smb_fname here, not fsp->fsp_name
-                * as smb_fname is relative to dirfsp, whereas
-                * fsp->fsp_name has been changed above to be
-                * full_fname, relative to the base of the share.
-                */
-               status = open_pathref_base_fsp(dirfsp, smb_fname, fsp);
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto fail;
-               }
-       }
-
        open_flags |= O_NONBLOCK;
 
        status = fd_openat(dirfsp, smb_fname, fsp, open_flags, 0);
@@ -601,16 +536,64 @@ fail:
                  smb_fname_str_dbg(smb_fname),
                  nt_errstr(status));
 
-       if (fsp_is_alternate_stream(fsp)) {
-               struct files_struct *tmp_base_fsp = fsp->base_fsp;
+       fd_close(fsp);
+       file_free(NULL, fsp);
+       return status;
+}
 
-               fsp_set_base_fsp(fsp, NULL);
+/*
+ * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
+ * available, open O_RDONLY as root. Both is done in fd_open() ->
+ * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
+ * true.
+ */
+NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
+                           struct smb_filename *smb_fname)
+{
+       connection_struct *conn = dirfsp->conn;
+       struct smb_filename *base_fname = NULL;
+       NTSTATUS status;
 
-               fd_close(tmp_base_fsp);
-               file_free(NULL, tmp_base_fsp);
+       DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
+
+       if (smb_fname->fsp != NULL) {
+               /* We already have one for this name. */
+               DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
+                       smb_fname_str_dbg(smb_fname));
+               return NT_STATUS_OK;
        }
-       fd_close(fsp);
-       file_free(NULL, fsp);
+
+       if (!(conn->fs_capabilities & FILE_NAMED_STREAMS) ||
+           !is_named_stream(smb_fname)) {
+               status = openat_pathref_nostream(dirfsp, smb_fname);
+               return status;
+       }
+
+       /*
+        * stream open
+        */
+       base_fname = cp_smb_filename_nostream(conn, smb_fname);
+       if (base_fname == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = openat_pathref_nostream(dirfsp, base_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_DEBUG("openat_pathref_nostream failed: %s\n",
+                         nt_errstr(status));
+               goto fail;
+       }
+
+       status = open_stream_pathref_fsp(dirfsp, &base_fname->fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_DEBUG("open_stream_pathref_fsp failed: %s\n",
+                         nt_errstr(status));
+               goto fail;
+       }
+
+       smb_fname_fsp_unlink(base_fname);
+fail:
+       TALLOC_FREE(base_fname);
        return status;
 }