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;
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;
}
/*
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;
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;
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;
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;
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:
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;
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;
}
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;
}
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;
}
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--;
}
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--;
}
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;
}