smbd: Fix a typo in a few places
[samba.git] / source3 / modules / vfs_gpfs.c
index 004c74cd43ae11699bc3fb7b67b1b116f5e9ac86..a8b4e38ff88c00c61285258f92c4f4a67de152a2 100644 (file)
@@ -288,11 +288,11 @@ static int vfs_gpfs_setlease(vfs_handle_struct *handle,
 }
 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
 
-static NTSTATUS vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
-                                          const struct smb_filename *path,
-                                          const char *name,
-                                          TALLOC_CTX *mem_ctx,
-                                          char **found_name)
+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;
@@ -308,17 +308,17 @@ static NTSTATUS vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
                                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->base_name, name,
+       full_path_len = full_path_tos(dirfsp->fsp_name->base_name, name,
                                      tmpbuf, sizeof(tmpbuf),
                                      &full_path, &to_free);
        if (full_path_len == -1) {
@@ -333,8 +333,8 @@ static NTSTATUS vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
        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) {
@@ -354,8 +354,10 @@ static NTSTATUS vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
                real_pathname[sizeof(real_pathname)-1] = '\0';
        }
 
-       DEBUG(10, ("smbd_gpfs_get_realfilename_path: %s/%s -> %s\n",
-                  path->base_name, name, real_pathname));
+       DBG_DEBUG("%s/%s -> %s\n",
+                 fsp_str_dbg(dirfsp),
+                 name,
+                 real_pathname);
 
        name = strrchr_m(real_pathname, '/');
        if (name == NULL) {
@@ -421,13 +423,15 @@ static void gpfs_dumpacl(int level, 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(fname, flags, buf);
+       ret = gpfswrap_fgetacl(fsp_get_pathref_fd(fsp), flags, buf);
        saved_errno = errno;
 
        drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
@@ -446,11 +450,11 @@ static int gpfs_getacl_with_capability(const char *fname, int flags, void *buf)
  *
  */
 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;
@@ -486,13 +490,13 @@ again:
        *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(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);
                }
        }
 
@@ -527,15 +531,17 @@ again:
  * 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",
@@ -648,7 +654,7 @@ static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
                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,
@@ -827,7 +833,7 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_str
        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);
@@ -836,14 +842,6 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_str
        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);
@@ -946,17 +944,18 @@ static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl, TALLOC_CTX *mem_ctx)
        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;
                }
@@ -1017,8 +1016,7 @@ static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
                DEBUG(0, ("Got invalid type: %d\n", type));
                smb_panic("exiting");
        }
-       return gpfsacl_get_posix_acl(fsp->fsp_name->base_name,
-                                    gpfs_type, mem_ctx);
+       return gpfsacl_get_posix_acl(fsp, gpfs_type, mem_ctx);
 }
 
 static int gpfsacl_sys_acl_blob_get_fd(vfs_handle_struct *handle,
@@ -1043,7 +1041,7 @@ 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);
 
@@ -1261,9 +1259,11 @@ static uint32_t gpfsacl_mask_filter(uint32_t aceType, uint32_t aceMask, uint32_t
 }
 
 static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
-                            const struct smb_filename *fname, mode_t mode)
+                            struct files_struct *fsp,
+                            mode_t mode)
 {
-       char *path = fname->base_name;
+       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};
@@ -1274,7 +1274,7 @@ static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
 
        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;
@@ -1363,23 +1363,24 @@ static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
 
 static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
 {
-                SMB_STRUCT_STAT st;
-                int rc;
+       SMB_STRUCT_STAT st;
+       int rc;
 
-                if (SMB_VFS_NEXT_FSTAT(handle, fsp, &st) != 0) {
-                        return -1;
-                }
+       rc = SMB_VFS_NEXT_FSTAT(handle, fsp, &st);
+       if (rc != 0) {
+               return -1;
+       }
 
-                /* avoid chmod() if possible, to preserve acls */
-                if ((st.st_ex_mode & ~S_IFMT) == mode) {
-                        return 0;
-                }
+       /* 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,
-                                       mode);
-                if (rc == 1)
-                        return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
-                return rc;
+       rc = gpfsacl_emu_chmod(handle, fsp, 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)
@@ -1434,40 +1435,6 @@ static unsigned int vfs_gpfs_dosmode_to_winattrs(uint32_t dosmode)
        return winattrs;
 }
 
-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 };
@@ -1479,13 +1446,11 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
 {
        struct gpfs_config_data *config;
        int fd = fsp_get_pathref_fd(fsp);
-       char buf[PATH_MAX];
+       struct sys_proc_fd_path_buf buf;
        const char *p = NULL;
        struct gpfs_iattr64 iattr = { };
-       unsigned int litemask = GPFS_SLITE_EXACT_BITS;
+       unsigned int litemask = 0;
        struct timespec ts;
-       uint64_t file_id;
-       NTSTATUS status;
        int ret;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config,
@@ -1498,10 +1463,7 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
 
        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, sizeof(buf));
-                       if (p == NULL) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
+                       p = sys_proc_fd_path(fd, &buf);
                } else {
                        p = fsp->fsp_name->base_name;
                }
@@ -1556,17 +1518,10 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
                return map_nt_error_from_unix(errno);
        }
 
-       ZERO_STRUCT(file_id);
-       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;
 }
@@ -1602,20 +1557,17 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct vfs_handle_struct *handle,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
-
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
+               struct sys_proc_fd_path_buf buf;
 
-               ret = gpfswrap_set_winattrs_path(p,
+               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",
-                                   p, fsp_str_dbg(fsp), strerror(errno));
+                       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;
@@ -1636,86 +1588,27 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct vfs_handle_struct *handle,
        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)
 {
-       int fd = -1;
-       NTSTATUS status;
-       struct smb_filename *dir_name = NULL;
-       struct smb_filename *rel_name = NULL;
-       struct stat st;
-       int ret = -1;
-
-       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;
+       if (is_omit_timespec(&ts)) {
+               return 0;
        }
 
-       fd = open(dir_name->base_name, O_RDONLY, 0);
-       if (fd == -1) {
-               TALLOC_FREE(dir_name);
+       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->base_name, &st, flag);
-       drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
-
-       TALLOC_FREE(dir_name);
-       close(fd);
-
-       if (ret == 0) {
-               init_stat_ex_from_stat(
-                       &smb_fname->st, &st,
-                       lp_fake_directory_create_times(SNUM(handle->conn)));
-       }
-
-       return ret;
-}
-
-static int vfs_gpfs_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_capability(handle, smb_fname, 0);
-       }
-       return ret;
-}
-
-static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
-                         struct smb_filename *smb_fname)
-{
-       int ret;
+       *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);
 
-       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);
-       }
-       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));
-       }
+       return 0;
 }
 
 static int smbd_gpfs_set_times(struct files_struct *fsp,
@@ -1726,10 +1619,21 @@ static int smbd_gpfs_set_times(struct files_struct *fsp,
        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);
+       rc = timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
+       if (rc != 0) {
+               return rc;
+       }
+
+       rc = timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
+       if (rc != 0) {
+               return rc;
+       }
+
        /* No good mapping from LastChangeTime to ctime, not storing */
-       timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+       rc = timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+       if (rc != 0) {
+               return rc;
+       }
 
        if (!flags) {
                DBG_DEBUG("nothing to do, return to avoid EINVAL\n");
@@ -1748,18 +1652,16 @@ static int smbd_gpfs_set_times(struct files_struct *fsp,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
-
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return -1;
-               }
+               struct sys_proc_fd_path_buf buf;
 
-               rc = gpfswrap_set_times_path(buf, flags, gpfs_times);
+               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), p, strerror(errno));
+                                   fsp_str_dbg(fsp),
+                                   buf.buf,
+                                   strerror(errno));
                }
                return rc;
        }
@@ -1804,7 +1706,7 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct *handle,
        if (ret == -1) {
                /* don't complain if access was denied */
                if (errno != EPERM && errno != EACCES) {
-                       DBG_WARNING("SMB_VFS_NEXT_FNTIMES failed: %s",
+                       DBG_WARNING("SMB_VFS_NEXT_FNTIMES failed: %s\n",
                                    strerror(errno));
                }
                return -1;
@@ -1836,17 +1738,12 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct *handle,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
+               struct sys_proc_fd_path_buf buf;
 
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return -1;
-               }
-
-               ret = gpfswrap_set_winattrs_path(p,
-                                                GPFS_WINATTR_SET_CREATION_TIME,
-                                                &attrs);
+               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;
@@ -1912,7 +1809,7 @@ static int vfs_gpfs_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
 }
 
 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;
@@ -1927,17 +1824,17 @@ static bool vfs_gpfs_is_offline(struct vfs_handle_struct *handle,
                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;
 }
 
@@ -1951,7 +1848,7 @@ static bool vfs_gpfs_fsp_is_offline(struct vfs_handle_struct *handle,
                /*
                 * 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);
        }
 
@@ -1959,7 +1856,7 @@ static bool vfs_gpfs_fsp_is_offline(struct vfs_handle_struct *handle,
                /*
                 * 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);
        }
 
@@ -1988,7 +1885,7 @@ 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 = GPFS_SLITE_EXACT_BITS;
+       unsigned int litemask = 0;
        int saved_errno;
        int fd;
        int ret;
@@ -2061,7 +1958,24 @@ static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
                return 0;
        }
 
-       gpfswrap_lib_init(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) {
@@ -2366,9 +2280,9 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
                           const struct files_struct *dirfsp,
                           const struct smb_filename *smb_fname,
                           files_struct *fsp,
-                          int flags,
-                          mode_t mode)
+                          const struct vfs_open_how *_how)
 {
+       struct vfs_open_how how = *_how;
        struct gpfs_config_data *config = NULL;
        struct gpfs_fsp_extension *ext = NULL;
        int ret;
@@ -2378,6 +2292,7 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
                                return -1);
 
        if (config->hsm && !config->recalls &&
+           !fsp->fsp_flags.is_pathref &&
            vfs_gpfs_fsp_is_offline(handle, fsp))
        {
                DBG_DEBUG("Refusing access to offline file %s\n",
@@ -2387,7 +2302,7 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
        }
 
        if (config->syncio) {
-               flags |= O_SYNC;
+               how.flags |= O_SYNC;
        }
 
        ext = VFS_ADD_FSP_EXTENSION(handle, fsp, struct gpfs_fsp_extension,
@@ -2402,7 +2317,7 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
         */
        *ext = (struct gpfs_fsp_extension) { .offline = true };
 
-       ret = SMB_VFS_NEXT_OPENAT(handle, dirfsp, 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);
        }
@@ -2592,7 +2507,7 @@ static struct vfs_fn_pointers vfs_gpfs_fns = {
        .fs_capabilities_fn = vfs_gpfs_capabilities,
        .filesystem_sharemode_fn = vfs_gpfs_filesystem_sharemode,
        .linux_setlease_fn = vfs_gpfs_setlease,
-       .get_real_filename_fn = vfs_gpfs_get_real_filename,
+       .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,
@@ -2605,8 +2520,10 @@ static struct vfs_fn_pointers vfs_gpfs_fns = {
        .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,
+       .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,
@@ -2624,13 +2541,6 @@ static struct vfs_fn_pointers vfs_gpfs_fns = {
 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);
 }