]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Add openat_internal_dir_from_pathref()
authorVolker Lendecke <vl@samba.org>
Sun, 13 Mar 2022 09:48:12 +0000 (10:48 +0100)
committerRalph Boehme <slow@samba.org>
Thu, 28 Apr 2022 13:12:33 +0000 (13:12 +0000)
If we have a directory pathref fsp, do an openat(dirfd, ".", O_RDONLY)
to cheaply get a real directory handle.

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

index 542f1fe4181522a6bfecede767419cb16e1d5278..caee85a674e02114b3ac51c24ff890a401cb58b6 100644 (file)
@@ -282,6 +282,56 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn,
        return NT_STATUS_OK;
 }
 
+/*
+ * Convert a pathref dirfsp into a real fsp. No need to do any cwd
+ * tricks, we just open ".".
+ */
+NTSTATUS openat_internal_dir_from_pathref(
+       struct files_struct *dirfsp,
+       int open_flags,
+       struct files_struct **_fsp)
+{
+       struct connection_struct *conn = dirfsp->conn;
+       struct smb_filename *smb_dname = dirfsp->fsp_name;
+       struct files_struct *fsp = NULL;
+       char dot[] = ".";
+       struct smb_filename smb_dot = {
+               .base_name = dot,
+               .flags = smb_dname->flags,
+               .twrp = smb_dname->twrp,
+       };
+       NTSTATUS status;
+
+       SMB_ASSERT(dirfsp != conn->cwd_fsp);
+       SMB_ASSERT(VALID_STAT(smb_dname->st));
+       SMB_ASSERT(S_ISDIR(smb_dname->st.st_ex_mode));
+       SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1);
+
+       status = create_internal_dirfsp(conn, smb_dname, &fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /*
+        * Pointless for opening ".", but you never know...
+        */
+       open_flags |= O_NOFOLLOW;
+
+       status = fd_openat(dirfsp, &smb_dot, fsp, open_flags, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
+                        fsp_str_dbg(dirfsp),
+                        nt_errstr(status));
+               file_free(NULL, fsp);
+               return status;
+       }
+
+       fsp->fsp_name->st = smb_dname->st;
+       fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
+       *_fsp = fsp;
+       return NT_STATUS_OK;
+}
+
 /*
  * The "link" in the name doesn't imply link in the filesystem
  * sense. It's a object that "links" together an fsp and an smb_fname
index b78111c25c26d8721468648c494d662d9e51ee95..b6449b105f3b66a93271ee07a9fff77ba175fef6 100644 (file)
@@ -439,6 +439,10 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn,
                              const struct smb_filename *smb_dname,
                              int open_flags,
                              struct files_struct **_fsp);
+NTSTATUS openat_internal_dir_from_pathref(
+       struct files_struct *dirfsp,
+       int open_flags,
+       struct files_struct **_fsp);
 
 NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
                            struct smb_filename *smb_fname);