added support for the output fields of SMB2 close
authorAndrew Tridgell <tridge@samba.org>
Tue, 27 May 2008 06:43:36 +0000 (16:43 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 27 May 2008 06:43:36 +0000 (16:43 +1000)
(This used to be commit 2633bc749792c224acc73a2e4ca723404331c19c)

source4/libcli/raw/interfaces.h
source4/ntvfs/cifs/vfs_cifs.c
source4/ntvfs/ntvfs_generic.c
source4/ntvfs/posix/pvfs_open.c

index 36d8c3abb0a7c3237d3bacc4cf384027e636113a..68ebc19bdbb3c8c32089657e3da4ea4aabf38026 100644 (file)
@@ -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;
index 2b6126873372dfe03fa21a57f6e47a3425ebabfe..844fa11cc5f584df597b0c791386b07354d08c98 100644 (file)
@@ -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,
index e449e61b34fa9e76f54bde0949000bef7fbf0a0e..a1c89e7df494dff90a4165ff85caf994c2739899 100644 (file)
@@ -1407,6 +1407,36 @@ 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
 */
@@ -1415,6 +1445,7 @@ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
                                  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);
 }
 
 /* 
index 908dd449afc6d314bbe0de51be3743777efb2b15..49710806c7e4a058f44223e68228405b1dcf2d22 100644 (file)
@@ -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;