#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
+#undef strcasecmp
+
/* a second stage function converts from the out parameters of the generic
call onto the out parameters of the specific call made */
typedef NTSTATUS (*second_stage_t)(struct ntvfs_module_context *,
*/
static void ntvfs_map_async_send(struct ntvfs_request *req)
{
- struct ntvfs_map_async *m = req->async_states->private_data;
+ struct ntvfs_map_async *m = talloc_get_type(req->async_states->private_data,
+ struct ntvfs_map_async);
ntvfs_async_state_pop(req);
/* the backend is replying immediately. call the 2nd stage function after popping our local
async state */
- m = req->async_states->private_data;
+ m = talloc_get_type(req->async_states->private_data,
+ struct ntvfs_map_async);
ntvfs_async_state_pop(req);
time_t write_time = 0;
uint32_t set_size = 0;
union smb_setfileinfo *sf;
- uint_t state;
+ unsigned int state;
if (!NT_STATUS_IS_OK(status)) {
return status;
break;
case RAW_OPEN_SMB2:
+ ZERO_STRUCT(io->smb2.out);
io->smb2.out.file.ntvfs = io2->generic.out.file.ntvfs;
- io->smb2.out.oplock_level = 0;
+ 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.size = io2->generic.out.size;
io->smb2.out.file_attr = io2->generic.out.attrib;
io->smb2.out.reserved2 = 0;
- io->smb2.out.blob = data_blob(NULL, 0);
+ io->smb2.out.maximal_access = io2->generic.out.maximal_access;
+ memcpy(io->smb2.out.on_disk_id, io2->generic.out.on_disk_id,
+ sizeof(io2->generic.out.on_disk_id));
break;
default:
sf->standard.in.create_time = 0;
sf->standard.in.write_time = write_time;
sf->standard.in.access_time = 0;
- status = ntvfs->ops->setfileinfo(ntvfs, req, sf);
+ status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
}
if (set_size != 0) {
sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
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);
+ status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
if (NT_STATUS_IS_OK(status)) {
io->openx.out.size = io->openx.in.size;
}
uint16_t open_func, const char *fname,
union smb_open *io2)
{
+ io2->generic.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+ io2->generic.in.private_flags = 0;
+
if (flags & OPENX_FLAGS_REQUEST_OPLOCK) {
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
}
break;
case OPENX_MODE_DENY_DOS:
/* DENY_DOS is quite strange - it depends on the filename! */
- io2->generic.in.create_options |=
- NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
+ io2->generic.in.private_flags |=
+ NTCREATEX_FLAG_DENY_DOS;
if (is_exe_filename(fname)) {
io2->generic.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
}
break;
case OPENX_MODE_DENY_FCB:
- io2->generic.in.create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
+ io2->generic.in.private_flags |= NTCREATEX_FLAG_DENY_FCB;
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
break;
default:
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_fn(ntvfs, req, io2);
break;
io2->generic.in.file_attr = io->openold.in.search_attrs;
io2->generic.in.fname = io->openold.in.fname;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ status = ntvfs->ops->open_fn(ntvfs, req, io2);
break;
case RAW_OPEN_T2OPEN:
io2->generic.in.ea_list->num_eas = io->t2open.in.num_eas;
io2->generic.in.ea_list->eas = io->t2open.in.eas;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ status = ntvfs->ops->open_fn(ntvfs, req, io2);
break;
case RAW_OPEN_MKNEW:
io2->generic.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ status = ntvfs->ops->open_fn(ntvfs, req, io2);
break;
case RAW_OPEN_CREATE:
io2->generic.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ status = ntvfs->ops->open_fn(ntvfs, req, io2);
break;
case RAW_OPEN_CTEMP:
io2->generic.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ status = ntvfs->ops->open_fn(ntvfs, req, io2);
break;
case RAW_OPEN_SMB2:
- io2->generic.in.flags = 0;
- io2->generic.in.root_fid = 0;
+ 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.fnum = 0;
io2->generic.in.access_mask = io->smb2.in.desired_access;
- io2->generic.in.alloc_size = 0;
+ 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.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 = NULL;
- io2->generic.in.ea_list = NULL;
- status = ntvfs->ops->open(ntvfs, req, io2);
+ 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;
+ io2->generic.in.query_on_disk_id = io->smb2.in.query_on_disk_id;
+ io2->generic.in.private_flags = 0;
+
+ /* 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_fn(ntvfs, req, io2);
break;
default:
/*
- NTVFS fsinfo generic to any mapper
+ NTVFS any to fsinfo mapper
*/
-NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req,
- union smb_fsinfo *fs)
+static NTSTATUS ntvfs_map_fsinfo_finish(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_fsinfo *fs,
+ union smb_fsinfo *fs2,
+ NTSTATUS status)
{
- NTSTATUS status;
- union smb_fsinfo *fs2;
-
- fs2 = talloc(req, union smb_fsinfo);
- if (fs2 == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (fs->generic.level == RAW_QFS_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- /* only used by the simple backend, which doesn't do async */
- req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
-
- /* ask the backend for the generic info */
- fs2->generic.level = RAW_QFS_GENERIC;
-
- status = ntvfs->ops->fsinfo(ntvfs, req, fs2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* and convert it to the required level */
switch (fs->generic.level) {
- case RAW_QFS_GENERIC:
- return NT_STATUS_INVALID_LEVEL;
-
case RAW_QFS_DSKATTR: {
/* map from generic to DSKATTR */
- uint_t bpunit = 64;
+ unsigned int bpunit = 64;
/* we need to scale the sizes to fit */
for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
fs->objectid_information.out.guid = fs2->generic.out.guid;
ZERO_STRUCT(fs->objectid_information.out.unknown);
return NT_STATUS_OK;
- }
+ case RAW_QFS_SECTOR_SIZE_INFORMATION:
+ fs->sector_size_info.out.logical_bytes_per_sector
+ = fs2->generic.out.block_size;
+ fs->sector_size_info.out.phys_bytes_per_sector_atomic
+ = fs2->generic.out.block_size;
+ fs->sector_size_info.out.phys_bytes_per_sector_perf
+ = fs2->generic.out.block_size;
+ fs->sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic
+ = fs2->generic.out.block_size;
+ fs->sector_size_info.out.flags
+ = QFS_SSINFO_FLAGS_ALIGNED_DEVICE
+ | QFS_SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE;
+ fs->sector_size_info.out.byte_off_sector_align = 0;
+ fs->sector_size_info.out.byte_off_partition_align = 0;
+ return NT_STATUS_OK;
+
+ case RAW_QFS_GENERIC:
+ case RAW_QFS_UNIX_INFO:
+ return NT_STATUS_INVALID_LEVEL;
+ }
return NT_STATUS_INVALID_LEVEL;
}
+/*
+ NTVFS fsinfo any to generic mapper
+*/
+NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_fsinfo *fs)
+{
+ NTSTATUS status;
+ union smb_fsinfo *fs2;
+
+ fs2 = talloc(req, union smb_fsinfo);
+ if (fs2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (fs->generic.level == RAW_QFS_GENERIC) {
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ status = ntvfs_map_async_setup(ntvfs, req, fs, fs2,
+ (second_stage_t)ntvfs_map_fsinfo_finish);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* ask the backend for the generic info */
+ fs2->generic.level = RAW_QFS_GENERIC;
+
+ status = ntvfs->ops->fsinfo_fn(ntvfs, req, fs2);
+ return ntvfs_map_async_finish(req, status);
+}
+
/*
NTVFS fileinfo generic to any mapper
int i;
/* and convert it to the required level using results in info2 */
switch (info->generic.level) {
- case RAW_FILEINFO_GENERIC:
- return NT_STATUS_INVALID_LEVEL;
case RAW_FILEINFO_GETATTR:
info->getattr.out.attrib = info2->generic.out.attrib & 0xff;
info->getattr.out.size = info2->generic.out.size;
case RAW_FILEINFO_ALT_NAME_INFO:
case RAW_FILEINFO_ALT_NAME_INFORMATION:
+ case RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION:
info->alt_name_info.out.fname.s = talloc_strdup(mem_ctx, info2->generic.out.alt_fname.s);
NT_STATUS_HAVE_NO_MEMORY(info->alt_name_info.out.fname.s);
info->alt_name_info.out.fname.private_length = info2->generic.out.alt_fname.private_length;
return NT_STATUS_NO_MEMORY;
}
info->all_eas.out.eas[i].value.data =
- talloc_memdup(info->all_eas.out.eas,
+ (uint8_t *)talloc_memdup(info->all_eas.out.eas,
info2->generic.out.eas[i].value.data,
info2->generic.out.eas[i].value.length);
if (!info->all_eas.out.eas[i].value.data) {
info->alignment_information.out.alignment_requirement =
info2->generic.out.alignment_requirement;
return NT_STATUS_OK;
-#if 0
case RAW_FILEINFO_UNIX_BASIC:
+#if 1
+ return NT_STATUS_INVALID_LEVEL;
+#else
info->unix_basic_info.out.end_of_file = info2->generic.out.end_of_file;
info->unix_basic_info.out.num_bytes = info2->generic.out.size;
info->unix_basic_info.out.status_change_time = info2->generic.out.change_time;
info->unix_basic_info.out.permissions = info2->generic.out.permissions;
info->unix_basic_info.out.nlink = info2->generic.out.nlink;
return NT_STATUS_OK;
-
+#endif
case RAW_FILEINFO_UNIX_LINK:
+#if 1
+ return NT_STATUS_INVALID_LEVEL;
+#else
info->unix_link_info.out.link_dest = info2->generic.out.link_dest;
return NT_STATUS_OK;
#endif
+ case RAW_FILEINFO_GENERIC:
+ case RAW_FILEINFO_SEC_DESC:
+ case RAW_FILEINFO_EA_LIST:
+ case RAW_FILEINFO_UNIX_INFO2:
+ case RAW_FILEINFO_SMB2_ALL_EAS:
+ case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+ return NT_STATUS_INVALID_LEVEL;
+ case RAW_FILEINFO_NORMALIZED_NAME_INFORMATION:
+ return NT_STATUS_NOT_SUPPORTED;
}
return NT_STATUS_INVALID_LEVEL;
}
/*
+ NTVFS any to fileinfo mapper
+*/
+static NTSTATUS ntvfs_map_qfileinfo_finish(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_fileinfo *info,
+ union smb_fileinfo *info2,
+ NTSTATUS status)
+{
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return ntvfs_map_fileinfo(req, info, info2);
+}
+
+/*
NTVFS fileinfo generic to any mapper
*/
NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_LEVEL;
}
+ status = ntvfs_map_async_setup(ntvfs, req, info, info2,
+ (second_stage_t)ntvfs_map_qfileinfo_finish);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* ask the backend for the generic info */
info2->generic.level = RAW_FILEINFO_GENERIC;
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;
+ status = ntvfs->ops->qfileinfo_fn(ntvfs, req, info2);
+ return ntvfs_map_async_finish(req, status);
+}
- status = ntvfs->ops->qfileinfo(ntvfs, req, info2);
+/*
+ NTVFS any to fileinfo mapper
+*/
+static NTSTATUS ntvfs_map_qpathinfo_finish(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_fileinfo *info,
+ union smb_fileinfo *info2,
+ NTSTATUS status)
+{
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+
return ntvfs_map_fileinfo(req, info, info2);
}
return NT_STATUS_INVALID_LEVEL;
}
+ status = ntvfs_map_async_setup(ntvfs, req, info, info2,
+ (second_stage_t)ntvfs_map_qpathinfo_finish);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* ask the backend for the generic info */
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;
-
- status = ntvfs->ops->qpathinfo(ntvfs, req, info2);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- return ntvfs_map_fileinfo(req, info, info2);
+ status = ntvfs->ops->qpathinfo_fn(ntvfs, req, info2);
+ return ntvfs_map_async_finish(req, status);
}
NTVFS lock generic to any mapper
*/
NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req,
- union smb_lock *lck)
+ struct ntvfs_request *req,
+ union smb_lock *lck)
{
union smb_lock *lck2;
struct smb_lock_entry *locks;
locks->count = lck->unlock.in.count;
break;
- case RAW_LOCK_SMB2:
- if (lck->smb2.in.unknown1 != 1) {
+ 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;
- if (lck->smb2.in.flags & SMB2_LOCK_FLAG_EXCLUSIV) {
- lck2->generic.in.mode = 0;
- } else {
- lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ 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;
}
- if (lck->smb2.in.flags & SMB2_LOCK_FLAG_NO_PENDING) {
- lck2->generic.in.timeout = 0;
+ /* 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) {
+ if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ lck2->generic.in.ulock_cnt = lck->smb2.in.lock_count;
+ isunlock = true;
} else {
- lck2->generic.in.timeout = UINT32_MAX;
+ lck2->generic.in.lock_cnt = lck->smb2.in.lock_count;
+ isunlock = false;
}
- if (lck->smb2.in.flags & SMB2_LOCK_FLAG_UNLOCK) {
- lck2->generic.in.ulock_cnt = 1;
- lck2->generic.in.lock_cnt = 0;
- } else {
- lck2->generic.in.ulock_cnt = 0;
- lck2->generic.in.lock_cnt = 1;
+ for (i=0;i<lck->smb2.in.lock_count;i++) {
+ if (!isunlock &&
+ lck->smb2.in.locks[i].flags == SMB2_LOCK_FLAG_NONE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (lck->smb2.in.locks[i].flags & ~SMB2_LOCK_FLAG_ALL_MASK) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
}
- lck2->generic.in.locks = locks;
- locks->pid = 0;
- locks->offset = lck->smb2.in.offset;
- locks->count = lck->smb2.in.count;
+ /* initialize output value */
+ lck->smb2.out.reserved = 0;
+ break;
+ }
+
+ 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.out.unknown1 = 0;
+ 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;
}
* as lock() doesn't have any output fields
*/
- return ntvfs->ops->lock(ntvfs, req, lck2);
+ return ntvfs->ops->lock_fn(ntvfs, req, lck2);
}
{
union smb_lock *lck;
union smb_close *cl;
- uint_t state;
+ unsigned int state;
if (NT_STATUS_IS_ERR(status)) {
return status;
/* do the lock sync for now */
state = req->async_states->state;
req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
- status = ntvfs->ops->lock(ntvfs, req, lck);
+ status = ntvfs->ops->lock_fn(ntvfs, req, lck);
req->async_states->state = state;
}
break;
/* do the close sync for now */
state = req->async_states->state;
req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
- status = ntvfs->ops->close(ntvfs, req, cl);
+ status = ntvfs->ops->close_fn(ntvfs, req, cl);
req->async_states->state = state;
}
break;
wr2->writex.in.remaining = wr->write.in.remaining;
wr2->writex.in.count = wr->write.in.count;
wr2->writex.in.data = wr->write.in.data;
- status = ntvfs->ops->write(ntvfs, req, wr2);
+ status = ntvfs->ops->write_fn(ntvfs, req, wr2);
break;
case RAW_WRITE_WRITEUNLOCK:
wr2->writex.in.remaining = wr->writeunlock.in.remaining;
wr2->writex.in.count = wr->writeunlock.in.count;
wr2->writex.in.data = wr->writeunlock.in.data;
- status = ntvfs->ops->write(ntvfs, req, wr2);
+ status = ntvfs->ops->write_fn(ntvfs, req, wr2);
break;
case RAW_WRITE_WRITECLOSE:
wr2->writex.in.remaining = 0;
wr2->writex.in.count = wr->writeclose.in.count;
wr2->writex.in.data = wr->writeclose.in.data;
- status = ntvfs->ops->write(ntvfs, req, wr2);
+ status = ntvfs->ops->write_fn(ntvfs, req, wr2);
break;
case RAW_WRITE_SPLWRITE:
wr2->writex.in.remaining = 0;
wr2->writex.in.count = wr->splwrite.in.count;
wr2->writex.in.data = wr->splwrite.in.data;
- status = ntvfs->ops->write(ntvfs, req, wr2);
+ status = ntvfs->ops->write_fn(ntvfs, req, wr2);
break;
case RAW_WRITE_SMB2:
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);
+ status = ntvfs->ops->write_fn(ntvfs, req, wr2);
}
return ntvfs_map_async_finish(req, status);
union smb_read *rd2;
union smb_lock *lck;
NTSTATUS status;
- uint_t state;
+ unsigned int state;
rd2 = talloc(req, union smb_read);
if (rd2 == NULL) {
rd2->readx.in.maxcnt = rd->read.in.count;
rd2->readx.in.remaining = rd->read.in.remaining;
rd2->readx.out.data = rd->read.out.data;
- status = ntvfs->ops->read(ntvfs, req, rd2);
+ status = ntvfs->ops->read_fn(ntvfs, req, rd2);
break;
case RAW_READ_READBRAW:
rd2->readx.in.maxcnt = rd->readbraw.in.maxcnt;
rd2->readx.in.remaining = 0;
rd2->readx.out.data = rd->readbraw.out.data;
- status = ntvfs->ops->read(ntvfs, req, rd2);
+ status = ntvfs->ops->read_fn(ntvfs, req, rd2);
break;
case RAW_READ_LOCKREAD:
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);
+ status = ntvfs->ops->lock_fn(ntvfs, req, lck);
req->async_states->state = state;
rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs;
rd2->readx.out.data = rd->lockread.out.data;
if (NT_STATUS_IS_OK(status)) {
- status = ntvfs->ops->read(ntvfs, req, rd2);
+ status = ntvfs->ops->read_fn(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.length;
+ 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);
+ status = ntvfs->ops->read_fn(ntvfs, req, rd2);
break;
}
}
+/*
+ NTVFS close generic to any mapper
+*/
+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
*/
union smb_close *cl)
{
union smb_close *cl2;
+ NTSTATUS status;
cl2 = talloc(req, union smb_close);
if (cl2 == NULL) {
}
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->generic.level = RAW_CLOSE_CLOSE;
- cl2->generic.in.file.ntvfs = cl->splclose.in.file.ntvfs;
+ 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_CLOSE;
- cl2->generic.in.file.ntvfs = cl->smb2.in.file.ntvfs;
+ cl2->generic.level = RAW_CLOSE_GENERIC;
+ cl2->generic.in.file = cl->smb2.in.file;
cl2->generic.in.write_time = 0;
- /* SMB2 Close has output parameter, but we just zero them */
- ZERO_STRUCT(cl->smb2.out);
+ 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);
- return ntvfs->ops->close(ntvfs, req, cl2);
+ status = ntvfs->ops->close_fn(ntvfs, req, cl2);
+
+ return ntvfs_map_async_finish(req, status);
}
/*
switch (nt->nttrans.level) {
case RAW_NOTIFY_SMB2:
if (nt2->nttrans.out.num_changes == 0) {
- return STATUS_NOTIFY_ENUM_DIR;
+ return NT_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);
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);
+ status = ntvfs->ops->notify_fn(ntvfs, req, nt2);
break;
}