summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 124c6109fe..6f2f281d63 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5960,6 +5960,47 @@ static void notify_rename(connection_struct *conn, bool is_dir,
}
/****************************************************************************
+ Returns an error if the parent directory for a filename is open in an
+ incompatible way.
+****************************************************************************/
+
+static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
+ const struct smb_filename *smb_fname_dst_in)
+{
+ char *parent_dir = NULL;
+ struct smb_filename smb_fname_parent;
+ struct file_id id;
+ files_struct *fsp = NULL;
+ int ret;
+
+ if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
+ &parent_dir, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCT(smb_fname_parent);
+ smb_fname_parent.base_name = parent_dir;
+
+ ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ /*
+ * We're only checking on this smbd here, mostly good
+ * enough.. and will pass tests.
+ */
+
+ id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
+ for (fsp = file_find_di_first(conn->sconn, id); fsp;
+ fsp = file_find_di_next(fsp)) {
+ if (fsp->access_mask & DELETE_ACCESS) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Rename an open file - given an fsp.
****************************************************************************/
@@ -5980,6 +6021,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
return status;
}
+ status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* Make a copy of the dst smb_fname structs */
status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);