summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-07-13 09:23:57 +0200
committerStefan Metzmacher <metze@samba.org>2009-07-15 11:56:19 +0200
commit722cd5944f9b70c7f642ec1d510d54bf1592beb5 (patch)
tree304280fe71d0b3df229812004ab68b72b318210e
parentd85cc986b85d3c8a6e40491f216c801a1cbde2ab (diff)
downloadsamba-722cd5944f9b70c7f642ec1d510d54bf1592beb5.tar.gz
samba-722cd5944f9b70c7f642ec1d510d54bf1592beb5.tar.bz2
samba-722cd5944f9b70c7f642ec1d510d54bf1592beb5.zip
s3:smbd: add support for SMB2 SetInfo File*Information
metze
-rw-r--r--source3/smbd/smb2_setinfo.c129
1 files changed, 128 insertions, 1 deletions
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index 110ce6c64a..2974695c9f 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -200,7 +200,134 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ if (IS_IPC(conn)) {
+ tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
+ return tevent_req_post(req, ev);
+ }
+
+ switch (in_info_type) {
+ case 0x01:/* SMB2_SETINFO_FILE */
+ {
+ uint16_t file_info_level;
+ struct smb_filename *smb_fname = NULL;
+ char *data;
+ int data_size;
+ int ret_size = 0;
+ NTSTATUS status;
+
+
+ file_info_level = in_file_info_class + 1000;
+ if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
+ file_info_level = 0xFF00 + in_file_info_class;
+ }
+
+ status = create_synthetic_smb_fname_split(state,
+ fsp->fsp_name,
+ NULL,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+
+ if (fsp->is_directory || fsp->fh->fd == -1) {
+ /*
+ * This is actually a SETFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+ if (INFO_LEVEL_IS_UNIX(file_info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn, smb_fname)) {
+ DEBUG(3,("smbd_smb2_setinfo_send: "
+ "SMB_VFS_LSTAT of %s failed "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+ } else {
+ if (SMB_VFS_STAT(conn, smb_fname) != 0) {
+ DEBUG(3,("smbd_smb2_setinfo_send: "
+ "fileinfo of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+ }
+ } else if (fsp->print_file) {
+ /*
+ * Doing a DELETE_ON_CLOSE should cancel a print job.
+ */
+ if ((file_info_level == SMB_SET_FILE_DISPOSITION_INFO)
+ && in_input_buffer.length >= 1
+ && CVAL(in_input_buffer.data,0)) {
+ fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
+
+ DEBUG(3,("smbd_smb2_setinfo_send: "
+ "Cancelling print job (%s)\n",
+ fsp->fsp_name));
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ } else {
+ tevent_req_nterror(req,
+ NT_STATUS_OBJECT_PATH_INVALID);
+ return tevent_req_post(req, ev);
+ }
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+
+ if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+ DEBUG(3,("smbd_smb2_setinfo_send: fstat "
+ "of fnum %d failed (%s)\n", fsp->fnum,
+ strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ data = NULL;
+ data_size = in_input_buffer.length;
+ if (data_size > 0) {
+ data = (char *)SMB_MALLOC_ARRAY(char, data_size);
+ if (tevent_req_nomem(data, req)) {
+
+ }
+ memcpy(data, in_input_buffer.data, data_size);
+ }
+
+ status = smbd_do_setfilepathinfo(conn, smbreq, state,
+ file_info_level,
+ fsp,
+ smb_fname,
+ &data,
+ data_size,
+ &ret_size);
+ SAFE_FREE(data);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
+ status = NT_STATUS_INVALID_INFO_CLASS;
+ }
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+ break;
+ }
+
+ default:
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_done(req);
return tevent_req_post(req, ev);
}