summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-02-25 11:15:16 -0800
committerJeremy Allison <jra@samba.org>2010-02-25 11:15:16 -0800
commit3551eb7cbfb3bf7573c00d349def884cd70c89c7 (patch)
treec5aaa7e7fb8a1ab6a4f897f08f7781cc1bacb5e9
parent166a3821c985696572359a38a1b75cc96b600a15 (diff)
downloadsamba-3551eb7cbfb3bf7573c00d349def884cd70c89c7.tar.gz
samba-3551eb7cbfb3bf7573c00d349def884cd70c89c7.tar.bz2
samba-3551eb7cbfb3bf7573c00d349def884cd70c89c7.zip
Implement rename/move in SMB2 from Windows7.
Jeremy.
-rw-r--r--source3/include/trans2.h1
-rw-r--r--source3/smbd/smb2_setinfo.c3
-rw-r--r--source3/smbd/trans2.c109
3 files changed, 112 insertions, 1 deletions
diff --git a/source3/include/trans2.h b/source3/include/trans2.h
index 3759d59681..d42554551a 100644
--- a/source3/include/trans2.h
+++ b/source3/include/trans2.h
@@ -294,6 +294,7 @@ Byte offset Type name description
#define SMB_FILE_ACCESS_INFORMATION 1008
#define SMB_FILE_NAME_INFORMATION 1009
#define SMB_FILE_RENAME_INFORMATION 1010
+#define SMB2_FILE_RENAME_INFORMATION_INTERNAL 0xFF0A /* Internal mapped version. */
#define SMB_FILE_LINK_INFORMATION 1011
#define SMB_FILE_NAMES_INFORMATION 1012
#define SMB_FILE_DISPOSITION_INFORMATION 1013
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index f3e3fc964f..a5193eba7a 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -213,7 +213,8 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
file_info_level = in_file_info_class + 1000;
if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
- file_info_level = 0xFF00 + in_file_info_class;
+ /* SMB2_FILE_RENAME_INFORMATION_INTERNAL == 0xFF00 + in_file_info_class */
+ file_info_level = SMB2_FILE_RENAME_INFORMATION_INTERNAL;
}
if (fsp->is_directory || fsp->fh->fd == -1) {
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 073bee628a..eff5fba676 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5888,6 +5888,107 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
}
/****************************************************************************
+ Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
+****************************************************************************/
+
+static NTSTATUS smb2_file_rename_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_rename_information: got name |%s|\n",
+ newname));
+
+#if 0
+ /* Check the new name has no '/' characters. */
+ if (strchr_m(newname, '/')) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+#endif
+
+ 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 && fsp->base_fsp) {
+ /* newname must be a stream name. */
+ if (newname[0] != ':') {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ /* Create an smb_fname to call rename_internals_fsp() with. */
+ status = create_synthetic_smb_fname(talloc_tos(),
+ fsp->base_fsp->fsp_name->base_name, newname, NULL,
+ &smb_fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ /*
+ * Set the original last component, since
+ * rename_internals_fsp() requires it.
+ */
+ smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
+ newname);
+ if (smb_fname_dst->original_lcomp == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ }
+
+ DEBUG(10,("smb_file_rename_information: "
+ "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
+ fsp->fnum, fsp_str_dbg(fsp),
+ smb_fname_str_dbg(smb_fname_dst)));
+ status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
+ overwrite);
+
+ out:
+ TALLOC_FREE(smb_fname_dst);
+ return status;
+}
+
+
+/****************************************************************************
Deal with SMB_FILE_RENAME_INFORMATION.
****************************************************************************/
@@ -7475,6 +7576,14 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
break;
}
+ case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
+ {
+ /* SMB2 rename information. */
+ status = smb2_file_rename_information(conn, req,
+ pdata, total_data,
+ fsp, smb_fname);
+ break;
+ }
#if defined(HAVE_POSIX_ACLS)
case SMB_SET_POSIX_ACL:
{