summaryrefslogtreecommitdiff
path: root/source4/ntvfs/ntvfs_generic.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-20 08:28:31 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:01:57 -0500
commit20d17b80571f0d0265c99c1ccdc21910c2eed043 (patch)
treef166a82fca637eaa303b21954e6bcb8b06efe70a /source4/ntvfs/ntvfs_generic.c
parent8050be6ea343221da9e8866d71b66103ba7fb122 (diff)
downloadsamba-20d17b80571f0d0265c99c1ccdc21910c2eed043.tar.gz
samba-20d17b80571f0d0265c99c1ccdc21910c2eed043.tar.bz2
samba-20d17b80571f0d0265c99c1ccdc21910c2eed043.zip
r3081: several updates to ntvfs and server side async request handling in
preparation for the full share modes and ntcreatex code that I am working on. highlights include: - changed the way a backend determines if it is allowed to process a request asynchronously. The previous method of looking at the send_fn caused problems when an intermediate ntvfs module disabled it, and the caller then wanted to finished processing using this function. The new method is a REQ_CONTROL_MAY_ASYNC flag in req->control_flags, which is also a bit easier to read - fixed 2 bugs in the readbraw server code. One related to trying to answer a readbraw with smb signing (which can't work, and crashed our signing code), the second related to error handling, which attempted to send a normal SMB error packet, when readbraw must send a 0 read reply (as it has no header) - added several more ntvfs_generic.c generic mapping functions. This means that backends no longer need to implement such esoteric functions as SMBwriteunlock() if they don't want to. The backend can just request the mapping layer turn it into a write followed by an unlock. This makes the backends considerably simpler as they only need to implement one style of each function for lock, read, write, open etc, rather than the full host of functions that SMB provides. A backend can still choose to implement them individually, of course, and the CIFS backend does that. - simplified the generic structures to make them identical to the principal call for several common SMB calls (such as RAW_WRITE_GENERIC now being an alias for RAW_WRITE_WRITEX). - started rewriting the pvfs_open() code in preparation for the full ntcreatex semantics. - in pvfs_open and ipc_open, initially allocate the open file structure as a child of the request, so on error we don't need to clean up. Then when we are going to succeed the open steal the pointer into the long term backend context. This makes for much simpler error handling (and fixes some bugs) - use a destructor in the ipc backend to make sure that everthing is cleaned up on receive error conditions. - switched the ipc backend to using idtree for fnum allocation - in the ntvfs_generic mapping routines, use a allocated secondary structure not a stack structure to ensure the request pointer remains valid even if the backend replies async. (This used to be commit 3457c1836c09c82956697eb21627dfa2ed37682e)
Diffstat (limited to 'source4/ntvfs/ntvfs_generic.c')
-rw-r--r--source4/ntvfs/ntvfs_generic.c483
1 files changed, 385 insertions, 98 deletions
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c
index 9e1d653465..b6f3d8e603 100644
--- a/source4/ntvfs/ntvfs_generic.c
+++ b/source4/ntvfs/ntvfs_generic.c
@@ -3,7 +3,7 @@
NTVFS generic level mapping code
- Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Andrew Tridgell 2003-2004
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
@@ -34,7 +34,8 @@
#include "includes.h"
/*
- see if a filename ends in EXE COM DLL or SYM. This is needed for the DENY_DOS mapping for OpenX
+ see if a filename ends in EXE COM DLL or SYM. This is needed for the
+ DENY_DOS mapping for OpenX
*/
static BOOL is_exe_file(const char *fname)
{
@@ -61,125 +62,133 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
struct ntvfs_module_context *ntvfs)
{
NTSTATUS status;
- union smb_open io2;
+ union smb_open *io2;
- if (io->generic.level == RAW_OPEN_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
+ io2 = talloc_p(req, union smb_open);
+ if (io2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
+ /* must be synchronous, or we won't be called to do the
+ translation */
+ req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+
switch (io->generic.level) {
+ case RAW_OPEN_GENERIC:
+ return NT_STATUS_INVALID_LEVEL;
+
case RAW_OPEN_OPENX:
- ZERO_STRUCT(io2.generic.in);
- io2.generic.level = RAW_OPEN_GENERIC;
+ ZERO_STRUCT(io2->generic.in);
+ io2->generic.level = RAW_OPEN_GENERIC;
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_OPLOCK) {
- io2.generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
+ io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
}
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
- io2.generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+ io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
}
switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) {
case OPENX_MODE_ACCESS_READ:
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
break;
case OPENX_MODE_ACCESS_WRITE:
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
break;
case OPENX_MODE_ACCESS_RDWR:
case OPENX_MODE_ACCESS_FCB:
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
break;
}
switch (io->openx.in.open_mode & OPENX_MODE_DENY_MASK) {
case OPENX_MODE_DENY_READ:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
break;
case OPENX_MODE_DENY_WRITE:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
break;
case OPENX_MODE_DENY_ALL:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
break;
case OPENX_MODE_DENY_NONE:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
break;
case OPENX_MODE_DENY_DOS:
/* DENY_DOS is quite strange - it depends on the filename! */
if (is_exe_file(io->openx.in.fname)) {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
} else {
if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) ==
OPENX_MODE_ACCESS_READ) {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
} else {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
}
}
break;
case OPENX_MODE_DENY_FCB:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
break;
}
switch (io->openx.in.open_func) {
case (OPENX_OPEN_FUNC_FAIL):
- io2.generic.in.open_disposition = NTCREATEX_DISP_CREATE;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
break;
case (OPENX_OPEN_FUNC_OPEN):
- io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
break;
case (OPENX_OPEN_FUNC_TRUNC):
- io2.generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
break;
case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
- io2.generic.in.open_disposition = NTCREATEX_DISP_CREATE;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
break;
case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
- io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
break;
case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
- io2.generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
break;
}
- io2.generic.in.alloc_size = io->openx.in.size;
- io2.generic.in.file_attr = io->openx.in.file_attrs;
- io2.generic.in.fname = io->openx.in.fname;
+ io2->generic.in.alloc_size = io->openx.in.size;
+ io2->generic.in.file_attr = io->openx.in.file_attrs;
+ io2->generic.in.fname = io->openx.in.fname;
- status = ntvfs->ops->open(ntvfs, req, &io2);
+ status = ntvfs->ops->open(ntvfs, req, io2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
ZERO_STRUCT(io->openx.out);
- io->openx.out.fnum = io2.generic.out.fnum;
- io->openx.out.attrib = io2.generic.out.attrib;
- io->openx.out.write_time = nt_time_to_unix(io2.generic.out.write_time);
- io->openx.out.size = io2.generic.out.size;
+ io->openx.out.fnum = io2->generic.out.fnum;
+ io->openx.out.attrib = io2->generic.out.attrib;
+ io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
+ io->openx.out.size = io2->generic.out.size;
return NT_STATUS_OK;
case RAW_OPEN_OPEN:
- ZERO_STRUCT(io2.generic.in);
- io2.generic.level = RAW_OPEN_GENERIC;
- io2.generic.in.file_attr = io->open.in.search_attrs;
- io2.generic.in.fname = io->open.in.fname;
- io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN;
+ ZERO_STRUCT(io2->generic.in);
+ io2->generic.level = RAW_OPEN_GENERIC;
+ io2->generic.in.file_attr = io->open.in.search_attrs;
+ io2->generic.in.fname = io->open.in.fname;
+ io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
DEBUG(9,("ntvfs_map_open(OPEN): mapping flags=0x%x\n",
io->open.in.flags));
switch (io->open.in.flags & OPEN_FLAGS_MODE_MASK) {
case OPEN_FLAGS_OPEN_READ:
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
io->open.out.rmode = DOS_OPEN_RDONLY;
break;
case OPEN_FLAGS_OPEN_WRITE:
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
io->open.out.rmode = DOS_OPEN_WRONLY;
break;
case OPEN_FLAGS_OPEN_RDWR:
case 0xf: /* FCB mode */
- io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ |
+ io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ |
GENERIC_RIGHTS_FILE_WRITE;
io->open.out.rmode = DOS_OPEN_RDWR; /* assume we got r/w */
break;
@@ -194,31 +203,31 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
/* DENY_DOS is quite strange - it depends on the filename! */
/* REWRITE: is this necessary for OPEN? */
if (is_exe_file(io->open.in.fname)) {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
} else {
if ((io->open.in.flags & OPEN_FLAGS_MODE_MASK) ==
OPEN_FLAGS_OPEN_READ) {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
} else {
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
}
}
break;
case OPEN_FLAGS_DENY_ALL:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
break;
case OPEN_FLAGS_DENY_WRITE:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
break;
case OPEN_FLAGS_DENY_READ:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
break;
case OPEN_FLAGS_DENY_NONE:
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE |
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE |
NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE;
break;
case 0x70: /* FCB mode */
- io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
break;
default:
DEBUG(2,("ntvfs_map_open(OPEN): invalid DENY 0x%x\n",
@@ -226,18 +235,18 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
return NT_STATUS_INVALID_PARAMETER;
}
DEBUG(9,("ntvfs_map_open(OPEN): mapped flags=0x%x to access_mask=0x%x and share_access=0x%x\n",
- io->open.in.flags, io2.generic.in.access_mask, io2.generic.in.share_access));
+ io->open.in.flags, io2->generic.in.access_mask, io2->generic.in.share_access));
- status = ntvfs->ops->open(ntvfs, req, &io2);
+ status = ntvfs->ops->open(ntvfs, req, io2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
ZERO_STRUCT(io->openx.out);
- io->open.out.fnum = io2.generic.out.fnum;
- io->open.out.attrib = io2.generic.out.attrib;
- io->open.out.write_time = nt_time_to_unix(io2.generic.out.write_time);
- io->open.out.size = io2.generic.out.size;
+ io->open.out.fnum = io2->generic.out.fnum;
+ io->open.out.attrib = io2->generic.out.attrib;
+ io->open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
+ io->open.out.size = io2->generic.out.size;
io->open.out.rmode = DOS_OPEN_RDWR;
return NT_STATUS_OK;
@@ -254,16 +263,21 @@ NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
struct ntvfs_module_context *ntvfs)
{
NTSTATUS status;
- union smb_fsinfo fs2;
+ union smb_fsinfo *fs2;
+
+ fs2 = talloc_p(req, union smb_fsinfo);
+ if (fs2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (fs->generic.level == RAW_QFS_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
/* ask the backend for the generic info */
- fs2.generic.level = RAW_QFS_GENERIC;
+ fs2->generic.level = RAW_QFS_GENERIC;
- status = ntvfs->ops->fsinfo(ntvfs, req, &fs2);
+ status = ntvfs->ops->fsinfo(ntvfs, req, fs2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -279,7 +293,7 @@ NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
/* we need to scale the sizes to fit */
for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
- if (fs2.generic.out.blocks_total * (double)fs2.generic.out.block_size < bpunit * 512 * 65535.0) {
+ if (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size < bpunit * 512 * 65535.0) {
break;
}
}
@@ -287,9 +301,9 @@ NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
fs->dskattr.out.blocks_per_unit = bpunit;
fs->dskattr.out.block_size = 512;
fs->dskattr.out.units_total =
- (fs2.generic.out.blocks_total * (double)fs2.generic.out.block_size) / (bpunit * 512);
+ (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size) / (bpunit * 512);
fs->dskattr.out.units_free =
- (fs2.generic.out.blocks_free * (double)fs2.generic.out.block_size) / (bpunit * 512);
+ (fs2->generic.out.blocks_free * (double)fs2->generic.out.block_size) / (bpunit * 512);
/* we must return a maximum of 2G to old DOS systems, or they get very confused */
if (bpunit > 64 && req->smb_conn->negotiate.protocol <= PROTOCOL_LANMAN2) {
@@ -301,63 +315,63 @@ NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
}
case RAW_QFS_ALLOCATION:
- fs->allocation.out.fs_id = fs2.generic.out.fs_id;
- fs->allocation.out.total_alloc_units = fs2.generic.out.blocks_total;
- fs->allocation.out.avail_alloc_units = fs2.generic.out.blocks_free;
+ fs->allocation.out.fs_id = fs2->generic.out.fs_id;
+ fs->allocation.out.total_alloc_units = fs2->generic.out.blocks_total;
+ fs->allocation.out.avail_alloc_units = fs2->generic.out.blocks_free;
fs->allocation.out.sectors_per_unit = 1;
- fs->allocation.out.bytes_per_sector = fs2.generic.out.block_size;
+ fs->allocation.out.bytes_per_sector = fs2->generic.out.block_size;
return NT_STATUS_OK;
case RAW_QFS_VOLUME:
- fs->volume.out.serial_number = fs2.generic.out.serial_number;
- fs->volume.out.volume_name.s = fs2.generic.out.volume_name;
+ fs->volume.out.serial_number = fs2->generic.out.serial_number;
+ fs->volume.out.volume_name.s = fs2->generic.out.volume_name;
return NT_STATUS_OK;
case RAW_QFS_VOLUME_INFO:
case RAW_QFS_VOLUME_INFORMATION:
- fs->volume_info.out.create_time = fs2.generic.out.create_time;
- fs->volume_info.out.serial_number = fs2.generic.out.serial_number;
- fs->volume_info.out.volume_name.s = fs2.generic.out.volume_name;
+ fs->volume_info.out.create_time = fs2->generic.out.create_time;
+ fs->volume_info.out.serial_number = fs2->generic.out.serial_number;
+ fs->volume_info.out.volume_name.s = fs2->generic.out.volume_name;
return NT_STATUS_OK;
case RAW_QFS_SIZE_INFO:
case RAW_QFS_SIZE_INFORMATION:
- fs->size_info.out.total_alloc_units = fs2.generic.out.blocks_total;
- fs->size_info.out.avail_alloc_units = fs2.generic.out.blocks_free;
+ fs->size_info.out.total_alloc_units = fs2->generic.out.blocks_total;
+ fs->size_info.out.avail_alloc_units = fs2->generic.out.blocks_free;
fs->size_info.out.sectors_per_unit = 1;
- fs->size_info.out.bytes_per_sector = fs2.generic.out.block_size;
+ fs->size_info.out.bytes_per_sector = fs2->generic.out.block_size;
return NT_STATUS_OK;
case RAW_QFS_DEVICE_INFO:
case RAW_QFS_DEVICE_INFORMATION:
- fs->device_info.out.device_type = fs2.generic.out.device_type;
- fs->device_info.out.characteristics = fs2.generic.out.device_characteristics;
+ fs->device_info.out.device_type = fs2->generic.out.device_type;
+ fs->device_info.out.characteristics = fs2->generic.out.device_characteristics;
return NT_STATUS_OK;
case RAW_QFS_ATTRIBUTE_INFO:
case RAW_QFS_ATTRIBUTE_INFORMATION:
- fs->attribute_info.out.fs_attr = fs2.generic.out.fs_attr;
- fs->attribute_info.out.max_file_component_length = fs2.generic.out.max_file_component_length;
- fs->attribute_info.out.fs_type.s = fs2.generic.out.fs_type;
+ fs->attribute_info.out.fs_attr = fs2->generic.out.fs_attr;
+ fs->attribute_info.out.max_file_component_length = fs2->generic.out.max_file_component_length;
+ fs->attribute_info.out.fs_type.s = fs2->generic.out.fs_type;
return NT_STATUS_OK;
case RAW_QFS_QUOTA_INFORMATION:
ZERO_STRUCT(fs->quota_information.out.unknown);
- fs->quota_information.out.quota_soft = fs2.generic.out.quota_soft;
- fs->quota_information.out.quota_hard = fs2.generic.out.quota_hard;
- fs->quota_information.out.quota_flags = fs2.generic.out.quota_flags;
+ fs->quota_information.out.quota_soft = fs2->generic.out.quota_soft;
+ fs->quota_information.out.quota_hard = fs2->generic.out.quota_hard;
+ fs->quota_information.out.quota_flags = fs2->generic.out.quota_flags;
return NT_STATUS_OK;
case RAW_QFS_FULL_SIZE_INFORMATION:
- fs->full_size_information.out.total_alloc_units = fs2.generic.out.blocks_total;
- fs->full_size_information.out.call_avail_alloc_units = fs2.generic.out.blocks_free;
- fs->full_size_information.out.actual_avail_alloc_units = fs2.generic.out.blocks_free;
+ fs->full_size_information.out.total_alloc_units = fs2->generic.out.blocks_total;
+ fs->full_size_information.out.call_avail_alloc_units = fs2->generic.out.blocks_free;
+ fs->full_size_information.out.actual_avail_alloc_units = fs2->generic.out.blocks_free;
fs->full_size_information.out.sectors_per_unit = 1;
- fs->full_size_information.out.bytes_per_sector = fs2.generic.out.block_size;
+ fs->full_size_information.out.bytes_per_sector = fs2->generic.out.block_size;
return NT_STATUS_OK;
case RAW_QFS_OBJECTID_INFORMATION:
- fs->objectid_information.out.guid = fs2.generic.out.guid;
+ fs->objectid_information.out.guid = fs2->generic.out.guid;
ZERO_STRUCT(fs->objectid_information.out.unknown);
return NT_STATUS_OK;
}
@@ -370,7 +384,8 @@ NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
/*
NTVFS fileinfo generic to any mapper
*/
-NTSTATUS ntvfs_map_fileinfo(struct smbsrv_request *req, union smb_fileinfo *info, union smb_fileinfo *info2)
+NTSTATUS ntvfs_map_fileinfo(struct smbsrv_request *req, union smb_fileinfo *info,
+ union smb_fileinfo *info2)
{
int i;
/* and convert it to the required level using results in info2 */
@@ -596,21 +611,26 @@ NTSTATUS ntvfs_map_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *inf
struct ntvfs_module_context *ntvfs)
{
NTSTATUS status;
- union smb_fileinfo info2;
+ union smb_fileinfo *info2;
+
+ info2 = talloc_p(req, union smb_fileinfo);
+ if (info2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (info->generic.level == RAW_FILEINFO_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
/* ask the backend for the generic info */
- info2.generic.level = RAW_FILEINFO_GENERIC;
- info2.generic.in.fnum = info->generic.in.fnum;
+ info2->generic.level = RAW_FILEINFO_GENERIC;
+ info2->generic.in.fnum = info->generic.in.fnum;
- status = ntvfs->ops->qfileinfo(ntvfs, req, &info2);
+ status = ntvfs->ops->qfileinfo(ntvfs, req, info2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return ntvfs_map_fileinfo(req, info, &info2);
+ return ntvfs_map_fileinfo(req, info, info2);
}
/*
@@ -620,19 +640,286 @@ NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *inf
struct ntvfs_module_context *ntvfs)
{
NTSTATUS status;
- union smb_fileinfo info2;
+ union smb_fileinfo *info2;
+
+ info2 = talloc_p(req, union smb_fileinfo);
+ if (info2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (info->generic.level == RAW_FILEINFO_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
/* ask the backend for the generic info */
- info2.generic.level = RAW_FILEINFO_GENERIC;
- info2.generic.in.fname = info->generic.in.fname;
+ info2->generic.level = RAW_FILEINFO_GENERIC;
+ info2->generic.in.fname = info->generic.in.fname;
+
+ /* must be synchronous, or we won't be called to do the
+ translation */
+ req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
- status = ntvfs->ops->qpathinfo(ntvfs, req, &info2);
+ status = ntvfs->ops->qpathinfo(ntvfs, req, info2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return ntvfs_map_fileinfo(req, info, &info2);
+ return ntvfs_map_fileinfo(req, info, info2);
+}
+
+
+/*
+ NTVFS lock generic to any mapper
+*/
+NTSTATUS ntvfs_map_lock(struct smbsrv_request *req, union smb_lock *lck,
+ struct ntvfs_module_context *ntvfs)
+{
+ union smb_lock *lck2;
+ struct smb_lock_entry *locks;
+
+ lck2 = talloc_p(req, union smb_lock);
+ if (lck2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ locks = talloc_array_p(lck2, struct smb_lock_entry, 1);
+ if (locks == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ switch (lck->generic.level) {
+ case RAW_LOCK_LOCKX:
+ return NT_STATUS_INVALID_LEVEL;
+
+ case RAW_LOCK_LOCK:
+ lck2->generic.in.ulock_cnt = 0;
+ lck2->generic.in.lock_cnt = 1;
+ break;
+
+ case RAW_LOCK_UNLOCK:
+ lck2->generic.in.ulock_cnt = 1;
+ lck2->generic.in.lock_cnt = 0;
+ break;
+ }
+
+ lck2->generic.level = RAW_LOCK_GENERIC;
+ lck2->generic.in.fnum = lck->lock.in.fnum;
+ lck2->generic.in.mode = 0;
+ lck2->generic.in.timeout = 0;
+ lck2->generic.in.locks = locks;
+ locks->pid = req->smbpid;
+ locks->offset = lck->lock.in.offset;
+ locks->count = lck->lock.in.count;
+
+ return ntvfs->ops->lock(ntvfs, req, lck2);
+}
+
+
+/*
+ NTVFS write generic to any mapper
+*/
+NTSTATUS ntvfs_map_write(struct smbsrv_request *req, union smb_write *wr,
+ struct ntvfs_module_context *ntvfs)
+{
+ union smb_write *wr2;
+ union smb_lock *lck;
+ union smb_close *cl;
+ NTSTATUS status;
+
+ wr2 = talloc_p(req, union smb_write);
+ if (wr2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ wr2->generic.level = RAW_WRITE_GENERIC;
+
+ /* we can't map asynchronously */
+ req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+
+ switch (wr->generic.level) {
+ case RAW_WRITE_WRITEX:
+ status = NT_STATUS_INVALID_LEVEL;
+ break;
+
+ case RAW_WRITE_WRITE:
+ wr2->generic.in.fnum = wr->write.in.fnum;
+ wr2->generic.in.offset = wr->write.in.offset;
+ wr2->generic.in.wmode = 0;
+ wr2->generic.in.remaining = wr->write.in.remaining;
+ wr2->generic.in.count = wr->write.in.count;
+ wr2->generic.in.data = wr->write.in.data;
+ status = ntvfs->ops->write(ntvfs, req, wr2);
+ wr->write.out.nwritten = wr2->generic.out.nwritten;
+ break;
+
+ case RAW_WRITE_WRITEUNLOCK:
+ lck = talloc_p(wr2, union smb_lock);
+ if (lck == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ wr2->generic.in.fnum = wr->writeunlock.in.fnum;
+ wr2->generic.in.offset = wr->writeunlock.in.offset;
+ wr2->generic.in.wmode = 0;
+ wr2->generic.in.remaining = wr->writeunlock.in.remaining;
+ wr2->generic.in.count = wr->writeunlock.in.count;
+ wr2->generic.in.data = wr->writeunlock.in.data;
+
+ lck->unlock.level = RAW_LOCK_UNLOCK;
+ lck->unlock.in.fnum = wr->writeunlock.in.fnum;
+ lck->unlock.in.count = wr->writeunlock.in.count;
+ lck->unlock.in.offset = wr->writeunlock.in.offset;
+
+ status = ntvfs->ops->write(ntvfs, req, wr2);
+
+ wr->writeunlock.out.nwritten = wr2->generic.out.nwritten;
+
+ if (NT_STATUS_IS_OK(status)) {
+ status = ntvfs->ops->lock(ntvfs, req, lck);
+ }
+ break;
+
+ case RAW_WRITE_WRITECLOSE:
+ cl = talloc_p(wr2, union smb_close);
+ if (cl == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ wr2->generic.in.fnum = wr->writeclose.in.fnum;
+ wr2->generic.in.offset = wr->writeclose.in.offset;
+ wr2->generic.in.wmode = 0;
+ wr2->generic.in.remaining = 0;
+ wr2->generic.in.count = wr->writeclose.in.count;
+ wr2->generic.in.data = wr->writeclose.in.data;
+
+ cl->close.level = RAW_CLOSE_CLOSE;
+ cl->close.in.fnum = wr->writeclose.in.fnum;
+ cl->close.in.write_time = wr->writeclose.in.mtime;
+
+ status = ntvfs->ops->write(ntvfs, req, wr2);
+ wr->writeclose.out.nwritten = wr2->generic.out.nwritten;
+
+ if (NT_STATUS_IS_OK(status)) {
+ status = ntvfs->ops->close(ntvfs, req, cl);
+ }
+ break;
+
+ case RAW_WRITE_SPLWRITE:
+ wr2->generic.in.fnum = wr->splwrite.in.fnum;
+ wr2->generic.in.offset = 0;
+ wr2->generic.in.wmode = 0;
+ wr2->generic.in.remaining = 0;
+ wr2->generic.in.count = wr->splwrite.in.count;
+ wr2->generic.in.data = wr->splwrite.in.data;
+ status = ntvfs->ops->write(ntvfs, req, wr2);
+ break;
+ }
+
+
+ return status;
+}
+
+
+/*
+ NTVFS read generic to any mapper
+*/
+NTSTATUS ntvfs_map_read(struct smbsrv_request *req, union smb_read *rd,
+ struct ntvfs_module_context *ntvfs)
+{
+ union smb_read *rd2;
+ union smb_lock *lck;
+ NTSTATUS status;
+
+ rd2 = talloc_p(req, union smb_read);
+ if (rd2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rd2->generic.level = RAW_READ_GENERIC;
+
+ /* we can't map asynchronously */
+ req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+
+ switch (rd->generic.level) {
+ case RAW_READ_READX:
+ status = NT_STATUS_INVALID_LEVEL;
+ break;
+
+ case RAW_READ_READ:
+ rd2->generic.in.fnum = rd->read.in.fnum;
+ rd2->generic.in.offset = rd->read.in.offset;
+ rd2->generic.in.mincnt = rd->read.in.count;
+ rd2->generic.in.maxcnt = rd->read.in.count;
+ rd2->generic.in.remaining = rd->read.in.remaining;
+ rd2->generic.out.data = rd->read.out.data;
+ status = ntvfs->ops->read(ntvfs, req, rd2);
+ rd->read.out.nread = rd2->generic.out.nread;
+ break;
+
+ case RAW_READ_READBRAW:
+ rd2->generic.in.fnum = rd->readbraw.in.fnum;
+ rd2->generic.in.offset = rd->readbraw.in.offset;
+ rd2->generic.in.mincnt = rd->readbraw.in.mincnt;
+ rd2->generic.in.maxcnt = rd->readbraw.in.maxcnt;
+ rd2->generic.in.remaining = 0;
+ rd2->generic.out.data = rd->readbraw.out.data;
+ status = ntvfs->ops->read(ntvfs, req, rd2);
+ rd->readbraw.out.nread = rd2->generic.out.nread;
+ break;
+
+ case RAW_READ_LOCKREAD:
+ lck = talloc_p(rd2, union smb_lock);
+ if (lck == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rd2->generic.in.fnum = rd->lockread.in.fnum;
+ rd2->generic.in.offset = rd->lockread.in.offset;
+ rd2->generic.in.mincnt = rd->lockread.in.count;
+ rd2->generic.in.maxcnt = rd->lockread.in.count;
+ rd2->generic.in.remaining = rd->lockread.in.remaining;
+ rd2->generic.out.data = rd->lockread.out.data;
+
+ lck->lock.level = RAW_LOCK_LOCK;
+ lck->lock.in.fnum = rd->lockread.in.fnum;
+ lck->lock.in.count = rd->lockread.in.count;
+ lck->lock.in.offset = rd->lockread.in.offset;
+
+ status = ntvfs->ops->lock(ntvfs, req, lck);
+
+ if (NT_STATUS_IS_OK(status)) {
+ status = ntvfs->ops->read(ntvfs, req, rd2);
+ rd->lockread.out.nread = rd2->generic.out.nread;
+ }
+ break;
+ }
+
+
+ return status;
+}
+
+
+/*
+ NTVFS close generic to any mapper
+*/
+NTSTATUS ntvfs_map_close(struct smbsrv_request *req, union smb_close *cl,
+ struct ntvfs_module_context *ntvfs)
+{
+ union smb_close *cl2;
+
+ cl2 = talloc_p(req, union smb_close);
+ if (cl2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ switch (cl2->generic.level) {
+ case RAW_CLOSE_CLOSE:
+ return NT_STATUS_INVALID_LEVEL;
+
+ case RAW_CLOSE_SPLCLOSE:
+ cl2->close.level = RAW_CLOSE_CLOSE;
+ cl2->close.in.fnum = cl->splclose.in.fnum;
+ break;
+ }
+
+ return ntvfs->ops->close(ntvfs, req, cl2);
}