X-Git-Url: http://git.samba.org/samba.git/?p=jra%2Fsamba%2F.git;a=blobdiff_plain;f=source4%2Fntvfs%2Fntvfs_generic.c;h=b03d57166bba0dcad8ad56294abc15ade7605662;hp=e4bc963882f4b52eeeb9f35a7f7762d89a57a46a;hb=24fb16f1f6d1e5ecbc1c6468bc1f35e7ecb3b0aa;hpb=7f0c7702f6b9db216fcd6c29165b2a11ea1f24a9
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c
index e4bc963882f..b03d57166bb 100644
--- a/source4/ntvfs/ntvfs_generic.c
+++ b/source4/ntvfs/ntvfs_generic.c
@@ -7,7 +7,7 @@
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
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see .
*/
/*
this implements mappings between info levels for NTVFS backend calls
@@ -32,9 +31,9 @@
*/
#include "includes.h"
-#include "smb_server/smb_server.h"
-#include "librpc/gen_ndr/ndr_security.h"
#include "ntvfs/ntvfs.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
/* a second stage function converts from the out parameters of the generic
call onto the out parameters of the specific call made */
@@ -117,21 +116,21 @@ static NTSTATUS ntvfs_map_async_finish(struct ntvfs_request *req, NTSTATUS statu
see if a filename ends in EXE COM DLL or SYM. This is needed for the
DENY_DOS mapping for OpenX
*/
-BOOL is_exe_filename(const char *fname)
+bool is_exe_filename(const char *fname)
{
char *p;
p = strrchr(fname, '.');
if (!p) {
- return False;
+ return false;
}
p++;
if (strcasecmp(p, "EXE") == 0 ||
strcasecmp(p, "COM") == 0 ||
strcasecmp(p, "DLL") == 0 ||
strcasecmp(p, "SYM") == 0) {
- return True;
+ return true;
}
- return False;
+ return false;
}
@@ -155,7 +154,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
switch (io->generic.level) {
case RAW_OPEN_OPEN:
- io->openold.file.fnum = io2->generic.file.fnum;
+ io->openold.out.file.ntvfs = io2->generic.out.file.ntvfs;
io->openold.out.attrib = io2->generic.out.attrib;
io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
io->openold.out.size = io2->generic.out.size;
@@ -163,7 +162,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
break;
case RAW_OPEN_OPENX:
- io->openx.file.fnum = io2->generic.file.fnum;
+ io->openx.out.file.ntvfs = io2->generic.out.file.ntvfs;
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;
@@ -183,7 +182,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
break;
case RAW_OPEN_T2OPEN:
- io->t2open.file.fnum = io2->generic.file.fnum;
+ io->t2open.out.file.ntvfs = io2->generic.out.file.ntvfs;
io->t2open.out.attrib = io2->generic.out.attrib;
io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
io->t2open.out.size = io2->generic.out.size;
@@ -196,17 +195,47 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
case RAW_OPEN_MKNEW:
case RAW_OPEN_CREATE:
- io->mknew.file.fnum = io2->generic.file.fnum;
- write_time = io->mknew.in.write_time;
+ io->mknew.out.file.ntvfs= io2->generic.out.file.ntvfs;
+ write_time = io->mknew.in.write_time;
break;
case RAW_OPEN_CTEMP:
- io->ctemp.file.fnum = io2->generic.file.fnum;
- io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname +
- strlen(io->ctemp.in.directory) + 1);
+ io->ctemp.out.file.ntvfs= io2->generic.out.file.ntvfs;
+ io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname +
+ strlen(io->ctemp.in.directory) + 1);
NT_STATUS_HAVE_NO_MEMORY(io->ctemp.out.name);
break;
+ case RAW_OPEN_SMB2:
+ ZERO_STRUCT(io->smb2.out);
+ io->smb2.out.file.ntvfs = io2->generic.out.file.ntvfs;
+ switch (io2->generic.out.oplock_level) {
+ case BATCH_OPLOCK_RETURN:
+ io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
+ break;
+ case EXCLUSIVE_OPLOCK_RETURN:
+ io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+ break;
+ case LEVEL_II_OPLOCK_RETURN:
+ io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_II;
+ break;
+ default:
+ io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
+ break;
+ }
+ io->smb2.out.reserved = 0;
+ io->smb2.out.create_action = io2->generic.out.create_action;
+ io->smb2.out.create_time = io2->generic.out.create_time;
+ io->smb2.out.access_time = io2->generic.out.access_time;
+ io->smb2.out.write_time = io2->generic.out.write_time;
+ io->smb2.out.change_time = io2->generic.out.change_time;
+ io->smb2.out.alloc_size = io2->generic.out.alloc_size;
+ io->smb2.out.size = io2->generic.out.size;
+ io->smb2.out.file_attr = io2->generic.out.attrib;
+ io->smb2.out.reserved2 = 0;
+ io->smb2.out.maximal_access = io2->generic.out.maximal_access;
+ break;
+
default:
return NT_STATUS_INVALID_LEVEL;
}
@@ -220,7 +249,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
sf = talloc(req, union smb_setfileinfo);
NT_STATUS_HAVE_NO_MEMORY(sf);
sf->generic.level = RAW_SFILEINFO_STANDARD;
- sf->generic.file.fnum = io2->generic.file.fnum;
+ sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs;
sf->standard.in.create_time = 0;
sf->standard.in.write_time = write_time;
sf->standard.in.access_time = 0;
@@ -231,7 +260,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
sf = talloc(req, union smb_setfileinfo);
NT_STATUS_HAVE_NO_MEMORY(sf);
sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
- sf->generic.file.fnum = io2->generic.file.fnum;
+ sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs;
sf->end_of_file_info.in.size = set_size;
status = ntvfs->ops->setfileinfo(ntvfs, req, sf);
if (NT_STATUS_IS_OK(status)) {
@@ -252,6 +281,8 @@ static NTSTATUS map_openx_open(uint16_t flags, uint16_t open_mode,
uint16_t open_func, const char *fname,
union smb_open *io2)
{
+ io2->generic.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+
if (flags & OPENX_FLAGS_REQUEST_OPLOCK) {
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
}
@@ -347,7 +378,7 @@ static NTSTATUS map_openx_open(uint16_t flags, uint16_t open_mode,
/*
NTVFS open generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_open *io)
{
@@ -456,7 +487,6 @@ _PUBLIC_ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
case RAW_OPEN_CTEMP:
io2->generic.in.file_attr = io->ctemp.in.attrib;
- io2->generic.in.file_attr = 0;
io2->generic.in.fname =
talloc_asprintf(io2, "%s\\SRV%s",
io->ctemp.in.directory,
@@ -470,6 +500,53 @@ _PUBLIC_ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
NTCREATEX_SHARE_ACCESS_WRITE;
status = ntvfs->ops->open(ntvfs, req, io2);
break;
+ case RAW_OPEN_SMB2:
+ switch (io->smb2.in.oplock_level) {
+ case SMB2_OPLOCK_LEVEL_BATCH:
+ io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK |
+ NTCREATEX_FLAGS_REQUEST_OPLOCK;
+ break;
+ case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
+ io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_OPLOCK;
+ break;
+ default:
+ io2->generic.in.flags = 0;
+ break;
+ }
+ io2->generic.in.root_fid = 0;
+ io2->generic.in.access_mask = io->smb2.in.desired_access;
+ io2->generic.in.alloc_size = io->smb2.in.alloc_size;
+ io2->generic.in.file_attr = io->smb2.in.file_attributes;
+ io2->generic.in.share_access = io->smb2.in.share_access;
+ io2->generic.in.open_disposition= io->smb2.in.create_disposition;
+ io2->generic.in.create_options = io->smb2.in.create_options;
+ io2->generic.in.impersonation = io->smb2.in.impersonation_level;
+ io2->generic.in.security_flags = 0;
+ io2->generic.in.fname = io->smb2.in.fname;
+ io2->generic.in.sec_desc = io->smb2.in.sec_desc;
+ io2->generic.in.ea_list = &io->smb2.in.eas;
+ io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access;
+
+ /* we don't support timewarp yet */
+ if (io->smb2.in.timewarp != 0) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ break;
+ }
+
+ /* we need to check these bits before we check the private mask */
+ if (io2->generic.in.create_options & SMB2_CREATE_OPTIONS_NOT_SUPPORTED_MASK) {
+ DEBUG(2,(__location__ " create_options 0x%x not supported\n",
+ io2->generic.in.create_options));
+ status = NT_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ /* TODO: find out why only SMB2 ignores these */
+ io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_SYNC_ALERT;
+ io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_ASYNC_ALERT;
+
+ status = ntvfs->ops->open(ntvfs, req, io2);
+ break;
default:
status = NT_STATUS_INVALID_LEVEL;
@@ -483,7 +560,7 @@ done:
/*
NTVFS fsinfo generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_fsinfo *fs)
{
@@ -534,7 +611,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
(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) {
+ if (bpunit > 64 && req->ctx->protocol <= PROTOCOL_LANMAN2) {
fs->dskattr.out.blocks_per_unit = 64;
fs->dskattr.out.units_total = 0xFFFF;
fs->dskattr.out.units_free = 0xFFFF;
@@ -612,7 +689,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
/*
NTVFS fileinfo generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_fileinfo(TALLOC_CTX *mem_ctx,
+NTSTATUS ntvfs_map_fileinfo(TALLOC_CTX *mem_ctx,
union smb_fileinfo *info,
union smb_fileinfo *info2)
{
@@ -843,7 +920,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_fileinfo(TALLOC_CTX *mem_ctx,
/*
NTVFS fileinfo generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_fileinfo *info)
{
@@ -861,7 +938,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
/* ask the backend for the generic info */
info2->generic.level = RAW_FILEINFO_GENERIC;
- info2->generic.file.fnum = info->generic.file.fnum;
+ info2->generic.in.file.ntvfs= info->generic.in.file.ntvfs;
/* only used by the simple backend, which doesn't do async */
req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
@@ -876,7 +953,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
/*
NTVFS pathinfo generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_fileinfo *info)
{
@@ -893,8 +970,8 @@ _PUBLIC_ NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
}
/* ask the backend for the generic info */
- info2->generic.level = RAW_FILEINFO_GENERIC;
- info2->generic.file.path = info->generic.file.path;
+ info2->generic.level = RAW_FILEINFO_GENERIC;
+ info2->generic.in.file.path = info->generic.in.file.path;
/* only used by the simple backend, which doesn't do async */
req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
@@ -910,9 +987,9 @@ _PUBLIC_ NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
/*
NTVFS lock generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req,
- union smb_lock *lck)
+NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_lock *lck)
{
union smb_lock *lck2;
struct smb_lock_entry *locks;
@@ -932,24 +1009,102 @@ _PUBLIC_ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_LEVEL;
case RAW_LOCK_LOCK:
+ lck2->generic.level = RAW_LOCK_GENERIC;
+ lck2->generic.in.file.ntvfs= lck->lock.in.file.ntvfs;
+ lck2->generic.in.mode = 0;
+ lck2->generic.in.timeout = 0;
lck2->generic.in.ulock_cnt = 0;
lck2->generic.in.lock_cnt = 1;
+ lck2->generic.in.locks = locks;
+ locks->pid = req->smbpid;
+ locks->offset = lck->lock.in.offset;
+ locks->count = lck->lock.in.count;
break;
case RAW_LOCK_UNLOCK:
+ lck2->generic.level = RAW_LOCK_GENERIC;
+ lck2->generic.in.file.ntvfs= lck->unlock.in.file.ntvfs;
+ lck2->generic.in.mode = 0;
+ lck2->generic.in.timeout = 0;
lck2->generic.in.ulock_cnt = 1;
lck2->generic.in.lock_cnt = 0;
+ lck2->generic.in.locks = locks;
+ locks->pid = req->smbpid;
+ locks->offset = lck->unlock.in.offset;
+ locks->count = lck->unlock.in.count;
+ break;
+
+ case RAW_LOCK_SMB2: {
+ /* this is only approximate! We need to change the
+ generic structure to fix this properly */
+ int i;
+ bool isunlock;
+ if (lck->smb2.in.lock_count < 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ lck2->generic.level = RAW_LOCK_GENERIC;
+ lck2->generic.in.file.ntvfs= lck->smb2.in.file.ntvfs;
+ lck2->generic.in.timeout = UINT32_MAX;
+ lck2->generic.in.mode = 0;
+ lck2->generic.in.lock_cnt = 0;
+ lck2->generic.in.ulock_cnt = 0;
+ lck2->generic.in.locks = talloc_zero_array(lck2, struct smb_lock_entry,
+ lck->smb2.in.lock_count);
+ if (lck2->generic.in.locks == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ /* only the first lock gives the UNLOCK bit - see
+ MS-SMB2 3.3.5.14 */
+ if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_UNLOCK) {
+ lck2->generic.in.ulock_cnt = lck->smb2.in.lock_count;
+ isunlock = true;
+ } else {
+ lck2->generic.in.lock_cnt = lck->smb2.in.lock_count;
+ isunlock = false;
+ }
+ for (i=0;ismb2.in.lock_count;i++) {
+ if (isunlock &&
+ (lck->smb2.in.locks[i].flags &
+ (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ if (!isunlock &&
+ (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ lck2->generic.in.locks[i].pid = req->smbpid;
+ lck2->generic.in.locks[i].offset = lck->smb2.in.locks[i].offset;
+ lck2->generic.in.locks[i].count = lck->smb2.in.locks[i].length;
+ if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) {
+ lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ }
+ if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
+ lck2->generic.in.timeout = 0;
+ }
+ }
+ /* initialize output value */
+ lck->smb2.out.reserved = 0;
break;
}
- lck2->generic.level = RAW_LOCK_GENERIC;
- lck2->generic.file.fnum = lck->lock.file.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;
+ case RAW_LOCK_SMB2_BREAK:
+ lck2->generic.level = RAW_LOCK_GENERIC;
+ lck2->generic.in.file.ntvfs = lck->smb2_break.in.file.ntvfs;
+ lck2->generic.in.mode = LOCKING_ANDX_OPLOCK_RELEASE |
+ ((lck->smb2_break.in.oplock_level << 8) & 0xFF00);
+ lck2->generic.in.timeout = 0;
+ lck2->generic.in.ulock_cnt = 0;
+ lck2->generic.in.lock_cnt = 0;
+ lck2->generic.in.locks = NULL;
+
+ /* initialize output value */
+ lck->smb2_break.out.oplock_level= lck->smb2_break.in.oplock_level;
+ lck->smb2_break.out.reserved = lck->smb2_break.in.reserved;
+ lck->smb2_break.out.reserved2 = lck->smb2_break.in.reserved2;
+ lck->smb2_break.out.file = lck->smb2_break.in.file;
+ break;
+ }
/*
* we don't need to call ntvfs_map_async_setup() here,
@@ -990,10 +1145,10 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
return NT_STATUS_NO_MEMORY;
}
- lck->unlock.level = RAW_LOCK_UNLOCK;
- lck->unlock.file.fnum = wr->writeunlock.file.fnum;
- lck->unlock.in.count = wr->writeunlock.in.count;
- lck->unlock.in.offset = wr->writeunlock.in.offset;
+ lck->unlock.level = RAW_LOCK_UNLOCK;
+ lck->unlock.in.file.ntvfs = wr->writeunlock.in.file.ntvfs;
+ lck->unlock.in.count = wr->writeunlock.in.count;
+ lck->unlock.in.offset = wr->writeunlock.in.offset;
if (lck->unlock.in.count != 0) {
/* do the lock sync for now */
@@ -1012,9 +1167,9 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
return NT_STATUS_NO_MEMORY;
}
- cl->close.level = RAW_CLOSE_CLOSE;
- cl->close.file.fnum = wr->writeclose.file.fnum;
- cl->close.in.write_time = wr->writeclose.in.mtime;
+ cl->close.level = RAW_CLOSE_CLOSE;
+ cl->close.in.file.ntvfs = wr->writeclose.in.file.ntvfs;
+ cl->close.in.write_time = wr->writeclose.in.mtime;
if (wr2->generic.in.count != 0) {
/* do the close sync for now */
@@ -1027,6 +1182,13 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
case RAW_WRITE_SPLWRITE:
break;
+
+ case RAW_WRITE_SMB2:
+ wr->smb2.out._pad = 0;
+ wr->smb2.out.nwritten = wr2->generic.out.nwritten;
+ wr->smb2.out.unknown1 = 0;
+ break;
+
default:
return NT_STATUS_INVALID_LEVEL;
}
@@ -1038,7 +1200,7 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
/*
NTVFS write generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_write *wr)
{
@@ -1064,7 +1226,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
break;
case RAW_WRITE_WRITE:
- wr2->writex.file.fnum = wr->write.file.fnum;
+ wr2->writex.in.file.ntvfs= wr->write.in.file.ntvfs;
wr2->writex.in.offset = wr->write.in.offset;
wr2->writex.in.wmode = 0;
wr2->writex.in.remaining = wr->write.in.remaining;
@@ -1074,7 +1236,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
break;
case RAW_WRITE_WRITEUNLOCK:
- wr2->writex.file.fnum = wr->writeunlock.file.fnum;
+ wr2->writex.in.file.ntvfs= wr->writeunlock.in.file.ntvfs;
wr2->writex.in.offset = wr->writeunlock.in.offset;
wr2->writex.in.wmode = 0;
wr2->writex.in.remaining = wr->writeunlock.in.remaining;
@@ -1084,7 +1246,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
break;
case RAW_WRITE_WRITECLOSE:
- wr2->writex.file.fnum = wr->writeclose.file.fnum;
+ wr2->writex.in.file.ntvfs= wr->writeclose.in.file.ntvfs;
wr2->writex.in.offset = wr->writeclose.in.offset;
wr2->writex.in.wmode = 0;
wr2->writex.in.remaining = 0;
@@ -1094,7 +1256,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
break;
case RAW_WRITE_SPLWRITE:
- wr2->writex.file.fnum = wr->splwrite.file.fnum;
+ wr2->writex.in.file.ntvfs= wr->splwrite.in.file.ntvfs;
wr2->writex.in.offset = 0;
wr2->writex.in.wmode = 0;
wr2->writex.in.remaining = 0;
@@ -1102,6 +1264,15 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
wr2->writex.in.data = wr->splwrite.in.data;
status = ntvfs->ops->write(ntvfs, req, wr2);
break;
+
+ case RAW_WRITE_SMB2:
+ wr2->writex.in.file.ntvfs= wr->smb2.in.file.ntvfs;
+ wr2->writex.in.offset = wr->smb2.in.offset;
+ wr2->writex.in.wmode = 0;
+ wr2->writex.in.remaining = 0;
+ wr2->writex.in.count = wr->smb2.in.data.length;
+ wr2->writex.in.data = wr->smb2.in.data.data;
+ status = ntvfs->ops->write(ntvfs, req, wr2);
}
return ntvfs_map_async_finish(req, status);
@@ -1119,13 +1290,18 @@ static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs,
{
switch (rd->generic.level) {
case RAW_READ_READ:
- rd->read.out.nread = rd2->generic.out.nread;
+ rd->read.out.nread = rd2->generic.out.nread;
break;
case RAW_READ_READBRAW:
- rd->readbraw.out.nread = rd2->generic.out.nread;
+ rd->readbraw.out.nread = rd2->generic.out.nread;
break;
case RAW_READ_LOCKREAD:
- rd->lockread.out.nread = rd2->generic.out.nread;
+ rd->lockread.out.nread = rd2->generic.out.nread;
+ break;
+ case RAW_READ_SMB2:
+ rd->smb2.out.data.length= rd2->generic.out.nread;
+ rd->smb2.out.remaining = 0;
+ rd->smb2.out.reserved = 0;
break;
default:
return NT_STATUS_INVALID_LEVEL;
@@ -1137,7 +1313,7 @@ static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs,
/*
NTVFS read* to readx mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
+NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_read *rd)
{
@@ -1158,7 +1334,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
}
rd2->readx.level = RAW_READ_READX;
- rd2->readx.in.read_for_execute = False;
+ rd2->readx.in.read_for_execute = false;
switch (rd->generic.level) {
case RAW_READ_READX:
@@ -1166,7 +1342,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
break;
case RAW_READ_READ:
- rd2->readx.file.fnum = rd->read.file.fnum;
+ rd2->readx.in.file.ntvfs= rd->read.in.file.ntvfs;
rd2->readx.in.offset = rd->read.in.offset;
rd2->readx.in.mincnt = rd->read.in.count;
rd2->readx.in.maxcnt = rd->read.in.count;
@@ -1176,7 +1352,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
break;
case RAW_READ_READBRAW:
- rd2->readx.file.fnum = rd->readbraw.file.fnum;
+ rd2->readx.in.file.ntvfs= rd->readbraw.in.file.ntvfs;
rd2->readx.in.offset = rd->readbraw.in.offset;
rd2->readx.in.mincnt = rd->readbraw.in.mincnt;
rd2->readx.in.maxcnt = rd->readbraw.in.maxcnt;
@@ -1195,14 +1371,14 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
status = NT_STATUS_NO_MEMORY;
goto done;
}
- lck->lock.level = RAW_LOCK_LOCK;
- lck->lock.file.fnum = rd->lockread.file.fnum;
- lck->lock.in.count = rd->lockread.in.count;
- lck->lock.in.offset = rd->lockread.in.offset;
+ lck->lock.level = RAW_LOCK_LOCK;
+ lck->lock.in.file.ntvfs = rd->lockread.in.file.ntvfs;
+ lck->lock.in.count = rd->lockread.in.count;
+ lck->lock.in.offset = rd->lockread.in.offset;
status = ntvfs->ops->lock(ntvfs, req, lck);
req->async_states->state = state;
- rd2->readx.file.fnum = rd->lockread.file.fnum;
+ rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs;
rd2->readx.in.offset = rd->lockread.in.offset;
rd2->readx.in.mincnt = rd->lockread.in.count;
rd2->readx.in.maxcnt = rd->lockread.in.count;
@@ -1213,6 +1389,16 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
status = ntvfs->ops->read(ntvfs, req, rd2);
}
break;
+
+ case RAW_READ_SMB2:
+ rd2->readx.in.file.ntvfs= rd->smb2.in.file.ntvfs;
+ rd2->readx.in.offset = rd->smb2.in.offset;
+ rd2->readx.in.mincnt = rd->smb2.in.min_count;
+ rd2->readx.in.maxcnt = rd->smb2.in.length;
+ rd2->readx.in.remaining = 0;
+ rd2->readx.out.data = rd->smb2.out.data.data;
+ status = ntvfs->ops->read(ntvfs, req, rd2);
+ break;
}
done:
@@ -1223,11 +1409,42 @@ done:
/*
NTVFS close generic to any mapper
*/
-_PUBLIC_ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
+static NTSTATUS ntvfs_map_close_finish(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_close *cl,
+ union smb_close *cl2,
+ NTSTATUS status)
+{
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ switch (cl->generic.level) {
+ case RAW_CLOSE_SMB2:
+ cl->smb2.out.flags = cl2->generic.out.flags;
+ cl->smb2.out._pad = 0;
+ cl->smb2.out.create_time = cl2->generic.out.create_time;
+ cl->smb2.out.access_time = cl2->generic.out.access_time;
+ cl->smb2.out.write_time = cl2->generic.out.write_time;
+ cl->smb2.out.change_time = cl2->generic.out.change_time;
+ cl->smb2.out.alloc_size = cl2->generic.out.alloc_size;
+ cl->smb2.out.size = cl2->generic.out.size;
+ cl->smb2.out.file_attr = cl2->generic.out.file_attr;
+ break;
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/*
+ NTVFS close generic to any mapper
+*/
+NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_close *cl)
{
union smb_close *cl2;
+ NTSTATUS status;
cl2 = talloc(req, union smb_close);
if (cl2 == NULL) {
@@ -1235,19 +1452,100 @@ _PUBLIC_ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
}
switch (cl->generic.level) {
- case RAW_CLOSE_CLOSE:
+ case RAW_CLOSE_GENERIC:
return NT_STATUS_INVALID_LEVEL;
+ case RAW_CLOSE_CLOSE:
+ cl2->generic.level = RAW_CLOSE_GENERIC;
+ cl2->generic.in.file = cl->close.in.file;
+ cl2->generic.in.write_time = cl->close.in.write_time;
+ cl2->generic.in.flags = 0;
+ break;
+
case RAW_CLOSE_SPLCLOSE:
- cl2->close.level = RAW_CLOSE_CLOSE;
- cl2->close.file.fnum = cl->splclose.file.fnum;
+ cl2->generic.level = RAW_CLOSE_GENERIC;
+ cl2->generic.in.file = cl->splclose.in.file;
+ cl2->generic.in.write_time = 0;
+ cl2->generic.in.flags = 0;
+ break;
+
+ case RAW_CLOSE_SMB2:
+ cl2->generic.level = RAW_CLOSE_GENERIC;
+ cl2->generic.in.file = cl->smb2.in.file;
+ cl2->generic.in.write_time = 0;
+ cl2->generic.in.flags = cl->smb2.in.flags;
break;
}
- /*
- * we don't need to call ntvfs_map_async_setup() here,
- * as close() doesn't have any output fields
- */
+ status = ntvfs_map_async_setup(ntvfs, req, cl, cl2,
+ (second_stage_t)ntvfs_map_close_finish);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = ntvfs->ops->close(ntvfs, req, cl2);
+
+ return ntvfs_map_async_finish(req, status);
+}
+
+/*
+ NTVFS notify generic to any mapper
+*/
+static NTSTATUS ntvfs_map_notify_finish(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_notify *nt,
+ union smb_notify *nt2,
+ NTSTATUS status)
+{
+ NT_STATUS_NOT_OK_RETURN(status);
- return ntvfs->ops->close(ntvfs, req, cl2);
+ switch (nt->nttrans.level) {
+ case RAW_NOTIFY_SMB2:
+ if (nt2->nttrans.out.num_changes == 0) {
+ return STATUS_NOTIFY_ENUM_DIR;
+ }
+ nt->smb2.out.num_changes = nt2->nttrans.out.num_changes;
+ nt->smb2.out.changes = talloc_steal(req, nt2->nttrans.out.changes);
+ break;
+
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ return status;
+}
+
+
+/*
+ NTVFS notify generic to any mapper
+*/
+NTSTATUS ntvfs_map_notify(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_notify *nt)
+{
+ union smb_notify *nt2;
+ NTSTATUS status;
+
+ nt2 = talloc(req, union smb_notify);
+ NT_STATUS_HAVE_NO_MEMORY(nt2);
+
+ status = ntvfs_map_async_setup(ntvfs, req, nt, nt2,
+ (second_stage_t)ntvfs_map_notify_finish);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ nt2->nttrans.level = RAW_NOTIFY_NTTRANS;
+
+ switch (nt->nttrans.level) {
+ case RAW_NOTIFY_NTTRANS:
+ status = NT_STATUS_INVALID_LEVEL;
+ break;
+
+ case RAW_NOTIFY_SMB2:
+ nt2->nttrans.in.file.ntvfs = nt->smb2.in.file.ntvfs;
+ nt2->nttrans.in.buffer_size = nt->smb2.in.buffer_size;
+ nt2->nttrans.in.completion_filter = nt->smb2.in.completion_filter;
+ nt2->nttrans.in.recursive = nt->smb2.in.recursive;
+ status = ntvfs->ops->notify(ntvfs, req, nt2);
+ break;
+ }
+
+ return ntvfs_map_async_finish(req, status);
}