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); }