mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Add the STREAMINFO vfs call
Based on jpeach's work, modified the streaminfo prototype Make use of it in trans2.c together with marshall_stream_info()
This commit is contained in:
parent
9996473290
commit
c34d729c7c
@ -104,6 +104,7 @@
|
||||
/* Leave at 22 - not yet released. Remove parameter fromfd from sendfile. - obnox */
|
||||
/* Leave at 22 - not yet released. Remove parameter fromfd from recvfile. - obnox */
|
||||
/* Leave at 22 - not yet released. Additional change: add operations for offline files -- ab */
|
||||
/* Leave at 22 - not yet released. Add the streaminfo call. -- jpeach, vl */
|
||||
|
||||
#define SMB_VFS_INTERFACE_VERSION 22
|
||||
|
||||
@ -198,6 +199,7 @@ typedef enum _vfs_op_type {
|
||||
SMB_VFS_OP_NOTIFY_WATCH,
|
||||
SMB_VFS_OP_CHFLAGS,
|
||||
SMB_VFS_OP_FILE_ID_CREATE,
|
||||
SMB_VFS_OP_STREAMINFO,
|
||||
|
||||
/* NT ACL operations. */
|
||||
|
||||
@ -339,6 +341,13 @@ struct vfs_ops {
|
||||
int (*chflags)(struct vfs_handle_struct *handle, const char *path, unsigned int flags);
|
||||
struct file_id (*file_id_create)(struct vfs_handle_struct *handle, SMB_DEV_T dev, SMB_INO_T inode);
|
||||
|
||||
NTSTATUS (*streaminfo)(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp,
|
||||
const char *fname,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
unsigned int *num_streams,
|
||||
struct stream_struct **streams);
|
||||
|
||||
/* NT ACL operations. */
|
||||
|
||||
NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle,
|
||||
@ -476,6 +485,7 @@ struct vfs_ops {
|
||||
struct vfs_handle_struct *notify_watch;
|
||||
struct vfs_handle_struct *chflags;
|
||||
struct vfs_handle_struct *file_id_create;
|
||||
struct vfs_handle_struct *streaminfo;
|
||||
|
||||
/* NT ACL operations. */
|
||||
|
||||
|
@ -82,6 +82,7 @@
|
||||
#define SMB_VFS_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs.ops.notify_watch((conn)->vfs.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
|
||||
#define SMB_VFS_CHFLAGS(conn, path, flags) ((conn)->vfs.ops.chflags((conn)->vfs.handles.chflags, (path), (flags)))
|
||||
#define SMB_VFS_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (dev), (inode)))
|
||||
#define SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs.ops.streaminfo((conn)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
|
||||
|
||||
/* NT ACL operations. */
|
||||
#define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
|
||||
@ -206,6 +207,7 @@
|
||||
#define SMB_VFS_OPAQUE_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_opaque.ops.notify_watch((conn)->vfs_opaque.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
|
||||
#define SMB_VFS_OPAQUE_CHFLAGS(conn, path, flags) ((conn)->vfs_opaque.ops.chflags((conn)->vfs_opaque.handles.chflags, (path), (flags)))
|
||||
#define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (dev), (inode)))
|
||||
#define SMB_VFS_OPAQUE_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs_opaque.ops.streaminfo((conn)->vfs_opaque.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
|
||||
|
||||
/* NT ACL operations. */
|
||||
#define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
|
||||
@ -331,6 +333,7 @@
|
||||
#define SMB_VFS_NEXT_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_next.ops.notify_watch((conn)->vfs_next.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
|
||||
#define SMB_VFS_NEXT_CHFLAGS(handle, path, flags) ((handle)->vfs_next.ops.chflags((handle)->vfs_next.handles.chflags, (path), (flags)))
|
||||
#define SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (dev), (inode)))
|
||||
#define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs.ops.streaminfo((handle)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
|
||||
|
||||
/* NT ACL operations. */
|
||||
#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
|
||||
|
@ -942,6 +942,63 @@ static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, S
|
||||
return file_id_create_dev(dev, inode);
|
||||
}
|
||||
|
||||
static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
|
||||
struct files_struct *fsp,
|
||||
const char *fname,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
unsigned int *pnum_streams,
|
||||
struct stream_struct **pstreams)
|
||||
{
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
NTSTATUS status;
|
||||
unsigned int num_streams = 0;
|
||||
struct stream_struct *streams = NULL;
|
||||
int ret;
|
||||
|
||||
if ((fsp != NULL) && (fsp->is_directory)) {
|
||||
/*
|
||||
* No default streams on directories
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((fsp != NULL) && (fsp->fh->fd != -1)) {
|
||||
ret = SMB_VFS_FSTAT(fsp, &sbuf);
|
||||
}
|
||||
else {
|
||||
ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
if (S_ISDIR(sbuf.st_mode)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
streams = talloc(mem_ctx, struct stream_struct);
|
||||
|
||||
if (streams == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
streams->size = sbuf.st_size;
|
||||
streams->alloc_size = get_allocation_size(handle->conn, fsp, &sbuf);
|
||||
|
||||
streams->name = talloc_strdup(streams, "::$DATA");
|
||||
if (streams->name == NULL) {
|
||||
TALLOC_FREE(streams);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
num_streams = 1;
|
||||
done:
|
||||
*pnum_streams = num_streams;
|
||||
*pstreams = streams;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
|
||||
files_struct *fsp,
|
||||
uint32 security_info, SEC_DESC **ppdesc)
|
||||
@ -1367,6 +1424,8 @@ static vfs_op_tuple vfs_default_ops[] = {
|
||||
SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(vfswrap_file_id_create), SMB_VFS_OP_FILE_ID_CREATE,
|
||||
SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(vfswrap_streaminfo), SMB_VFS_OP_STREAMINFO,
|
||||
SMB_VFS_LAYER_OPAQUE},
|
||||
|
||||
/* NT ACL operations. */
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Copyright (C) Stefan (metze) Metzmacher 2003
|
||||
Copyright (C) Volker Lendecke 2005-2007
|
||||
Copyright (C) Steve French 2005
|
||||
Copyright (C) James Peach 2007
|
||||
Copyright (C) James Peach 2006-2007
|
||||
|
||||
Extensively modified by Andrew Tridgell, 1995
|
||||
|
||||
@ -3568,6 +3568,72 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static NTSTATUS marshall_stream_info(unsigned int num_streams,
|
||||
const struct stream_struct *streams,
|
||||
char *data,
|
||||
unsigned int max_data_bytes,
|
||||
unsigned int *data_size)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int ofs = 0;
|
||||
|
||||
for (i=0; i<num_streams; i++) {
|
||||
unsigned int next_offset;
|
||||
size_t namelen;
|
||||
smb_ucs2_t *namebuf;
|
||||
|
||||
namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
|
||||
streams[i].name);
|
||||
|
||||
if ((namelen == (size_t)-1) || (namelen <= 2)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/*
|
||||
* name_buf is now null-terminated, we need to marshall as not
|
||||
* terminated
|
||||
*/
|
||||
|
||||
namelen -= 2;
|
||||
|
||||
if (ofs + 24 + namelen > max_data_bytes) {
|
||||
TALLOC_FREE(namebuf);
|
||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
SIVAL(data, ofs+4, namelen);
|
||||
SOFF_T(data, ofs+8, streams[i].size);
|
||||
SOFF_T(data, ofs+16, streams[i].alloc_size);
|
||||
memcpy(data+ofs+24, namebuf, namelen);
|
||||
TALLOC_FREE(namebuf);
|
||||
|
||||
next_offset = ofs + 24 + namelen;
|
||||
|
||||
if (i == num_streams-1) {
|
||||
SIVAL(data, ofs, 0);
|
||||
}
|
||||
else {
|
||||
unsigned int align = ndr_align_size(next_offset, 8);
|
||||
|
||||
if (next_offset + align > max_data_bytes) {
|
||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
memset(data+next_offset, 0, align);
|
||||
next_offset += align;
|
||||
|
||||
SIVAL(data, ofs, next_offset - ofs);
|
||||
ofs = next_offset;
|
||||
}
|
||||
|
||||
ofs = next_offset;
|
||||
}
|
||||
|
||||
*data_size = ofs;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a TRANSACT2_QFILEINFO on a PIPE !
|
||||
****************************************************************************/
|
||||
@ -4273,20 +4339,40 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
|
||||
*/
|
||||
case SMB_QUERY_FILE_STREAM_INFO:
|
||||
#endif
|
||||
case SMB_FILE_STREAM_INFORMATION:
|
||||
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
|
||||
if (mode & aDIR) {
|
||||
data_size = 0;
|
||||
} else {
|
||||
size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
|
||||
SIVAL(pdata,0,0); /* ??? */
|
||||
SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
|
||||
SOFF_T(pdata,8,file_size);
|
||||
SOFF_T(pdata,16,allocation_size);
|
||||
data_size = 24 + byte_len;
|
||||
}
|
||||
break;
|
||||
case SMB_FILE_STREAM_INFORMATION: {
|
||||
unsigned int num_streams;
|
||||
struct stream_struct *streams;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(10,("call_trans2qfilepathinfo: "
|
||||
"SMB_FILE_STREAM_INFORMATION\n"));
|
||||
|
||||
status = SMB_VFS_STREAMINFO(
|
||||
conn, fsp, fname, talloc_tos(),
|
||||
&num_streams, &streams);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("could not get stream info: %s\n",
|
||||
nt_errstr(status)));
|
||||
reply_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = marshall_stream_info(num_streams, streams,
|
||||
pdata, max_data_bytes,
|
||||
&data_size);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("marshall_stream_info failed: %s\n",
|
||||
nt_errstr(status)));
|
||||
reply_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
TALLOC_FREE(streams);
|
||||
|
||||
break;
|
||||
}
|
||||
case SMB_QUERY_COMPRESSION_INFO:
|
||||
case SMB_FILE_COMPRESSION_INFORMATION:
|
||||
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
|
||||
|
Loading…
Reference in New Issue
Block a user