Implement the SMB2 close flag SMB2_CLOSE_FLAGS_FULL_INFORMATION (and move definition...
authorJeremy Allison <jra@samba.org>
Thu, 24 Feb 2011 22:52:58 +0000 (14:52 -0800)
committerJeremy Allison <jra@samba.org>
Thu, 24 Feb 2011 23:40:52 +0000 (00:40 +0100)
Thanks to Nick Meier @ Microsoft for finding this @ Connectathon.

Jeremy.

Autobuild-User: Jeremy Allison <jra@samba.org>
Autobuild-Date: Fri Feb 25 00:40:52 CET 2011 on sn-devel-104

libcli/smb/smb2_constants.h
source3/smbd/smb2_close.c
source4/libcli/raw/interfaces.h

index 6d29d6e9ea175ab0e59a29794710e23d3230a561..7ab496df22d33f438c7a0856f116e56a7a94d4e0 100644 (file)
 #define SMB2_GETINFO_SECURITY           0x03
 #define SMB2_GETINFO_QUOTA              0x04
 
+#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (0x01)
+
 #endif
index 56e3167e24bc9559bff6fc4485cdf530333aa9a4..8ef9dfa8208065c8c16eb8e0a59ef352da133327 100644 (file)
@@ -24,7 +24,8 @@
 
 static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
                                uint16_t in_flags,
-                               uint64_t in_file_id_volatile);
+                               uint64_t in_file_id_volatile,
+                               DATA_BLOB *outbody);
 
 NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
 {
@@ -52,6 +53,11 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
        }
 
+       outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
+       if (outbody.data == NULL) {
+               return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+       }
+
        in_flags                = SVAL(inbody, 0x02);
        in_file_id_persistent   = BVAL(inbody, 0x08);
        in_file_id_volatile     = BVAL(inbody, 0x10);
@@ -64,40 +70,37 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
 
        status = smbd_smb2_close(req,
                                in_flags,
-                               in_file_id_volatile);
+                               in_file_id_volatile,
+                               &outbody);
        if (!NT_STATUS_IS_OK(status)) {
                return smbd_smb2_request_error(req, status);
        }
 
        outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
-       outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
-       if (outbody.data == NULL) {
-               return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
-       }
-
-       SSVAL(outbody.data, 0x00, 0x3C);        /* struct size */
-       SSVAL(outbody.data, 0x02, 0);           /* flags */
-       SIVAL(outbody.data, 0x04, 0);           /* reserved */
-       SBVAL(outbody.data, 0x08, 0);           /* creation time */
-       SBVAL(outbody.data, 0x10, 0);           /* last access time */
-       SBVAL(outbody.data, 0x18, 0);           /* last write time */
-       SBVAL(outbody.data, 0x20, 0);           /* change time */
-       SBVAL(outbody.data, 0x28, 0);           /* allocation size */
-       SBVAL(outbody.data, 0x30, 0);           /* end of size */
-       SIVAL(outbody.data, 0x38, 0);           /* file attributes */
-
        return smbd_smb2_request_done(req, outbody, NULL);
 }
 
 static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
                                uint16_t in_flags,
-                               uint64_t in_file_id_volatile)
+                               uint64_t in_file_id_volatile,
+                               DATA_BLOB *outbody)
 {
        NTSTATUS status;
        struct smb_request *smbreq;
        connection_struct *conn = req->tcon->compat_conn;
        files_struct *fsp;
+       struct smb_filename *smb_fname = NULL;
+       struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
+       uint64_t allocation_size = 0;
+       uint64_t file_size = 0;
+       uint32_t dos_attrs = 0;
+       uint16_t out_flags = 0;
+       bool posix_open = false;
+
+       ZERO_STRUCT(create_date_ts);
+       ZERO_STRUCT(adate_ts);
+       ZERO_STRUCT(mdate_ts);
+       ZERO_STRUCT(cdate_ts);
 
        DEBUG(10,("smbd_smb2_close: file_id[0x%016llX]\n",
                  (unsigned long long)in_file_id_volatile));
@@ -118,6 +121,14 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
                return NT_STATUS_FILE_CLOSED;
        }
 
+       posix_open = fsp->posix_open;
+       status = copy_smb_filename(talloc_tos(),
+                               fsp->fsp_name,
+                               &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        status = close_file(smbreq, fsp, NORMAL_CLOSE);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
@@ -125,5 +136,49 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
                return status;
        }
 
+       if (in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
+               int ret;
+               if (posix_open) {
+                       ret = SMB_VFS_LSTAT(conn, smb_fname);
+               } else {
+                       ret = SMB_VFS_STAT(conn, smb_fname);
+               }
+               if (ret == 0) {
+                       out_flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
+                       dos_attrs = dos_mode(conn, smb_fname);
+                       mdate_ts = smb_fname->st.st_ex_mtime;
+                       adate_ts = smb_fname->st.st_ex_atime;
+                       create_date_ts = get_create_timespec(conn, NULL, smb_fname);
+                       cdate_ts = get_change_timespec(conn, NULL, smb_fname);
+
+                       if (lp_dos_filetime_resolution(SNUM(conn))) {
+                               dos_filetime_timespec(&create_date_ts);
+                               dos_filetime_timespec(&mdate_ts);
+                               dos_filetime_timespec(&adate_ts);
+                               dos_filetime_timespec(&cdate_ts);
+                       }
+                       if (!(dos_attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+                               file_size = get_file_size_stat(&smb_fname->st);
+                       }
+
+                       allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
+               }
+       }
+
+       SSVAL(outbody->data, 0x00, 0x3C);       /* struct size */
+       SSVAL(outbody->data, 0x02, out_flags);  /* flags */
+       SIVAL(outbody->data, 0x04, 0);          /* reserved */
+       put_long_date_timespec(conn->ts_res,
+               (char *)&outbody->data[0x8],create_date_ts); /* creation time */
+       put_long_date_timespec(conn->ts_res,
+               (char *)&outbody->data[0x10],adate_ts); /* last access time */
+       put_long_date_timespec(conn->ts_res,
+               (char *)&outbody->data[0x18],mdate_ts); /* last write time */
+       put_long_date_timespec(conn->ts_res,
+               (char *)&outbody->data[0x20],cdate_ts); /* change time */
+       SBVAL(outbody->data, 0x28, allocation_size);/* allocation size */
+       SBVAL(outbody->data, 0x30, file_size);  /* end of file */
+       SIVAL(outbody->data, 0x38, dos_attrs);  /* file attributes */
+
        return NT_STATUS_OK;
 }
index f6d090539c4e02a21f9c87a1af38bd69b69db1b0..f3ce4e9c5f2b8fa8b81f21edeb541b64f98b6ca8 100644 (file)
@@ -2090,7 +2090,6 @@ union smb_close {
                struct {
                        union smb_handle file;
                        time_t write_time;
-#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0)
                        uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
                } in;
                struct {