[PATCH 3/8] smb2/ioctl: add support for FSCTL_[GET/SET]_COMPRESSION

David Disseldorp ddiss at samba.org
Mon Sep 16 09:52:48 CEST 2013


Signed-off-by: David Disseldorp <ddiss at samba.org>
---
 source3/smbd/smb2_ioctl_filesys.c | 121 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 2 deletions(-)

diff --git a/source3/smbd/smb2_ioctl_filesys.c b/source3/smbd/smb2_ioctl_filesys.c
index bc2925b..f89a15f 100644
--- a/source3/smbd/smb2_ioctl_filesys.c
+++ b/source3/smbd/smb2_ioctl_filesys.c
@@ -3,6 +3,7 @@
    Core SMB2 server
 
    Copyright (C) Stefan Metzmacher 2009
+   Copyright (C) David Disseldorp 2013
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,20 +23,136 @@
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "../libcli/smb/smb_common.h"
+#include "../libcli/security/security.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "rpc_server/srv_pipe_hnd.h"
 #include "include/ntioctl.h"
+#include "../librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_ioctl.h"
 #include "smb2_ioctl_private.h"
 
+static NTSTATUS fsctl_get_cmprn(TALLOC_CTX *mem_ctx,
+				struct tevent_context *ev,
+				struct files_struct *fsp,
+				size_t in_max_output,
+				DATA_BLOB *out_output)
+{
+	struct compression_state cmpr_state;
+	enum ndr_err_code ndr_ret;
+	DATA_BLOB output;
+	NTSTATUS status;
+
+	if (fsp == NULL) {
+		return NT_STATUS_FILE_CLOSED;
+	}
+
+	status = check_access(fsp->conn, fsp, NULL,
+			      FILE_READ_ATTRIBUTES);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (fsp->conn->fs_capabilities & FILE_FILE_COMPRESSION == 0) {
+		DEBUG(4, ("FS does not advertise compression support\n"));
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	ZERO_STRUCT(cmpr_state);
+	status = SMB_VFS_GET_COMPRESSION(fsp->conn,
+					 mem_ctx,
+					 fsp,
+					 NULL,
+					 &cmpr_state.format);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	ndr_ret = ndr_push_struct_blob(&output, mem_ctx,
+				       &cmpr_state,
+			(ndr_push_flags_fn_t)ndr_push_compression_state);
+	if (ndr_ret != NDR_ERR_SUCCESS) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (in_max_output < output.length) {
+		DEBUG(1, ("max output %u too small for compression state %ld\n",
+		      (unsigned int)in_max_output, (long int)output.length));
+		return NT_STATUS_INVALID_USER_BUFFER;
+	}
+	*out_output = output;
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS fsctl_set_cmprn(TALLOC_CTX *mem_ctx,
+				struct tevent_context *ev,
+				struct files_struct *fsp,
+				DATA_BLOB *in_input)
+{
+	struct compression_state cmpr_state;
+	enum ndr_err_code ndr_ret;
+	NTSTATUS status;
+
+	if (fsp == NULL) {
+		return NT_STATUS_FILE_CLOSED;
+	}
+
+	status = check_access(fsp->conn, fsp, NULL,
+			      FILE_WRITE_ATTRIBUTES);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (fsp->conn->fs_capabilities & FILE_FILE_COMPRESSION == 0) {
+		DEBUG(4, ("FS does not advertise compression support\n"));
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	ndr_ret = ndr_pull_struct_blob(in_input, mem_ctx, &cmpr_state,
+			(ndr_pull_flags_fn_t)ndr_pull_compression_state);
+	if (ndr_ret != NDR_ERR_SUCCESS) {
+		DEBUG(0, ("failed to unmarshall set compression req\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	status = SMB_VFS_SET_COMPRESSION(fsp->conn,
+					 mem_ctx,
+					 fsp,
+					 NULL,
+					 cmpr_state.format);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
 struct tevent_req *smb2_ioctl_filesys(uint32_t ctl_code,
 				      struct tevent_context *ev,
 				      struct tevent_req *req,
 				      struct smbd_smb2_ioctl_state *state)
 {
+	NTSTATUS status;
+
 	switch (ctl_code) {
-	/* no filesystem device type ioctls are supported yet */
+	case FSCTL_GET_COMPRESSION:
+		status = fsctl_get_cmprn(state, ev, state->fsp,
+					 state->in_max_output,
+					 &state->out_output);
+		if (!tevent_req_nterror(req, status)) {
+			tevent_req_done(req);
+		}
+		return tevent_req_post(req, ev);
+		break;
+	case FSCTL_SET_COMPRESSION:
+		status = fsctl_set_cmprn(state, ev, state->fsp,
+					 &state->in_input);
+		if (!tevent_req_nterror(req, status)) {
+			tevent_req_done(req);
+		}
+		return tevent_req_post(req, ev);
+		break;
 	default: {
-		NTSTATUS status;
 		uint8_t *out_data = NULL;
 		uint32_t out_data_len = 0;
 
-- 
1.8.1.4



More information about the samba-technical mailing list