[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Tue May 18 19:43:48 MDT 2010


The branch, master has been updated
       via  572e5de... Implement missing info level SMB_FILE_LINK_INFORMATION.
      from  c798207... Keep track of credits we're giving out. Set initial credits to 1 (MS-SMB2 spec required).

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 572e5dec1bbd4af3ccc4b8bfe56a72ded4c9aa6e
Author: Jeremy Allison <jra at samba.org>
Date:   Tue May 18 18:34:54 2010 -0700

    Implement missing info level SMB_FILE_LINK_INFORMATION.
    
    Fix bug #7435 - SMB2 hardlink fails (invalid level).
    Found at the Microsoft plugsharing plugfest.
    
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/include/proto.h |    4 +-
 source3/smbd/nttrans.c  |    2 +
 source3/smbd/trans2.c   |  104 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 104 insertions(+), 6 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 154efeb..3deeb9f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6368,8 +6368,10 @@ void send_trans2_replies(connection_struct *conn,
 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16]);
 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
 		connection_struct *conn,
+		struct smb_request *req,
+		bool overwrite_if_exists,
 		const struct smb_filename *smb_fname_old,
-		const struct smb_filename *smb_fname_new);
+		struct smb_filename *smb_fname_new);
 NTSTATUS smb_set_file_time(connection_struct *conn,
 			   files_struct *fsp,
 			   const struct smb_filename *smb_fname,
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index b42d665..9b4d38a 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1550,6 +1550,8 @@ void reply_ntrename(struct smb_request *req)
 				status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
 			} else {
 				status = hardlink_internals(ctx, conn,
+							    req,
+							    false,
 							    smb_fname_old,
 							    smb_fname_new);
 			}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 56d22b3..dec9d7f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5348,8 +5348,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
 		connection_struct *conn,
+		struct smb_request *req,
+		bool overwrite_if_exists,
 		const struct smb_filename *smb_fname_old,
-		const struct smb_filename *smb_fname_new)
+		struct smb_filename *smb_fname_new)
 {
 	NTSTATUS status = NT_STATUS_OK;
 
@@ -5358,9 +5360,23 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
-	/* Disallow if newname already exists. */
 	if (VALID_STAT(smb_fname_new->st)) {
-		return NT_STATUS_OBJECT_NAME_COLLISION;
+		if (overwrite_if_exists) {
+			if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
+				return NT_STATUS_FILE_IS_A_DIRECTORY;
+			}
+			status = unlink_internals(conn,
+						req,
+						FILE_ATTRIBUTE_NORMAL,
+						smb_fname_new,
+						false);
+			if (!NT_STATUS_IS_OK(status)) {
+				return status;
+			}
+		} else {
+			/* Disallow if newname already exists. */
+			return NT_STATUS_OBJECT_NAME_COLLISION;
+		}
 	}
 
 	/* No links from a directory. */
@@ -5870,7 +5886,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 					struct smb_request *req,
 					const char *pdata, int total_data,
-					const struct smb_filename *smb_fname_new)
+					struct smb_filename *smb_fname_new)
 {
 	char *oldname = NULL;
 	struct smb_filename *smb_fname_old = NULL;
@@ -5902,7 +5918,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 		return status;
 	}
 
-	return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
+	return hardlink_internals(ctx, conn, req, false,
+			smb_fname_old, smb_fname_new);
 }
 
 /****************************************************************************
@@ -6006,6 +6023,75 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
 	return status;
 }
 
+static NTSTATUS smb_file_link_information(connection_struct *conn,
+					    struct smb_request *req,
+					    const char *pdata,
+					    int total_data,
+					    files_struct *fsp,
+					    struct smb_filename *smb_fname_src)
+{
+	bool overwrite;
+	uint32_t len;
+	char *newname = NULL;
+	struct smb_filename *smb_fname_dst = NULL;
+	NTSTATUS status = NT_STATUS_OK;
+	TALLOC_CTX *ctx = talloc_tos();
+
+	if (!fsp) {
+		return NT_STATUS_INVALID_HANDLE;
+	}
+
+	if (total_data < 20) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	overwrite = (CVAL(pdata,0) ? true : false);
+	len = IVAL(pdata,16);
+
+	if (len > (total_data - 20) || (len == 0)) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	srvstr_get_path(ctx, pdata, req->flags2, &newname,
+				&pdata[20], len, STR_TERMINATE,
+				&status);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	DEBUG(10,("smb_file_link_information: got name |%s|\n",
+				newname));
+
+	status = filename_convert(ctx,
+				conn,
+				req->flags2 & FLAGS2_DFS_PATHNAMES,
+				newname,
+				0,
+				NULL,
+				&smb_fname_dst);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (fsp->base_fsp) {
+		/* No stream names. */
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	DEBUG(10,("smb_file_link_information: "
+		  "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
+		  fsp->fnum, fsp_str_dbg(fsp),
+		  smb_fname_str_dbg(smb_fname_dst)));
+	status = hardlink_internals(ctx,
+				conn,
+				req,
+				overwrite,
+				fsp->fsp_name,
+				smb_fname_dst);
+
+	TALLOC_FREE(smb_fname_dst);
+	return status;
+}
 
 /****************************************************************************
  Deal with SMB_FILE_RENAME_INFORMATION.
@@ -7609,6 +7695,14 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
 			break;
 		}
 
+		case SMB_FILE_LINK_INFORMATION:
+		{
+			status = smb_file_link_information(conn, req,
+							pdata, total_data,
+							fsp, smb_fname);
+			break;
+		}
+
 #if defined(HAVE_POSIX_ACLS)
 		case SMB_SET_POSIX_ACL:
 		{


-- 
Samba Shared Repository


More information about the samba-cvs mailing list