<member>close</member>
<member>closedir</member>
<member>connect</member>
+ <member>copy_chunk_send</member>
+ <member>copy_chunk_recv</member>
<member>disconnect</member>
<member>disk_free</member>
<member>fchmod</member>
return id;
}
+static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ return NULL;
+}
+
+static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *fname,
.notify_watch_fn = skel_notify_watch,
.chflags_fn = skel_chflags,
.file_id_create_fn = skel_file_id_create,
+ .copy_chunk_send_fn = skel_copy_chunk_send,
+ .copy_chunk_recv_fn = skel_copy_chunk_recv,
.streaminfo_fn = skel_streaminfo,
.get_real_filename_fn = skel_get_real_filename,
return SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
}
+static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ return SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off,
+ dest_fsp, dest_off, num);
+}
+
+static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ return SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied);
+}
+
static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *fname,
.notify_watch_fn = skel_notify_watch,
.chflags_fn = skel_chflags,
.file_id_create_fn = skel_file_id_create,
+ .copy_chunk_send_fn = skel_copy_chunk_send,
+ .copy_chunk_recv_fn = skel_copy_chunk_recv,
.streaminfo_fn = skel_streaminfo,
.get_real_filename_fn = skel_get_real_filename,
/* Leave at 29 - not yet released. Added sys_acl_blob_get_file and sys_acl_blob_get_fd */
/* Bump to version 30 - Samba 4.0.0 will ship with interface version 30 */
/* Leave at 30 - not yet released. Added conn->cwd to save vfs_GetWd() calls. */
+/* Leave at 30 - not yet released. add SMB_VFS_COPY_CHUNK() */
#define SMB_VFS_INTERFACE_VERSION 30
/*
int (*chflags_fn)(struct vfs_handle_struct *handle, const char *path, unsigned int flags);
struct file_id (*file_id_create_fn)(struct vfs_handle_struct *handle,
const SMB_STRUCT_STAT *sbuf);
+ struct tevent_req *(*copy_chunk_send_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num);
+ NTSTATUS (*copy_chunk_recv_fn)(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied);
NTSTATUS (*streaminfo_fn)(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32_t in_len,
uint8_t **_out_data,
uint32_t max_out_len,
- uint32_t *out_len);
+ uint32_t *out_len);
+struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num);
+NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied);
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32 security_info,
#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_COPY_CHUNK_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
+ smb_vfs_call_copy_chunk_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num))
+#define SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
+ smb_vfs_call_copy_chunk_send((handle)->next, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num))
+
+#define SMB_VFS_COPY_CHUNK_RECV(conn, req, copied) \
+ smb_vfs_call_copy_chunk_recv((conn)->vfs_handles, (req), (copied))
+#define SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied) \
+ smb_vfs_call_copy_chunk_recv((handle)->next, (req), (copied))
+
#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) \
#include "librpc/gen_ndr/ndr_dfsblobs.h"
#include "lib/util/tevent_unix.h"
#include "lib/asys/asys.h"
+#include "lib/util/tevent_ntstatus.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
return NT_STATUS_NOT_SUPPORTED;
}
+struct vfs_cc_state {
+ off_t copied;
+ NTSTATUS status;
+};
+
+static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ struct tevent_req *req;
+ struct vfs_cc_state *vfs_cc_state;
+
+ DEBUG(10,("performing server side copy chunk of length %lu\n", num));
+
+ req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* everything is done synchronously for now */
+ if (SMB_VFS_LSEEK(src_fsp, src_off, SEEK_SET) != src_off) {
+ vfs_cc_state->status = map_nt_error_from_unix(errno);
+ goto err_out;
+ }
+ if (SMB_VFS_LSEEK(dest_fsp, dest_off, SEEK_SET) != dest_off) {
+ vfs_cc_state->status = map_nt_error_from_unix(errno);
+ goto err_out;
+ }
+
+ vfs_cc_state->copied = vfs_transfer_file(src_fsp, dest_fsp, num);
+ if (vfs_cc_state->copied == -1) {
+ vfs_cc_state->status = map_nt_error_from_unix(errno);
+ goto err_out;
+ }
+ vfs_cc_state->status = NT_STATUS_OK;
+
+err_out:
+ if (!tevent_req_nterror(req, vfs_cc_state->status)) {
+ tevent_req_done(req);
+ }
+ return tevent_req_post(req, ev);
+}
+
+static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
+ struct vfs_cc_state);
+
+ *copied = vfs_cc_state->copied;
+ DEBUG(10,("server side copy chunk copied %lu\n", *copied));
+
+ return vfs_cc_state->status;
+}
+
/********************************************************************
Given a stat buffer return the allocated size on disk, taking into
account sparse files.
.strict_unlock_fn = vfswrap_strict_unlock,
.translate_name_fn = vfswrap_translate_name,
.fsctl_fn = vfswrap_fsctl,
+ .copy_chunk_send_fn = vfswrap_copy_chunk_send,
+ .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
/* NT ACL operations. */
SMB_VFS_OP_STRICT_LOCK,
SMB_VFS_OP_STRICT_UNLOCK,
SMB_VFS_OP_TRANSLATE_NAME,
+ SMB_VFS_OP_COPY_CHUNK_SEND,
+ SMB_VFS_OP_COPY_CHUNK_RECV,
/* NT ACL operations. */
{ SMB_VFS_OP_STRICT_LOCK, "strict_lock" },
{ SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" },
{ SMB_VFS_OP_TRANSLATE_NAME, "translate_name" },
+ { SMB_VFS_OP_COPY_CHUNK_SEND, "copy_chunk_send" },
+ { SMB_VFS_OP_COPY_CHUNK_RECV, "copy_chunk_recv" },
{ SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" },
{ SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" },
{ SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" },
return result;
}
+static struct tevent_req *smb_full_audit_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ struct tevent_req *req;
+
+ req = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp,
+ src_off, dest_fsp, dest_off, num);
+
+ do_log(SMB_VFS_OP_COPY_CHUNK_SEND, req, handle, "");
+
+ return req;
+}
+
+static NTSTATUS smb_full_audit_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ NTSTATUS result;
+
+ result = SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied);
+
+ do_log(SMB_VFS_OP_COPY_CHUNK_RECV, NT_STATUS_IS_OK(result), handle, "");
+
+ return result;
+}
+
static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info,
struct security_descriptor **ppdesc)
.strict_lock_fn = smb_full_audit_strict_lock,
.strict_unlock_fn = smb_full_audit_strict_unlock,
.translate_name_fn = smb_full_audit_translate_name,
+ .copy_chunk_send_fn = smb_full_audit_copy_chunk_send,
+ .copy_chunk_recv_fn = smb_full_audit_copy_chunk_recv,
.fget_nt_acl_fn = smb_full_audit_fget_nt_acl,
.get_nt_acl_fn = smb_full_audit_get_nt_acl,
.fset_nt_acl_fn = smb_full_audit_fset_nt_acl,
#include "smbd/smbd.h"
#include "ntioctl.h"
#include "lib/util/tevent_unix.h"
+#include "lib/util/tevent_ntstatus.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
return result;
}
+struct time_audit_cc_state {
+ struct timespec ts_send;
+ struct vfs_handle_struct *handle;
+ off_t copied;
+ NTSTATUS status;
+ struct tevent_req *subreq;
+};
+static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq);
+
+static struct tevent_req *smb_time_audit_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ struct tevent_req *req;
+ struct time_audit_cc_state *cc_state;
+
+ req = tevent_req_create(mem_ctx, &cc_state, struct time_audit_cc_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ cc_state->handle = handle;
+ cc_state->status = NT_STATUS_OK;
+ clock_gettime_mono(&cc_state->ts_send);
+ cc_state->subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev,
+ src_fsp, src_off,
+ dest_fsp, dest_off,
+ num);
+ if (tevent_req_nomem(cc_state->subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_set_callback(cc_state->subreq,
+ smb_time_audit_copy_chunk_done,
+ req);
+ return req;
+}
+
+static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct time_audit_cc_state *cc_state
+ = tevent_req_data(req, struct time_audit_cc_state);
+
+ cc_state->status = SMB_VFS_NEXT_COPY_CHUNK_RECV(cc_state->handle,
+ cc_state->subreq, &cc_state->copied);
+ if (tevent_req_nterror(req, cc_state->status)) {
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static NTSTATUS smb_time_audit_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ struct time_audit_cc_state *cc_state
+ = tevent_req_data(req, struct time_audit_cc_state);
+ struct timespec ts_recv;
+ double timediff;
+
+ clock_gettime_mono(&ts_recv);
+ timediff = nsec_time_diff(&ts_recv, &cc_state->ts_send)*1.0e-9;
+ if (timediff > audit_timeout) {
+ smb_time_audit_log("copy_chunk", timediff);
+ }
+
+ *copied = cc_state->copied;
+ return cc_state->status;
+}
+
static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
files_struct *fsp,
uint32 security_info,
.strict_lock_fn = smb_time_audit_strict_lock,
.strict_unlock_fn = smb_time_audit_strict_unlock,
.translate_name_fn = smb_time_audit_translate_name,
+ .copy_chunk_send_fn = smb_time_audit_copy_chunk_send,
+ .copy_chunk_recv_fn = smb_time_audit_copy_chunk_recv,
.fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
.get_nt_acl_fn = smb_time_audit_get_nt_acl,
.fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
uint32_t *out_len)
{
VFS_FIND(fsctl);
- return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
- in_data, in_len, out_data, max_out_len,
+ return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
+ in_data, in_len, out_data, max_out_len,
out_len);
}
+struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ off_t src_off,
+ struct files_struct *dest_fsp,
+ off_t dest_off,
+ off_t num)
+{
+ VFS_FIND(copy_chunk_send);
+ return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
+ src_off, dest_fsp, dest_off, num);
+}
+
+NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ off_t *copied)
+{
+ VFS_FIND(copy_chunk_recv);
+ return handle->fns->copy_chunk_recv_fn(handle, req, copied);
+}
+
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32 security_info,