diff options
Diffstat (limited to 'source4/ntvfs')
-rw-r--r-- | source4/ntvfs/cifs/vfs_cifs.c | 10 | ||||
-rw-r--r-- | source4/ntvfs/ntvfs_generic.c | 63 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 29 |
3 files changed, 87 insertions, 15 deletions
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 2b61268733..844fa11cc5 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -769,6 +769,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; struct cvfs_file *f; + union smb_close io2; SETUP_PID; @@ -776,6 +777,15 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, private->map_generic) { return ntvfs_map_close(ntvfs, req, io); } + + if (io->generic.level == RAW_CLOSE_GENERIC) { + ZERO_STRUCT(io2); + io2.close.level = RAW_CLOSE_CLOSE; + io2.close.in.file = io->generic.in.file; + io2.close.in.write_time = io->generic.in.write_time; + io = &io2; + } + SETUP_FILE_HERE(f); /* Note, we aren't free-ing f, or it's h here. Should we? even if file-close fails, we'll remove it from the list, diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index e449e61b34..a1c89e7df4 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1410,11 +1410,42 @@ done: /* 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 +*/ 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) { @@ -1422,30 +1453,38 @@ 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->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); + + status = ntvfs->ops->close(ntvfs, req, cl2); - return ntvfs->ops->close(ntvfs, req, cl2); + return ntvfs_map_async_finish(req, status); } /* diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 908dd449af..49710806c7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1514,21 +1514,44 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_DOS(ERRSRV, ERRerror); } - if (io->generic.level != RAW_CLOSE_CLOSE) { + if (io->generic.level != RAW_CLOSE_GENERIC) { return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); + f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (!null_time(io->close.in.write_time)) { + if (!null_time(io->generic.in.write_time)) { unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); } + if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { + struct pvfs_filename *name; + NTSTATUS status; + struct pvfs_file_handle *h = f->handle; + + status = pvfs_resolve_name_handle(pvfs, h); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + name = h->name; + + io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_attr = name->dos.attrib; + } else { + ZERO_STRUCT(io->generic.out); + } + talloc_free(f); return NT_STATUS_OK; |