return 0;
}
+static int fstatat_with_cap_dac_override(int fd,
+ const char *pathname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags,
+ bool fake_dir_create_times)
+{
+ int ret;
+
+ set_effective_capability(DAC_OVERRIDE_CAPABILITY);
+ ret = sys_fstatat(fd,
+ pathname,
+ sbuf,
+ flags,
+ fake_dir_create_times);
+ drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ return ret;
+}
+
+static int stat_with_cap_dac_override(struct vfs_handle_struct *handle,
+ struct smb_filename *smb_fname, int flag)
+{
+ bool fake_dctime = lp_fake_directory_create_times(SNUM(handle->conn));
+ int fd = -1;
+ NTSTATUS status;
+ struct smb_filename *dir_name = NULL;
+ struct smb_filename *rel_name = NULL;
+ int ret = -1;
+#ifdef O_PATH
+ int open_flags = O_PATH;
+#else
+ int open_flags = O_RDONLY;
+#endif
+
+ status = SMB_VFS_PARENT_PATHNAME(handle->conn,
+ talloc_tos(),
+ smb_fname,
+ &dir_name,
+ &rel_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+
+ fd = open(dir_name->base_name, open_flags, 0);
+ if (fd == -1) {
+ TALLOC_FREE(dir_name);
+ return -1;
+ }
+
+ ret = fstatat_with_cap_dac_override(fd,
+ rel_name->base_name,
+ &smb_fname->st,
+ flag,
+ fake_dctime);
+
+ TALLOC_FREE(dir_name);
+ close(fd);
+
+ return ret;
+}
+
+int nfs4_acl_stat(struct vfs_handle_struct *handle,
+ struct smb_filename *smb_fname)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+ if (ret == -1 && errno == EACCES) {
+ DEBUG(10, ("Trying stat with capability for %s\n",
+ smb_fname->base_name));
+ ret = stat_with_cap_dac_override(handle, smb_fname, 0);
+ }
+ return ret;
+}
+
+static int fstat_with_cap_dac_override(int fd, SMB_STRUCT_STAT *sbuf,
+ bool fake_dir_create_times)
+{
+ int ret;
+
+ set_effective_capability(DAC_OVERRIDE_CAPABILITY);
+ ret = sys_fstat(fd, sbuf, fake_dir_create_times);
+ drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ return ret;
+}
+
+int nfs4_acl_fstat(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ SMB_STRUCT_STAT *sbuf)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+ if (ret == -1 && errno == EACCES) {
+ bool fake_dctime =
+ lp_fake_directory_create_times(SNUM(handle->conn));
+
+ DBG_DEBUG("fstat for %s failed with EACCES. Trying with "
+ "CAP_DAC_OVERRIDE.\n", fsp->fsp_name->base_name);
+ ret = fstat_with_cap_dac_override(fsp_get_pathref_fd(fsp),
+ sbuf,
+ fake_dctime);
+ }
+
+ return ret;
+}
+
+int nfs4_acl_lstat(struct vfs_handle_struct *handle,
+ struct smb_filename *smb_fname)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+ if (ret == -1 && errno == EACCES) {
+ DEBUG(10, ("Trying lstat with capability for %s\n",
+ smb_fname->base_name));
+ ret = stat_with_cap_dac_override(handle, smb_fname,
+ AT_SYMLINK_NOFOLLOW);
+ }
+ return ret;
+}
+
+int nfs4_acl_fstatat(struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
+ if (ret == -1 && errno == EACCES) {
+ bool fake_dctime =
+ lp_fake_directory_create_times(SNUM(handle->conn));
+
+ DBG_DEBUG("fstatat for %s failed with EACCES. Trying with "
+ "CAP_DAC_OVERRIDE.\n", dirfsp->fsp_name->base_name);
+ ret = fstatat_with_cap_dac_override(fsp_get_pathref_fd(dirfsp),
+ smb_fname->base_name,
+ sbuf,
+ flags,
+ fake_dctime);
+ }
+
+ return ret;
+}
+
/************************************************
Split the ACE flag mapping between nfs4 and Windows
into two separate functions rather than trying to do
(win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
SEC_ACE_FLAG_CONTAINER_INHERIT))) {
/*
- * GPFS sets inherits dir_inhert and file_inherit flags
+ * GPFS sets inherits dir_inherit and file_inherit flags
* to files, too, which confuses windows, and seems to
* be wrong anyways. ==> Map these bits away for files.
*/