]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: add parent_pathref()
authorRalph Boehme <slow@samba.org>
Thu, 21 Jan 2021 16:05:17 +0000 (17:05 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 28 Jan 2021 08:11:49 +0000 (08:11 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/files.c
source3/smbd/proto.h

index eceeaf2c6af80d91448bcfcf71cdb005290af485..448a284780ba1c870666263b334d36c41f9077a8 100644 (file)
@@ -674,6 +674,70 @@ NTSTATUS synthetic_pathref(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+static int atname_destructor(struct smb_filename *smb_fname)
+{
+       destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
+       return 0;
+}
+
+/**
+ * Turn a path into a parent pathref and atname
+ *
+ * This returns the parent pathref in _parent and the name relative to it. If
+ * smb_fname was a pathref (ie smb_fname->fsp != NULL), then _atname will be a
+ * pathref as well, ie _atname->fsp will point at the same fsp as
+ * smb_fname->fsp.
+ **/
+NTSTATUS parent_pathref(TALLOC_CTX *mem_ctx,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       struct smb_filename **_parent,
+                       struct smb_filename **_atname)
+{
+       struct smb_filename *parent = NULL;
+       struct smb_filename *atname = NULL;
+       NTSTATUS status;
+       int ret;
+       bool ok;
+
+       ok = parent_smb_fname(mem_ctx,
+                             smb_fname,
+                             &parent,
+                             &atname);
+       if (!ok) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ret = vfs_stat(dirfsp->conn, parent);
+       if (ret != 0) {
+               TALLOC_FREE(parent);
+               return map_nt_error_from_unix(errno);
+       }
+
+       status = openat_pathref_fsp(dirfsp, parent);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
+               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(parent);
+               return status;
+       }
+
+       if (smb_fname->fsp != NULL) {
+               status = fsp_smb_fname_link(smb_fname->fsp,
+                                           &atname->fsp_link,
+                                           &atname->fsp);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(parent);
+                       return status;
+               }
+               talloc_set_destructor(atname, atname_destructor);
+       }
+       *_parent = parent;
+       *_atname = atname;
+       return NT_STATUS_OK;
+}
+
 /****************************************************************************
  Close all open files for a connection.
 ****************************************************************************/
index a65c786c24df1fad094607b6dbc4b26a25b417c0..f67daf2d2be78904e8f120bb5863bc4d9f82dba3 100644 (file)
@@ -477,6 +477,12 @@ NTSTATUS synthetic_pathref(TALLOC_CTX *mem_ctx,
                           uint32_t flags,
                           struct smb_filename **_smb_fname);
 
+NTSTATUS parent_pathref(TALLOC_CTX *mem_ctx,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       struct smb_filename **_parent,
+                       struct smb_filename **_atname);
+
 /* The following definitions come from smbd/ipc.c  */
 
 NTSTATUS nt_status_np_pipe(NTSTATUS status);