bool acl;
bool settimes;
bool recalls;
+ struct {
+ bool gpfs_fstat_x;
+ } pathref_ok;
};
struct gpfs_fsp_extension {
DBG_DEBUG("access_mask=0x%x, allow=0x%x, share_access=0x%x, "
"deny=0x%x\n", access_mask, allow, share_access, deny);
- result = gpfswrap_set_share(fsp->fh->fd, allow, deny);
+ result = gpfswrap_set_share(fsp_get_io_fd(fsp), allow, deny);
if (result == 0) {
return 0;
}
return result;
}
-static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
- uint32_t share_access, uint32_t access_mask)
+static int vfs_gpfs_filesystem_sharemode(vfs_handle_struct *handle,
+ files_struct *fsp,
+ uint32_t share_access,
+ uint32_t access_mask)
{
struct gpfs_config_data *config;
int ret = 0;
- START_PROFILE(syscall_kernel_flock);
-
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
return -1);
/*
* A named stream fsp will have the basefile open in the fsp
* fd, so lacking a distinct fd for the stream we have to skip
- * kernel_flock and set_gpfs_sharemode for stream.
+ * set_gpfs_sharemode for stream.
*/
- if (is_named_stream(fsp->fsp_name)) {
+ if (fsp_is_alternate_stream(fsp)) {
DBG_NOTICE("Not requesting GPFS sharemode on stream: %s/%s\n",
fsp->conn->connectpath,
fsp_str_dbg(fsp));
return 0;
}
- kernel_flock(fsp->fh->fd, share_access, access_mask);
-
ret = set_gpfs_sharemode(fsp, access_mask, share_access);
- END_PROFILE(syscall_kernel_flock);
-
return ret;
}
struct gpfs_config_data,
return -1);
- if (config->sharemodes && fsp->kernel_share_modes_taken) {
+ if (config->sharemodes &&
+ (fsp->fsp_flags.kernel_share_modes_taken))
+ {
/*
* Always clear GPFS sharemode in case the actual
* close gets deferred due to outstanding POSIX locks
* (see fd_close_posix)
*/
- int ret = gpfswrap_set_share(fsp->fh->fd, 0, 0);
+ int ret = gpfswrap_set_share(fsp_get_io_fd(fsp), 0, 0);
if (ret != 0) {
DBG_ERR("Clearing GPFS sharemode on close failed for "
" %s/%s: %s\n",
return SMB_VFS_NEXT_CLOSE(handle, fsp);
}
-static int set_gpfs_lease(int fd, int leasetype)
+#ifdef HAVE_KERNEL_OPLOCKS_LINUX
+static int lease_type_to_gpfs(int leasetype)
{
- int gpfs_type = GPFS_LEASE_NONE;
-
if (leasetype == F_RDLCK) {
- gpfs_type = GPFS_LEASE_READ;
+ return GPFS_LEASE_READ;
}
+
if (leasetype == F_WRLCK) {
- gpfs_type = GPFS_LEASE_WRITE;
+ return GPFS_LEASE_WRITE;
}
- return gpfswrap_set_lease(fd, gpfs_type);
+ return GPFS_LEASE_NONE;
}
static int vfs_gpfs_setlease(vfs_handle_struct *handle,
struct gpfs_config_data,
return -1);
- ret = linux_set_lease_sighandler(fsp->fh->fd);
+ ret = linux_set_lease_sighandler(fsp_get_io_fd(fsp));
if (ret == -1) {
goto failure;
}
if (config->leases) {
+ int gpfs_lease_type = lease_type_to_gpfs(leasetype);
+ int saved_errno = 0;
+
/*
* Ensure the lease owner is root to allow
* correct delivery of lease-break signals.
*/
become_root();
- ret = set_gpfs_lease(fsp->fh->fd,leasetype);
+ ret = gpfswrap_set_lease(fsp_get_io_fd(fsp), gpfs_lease_type);
+ if (ret < 0) {
+ saved_errno = errno;
+ }
unbecome_root();
+
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
}
failure:
return ret;
}
-static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
- const char *path,
- const char *name,
- TALLOC_CTX *mem_ctx,
- char **found_name)
+#else /* HAVE_KERNEL_OPLOCKS_LINUX */
+
+static int vfs_gpfs_setlease(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int leasetype)
+{
+ return ENOSYS;
+}
+#endif /* HAVE_KERNEL_OPLOCKS_LINUX */
+
+static NTSTATUS vfs_gpfs_get_real_filename_at(struct vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const char *name,
+ TALLOC_CTX *mem_ctx,
+ char **found_name)
{
int result;
char *full_path = NULL;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
- return -1);
+ return NT_STATUS_INTERNAL_ERROR);
if (!config->getrealfilename) {
- return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
- mem_ctx, found_name);
+ return SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
+ handle, dirfsp, name, mem_ctx, found_name);
}
mangled = mangle_is_mangled(name, handle->conn->params);
if (mangled) {
- return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
- mem_ctx, found_name);
+ return SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
+ handle, dirfsp, name, mem_ctx, found_name);
}
- full_path_len = full_path_tos(path, name, tmpbuf, sizeof(tmpbuf),
+ full_path_len = full_path_tos(dirfsp->fsp_name->base_name, name,
+ tmpbuf, sizeof(tmpbuf),
&full_path, &to_free);
if (full_path_len == -1) {
- errno = ENOMEM;
- return -1;
+ return NT_STATUS_NO_MEMORY;
}
buflen = sizeof(real_pathname) - 1;
TALLOC_FREE(to_free);
if ((result == -1) && (errno == ENOSYS)) {
- return SMB_VFS_NEXT_GET_REAL_FILENAME(
- handle, path, name, mem_ctx, found_name);
+ return SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
+ handle, dirfsp, name, mem_ctx, found_name);
}
if (result == -1) {
DEBUG(10, ("smbd_gpfs_get_realfilename_path returned %s\n",
strerror(errno)));
- return -1;
+ return map_nt_error_from_unix(errno);
}
/*
real_pathname[sizeof(real_pathname)-1] = '\0';
}
- DEBUG(10, ("smbd_gpfs_get_realfilename_path: %s/%s -> %s\n",
- path, name, real_pathname));
+ DBG_DEBUG("%s/%s -> %s\n",
+ fsp_str_dbg(dirfsp),
+ name,
+ real_pathname);
name = strrchr_m(real_pathname, '/');
if (name == NULL) {
- errno = ENOENT;
- return -1;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
*found_name = talloc_strdup(mem_ctx, name+1);
if (*found_name == NULL) {
- errno = ENOMEM;
- return -1;
+ return NT_STATUS_NO_MEMORY;
}
- return 0;
+ return NT_STATUS_OK;
}
static void sd2gpfs_control(uint16_t control, struct gpfs_acl *gacl)
}
}
-static int gpfs_getacl_with_capability(const char *fname, int flags, void *buf)
+static int gpfs_getacl_with_capability(struct files_struct *fsp,
+ int flags,
+ void *buf)
{
int ret, saved_errno;
set_effective_capability(DAC_OVERRIDE_CAPABILITY);
- ret = gpfswrap_getacl(discard_const_p(char, fname), flags, buf);
+ ret = gpfswrap_fgetacl(fsp_get_pathref_fd(fsp), flags, buf);
saved_errno = errno;
drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
*
*/
static void *vfs_gpfs_getacl(TALLOC_CTX *mem_ctx,
- const char *fname,
+ struct files_struct *fsp,
const bool raw,
const gpfs_aclType_t type)
{
-
+ const char *fname = fsp->fsp_name->base_name;
void *aclbuf;
size_t size = 512;
int ret, flags;
*len = size;
if (use_capability) {
- ret = gpfs_getacl_with_capability(fname, flags, aclbuf);
+ ret = gpfs_getacl_with_capability(fsp, flags, aclbuf);
} else {
- ret = gpfswrap_getacl(discard_const_p(char, fname),
- flags, aclbuf);
+ ret = gpfswrap_fgetacl(fsp_get_pathref_fd(fsp), flags, aclbuf);
if ((ret != 0) && (errno == EACCES)) {
DBG_DEBUG("Retry with DAC capability for %s\n", fname);
use_capability = true;
- ret = gpfs_getacl_with_capability(fname, flags, aclbuf);
+ ret = gpfs_getacl_with_capability(fsp, flags, aclbuf);
}
}
* On failure returns -1 if there is system (GPFS) error, check errno.
* Returns 0 on success
*/
-static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname,
+static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
struct SMB4ACL_T **ppacl)
{
+ const char *fname = fsp->fsp_name->base_name;
gpfs_aclCount_t i;
struct gpfs_acl *gacl = NULL;
DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fname));
/* Get the ACL */
- gacl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(), fname,
+ gacl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(), fsp,
false, 0);
if (gacl == NULL) {
DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
return status;
}
- result = gpfs_get_nfs4_acl(frame, fsp->fsp_name->base_name, &pacl);
+ result = gpfs_get_nfs4_acl(frame, fsp, &pacl);
if (result == 0) {
status = smb_fget_nt_acl_nfs4(fsp, &config->nfs4_params,
return map_nt_error_from_unix(errno);
}
-static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
-{
- struct SMB4ACL_T *pacl = NULL;
- int result;
- struct gpfs_config_data *config;
- TALLOC_CTX *frame = talloc_stackframe();
- NTSTATUS status;
-
- *ppdesc = NULL;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return NT_STATUS_INTERNAL_ERROR);
-
- if (!config->acl) {
- status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname,
- security_info,
- mem_ctx, ppdesc);
- TALLOC_FREE(frame);
- return status;
- }
-
- result = gpfs_get_nfs4_acl(frame, smb_fname->base_name, &pacl);
-
- if (result == 0) {
- status = smb_get_nt_acl_nfs4(handle->conn, smb_fname,
- &config->nfs4_params,
- security_info, mem_ctx, ppdesc,
- pacl);
- TALLOC_FREE(frame);
- return status;
- }
-
- if (result > 0) {
- DEBUG(10, ("retrying with posix acl...\n"));
- status = posix_get_nt_acl(handle->conn, smb_fname,
- security_info, mem_ctx, ppdesc);
- TALLOC_FREE(frame);
- return status;
- }
-
- /* GPFS ACL was not read, something wrong happened, error code is set in errno */
- TALLOC_FREE(frame);
- return map_nt_error_from_unix(errno);
-}
-
static bool vfs_gpfs_nfs4_ace_to_gpfs_ace(SMB_ACE4PROP_T *nfs4_ace,
struct gpfs_ace_v4 *gace,
uid_t owner_uid)
NTSTATUS result = NT_STATUS_ACCESS_DENIED;
acl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(),
- fsp->fsp_name->base_name,
+ fsp,
false, 0);
if (acl == NULL) {
return map_nt_error_from_unix(errno);
if (acl->acl_version == GPFS_ACL_VERSION_NFS4) {
struct gpfs_config_data *config;
- if (lp_parm_bool(fsp->conn->params->service, "gpfs",
- "refuse_dacl_protected", false)
- && (psd->type&SEC_DESC_DACL_PROTECTED)) {
- DEBUG(2, ("Rejecting unsupported ACL with DACL_PROTECTED bit set\n"));
- talloc_free(acl);
- return NT_STATUS_NOT_SUPPORTED;
- }
-
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
return NT_STATUS_INTERNAL_ERROR);
return result;
}
-static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type,
+static SMB_ACL_T gpfsacl_get_posix_acl(struct files_struct *fsp,
+ gpfs_aclType_t type,
TALLOC_CTX *mem_ctx)
{
struct gpfs_acl *pacl;
SMB_ACL_T result = NULL;
- pacl = vfs_gpfs_getacl(talloc_tos(), path, false, type);
+ pacl = vfs_gpfs_getacl(talloc_tos(), fsp, false, type);
if (pacl == NULL) {
- DEBUG(10, ("vfs_gpfs_getacl failed for %s with %s\n",
- path, strerror(errno)));
+ DBG_DEBUG("vfs_gpfs_getacl failed for %s with %s\n",
+ fsp_str_dbg(fsp), strerror(errno));
if (errno == 0) {
errno = EINVAL;
}
return result;
}
-static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- SMB_ACL_TYPE_T type,
- TALLOC_CTX *mem_ctx)
+static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_TYPE_T type,
+ TALLOC_CTX *mem_ctx)
{
gpfs_aclType_t gpfs_type;
struct gpfs_config_data *config;
return NULL);
if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, smb_fname,
- type, mem_ctx);
+ return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, type, mem_ctx);
}
switch(type) {
DEBUG(0, ("Got invalid type: %d\n", type));
smb_panic("exiting");
}
-
- return gpfsacl_get_posix_acl(smb_fname->base_name, gpfs_type, mem_ctx);
-}
-
-static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- TALLOC_CTX *mem_ctx)
-{
- struct gpfs_config_data *config;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return NULL);
-
- if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
- }
-
- return gpfsacl_get_posix_acl(fsp->fsp_name->base_name,
- GPFS_ACL_TYPE_ACCESS, mem_ctx);
-}
-
-static int gpfsacl_sys_acl_blob_get_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- TALLOC_CTX *mem_ctx,
- char **blob_description,
- DATA_BLOB *blob)
-{
- struct gpfs_config_data *config;
- struct gpfs_opaque_acl *acl = NULL;
- DATA_BLOB aclblob;
- int result;
- const char *path_p = smb_fname->base_name;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return -1);
-
- if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle, smb_fname,
- mem_ctx,
- blob_description,
- blob);
- }
-
- errno = 0;
- acl = (struct gpfs_opaque_acl *)
- vfs_gpfs_getacl(mem_ctx,
- path_p,
- true,
- GPFS_ACL_TYPE_NFS4);
-
- if (errno) {
- DEBUG(5, ("vfs_gpfs_getacl finished with errno %d: %s\n",
- errno, strerror(errno)));
-
- /* EINVAL means POSIX ACL, bail out on other cases */
- if (errno != EINVAL) {
- return -1;
- }
- }
-
- if (acl != NULL) {
- /*
- * file has NFSv4 ACL
- *
- * we only need the actual ACL blob here
- * acl_version will always be NFS4 because we asked
- * for NFS4
- * acl_type is only used for POSIX ACLs
- */
- aclblob.data = (uint8_t*) acl->acl_var_data;
- aclblob.length = acl->acl_buffer_len;
-
- *blob_description = talloc_strdup(mem_ctx, "gpfs_nfs4_acl");
- if (!*blob_description) {
- talloc_free(acl);
- errno = ENOMEM;
- return -1;
- }
-
- result = non_posix_sys_acl_blob_get_file_helper(handle, smb_fname,
- aclblob,
- mem_ctx, blob);
-
- talloc_free(acl);
- return result;
- }
-
- /* fall back to POSIX ACL */
- return posix_sys_acl_blob_get_file(handle, smb_fname, mem_ctx,
- blob_description, blob);
+ return gpfsacl_get_posix_acl(fsp, gpfs_type, mem_ctx);
}
static int gpfsacl_sys_acl_blob_get_fd(vfs_handle_struct *handle,
errno = 0;
acl = (struct gpfs_opaque_acl *) vfs_gpfs_getacl(mem_ctx,
- fsp->fsp_name->base_name,
+ fsp,
true,
GPFS_ACL_TYPE_NFS4);
return result;
}
-static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- SMB_ACL_TYPE_T type,
- SMB_ACL_T theacl)
+static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
{
- struct gpfs_acl *gpfs_acl;
- int result;
struct gpfs_config_data *config;
+ struct gpfs_acl *gpfs_acl = NULL;
+ int result;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
return -1);
if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, smb_fname,
- type, theacl);
+ return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, type, theacl);
}
gpfs_acl = smb2gpfs_acl(theacl, type);
return -1;
}
- result = gpfswrap_putacl(discard_const_p(char, smb_fname->base_name),
- GPFS_PUTACL_STRUCT|GPFS_ACL_SAMBA, gpfs_acl);
-
+ /*
+ * This is no longer a handle based call.
+ */
+ result = gpfswrap_putacl(fsp->fsp_name->base_name,
+ GPFS_PUTACL_STRUCT|GPFS_ACL_SAMBA,
+ gpfs_acl);
SAFE_FREE(gpfs_acl);
return result;
}
-static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- SMB_ACL_T theacl)
-{
- struct gpfs_config_data *config;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return -1);
-
- if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
- }
-
- return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name,
- SMB_ACL_TYPE_ACCESS, theacl);
-}
-
-static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
+static int gpfsacl_sys_acl_delete_def_fd(vfs_handle_struct *handle,
+ files_struct *fsp)
{
struct gpfs_config_data *config;
return -1);
if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, smb_fname);
+ return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FD(handle, fsp);
}
errno = ENOTSUP;
return -1;
}
+
/*
* Assumed: mode bits are shiftable and standard
* Output: the new aceMask field for an smb nfs4 ace
}
static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
- const char *path, mode_t mode)
+ struct files_struct *fsp,
+ mode_t mode)
{
+ struct smb_filename *fname = fsp->fsp_name;
+ char *path = fsp->fsp_name->base_name;
struct SMB4ACL_T *pacl = NULL;
int result;
bool haveAllowEntry[SMB_ACE4_WHO_EVERYONE + 1] = {False, False, False, False};
DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
- result = gpfs_get_nfs4_acl(frame, path, &pacl);
+ result = gpfs_get_nfs4_acl(frame, fsp, &pacl);
if (result) {
TALLOC_FREE(frame);
return result;
}
/* don't add complementary DENY ACEs here */
- fake_fsp.fsp_name = synthetic_smb_fname(
- frame, path, NULL, NULL, 0);
+ fake_fsp.fsp_name = synthetic_smb_fname(frame,
+ path,
+ NULL,
+ NULL,
+ fname->twrp,
+ 0);
if (fake_fsp.fsp_name == NULL) {
errno = ENOMEM;
TALLOC_FREE(frame);
return 0; /* ok for [f]chmod */
}
-static int vfs_gpfs_chmod(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- mode_t mode)
+static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
{
- struct smb_filename *smb_fname_cpath;
+ SMB_STRUCT_STAT st;
int rc;
- smb_fname_cpath = cp_smb_filename(talloc_tos(), smb_fname);
- if (smb_fname_cpath == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- if (SMB_VFS_NEXT_STAT(handle, smb_fname_cpath) != 0) {
- TALLOC_FREE(smb_fname_cpath);
+ rc = SMB_VFS_NEXT_FSTAT(handle, fsp, &st);
+ if (rc != 0) {
return -1;
}
/* avoid chmod() if possible, to preserve acls */
- if ((smb_fname_cpath->st.st_ex_mode & ~S_IFMT) == mode) {
- TALLOC_FREE(smb_fname_cpath);
+ if ((st.st_ex_mode & ~S_IFMT) == mode) {
return 0;
}
- rc = gpfsacl_emu_chmod(handle, smb_fname->base_name, mode);
- if (rc == 1)
- return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
-
- TALLOC_FREE(smb_fname_cpath);
+ rc = gpfsacl_emu_chmod(handle, fsp, mode);
+ if (rc == 1) {
+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
+ }
return rc;
}
-static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
-{
- SMB_STRUCT_STAT st;
- int rc;
-
- if (SMB_VFS_NEXT_FSTAT(handle, fsp, &st) != 0) {
- return -1;
- }
-
- /* avoid chmod() if possible, to preserve acls */
- if ((st.st_ex_mode & ~S_IFMT) == mode) {
- return 0;
- }
-
- rc = gpfsacl_emu_chmod(handle, fsp->fsp_name->base_name,
- mode);
- if (rc == 1)
- return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
- return rc;
-}
-
static uint32_t vfs_gpfs_winattrs_to_dosmode(unsigned int winattrs)
{
uint32_t dosmode = 0;
return winattrs;
}
-static int get_dos_attr_with_capability(struct smb_filename *smb_fname,
- unsigned int *litemask,
- struct gpfs_iattr64 *iattr)
-{
- int saved_errno = 0;
- int ret;
-
- /*
- * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to an
- * Existing File" FILE_LIST_DIRECTORY on a directory implies
- * FILE_READ_ATTRIBUTES for directory entries. Being able to stat() a
- * file implies FILE_LIST_DIRECTORY for the directory containing the
- * file.
- */
-
- if (!VALID_STAT(smb_fname->st)) {
- /*
- * Safety net: dos_mode() already checks this, but as we set
- * DAC_OVERRIDE_CAPABILITY based on this, add an additional
- * layer of defense.
- */
- DBG_ERR("Rejecting DAC override, invalid stat [%s]\n",
- smb_fname_str_dbg(smb_fname));
- errno = EACCES;
- return -1;
- }
-
- set_effective_capability(DAC_OVERRIDE_CAPABILITY);
-
- ret = gpfswrap_stat_x(smb_fname->base_name, litemask,
- iattr, sizeof(*iattr));
- if (ret == -1) {
- saved_errno = errno;
- }
-
- drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
-
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
-}
-
-static NTSTATUS vfs_gpfs_get_file_id(struct gpfs_iattr64 *iattr,
- uint64_t *fileid)
-{
- uint8_t input[sizeof(gpfs_ino64_t) +
- sizeof(gpfs_gen64_t) +
- sizeof(gpfs_snapid64_t)];
- uint8_t digest[gnutls_hash_get_len(GNUTLS_DIG_SHA1)];
- int rc;
-
- DBG_DEBUG("ia_inode 0x%llx, ia_gen 0x%llx, ia_modsnapid 0x%llx\n",
- iattr->ia_inode, iattr->ia_gen, iattr->ia_modsnapid);
-
- SBVAL(input,
- 0, iattr->ia_inode);
- SBVAL(input,
- sizeof(gpfs_ino64_t), iattr->ia_gen);
- SBVAL(input,
- sizeof(gpfs_ino64_t) + sizeof(gpfs_gen64_t), iattr->ia_modsnapid);
-
- GNUTLS_FIPS140_SET_LAX_MODE();
- rc = gnutls_hash_fast(GNUTLS_DIG_SHA1, input, sizeof(input), &digest);
- GNUTLS_FIPS140_SET_STRICT_MODE();
-
- if (rc != 0) {
- return gnutls_error_to_ntstatus(rc,
- NT_STATUS_HASH_NOT_SUPPORTED);
- }
-
- memcpy(fileid, &digest, sizeof(*fileid));
- DBG_DEBUG("file_id 0x%" PRIx64 "\n", *fileid);
-
- return NT_STATUS_OK;
-}
-
static struct timespec gpfs_timestruc64_to_timespec(struct gpfs_timestruc64 g)
{
return (struct timespec) { .tv_sec = g.tv_sec, .tv_nsec = g.tv_nsec };
}
-static NTSTATUS vfs_gpfs_get_dos_attributes(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- uint32_t *dosmode)
-{
- struct gpfs_config_data *config;
- struct gpfs_iattr64 iattr = { };
- unsigned int litemask = 0;
- struct timespec ts;
- uint64_t file_id;
- NTSTATUS status;
- int ret;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return NT_STATUS_INTERNAL_ERROR);
-
- if (!config->winattr) {
- return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
- smb_fname, dosmode);
- }
-
- ret = gpfswrap_stat_x(smb_fname->base_name, &litemask,
- &iattr, sizeof(iattr));
- if (ret == -1 && errno == ENOSYS) {
- return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, smb_fname,
- dosmode);
- }
- if (ret == -1 && errno == EACCES) {
- ret = get_dos_attr_with_capability(smb_fname, &litemask,
- &iattr);
- }
-
- if (ret == -1 && errno == EBADF) {
- /*
- * Returned for directory listings in gpfs root for
- * .. entry which steps out of gpfs.
- */
- DBG_DEBUG("Getting winattrs for %s returned EBADF.\n",
- smb_fname->base_name);
- return map_nt_error_from_unix(errno);
- } else if (ret == -1) {
- DBG_WARNING("Getting winattrs failed for %s: %s\n",
- smb_fname->base_name, strerror(errno));
- return map_nt_error_from_unix(errno);
- }
-
- status = vfs_gpfs_get_file_id(&iattr, &file_id);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- ts = gpfs_timestruc64_to_timespec(iattr.ia_createtime);
-
- *dosmode |= vfs_gpfs_winattrs_to_dosmode(iattr.ia_winflags);
- update_stat_ex_create_time(&smb_fname->st, ts);
- update_stat_ex_file_id(&smb_fname->st, file_id);
-
- return NT_STATUS_OK;
-}
-
static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32_t *dosmode)
{
struct gpfs_config_data *config;
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
+ const char *p = NULL;
struct gpfs_iattr64 iattr = { };
- unsigned int litemask;
+ unsigned int litemask = 0;
struct timespec ts;
- uint64_t file_id;
- NTSTATUS status;
int ret;
SMB_VFS_HANDLE_GET_DATA(handle, config,
return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
}
- ret = gpfswrap_fstat_x(fsp->fh->fd, &litemask, &iattr, sizeof(iattr));
+ if (fsp->fsp_flags.is_pathref && !config->pathref_ok.gpfs_fstat_x) {
+ if (fsp->fsp_flags.have_proc_fds) {
+ p = sys_proc_fd_path(fd, &buf);
+ } else {
+ p = fsp->fsp_name->base_name;
+ }
+ }
+
+ if (p != NULL) {
+ ret = gpfswrap_stat_x(p, &litemask, &iattr, sizeof(iattr));
+ } else {
+ ret = gpfswrap_fstat_x(fd, &litemask, &iattr, sizeof(iattr));
+ }
if (ret == -1 && errno == ENOSYS) {
return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
}
set_effective_capability(DAC_OVERRIDE_CAPABILITY);
- ret = gpfswrap_fstat_x(fsp->fh->fd, &litemask,
- &iattr, sizeof(iattr));
+ if (p != NULL) {
+ ret = gpfswrap_stat_x(p,
+ &litemask,
+ &iattr,
+ sizeof(iattr));
+ } else {
+ ret = gpfswrap_fstat_x(fd,
+ &litemask,
+ &iattr,
+ sizeof(iattr));
+ }
if (ret == -1) {
saved_errno = errno;
}
return map_nt_error_from_unix(errno);
}
- status = vfs_gpfs_get_file_id(&iattr, &file_id);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
ts = gpfs_timestruc64_to_timespec(iattr.ia_createtime);
*dosmode |= vfs_gpfs_winattrs_to_dosmode(iattr.ia_winflags);
update_stat_ex_create_time(&fsp->fsp_name->st, ts);
- update_stat_ex_file_id(&fsp->fsp_name->st, file_id);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS vfs_gpfs_set_dos_attributes(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- uint32_t dosmode)
-{
- struct gpfs_config_data *config;
- struct gpfs_winattr attrs = { };
- int ret;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return NT_STATUS_INTERNAL_ERROR);
-
- if (!config->winattr) {
- return SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
- smb_fname, dosmode);
- }
-
- attrs.winAttrs = vfs_gpfs_dosmode_to_winattrs(dosmode);
- ret = gpfswrap_set_winattrs_path(smb_fname->base_name,
- GPFS_WINATTR_SET_ATTRS, &attrs);
-
- if (ret == -1 && errno == ENOSYS) {
- return SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
- smb_fname, dosmode);
- }
-
- if (ret == -1) {
- DBG_WARNING("Setting winattrs failed for %s: %s\n",
- smb_fname->base_name, strerror(errno));
- return map_nt_error_from_unix(errno);
- }
return NT_STATUS_OK;
}
}
attrs.winAttrs = vfs_gpfs_dosmode_to_winattrs(dosmode);
- ret = gpfswrap_set_winattrs(fsp->fh->fd,
- GPFS_WINATTR_SET_ATTRS, &attrs);
- if (ret == -1 && errno == ENOSYS) {
- return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
+ if (!fsp->fsp_flags.is_pathref) {
+ ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
+ GPFS_WINATTR_SET_ATTRS, &attrs);
+ if (ret == -1) {
+ DBG_WARNING("Setting winattrs failed for %s: %s\n",
+ fsp_str_dbg(fsp), strerror(errno));
+ return map_nt_error_from_unix(errno);
+ }
+ return NT_STATUS_OK;
}
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
+
+ ret = gpfswrap_set_winattrs_path(sys_proc_fd_path(fd, &buf),
+ GPFS_WINATTR_SET_ATTRS,
+ &attrs);
+ if (ret == -1) {
+ DBG_WARNING("Setting winattrs failed for "
+ "[%s][%s]: %s\n",
+ buf.buf,
+ fsp_str_dbg(fsp),
+ strerror(errno));
+ return map_nt_error_from_unix(errno);
+ }
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ ret = gpfswrap_set_winattrs_path(fsp->fsp_name->base_name,
+ GPFS_WINATTR_SET_ATTRS,
+ &attrs);
if (ret == -1) {
- DBG_WARNING("Setting winattrs failed for %s: %s\n",
- fsp->fsp_name->base_name, strerror(errno));
+ DBG_WARNING("Setting winattrs failed for [%s]: %s\n",
+ fsp_str_dbg(fsp), strerror(errno));
return map_nt_error_from_unix(errno);
}
return NT_STATUS_OK;
}
-static int stat_with_capability(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname, int flag)
+static int timespec_to_gpfs_time(
+ struct timespec ts, gpfs_timestruc_t *gt, int idx, int *flags)
{
-#if defined(HAVE_FSTATAT)
- int fd = -1;
- bool b;
- char *dir_name;
- const char *rel_name = NULL;
- struct stat st;
- int ret = -1;
-
- b = parent_dirname(talloc_tos(), smb_fname->base_name,
- &dir_name, &rel_name);
- if (!b) {
- errno = ENOMEM;
- return -1;
+ if (is_omit_timespec(&ts)) {
+ return 0;
}
- fd = open(dir_name, O_RDONLY, 0);
- TALLOC_FREE(dir_name);
- if (fd == -1) {
+ if (ts.tv_sec < 0 || ts.tv_sec > UINT32_MAX) {
+ DBG_NOTICE("GPFS uses 32-bit unsigned timestamps "
+ "and cannot handle %jd.\n",
+ (intmax_t)ts.tv_sec);
+ errno = ERANGE;
return -1;
}
- set_effective_capability(DAC_OVERRIDE_CAPABILITY);
- ret = fstatat(fd, rel_name, &st, flag);
- drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
-
- close(fd);
-
- if (ret == 0) {
- init_stat_ex_from_stat(
- &smb_fname->st, &st,
- lp_fake_directory_create_times(SNUM(handle->conn)));
- }
+ *flags |= 1 << idx;
+ gt[idx].tv_sec = ts.tv_sec;
+ gt[idx].tv_nsec = ts.tv_nsec;
+ DBG_DEBUG("Setting GPFS time %d, flags 0x%x\n", idx, *flags);
- return ret;
-#else
- return -1;
-#endif
+ return 0;
}
-static int vfs_gpfs_stat(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname)
+static int smbd_gpfs_set_times(struct files_struct *fsp,
+ struct smb_file_time *ft)
{
- int ret;
- struct gpfs_config_data *config;
-
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return -1);
+ gpfs_timestruc_t gpfs_times[4];
+ int flags = 0;
+ int rc;
- 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_capability(handle, smb_fname, 0);
+ ZERO_ARRAY(gpfs_times);
+ rc = timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
+ if (rc != 0) {
+ return rc;
}
- return ret;
-}
-static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname)
-{
- int ret;
- struct gpfs_config_data *config;
+ rc = timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
+ if (rc != 0) {
+ return rc;
+ }
- SMB_VFS_HANDLE_GET_DATA(handle, config,
- struct gpfs_config_data,
- return -1);
+ /* No good mapping from LastChangeTime to ctime, not storing */
+ rc = timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+ if (rc != 0) {
+ return rc;
+ }
- 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_capability(handle, smb_fname,
- AT_SYMLINK_NOFOLLOW);
+ if (!flags) {
+ DBG_DEBUG("nothing to do, return to avoid EINVAL\n");
+ return 0;
}
- return ret;
-}
-static void timespec_to_gpfs_time(struct timespec ts, gpfs_timestruc_t *gt,
- int idx, int *flags)
-{
- if (!is_omit_timespec(&ts)) {
- *flags |= 1 << idx;
- gt[idx].tv_sec = ts.tv_sec;
- gt[idx].tv_nsec = ts.tv_nsec;
- DEBUG(10, ("Setting GPFS time %d, flags 0x%x\n", idx, *flags));
+ if (!fsp->fsp_flags.is_pathref) {
+ rc = gpfswrap_set_times(fsp_get_io_fd(fsp), flags, gpfs_times);
+ if (rc != 0) {
+ DBG_WARNING("gpfs_set_times(%s) failed: %s\n",
+ fsp_str_dbg(fsp), strerror(errno));
+ }
+ return rc;
}
-}
-static int smbd_gpfs_set_times_path(char *path, struct smb_file_time *ft)
-{
- gpfs_timestruc_t gpfs_times[4];
- int flags = 0;
- int rc;
- ZERO_ARRAY(gpfs_times);
- timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
- timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
- /* No good mapping from LastChangeTime to ctime, not storing */
- timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
- if (!flags) {
- DEBUG(10, ("nothing to do, return to avoid EINVAL\n"));
- return 0;
+ rc = gpfswrap_set_times_path(sys_proc_fd_path(fd, &buf),
+ flags,
+ gpfs_times);
+ if (rc != 0) {
+ DBG_WARNING("gpfs_set_times_path(%s,%s) failed: %s\n",
+ fsp_str_dbg(fsp),
+ buf.buf,
+ strerror(errno));
+ }
+ return rc;
}
- rc = gpfswrap_set_times_path(path, flags, gpfs_times);
+ /*
+ * This is no longer a handle based call.
+ */
- if (rc != 0 && errno != ENOSYS) {
- DEBUG(1,("gpfs_set_times() returned with error %s\n",
- strerror(errno)));
+ rc = gpfswrap_set_times_path(fsp->fsp_name->base_name,
+ flags,
+ gpfs_times);
+ if (rc != 0) {
+ DBG_WARNING("gpfs_set_times_path(%s) failed: %s\n",
+ fsp_str_dbg(fsp), strerror(errno));
}
-
return rc;
}
-static int vfs_gpfs_ntimes(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct smb_file_time *ft)
+static int vfs_gpfs_fntimes(struct vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct smb_file_time *ft)
{
- struct gpfs_winattr attrs;
- int ret;
+ struct gpfs_winattr attrs;
+ int ret;
struct gpfs_config_data *config;
- SMB_VFS_HANDLE_GET_DATA(handle, config,
+ SMB_VFS_HANDLE_GET_DATA(handle,
+ config,
struct gpfs_config_data,
return -1);
/* Try to use gpfs_set_times if it is enabled and available */
if (config->settimes) {
- ret = smbd_gpfs_set_times_path(smb_fname->base_name, ft);
-
- if (ret == 0 || (ret == -1 && errno != ENOSYS)) {
- return ret;
- }
+ return smbd_gpfs_set_times(fsp, ft);
}
- DEBUG(10,("gpfs_set_times() not available or disabled, "
- "use ntimes and winattr\n"));
+ DBG_DEBUG("gpfs_set_times() not available or disabled, "
+ "use ntimes and winattr\n");
- ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
- if(ret == -1){
+ ret = SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
+ if (ret == -1) {
/* don't complain if access was denied */
if (errno != EPERM && errno != EACCES) {
- DEBUG(1,("vfs_gpfs_ntimes: SMB_VFS_NEXT_NTIMES failed:"
- "%s", strerror(errno)));
+ DBG_WARNING("SMB_VFS_NEXT_FNTIMES failed: %s\n",
+ strerror(errno));
}
- return -1;
- }
+ return -1;
+ }
- if (is_omit_timespec(&ft->create_time)){
- DEBUG(10,("vfs_gpfs_ntimes:Create Time is NULL\n"));
- return 0;
- }
+ if (is_omit_timespec(&ft->create_time)) {
+ DBG_DEBUG("Create Time is NULL\n");
+ return 0;
+ }
if (!config->winattr) {
return 0;
}
- attrs.winAttrs = 0;
- attrs.creationTime.tv_sec = ft->create_time.tv_sec;
- attrs.creationTime.tv_nsec = ft->create_time.tv_nsec;
+ attrs.winAttrs = 0;
+ attrs.creationTime.tv_sec = ft->create_time.tv_sec;
+ attrs.creationTime.tv_nsec = ft->create_time.tv_nsec;
- ret = gpfswrap_set_winattrs_path(smb_fname->base_name,
+ if (!fsp->fsp_flags.is_pathref) {
+ ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
+ GPFS_WINATTR_SET_CREATION_TIME,
+ &attrs);
+ if (ret == -1 && errno != ENOSYS) {
+ DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
+ return -1;
+ }
+ return ret;
+ }
+
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
+
+ ret = gpfswrap_set_winattrs_path(
+ sys_proc_fd_path(fd, &buf),
+ GPFS_WINATTR_SET_CREATION_TIME,
+ &attrs);
+ if (ret == -1 && errno != ENOSYS) {
+ DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
+ return -1;
+ }
+ return ret;
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ ret = gpfswrap_set_winattrs_path(fsp->fsp_name->base_name,
GPFS_WINATTR_SET_CREATION_TIME,
&attrs);
- if(ret == -1 && errno != ENOSYS){
- DEBUG(1,("vfs_gpfs_ntimes: set GPFS ntimes failed %d\n",ret));
- return -1;
- }
- return 0;
+ if (ret == -1 && errno != ENOSYS) {
+ DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
+ return -1;
+ }
+ return 0;
}
static int vfs_gpfs_fallocate(struct vfs_handle_struct *handle,
off_t offset, off_t len)
{
if (mode == (VFS_FALLOCATE_FL_PUNCH_HOLE|VFS_FALLOCATE_FL_KEEP_SIZE) &&
- !fsp->is_sparse &&
+ !fsp->fsp_flags.is_sparse &&
lp_strict_allocate(SNUM(fsp->conn))) {
/*
* This is from a ZERO_DATA request on a non-sparse
return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
}
- result = gpfswrap_ftruncate(fsp->fh->fd, len);
+ result = gpfswrap_ftruncate(fsp_get_io_fd(fsp), len);
if ((result == -1) && (errno == ENOSYS)) {
return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
}
}
static bool vfs_gpfs_is_offline(struct vfs_handle_struct *handle,
- const struct smb_filename *fname,
+ struct files_struct *fsp,
SMB_STRUCT_STAT *sbuf)
{
struct gpfs_winattr attrs;
return false;
}
- ret = gpfswrap_get_winattrs_path(fname->base_name, &attrs);
+ ret = gpfswrap_get_winattrs(fsp_get_pathref_fd(fsp), &attrs);
if (ret == -1) {
return false;
}
if ((attrs.winAttrs & GPFS_WINATTR_OFFLINE) != 0) {
- DBG_DEBUG("%s is offline\n", fname->base_name);
+ DBG_DEBUG("%s is offline\n", fsp_str_dbg(fsp));
return true;
}
- DBG_DEBUG("%s is online\n", fname->base_name);
+ DBG_DEBUG("%s is online\n", fsp_str_dbg(fsp));
return false;
}
/*
* Something bad happened, always ask.
*/
- return vfs_gpfs_is_offline(handle, fsp->fsp_name,
+ return vfs_gpfs_is_offline(handle, fsp,
&fsp->fsp_name->st);
}
/*
* As long as it's offline, ask.
*/
- ext->offline = vfs_gpfs_is_offline(handle, fsp->fsp_name,
+ ext->offline = vfs_gpfs_is_offline(handle, fsp,
&fsp->fsp_name->st);
}
return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, hdr, offset, n);
}
+#ifdef O_PATH
+static int vfs_gpfs_check_pathref_fstat_x(struct gpfs_config_data *config,
+ struct connection_struct *conn)
+{
+ struct gpfs_iattr64 iattr = {0};
+ unsigned int litemask = 0;
+ int saved_errno;
+ int fd;
+ int ret;
+
+ fd = open(conn->connectpath, O_PATH);
+ if (fd == -1) {
+ DBG_ERR("openat() of share with O_PATH failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ ret = gpfswrap_fstat_x(fd, &litemask, &iattr, sizeof(iattr));
+ if (ret == 0) {
+ close(fd);
+ config->pathref_ok.gpfs_fstat_x = true;
+ return 0;
+ }
+
+ saved_errno = errno;
+ ret = close(fd);
+ if (ret != 0) {
+ DBG_ERR("close failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (saved_errno != EBADF) {
+ DBG_ERR("gpfswrap_fstat_x() of O_PATH handle failed: %s\n",
+ strerror(saved_errno));
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static int vfs_gpfs_check_pathref(struct gpfs_config_data *config,
+ struct connection_struct *conn)
+{
+#ifndef O_PATH
+ /*
+ * This code path leaves all struct gpfs_config_data.pathref_ok members
+ * initialized to false.
+ */
+ return 0;
+#else
+ int ret;
+
+ ret = vfs_gpfs_check_pathref_fstat_x(config, conn);
+ if (ret != 0) {
+ return -1;
+ }
+
+ return 0;
+#endif
+}
+
static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
const char *service, const char *user)
{
int ret;
bool check_fstype;
- gpfswrap_lib_init(0);
+ ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (IS_IPC(handle->conn)) {
+ return 0;
+ }
+
+ ret = gpfswrap_init();
+ if (ret < 0) {
+ DBG_ERR("Could not load GPFS library.\n");
+ return ret;
+ }
+
+ ret = gpfswrap_lib_init(0);
+ if (ret < 0) {
+ DBG_ERR("Could not open GPFS device file: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ ret = gpfswrap_register_cifs_export();
+ if (ret < 0) {
+ DBG_ERR("Failed to register with GPFS: %s\n", strerror(errno));
+ return ret;
+ }
config = talloc_zero(handle->conn, struct gpfs_config_data);
if (!config) {
return -1;
}
- ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
- if (ret < 0) {
- TALLOC_FREE(config);
- return ret;
- }
-
check_fstype = lp_parm_bool(SNUM(handle->conn), "gpfs",
"check_fstype", true);
- if (check_fstype && !IS_IPC(handle->conn)) {
+ if (check_fstype) {
const char *connectpath = handle->conn->connectpath;
struct statfs buf = { 0 };
config->recalls = lp_parm_bool(SNUM(handle->conn), "gpfs",
"recalls", true);
+ ret = vfs_gpfs_check_pathref(config, handle->conn);
+ if (ret != 0) {
+ DBG_ERR("vfs_gpfs_check_pathref() on [%s] failed\n",
+ handle->conn->connectpath);
+ TALLOC_FREE(config);
+ return -1;
+ }
+
SMB_VFS_HANDLE_SET_DATA(handle, config,
NULL, struct gpfs_config_data,
return -1);
{
int ret;
- ret = gpfswrap_quotactl(discard_const_p(char, pathname),
- GPFS_QCMD(Q_GETQUOTA, type), id, qi);
+ ret = gpfswrap_quotactl(pathname, GPFS_QCMD(Q_GETQUOTA, type), id, qi);
if (ret) {
if (errno == GPFS_E_NO_QUOTA_INST) {
return next;
}
-static int vfs_gpfs_open(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname, files_struct *fsp,
- int flags, mode_t mode)
+static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ files_struct *fsp,
+ const struct vfs_open_how *_how)
{
- struct gpfs_config_data *config;
+ struct vfs_open_how how = *_how;
+ struct gpfs_config_data *config = NULL;
+ struct gpfs_fsp_extension *ext = NULL;
int ret;
- struct gpfs_fsp_extension *ext;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
return -1);
if (config->hsm && !config->recalls &&
- vfs_gpfs_fsp_is_offline(handle, fsp)) {
- DEBUG(10, ("Refusing access to offline file %s\n",
- fsp_str_dbg(fsp)));
+ !fsp->fsp_flags.is_pathref &&
+ vfs_gpfs_fsp_is_offline(handle, fsp))
+ {
+ DBG_DEBUG("Refusing access to offline file %s\n",
+ fsp_str_dbg(fsp));
errno = EACCES;
return -1;
}
if (config->syncio) {
- flags |= O_SYNC;
+ how.flags |= O_SYNC;
}
ext = VFS_ADD_FSP_EXTENSION(handle, fsp, struct gpfs_fsp_extension,
*/
*ext = (struct gpfs_fsp_extension) { .offline = true };
- ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+ ret = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, &how);
if (ret == -1) {
VFS_REMOVE_FSP_EXTENSION(handle, fsp);
}
.disk_free_fn = vfs_gpfs_disk_free,
.get_quota_fn = vfs_gpfs_get_quota,
.fs_capabilities_fn = vfs_gpfs_capabilities,
- .kernel_flock_fn = vfs_gpfs_kernel_flock,
+ .filesystem_sharemode_fn = vfs_gpfs_filesystem_sharemode,
.linux_setlease_fn = vfs_gpfs_setlease,
- .get_real_filename_fn = vfs_gpfs_get_real_filename,
- .get_dos_attributes_fn = vfs_gpfs_get_dos_attributes,
+ .get_real_filename_at_fn = vfs_gpfs_get_real_filename_at,
.get_dos_attributes_send_fn = vfs_not_implemented_get_dos_attributes_send,
.get_dos_attributes_recv_fn = vfs_not_implemented_get_dos_attributes_recv,
.fget_dos_attributes_fn = vfs_gpfs_fget_dos_attributes,
- .set_dos_attributes_fn = vfs_gpfs_set_dos_attributes,
.fset_dos_attributes_fn = vfs_gpfs_fset_dos_attributes,
.fget_nt_acl_fn = gpfsacl_fget_nt_acl,
- .get_nt_acl_fn = gpfsacl_get_nt_acl,
.fset_nt_acl_fn = gpfsacl_fset_nt_acl,
- .sys_acl_get_file_fn = gpfsacl_sys_acl_get_file,
.sys_acl_get_fd_fn = gpfsacl_sys_acl_get_fd,
- .sys_acl_blob_get_file_fn = gpfsacl_sys_acl_blob_get_file,
.sys_acl_blob_get_fd_fn = gpfsacl_sys_acl_blob_get_fd,
- .sys_acl_set_file_fn = gpfsacl_sys_acl_set_file,
.sys_acl_set_fd_fn = gpfsacl_sys_acl_set_fd,
- .sys_acl_delete_def_file_fn = gpfsacl_sys_acl_delete_def_file,
- .chmod_fn = vfs_gpfs_chmod,
+ .sys_acl_delete_def_fd_fn = gpfsacl_sys_acl_delete_def_fd,
.fchmod_fn = vfs_gpfs_fchmod,
.close_fn = vfs_gpfs_close,
- .stat_fn = vfs_gpfs_stat,
- .lstat_fn = vfs_gpfs_lstat,
- .ntimes_fn = vfs_gpfs_ntimes,
+ .stat_fn = nfs4_acl_stat,
+ .fstat_fn = nfs4_acl_fstat,
+ .lstat_fn = nfs4_acl_lstat,
+ .fstatat_fn = nfs4_acl_fstatat,
+ .fntimes_fn = vfs_gpfs_fntimes,
.aio_force_fn = vfs_gpfs_aio_force,
.sendfile_fn = vfs_gpfs_sendfile,
.fallocate_fn = vfs_gpfs_fallocate,
- .open_fn = vfs_gpfs_open,
+ .openat_fn = vfs_gpfs_openat,
.pread_fn = vfs_gpfs_pread,
.pread_send_fn = vfs_gpfs_pread_send,
.pread_recv_fn = vfs_gpfs_pread_recv,
static_decl_vfs;
NTSTATUS vfs_gpfs_init(TALLOC_CTX *ctx)
{
- int ret;
-
- ret = gpfswrap_init();
- if (ret != 0) {
- DEBUG(1, ("Could not initialize GPFS library wrapper\n"));
- }
-
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",
&vfs_gpfs_fns);
}