SMB2 doesn't have NAME_INFORMATION level
[kai/samba.git] / source4 / ntvfs / posix / pvfs_qfileinfo.c
index b01b7bb649b96017d5e3a6ea2492b3b897485957..b9f763c2e0f06b999d903c840824fff79d8a0dba 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "vfs_posix.h"
-#include "librpc/gen_ndr/ndr_xattr.h"
+#include "librpc/gen_ndr/xattr.h"
 
 
 /*
   determine what access bits are needed for a call
 */
-static uint32_t pvfs_fileinfo_access(enum smb_fileinfo_level level)
+static uint32_t pvfs_fileinfo_access(union smb_fileinfo *info)
 {
        uint32_t needed;
 
-       switch (level) {
+       switch (info->generic.level) {
        case RAW_FILEINFO_EA_LIST:
        case RAW_FILEINFO_ALL_EAS:
                needed = SEC_FILE_READ_EA;
@@ -43,14 +42,24 @@ static uint32_t pvfs_fileinfo_access(enum smb_fileinfo_level level)
                break;
 
        case RAW_FILEINFO_SEC_DESC:
-               needed = SEC_STD_READ_CONTROL;
+               needed = 0;
+               if (info->query_secdesc.in.secinfo_flags & (SECINFO_OWNER|SECINFO_GROUP)) {
+                       needed |= SEC_STD_READ_CONTROL;
+               }
+               if (info->query_secdesc.in.secinfo_flags & SECINFO_DACL) {
+                       needed |= SEC_STD_READ_CONTROL;
+               }
+               if (info->query_secdesc.in.secinfo_flags & SECINFO_SACL) {
+                       needed |= SEC_FLAG_SYSTEM_SECURITY;
+               }
                break;
 
        default:
                needed = SEC_FILE_READ_ATTRIBUTE;
                break;
        }
-       return needed;  
+
+       return needed;
 }
 
 /*
@@ -169,6 +178,15 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
        case RAW_FILEINFO_ALL_EAS:
                return pvfs_query_all_eas(pvfs, req, name, fd, &info->all_eas.out);
 
+       case RAW_FILEINFO_SMB2_ALL_EAS: {
+               NTSTATUS status = pvfs_query_all_eas(pvfs, req, name, fd, &info->all_eas.out);
+               if (NT_STATUS_IS_OK(status) &&
+                   info->all_eas.out.num_eas == 0) {
+                       return NT_STATUS_NO_EAS_ON_FILE;
+               }
+               return status;
+       }
+
        case RAW_FILEINFO_IS_NAME_VALID:
                return NT_STATUS_OK;
 
@@ -186,7 +204,7 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
                info->standard_info.out.alloc_size     = name->dos.alloc_size;
                info->standard_info.out.size           = name->st.st_size;
                info->standard_info.out.nlink          = name->dos.nlink;
-               info->standard_info.out.delete_pending = 0;
+               info->standard_info.out.delete_pending = 0; /* only for qfileinfo */
                info->standard_info.out.directory   = 
                        (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
                return NT_STATUS_OK;
@@ -198,6 +216,10 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
 
        case RAW_FILEINFO_NAME_INFO:
        case RAW_FILEINFO_NAME_INFORMATION:
+               if (req->ctx->protocol == PROTOCOL_SMB2) {
+                       /* strange that SMB2 doesn't have this */
+                       return NT_STATUS_NOT_SUPPORTED;
+               }
                info->name_info.out.fname.s = name->original_name;
                return NT_STATUS_OK;
 
@@ -211,7 +233,7 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
                info->all_info.out.alloc_size     = name->dos.alloc_size;
                info->all_info.out.size           = name->st.st_size;
                info->all_info.out.nlink          = name->dos.nlink;
-               info->all_info.out.delete_pending = 0;
+               info->all_info.out.delete_pending = 0; /* only set by qfileinfo */
                info->all_info.out.directory      = 
                        (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
                info->all_info.out.ea_size        = name->dos.ea_size;
@@ -241,15 +263,15 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_ACCESS_INFORMATION:
-               info->access_information.out.access_flags = 0;
+               info->access_information.out.access_flags = 0; /* only set by qfileinfo */
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_POSITION_INFORMATION:
-               info->position_information.out.position = 0;
+               info->position_information.out.position = 0; /* only set by qfileinfo */
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_MODE_INFORMATION:
-               info->mode_information.out.mode = 0;
+               info->mode_information.out.mode = 0; /* only set by qfileinfo */
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_ALIGNMENT_INFORMATION:
@@ -273,6 +295,34 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
 
        case RAW_FILEINFO_SEC_DESC:
                return pvfs_acl_query(pvfs, req, name, fd, info);
+
+       case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+               info->all_info2.out.create_time    = name->dos.create_time;
+               info->all_info2.out.access_time    = name->dos.access_time;
+               info->all_info2.out.write_time     = name->dos.write_time;
+               info->all_info2.out.change_time    = name->dos.change_time;
+               info->all_info2.out.attrib         = name->dos.attrib;
+               info->all_info2.out.unknown1       = 0;
+               info->all_info2.out.alloc_size     = name->dos.alloc_size;
+               info->all_info2.out.size           = name->st.st_size;
+               info->all_info2.out.nlink          = name->dos.nlink;
+               info->all_info2.out.delete_pending = 0; /* only set by qfileinfo */
+               info->all_info2.out.directory      = 
+                       (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
+               info->all_info2.out.file_id        = name->dos.file_id;
+               info->all_info2.out.ea_size        = name->dos.ea_size;
+               info->all_info2.out.access_mask    = 0; /* only set by qfileinfo */
+               info->all_info2.out.position       = 0; /* only set by qfileinfo */
+               info->all_info2.out.mode           = 0; /* only set by qfileinfo */
+               /* windows wants the full path on disk for this
+                  result, but I really don't want to expose that on
+                  the wire, so I'll give the path with a share
+                  prefix, which is a good approximation */
+               info->all_info2.out.fname.s = talloc_asprintf(req, "\\%s\\%s",
+                                                             pvfs->share_name, 
+                                                             name->original_name);
+               NT_STATUS_HAVE_NO_MEMORY(info->all_info2.out.fname.s);
+               return NT_STATUS_OK;
        }
 
        return NT_STATUS_INVALID_LEVEL;
@@ -289,7 +339,7 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
        NTSTATUS status;
 
        /* resolve the cifs name to a posix name */
-       status = pvfs_resolve_name(pvfs, req, info->generic.file.path, PVFS_RESOLVE_STREAMS, &name);
+       status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path, PVFS_RESOLVE_STREAMS, &name);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -300,11 +350,11 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
 
        status = pvfs_can_stat(pvfs, req, name);
        if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_DELETE_PENDING;
+               return status;
        }
 
        status = pvfs_access_check_simple(pvfs, req, name, 
-                                         pvfs_fileinfo_access(info->generic.level));
+                                         pvfs_fileinfo_access(info));
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -326,19 +376,19 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
        NTSTATUS status;
        uint32_t access_needed;
 
-       f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
+       f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs);
        if (!f) {
                return NT_STATUS_INVALID_HANDLE;
        }
        h = f->handle;
 
-       access_needed = pvfs_fileinfo_access(info->generic.level);
+       access_needed = pvfs_fileinfo_access(info);
        if ((f->access_mask & access_needed) != access_needed) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
        /* update the file information */
-       status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
+       status = pvfs_resolve_name_handle(pvfs, h);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -350,7 +400,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
        switch (info->generic.level) {
        case RAW_FILEINFO_STANDARD_INFO:
        case RAW_FILEINFO_STANDARD_INFORMATION:
-               if (pvfs_delete_on_close_set(pvfs, h, NULL, NULL)) {
+               if (pvfs_delete_on_close_set(pvfs, h)) {
                        info->standard_info.out.delete_pending = 1;
                        info->standard_info.out.nlink--;
                }
@@ -358,7 +408,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
 
        case RAW_FILEINFO_ALL_INFO:
        case RAW_FILEINFO_ALL_INFORMATION:
-               if (pvfs_delete_on_close_set(pvfs, h, NULL, NULL)) {
+               if (pvfs_delete_on_close_set(pvfs, h)) {
                        info->all_info.out.delete_pending = 1;
                        info->all_info.out.nlink--;
                }
@@ -376,6 +426,16 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
                info->mode_information.out.mode = h->mode;
                break;
 
+       case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+               if (pvfs_delete_on_close_set(pvfs, h)) {
+                       info->all_info2.out.delete_pending = 1;
+                       info->all_info2.out.nlink--;
+               }
+               info->all_info2.out.position    = h->position;
+               info->all_info2.out.access_mask = f->access_mask;
+               info->all_info2.out.mode        = h->mode;
+               break;
+
        default:
                break;
        }