The Samba-Bugzilla – Attachment 6908 Details for
Bug 8462
Move FSCTL processing into the VFS so that vendors can easily implement them
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Reworked the patch to pass a talloc_context at Volker's suggestion
0001-Move-FSCTL-handling-into-the-VFS.-Initial-code-chang.patch (text/plain), 25.20 KB, created by
Richard Sharpe
on 2011-09-17 22:34:28 UTC
(
hide
)
Description:
Reworked the patch to pass a talloc_context at Volker's suggestion
Filename:
MIME Type:
Creator:
Richard Sharpe
Created:
2011-09-17 22:34:28 UTC
Size:
25.20 KB
patch
obsolete
>From b7bda6ade27f33a508667acf3cc972866ebf9444 Mon Sep 17 00:00:00 2001 >From: Richard Sharpe <realrichardsharpe@gmail.com> >Date: Fri, 16 Sep 2011 11:52:22 -0700 >Subject: [PATCH] Move FSCTL handling into the VFS. Initial code changes. > Passes smbtorture NTTRANS-FSCTL. > >--- > source3/include/vfs.h | 22 +++ > source3/include/vfs_macros.h | 6 + > source3/modules/vfs_default.c | 333 +++++++++++++++++++++++++++++++++++++ > source3/smbd/nttrans.c | 367 ++++------------------------------------- > source3/smbd/vfs.c | 17 ++ > 5 files changed, 410 insertions(+), 335 deletions(-) > >diff --git a/source3/include/vfs.h b/source3/include/vfs.h >index b47e80f..1079228 100644 >--- a/source3/include/vfs.h >+++ b/source3/include/vfs.h >@@ -136,6 +136,7 @@ > /* Leave at 28 - not yet released. Rename open function to open_fn. - gd */ > /* Leave at 28 - not yet released. Make getwd function always return malloced memory. JRA. */ > /* Bump to version 29 - Samba 3.6.0 will ship with interface version 28. */ >+/* Leave at 29 - not yet releases. Add fsctl. Richard Sharpe */ > #define SMB_VFS_INTERFACE_VERSION 29 > > /* >@@ -329,6 +330,17 @@ struct vfs_fn_pointers { > TALLOC_CTX *mem_ctx, > char **mapped_name); > >+ NTSTATUS (*fsctl)(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ TALLOC_CTX *ctx, >+ uint32_t function, >+ uint16_t req_flags, >+ const char *in_data, >+ uint32_t in_len, >+ char **out_data, >+ uint32_t max_out_len, >+ uint32_t *out_len); >+ > /* NT ACL operations. */ > > NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle, >@@ -692,6 +704,16 @@ NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle, > enum vfs_translate_direction direction, > TALLOC_CTX *mem_ctx, > char **mapped_name); >+NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ TALLOC_CTX *ctx, >+ uint32_t function, >+ uint16_t req_flags, >+ const char *in_data, >+ uint32_t in_len, >+ char **out_data, >+ uint32_t max_out_len, >+ uint32_t *out_len); > NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, > struct files_struct *fsp, > uint32 security_info, >diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h >index c7686f1..3dd6a64 100644 >--- a/source3/include/vfs_macros.h >+++ b/source3/include/vfs_macros.h >@@ -364,6 +364,12 @@ > #define SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx, mapped_name) \ > smb_vfs_call_translate_name((handle)->next, (name), (direction), (mem_ctx), (mapped_name)) > >+#define SMB_VFS_FSCTL(fsp, ctx, function, req_flags, in_data, in_len, out_data, max_out_len, out_len) \ >+ smb_vfs_call_fsctl((fsp)->conn->vfs_handles, (fsp), (ctx), (function), (req_flags), (in_data), (in_len), (out_data), (max_out_len), (out_len)) >+ >+#define SMB_VFS_NEXT_FSCTL(handle, fsp, ctx, function, req_flags, in_data, in_len, out_data, max_out_len, out_len) \ >+ smb_vfs_call_fsctl((handle)->next, (fsp), (ctx), (function), (req_flags), (in_data), (in_len), (out_data), (max_out_len), (out_len)) >+ > #define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) \ > smb_vfs_call_fget_nt_acl((fsp)->conn->vfs_handles, (fsp), (security_info), (ppdesc)) > #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) \ >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index 2dc7ec7..d056c7c 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -24,6 +24,8 @@ > #include "smbd/smbd.h" > #include "ntioctl.h" > #include "smbprofile.h" >+#include "../libcli/security/security.h" >+#include "passdb/lookup_sid.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_VFS >@@ -591,6 +593,336 @@ static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle, > return NT_STATUS_NONE_MAPPED; > } > >+/* >+ * Implement the default fsctl operation. >+ */ >+static bool vfswrap_logged_ioctl_message = false; >+ >+static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ TALLOC_CTX *ctx, >+ uint32_t function, >+ uint16_t req_flags, /* Needed for UNICODE ... */ >+ const char *in_data, >+ uint32_t in_len, >+ char **out_data, >+ uint32_t max_out_len, >+ uint32_t *out_len) >+{ >+ >+ switch (function) { >+ case FSCTL_SET_SPARSE: >+ { >+ bool set_sparse = true; >+ NTSTATUS status; >+ >+ if (in_len >= 1 && in_data[0] == 0) { >+ set_sparse = false; >+ } >+ >+ status = file_set_sparse(handle->conn, fsp, set_sparse); >+ >+ DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9, >+ ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n", >+ smb_fname_str_dbg(fsp->fsp_name), set_sparse, >+ nt_errstr(status))); >+ >+ return status; >+ } >+ >+ case FSCTL_CREATE_OR_GET_OBJECT_ID: >+ { >+ unsigned char objid[16]; >+ char *return_data = NULL; >+ >+ /* This should return the object-id on this file. >+ * I think I'll make this be the inode+dev. JRA. >+ */ >+ >+ DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fsp->fnum)); >+ >+ *out_len = (max_out_len >= 64) ? 64 : max_out_len; >+ /* Hmmm, will this cause problems if less data asked for? */ >+ return_data = talloc_size(ctx, 64); >+ if (return_data == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ /* For backwards compatibility only store the dev/inode. */ >+ push_file_id_16(return_data, &fsp->file_id); >+ memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16); >+ push_file_id_16(return_data+32, &fsp->file_id); >+ *out_data = return_data; >+ return NT_STATUS_OK; >+ } >+ >+ case FSCTL_GET_REPARSE_POINT: >+ { >+ /* Fail it with STATUS_NOT_A_REPARSE_POINT */ >+ DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X] Status: NOT_IMPLEMENTED\n", fsp->fnum)); >+ return NT_STATUS_NOT_A_REPARSE_POINT; >+ } >+ >+ case FSCTL_SET_REPARSE_POINT: >+ { >+ /* Fail it with STATUS_NOT_A_REPARSE_POINT */ >+ DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X] Status: NOT_IMPLEMENTED\n", fsp->fnum)); >+ return NT_STATUS_NOT_A_REPARSE_POINT; >+ } >+ >+ case FSCTL_GET_SHADOW_COPY_DATA: >+ { >+ /* >+ * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots) >+ * and return their volume names. If max_data_count is 16, then it is just >+ * asking for the number of volumes and length of the combined names. >+ * >+ * pdata is the data allocated by our caller, but that uses >+ * total_data_count (which is 0 in our case) rather than max_data_count. >+ * Allocate the correct amount and return the pointer to let >+ * it be deallocated when we return. >+ */ >+ struct shadow_copy_data *shadow_data = NULL; >+ bool labels = False; >+ uint32 labels_data_count = 0; >+ uint32 i; >+ char *cur_pdata = NULL; >+ >+ if (max_out_len < 16) { >+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n", >+ max_out_len)); >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (max_out_len > 16) { >+ labels = True; >+ } >+ >+ shadow_data = talloc_zero(ctx, struct shadow_copy_data); >+ if (shadow_data == NULL) { >+ DEBUG(0,("TALLOC_ZERO() failed!\n")); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ /* >+ * Call the VFS routine to actually do the work. >+ */ >+ if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) { >+ TALLOC_FREE(shadow_data); >+ if (errno == ENOSYS) { >+ DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", >+ fsp->conn->connectpath)); >+ return NT_STATUS_NOT_SUPPORTED; >+ } else { >+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", >+ fsp->conn->connectpath)); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ } >+ >+ labels_data_count = (shadow_data->num_volumes * 2 * >+ sizeof(SHADOW_COPY_LABEL)) + 2; >+ >+ if (!labels) { >+ *out_len = 16; >+ } else { >+ *out_len = 12 + labels_data_count + 4; >+ } >+ >+ if (max_out_len < *out_len) { >+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n", >+ max_out_len, *out_len)); >+ TALLOC_FREE(shadow_data); >+ return NT_STATUS_BUFFER_TOO_SMALL; >+ } >+ >+ cur_pdata = talloc_size(ctx, *out_len); >+ if (cur_pdata == NULL) { >+ TALLOC_FREE(shadow_data); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ *out_data = cur_pdata; >+ >+ /* num_volumes 4 bytes */ >+ SIVAL(cur_pdata, 0, shadow_data->num_volumes); >+ >+ if (labels) { >+ /* num_labels 4 bytes */ >+ SIVAL(cur_pdata, 4, shadow_data->num_volumes); >+ } >+ >+ /* needed_data_count 4 bytes */ >+ SIVAL(cur_pdata, 8, labels_data_count + 4); >+ >+ cur_pdata += 12; >+ >+ DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n", >+ shadow_data->num_volumes, fsp_str_dbg(fsp))); >+ if (labels && shadow_data->labels) { >+ for (i=0; i<shadow_data->num_volumes; i++) { >+ srvstr_push(cur_pdata, req_flags, >+ cur_pdata, shadow_data->labels[i], >+ 2 * sizeof(SHADOW_COPY_LABEL), >+ STR_UNICODE|STR_TERMINATE); >+ cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL); >+ DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i])); >+ } >+ } >+ >+ TALLOC_FREE(shadow_data); >+ >+ return NT_STATUS_OK; >+ } >+ >+ case FSCTL_FIND_FILES_BY_SID: >+ { >+ /* pretend this succeeded - >+ * >+ * we have to send back a list with all files owned by this SID >+ * >+ * but I have to check that --metze >+ */ >+ struct dom_sid sid; >+ uid_t uid; >+ size_t sid_len; >+ >+ DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n", fsp->fnum)); >+ >+ if (in_len < 8) { >+ /* NT_STATUS_BUFFER_TOO_SMALL maybe? */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ sid_len = MIN(in_len - 4,SID_MAX_SIZE); >+ >+ /* unknown 4 bytes: this is not the length of the sid :-( */ >+ /*unknown = IVAL(pdata,0);*/ >+ >+ if (!sid_parse(in_data + 4, sid_len, &sid)) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid))); >+ >+ if (!sid_to_uid(&sid, &uid)) { >+ DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n", >+ sid_string_dbg(&sid), >+ (unsigned long)sid_len)); >+ uid = (-1); >+ } >+ >+ /* we can take a look at the find source :-) >+ * >+ * find ./ -uid $uid -name '*' is what we need here >+ * >+ * >+ * and send 4bytes len and then NULL terminated unicode strings >+ * for each file >+ * >+ * but I don't know how to deal with the paged results >+ * (maybe we can hang the result anywhere in the fsp struct) >+ * >+ * but I don't know how to deal with the paged results >+ * (maybe we can hang the result anywhere in the fsp struct) >+ * >+ * we don't send all files at once >+ * and at the next we should *not* start from the beginning, >+ * so we have to cache the result >+ * >+ * --metze >+ */ >+ >+ /* this works for now... */ >+ return NT_STATUS_OK; >+ } >+ >+ case FSCTL_QUERY_ALLOCATED_RANGES: >+ { >+ /* FIXME: This is just a dummy reply, telling that all of the >+ * file is allocated. MKS cp needs that. >+ * Adding the real allocated ranges via FIEMAP on Linux >+ * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make >+ * this FSCTL correct for sparse files. >+ */ >+ NTSTATUS status; >+ uint64_t offset, length; >+ char *out_data_tmp = NULL; >+ >+ if (in_len != 16) { >+ DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n", >+ in_len)); >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (max_out_len < 16) { >+ DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n", >+ max_out_len)); >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ offset = BVAL(in_data,0); >+ length = BVAL(in_data,8); >+ >+ if (offset + length < offset) { >+ /* No 64-bit integer wrap. */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ /* Shouldn't this be SMB_VFS_STAT ... ? */ >+ status = vfs_stat_fsp(fsp); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ *out_len = 16; >+ out_data_tmp = talloc_size(ctx, *out_len); >+ if (out_data_tmp == NULL) { >+ DEBUG(10, ("unable to allocate memory for response\n")); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ if (offset > fsp->fsp_name->st.st_ex_size || >+ fsp->fsp_name->st.st_ex_size == 0 || >+ length == 0) { >+ memset(out_data_tmp, 0, *out_len); >+ } else { >+ uint64_t end = offset + length; >+ end = MIN(end, fsp->fsp_name->st.st_ex_size); >+ SBVAL(out_data_tmp, 0, 0); >+ SBVAL(out_data_tmp, 8, end); >+ } >+ >+ *out_data = out_data_tmp; >+ >+ return NT_STATUS_OK; >+ } >+ >+ case FSCTL_IS_VOLUME_DIRTY: >+ { >+ DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on FID[0x%04X] " >+ "(but not implemented)\n", fsp->fnum)); >+ /* >+ * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx >+ * says we have to respond with NT_STATUS_INVALID_PARAMETER >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ default: >+ /* >+ * Only print once ... unfortunately there could be lots of >+ * different FSCTLs that are called. >+ */ >+ if (!vfswrap_logged_ioctl_message) { >+ vfswrap_logged_ioctl_message = true; >+ DEBUG(2, ("%s (0x%x): Currently not implemented.\n", >+ __func__, function)); >+ } >+ } >+ >+ return NT_STATUS_NOT_SUPPORTED; >+} >+ > /******************************************************************** > Given a stat buffer return the allocated size on disk, taking into > account sparse files. >@@ -1727,6 +2059,7 @@ static struct vfs_fn_pointers vfs_default_fns = { > .strict_lock = vfswrap_strict_lock, > .strict_unlock = vfswrap_strict_unlock, > .translate_name = vfswrap_translate_name, >+ .fsctl = vfswrap_fsctl, > > /* NT ACL operations. */ > >diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c >index 8900ec8..9eac0aa 100644 >--- a/source3/smbd/nttrans.c >+++ b/source3/smbd/nttrans.c >@@ -2096,12 +2096,16 @@ static void call_nt_transact_ioctl(connection_struct *conn, > char **ppdata, uint32 data_count, > uint32 max_data_count) > { >+ NTSTATUS status; > uint32 function; > uint16 fidnum; > files_struct *fsp; > uint8 isFSctl; > uint8 compfilter; >+ char *out_data = NULL; >+ uint32 out_data_len = 0; > char *pdata = *ppdata; >+ TALLOC_CTX *ctx = talloc_tos(); > > if (setup_count != 8) { > DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); >@@ -2114,353 +2118,46 @@ static void call_nt_transact_ioctl(connection_struct *conn, > isFSctl = CVAL(*ppsetup, 6); > compfilter = CVAL(*ppsetup, 7); > >- DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", >+ DEBUG(10, ("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", > function, fidnum, isFSctl, compfilter)); > > fsp=file_fsp(req, fidnum); >- /* this check is done in each implemented function case for now >- because I don't want to break anything... --metze >- FSP_BELONGS_CONN(fsp,conn);*/ >- >- SMB_PERFCOUNT_SET_IOCTL(&req->pcd, function); >- >- switch (function) { >- case FSCTL_SET_SPARSE: >- { >- bool set_sparse = true; >- NTSTATUS status; >- >- if (data_count >= 1 && pdata[0] == 0) { >- set_sparse = false; >- } > >- DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X]set[%u]\n", >- fidnum, set_sparse)); >- >- if (!check_fsp_open(conn, req, fsp)) { >- return; >- } >- >- status = file_set_sparse(conn, fsp, set_sparse); >- if (!NT_STATUS_IS_OK(status)) { >- DEBUG(9,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n", >- smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status))); >- reply_nterror(req, status); >- return; >- } >- >- DEBUG(10,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n", >- smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status))); >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); >+ /* >+ * We don't really implement IOCTLs, especially on files. >+ */ >+ if (!isFSctl) { >+ DEBUG(10, ("isFSctl: 0x%02X indicates IOCTL, not FSCTL!\n", >+ isFSctl)); >+ reply_nterror(req, NT_STATUS_NOT_SUPPORTED); > return; > } >- case FSCTL_CREATE_OR_GET_OBJECT_ID: >- { >- unsigned char objid[16]; >- >- /* This should return the object-id on this file. >- * I think I'll make this be the inode+dev. JRA. >- */ >- >- DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum)); > >- if (!check_fsp_open(conn, req, fsp)) { >- return; >- } >- >- data_count = 64; >- pdata = nttrans_realloc(ppdata, data_count); >- if (pdata == NULL) { >- reply_nterror(req, NT_STATUS_NO_MEMORY); >- return; >- } >- >- /* For backwards compatibility only store the dev/inode. */ >- push_file_id_16(pdata, &fsp->file_id); >- memcpy(pdata+16,create_volume_objectid(conn,objid),16); >- push_file_id_16(pdata+32, &fsp->file_id); >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, >- pdata, data_count); >+ /* Has to be for an open file! */ >+ if (!check_fsp_open(conn, req, fsp)) { > return; > } > >- case FSCTL_GET_REPARSE_POINT: >- /* pretend this fail - my winXP does it like this >- * --metze >- */ >- >- DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); >- reply_nterror(req, NT_STATUS_NOT_A_REPARSE_POINT); >- return; >- >- case FSCTL_SET_REPARSE_POINT: >- /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case. >- * --metze >- */ >- >- DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); >- reply_nterror(req, NT_STATUS_NOT_A_REPARSE_POINT); >- return; >- >- case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ >- { >- /* >- * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots) >- * and return their volume names. If max_data_count is 16, then it is just >- * asking for the number of volumes and length of the combined names. >- * >- * pdata is the data allocated by our caller, but that uses >- * total_data_count (which is 0 in our case) rather than max_data_count. >- * Allocate the correct amount and return the pointer to let >- * it be deallocated when we return. >- */ >- struct shadow_copy_data *shadow_data = NULL; >- bool labels = False; >- uint32 labels_data_count = 0; >- uint32 i; >- char *cur_pdata; >- >- if (!check_fsp_open(conn, req, fsp)) { >- return; >- } >- >- if (max_data_count < 16) { >- DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n", >- max_data_count)); >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- >- if (max_data_count > 16) { >- labels = True; >- } >- >- shadow_data = talloc_zero(talloc_tos(), >- struct shadow_copy_data); >- if (shadow_data == NULL) { >- DEBUG(0,("TALLOC_ZERO() failed!\n")); >- reply_nterror(req, NT_STATUS_NO_MEMORY); >- return; >- } >- >- /* >- * Call the VFS routine to actually do the work. >- */ >- if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) { >- TALLOC_FREE(shadow_data); >- if (errno == ENOSYS) { >- DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", >- conn->connectpath)); >- reply_nterror(req, NT_STATUS_NOT_SUPPORTED); >- return; >- } else { >- DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", >- conn->connectpath)); >- reply_nterror(req, NT_STATUS_UNSUCCESSFUL); >- return; >- } >- } >- >- labels_data_count = (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))+2; >- >- if (!labels) { >- data_count = 16; >- } else { >- data_count = 12+labels_data_count+4; >- } >- >- if (max_data_count<data_count) { >- DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n", >- max_data_count,data_count)); >- TALLOC_FREE(shadow_data); >- reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); >- return; >- } >- >- pdata = nttrans_realloc(ppdata, data_count); >- if (pdata == NULL) { >- TALLOC_FREE(shadow_data); >- reply_nterror(req, NT_STATUS_NO_MEMORY); >- return; >- } >- >- cur_pdata = pdata; >- >- /* num_volumes 4 bytes */ >- SIVAL(pdata,0,shadow_data->num_volumes); >- >- if (labels) { >- /* num_labels 4 bytes */ >- SIVAL(pdata,4,shadow_data->num_volumes); >- } >- >- /* needed_data_count 4 bytes */ >- SIVAL(pdata, 8, labels_data_count+4); >- >- cur_pdata+=12; >- >- DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n", >- shadow_data->num_volumes, fsp_str_dbg(fsp))); >- if (labels && shadow_data->labels) { >- for (i=0;i<shadow_data->num_volumes;i++) { >- srvstr_push(pdata, req->flags2, >- cur_pdata, shadow_data->labels[i], >- 2*sizeof(SHADOW_COPY_LABEL), >- STR_UNICODE|STR_TERMINATE); >- cur_pdata+=2*sizeof(SHADOW_COPY_LABEL); >- DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i])); >- } >- } >- >- TALLOC_FREE(shadow_data); >- >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, >- pdata, data_count); >- >- return; >- } >- >- case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ >- { >- /* pretend this succeeded - >- * >- * we have to send back a list with all files owned by this SID >- * >- * but I have to check that --metze >- */ >- struct dom_sid sid; >- uid_t uid; >- size_t sid_len; >- >- DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); >- >- if (!check_fsp_open(conn, req, fsp)) { >- return; >- } >- >- if (data_count < 8) { >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- >- sid_len = MIN(data_count-4,SID_MAX_SIZE); >- >- /* unknown 4 bytes: this is not the length of the sid :-( */ >- /*unknown = IVAL(pdata,0);*/ >- >- if (!sid_parse(pdata+4,sid_len,&sid)) { >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid))); >- >- if (!sid_to_uid(&sid, &uid)) { >- DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n", >- sid_string_dbg(&sid), >- (unsigned long)sid_len)); >- uid = (-1); >- } >- >- /* we can take a look at the find source :-) >- * >- * find ./ -uid $uid -name '*' is what we need here >- * >- * >- * and send 4bytes len and then NULL terminated unicode strings >- * for each file >- * >- * but I don't know how to deal with the paged results >- * (maybe we can hang the result anywhere in the fsp struct) >- * >- * we don't send all files at once >- * and at the next we should *not* start from the beginning, >- * so we have to cache the result >- * >- * --metze >- */ >- >- /* this works for now... */ >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); >- return; >- } >- case FSCTL_QUERY_ALLOCATED_RANGES: >- { >- /* FIXME: This is just a dummy reply, telling that all of the >- * file is allocated. MKS cp needs that. >- * Adding the real allocated ranges via FIEMAP on Linux >- * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make >- * this FSCTL correct for sparse files. >- */ >- NTSTATUS status; >- uint64_t offset, length; >- >- if (!check_fsp_open(conn, req, fsp)) { >- return; >- } >- >- if (data_count != 16) { >- DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n", >- data_count)); >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- >- if (max_data_count < 16) { >- DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_data_count(%u) < 16 is invalid!\n", >- max_data_count)); >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- >- offset = BVAL(pdata,0); >- length = BVAL(pdata,8); >- >- if (offset + length < offset) { >- /* No 64-bit integer wrap. */ >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- } >- >- status = vfs_stat_fsp(fsp); >- if (!NT_STATUS_IS_OK(status)) { >- reply_nterror(req, status); >- return; >- } >+ SMB_PERFCOUNT_SET_IOCTL(&req->pcd, function); > >- if (offset > fsp->fsp_name->st.st_ex_size || >- fsp->fsp_name->st.st_ex_size == 0 || >- length == 0) { >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); >- } else { >- uint64_t end = offset + length; >- end = MIN(end, fsp->fsp_name->st.st_ex_size); >- SBVAL(pdata,0,0); >- SBVAL(pdata,8,end); >- send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, >- pdata, 16); >- } >- return; >- } >- case FSCTL_IS_VOLUME_DIRTY: >- DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on FID[0x%04X] " >- "(but not implemented)\n", (int)fidnum)); >- /* >- * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx >- * says we have to respond with NT_STATUS_INVALID_PARAMETER >- */ >- reply_nterror(req, NT_STATUS_INVALID_PARAMETER); >- return; >- default: >- /* Only print this once... */ >- if (!logged_ioctl_message) { >- logged_ioctl_message = true; >- DEBUG(2,("call_nt_transact_ioctl(0x%x): " >- "Currently not implemented.\n", >- function)); >- } >+ /* >+ * out_data might be allocated by the VFS module, but talloc should be >+ * used, and should be cleaned up when the request ends. >+ */ >+ status = SMB_VFS_FSCTL(fsp, >+ ctx, >+ function, >+ req->flags2, >+ pdata, >+ data_count, >+ &out_data, >+ max_data_count, >+ &out_data_len); >+ if (!NT_STATUS_IS_OK(status)) { >+ reply_nterror(req, status); >+ } else { >+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, out_data, out_data_len); > } >- >- reply_nterror(req, NT_STATUS_NOT_SUPPORTED); > } > > >diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c >index c6edef2..2d0f6a4 100644 >--- a/source3/smbd/vfs.c >+++ b/source3/smbd/vfs.c >@@ -1721,6 +1721,23 @@ NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle, > mapped_name); > } > >+NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ TALLOC_CTX *ctx, >+ uint32_t function, >+ uint16_t req_flags, >+ const char *in_data, >+ uint32_t in_len, >+ char **out_data, >+ uint32_t max_out_len, >+ uint32_t *out_len) >+{ >+ VFS_FIND(fsctl); >+ return handle->fns->fsctl(handle, fsp, ctx, function, req_flags, >+ in_data, in_len, out_data, max_out_len, >+ out_len); >+} >+ > NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, > struct files_struct *fsp, > uint32 security_info, >-- >1.7.4.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 8462
:
6898
|
6900
|
6906
|
6908
|
6933
|
6935