summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/libcli/raw/interfaces.h31
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c10
-rw-r--r--source4/ntvfs/ntvfs_generic.c63
-rw-r--r--source4/ntvfs/posix/pvfs_open.c29
4 files changed, 112 insertions, 21 deletions
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index 36d8c3abb0..68ebc19bdb 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1950,23 +1950,43 @@ union smb_lock {
enum smb_close_level {
RAW_CLOSE_CLOSE,
RAW_CLOSE_SPLCLOSE,
- RAW_CLOSE_SMB2
+ RAW_CLOSE_SMB2,
+ RAW_CLOSE_GENERIC,
};
-#define RAW_CLOSE_GENERIC RAW_CLOSE_CLOSE
-
/*
union for close() backend call
*/
union smb_close {
- /* SMBclose (and generic) interface */
+ /* generic interface */
struct {
enum smb_close_level level;
struct {
union smb_handle file;
time_t write_time;
+#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0)
+ uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
} in;
- } close, generic;
+ struct {
+ uint16_t flags;
+ NTTIME create_time;
+ NTTIME access_time;
+ NTTIME write_time;
+ NTTIME change_time;
+ uint64_t alloc_size;
+ uint64_t size;
+ uint32_t file_attr;
+ } out;
+ } generic;
+
+ /* SMBclose interface */
+ struct {
+ enum smb_close_level level;
+ struct {
+ union smb_handle file;
+ time_t write_time;
+ } in;
+ } close;
/* SMBsplclose interface - empty! */
struct {
@@ -1984,7 +2004,6 @@ union smb_close {
/* static body buffer 24 (0x18) bytes */
/* uint16_t buffer_code; 0x18 */
-#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0)
uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
uint32_t _pad;
} in;
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;