smbd: Fix a typo in a few places
[samba.git] / source3 / modules / vfs_cap.c
index 44a81bbcefb6d4a9a08197ee469cbb3637d5fbe5..3553e118cc2cfcd6fce559e8bbe45ba71ff56885 100644 (file)
@@ -46,6 +46,7 @@ static uint64_t cap_disk_free(vfs_handle_struct *handle,
                                        capname,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(capname);
@@ -73,6 +74,7 @@ static int cap_get_quota(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
@@ -82,34 +84,8 @@ static int cap_get_quota(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_GET_QUOTA(handle, cap_smb_fname, qtype, id, dq);
 }
 
-static DIR *cap_opendir(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       const char *mask,
-                       uint32_t attr)
-{
-       char *capname = capencode(talloc_tos(), smb_fname->base_name);
-       struct smb_filename *cap_smb_fname = NULL;
-
-       if (!capname) {
-               errno = ENOMEM;
-               return NULL;
-       }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       capname,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(capname);
-               errno = ENOMEM;
-               return NULL;
-       }
-       return SMB_VFS_NEXT_OPENDIR(handle, cap_smb_fname, mask, attr);
-}
-
-static struct dirent *cap_readdir(vfs_handle_struct *handle,
-                                     DIR *dirp,
-                                     SMB_STRUCT_STAT *sbuf)
+static struct dirent *
+cap_readdir(vfs_handle_struct *handle, struct files_struct *dirfsp, DIR *dirp)
 {
        struct dirent *result;
        struct dirent *newdirent;
@@ -117,7 +93,7 @@ static struct dirent *cap_readdir(vfs_handle_struct *handle,
        size_t newnamelen;
        DEBUG(3,("cap: cap_readdir\n"));
 
-       result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
+       result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp);
        if (!result) {
                return NULL;
        }
@@ -139,7 +115,8 @@ static struct dirent *cap_readdir(vfs_handle_struct *handle,
        return newdirent;
 }
 
-static int cap_mkdir(vfs_handle_struct *handle,
+static int cap_mkdirat(vfs_handle_struct *handle,
+               struct files_struct *dirfsp,
                const struct smb_filename *smb_fname,
                mode_t mode)
 {
@@ -155,6 +132,7 @@ static int cap_mkdir(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
@@ -162,84 +140,99 @@ static int cap_mkdir(vfs_handle_struct *handle,
                return -1;
        }
 
-       return SMB_VFS_NEXT_MKDIR(handle, cap_smb_fname, mode);
+       return SMB_VFS_NEXT_MKDIRAT(handle,
+                       dirfsp,
+                       cap_smb_fname,
+                       mode);
 }
 
-static int cap_rmdir(vfs_handle_struct *handle,
-               const struct smb_filename *smb_fname)
+static int cap_openat(vfs_handle_struct *handle,
+                     const struct files_struct *dirfsp,
+                     const struct smb_filename *smb_fname_in,
+                     files_struct *fsp,
+                     const struct vfs_open_how *how)
 {
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       struct smb_filename *cap_smb_fname = NULL;
+       char *cappath = NULL;
+       struct smb_filename *smb_fname = NULL;
+       int ret;
+       int saved_errno = 0;
 
-       if (!cappath) {
+       cappath = capencode(talloc_tos(), smb_fname_in->base_name);
+       if (cappath == NULL) {
                errno = ENOMEM;
                return -1;
        }
 
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
+       smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
+       if (smb_fname == NULL) {
                TALLOC_FREE(cappath);
                errno = ENOMEM;
                return -1;
        }
-
-       return SMB_VFS_NEXT_RMDIR(handle, cap_smb_fname);
-}
-
-static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
-                   files_struct *fsp, int flags, mode_t mode)
-{
-       char *cappath;
-       char *tmp_base_name = NULL;
-       int ret;
-
-       cappath = capencode(talloc_tos(), smb_fname->base_name);
-
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       tmp_base_name = smb_fname->base_name;
        smb_fname->base_name = cappath;
 
-       DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname)));
-       ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-
-       smb_fname->base_name = tmp_base_name;
+       DBG_DEBUG("cap_open for %s\n", smb_fname_str_dbg(smb_fname));
+       ret = SMB_VFS_NEXT_OPENAT(handle,
+                                 dirfsp,
+                                 smb_fname,
+                                 fsp,
+                                 how);
+       if (ret == -1) {
+               saved_errno = errno;
+       }
        TALLOC_FREE(cappath);
-
+       TALLOC_FREE(smb_fname);
+       if (saved_errno != 0) {
+               errno = saved_errno;
+       }
        return ret;
 }
 
-static int cap_rename(vfs_handle_struct *handle,
-                     const struct smb_filename *smb_fname_src,
-                     const struct smb_filename *smb_fname_dst)
+static int cap_renameat(vfs_handle_struct *handle,
+                       files_struct *srcfsp,
+                       const struct smb_filename *smb_fname_src,
+                       files_struct *dstfsp,
+                       const struct smb_filename *smb_fname_dst)
 {
        char *capold = NULL;
        char *capnew = NULL;
        struct smb_filename *smb_fname_src_tmp = NULL;
        struct smb_filename *smb_fname_dst_tmp = NULL;
+       struct smb_filename *full_fname_src = NULL;
+       struct smb_filename *full_fname_dst = NULL;
        int ret = -1;
+       int saved_errno = 0;
+
+       full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 srcfsp,
+                                                 smb_fname_src);
+       if (full_fname_src == NULL) {
+               errno = ENOMEM;
+               goto out;
+       }
+
+       full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dstfsp,
+                                                 smb_fname_dst);
+       if (full_fname_dst == NULL) {
+               errno = ENOMEM;
+               goto out;
+       }
 
-       capold = capencode(talloc_tos(), smb_fname_src->base_name);
-       capnew = capencode(talloc_tos(), smb_fname_dst->base_name);
+       capold = capencode(talloc_tos(), full_fname_src->base_name);
+       capnew = capencode(talloc_tos(), full_fname_dst->base_name);
        if (!capold || !capnew) {
                errno = ENOMEM;
                goto out;
        }
 
        /* Setup temporary smb_filename structs. */
-       smb_fname_src_tmp = cp_smb_filename(talloc_tos(), smb_fname_src);
+       smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
        if (smb_fname_src_tmp == NULL) {
                errno = ENOMEM;
                goto out;
        }
-       smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), smb_fname_dst);
+       smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
        if (smb_fname_dst_tmp == NULL) {
                errno = ENOMEM;
                goto out;
@@ -248,14 +241,29 @@ static int cap_rename(vfs_handle_struct *handle,
        smb_fname_src_tmp->base_name = capold;
        smb_fname_dst_tmp->base_name = capnew;
 
-       ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
-                                 smb_fname_dst_tmp);
+       ret = SMB_VFS_NEXT_RENAMEAT(handle,
+                               srcfsp->conn->cwd_fsp,
+                               smb_fname_src_tmp,
+                               dstfsp->conn->cwd_fsp,
+                               smb_fname_dst_tmp);
+
  out:
+
+       if (ret != 0) {
+               saved_errno = errno;
+       }
+
+       TALLOC_FREE(full_fname_src);
+       TALLOC_FREE(full_fname_dst);
        TALLOC_FREE(capold);
        TALLOC_FREE(capnew);
        TALLOC_FREE(smb_fname_src_tmp);
        TALLOC_FREE(smb_fname_dst_tmp);
 
+       if (ret != 0) {
+               errno = saved_errno;
+       }
+
        return ret;
 }
 
@@ -307,21 +315,33 @@ static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
        return ret;
 }
 
-static int cap_unlink(vfs_handle_struct *handle,
-                     const struct smb_filename *smb_fname)
+static int cap_unlinkat(vfs_handle_struct *handle,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       int flags)
 {
+       struct smb_filename *full_fname = NULL;
        struct smb_filename *smb_fname_tmp = NULL;
        char *cappath = NULL;
        int ret;
 
-       cappath = capencode(talloc_tos(), smb_fname->base_name);
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dirfsp,
+                                                 smb_fname);
+       if (full_fname == NULL) {
+               return -1;
+       }
+
+       cappath = capencode(talloc_tos(), full_fname->base_name);
        if (!cappath) {
+               TALLOC_FREE(full_fname);
                errno = ENOMEM;
                return -1;
        }
 
        /* Setup temporary smb_filename structs. */
-       smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
+       smb_fname_tmp = cp_smb_filename(talloc_tos(), full_fname);
+       TALLOC_FREE(full_fname);
        if (smb_fname_tmp == NULL) {
                errno = ENOMEM;
                return -1;
@@ -329,79 +349,15 @@ static int cap_unlink(vfs_handle_struct *handle,
 
        smb_fname_tmp->base_name = cappath;
 
-       ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
+       ret = SMB_VFS_NEXT_UNLINKAT(handle,
+                       dirfsp->conn->cwd_fsp,
+                       smb_fname_tmp,
+                       flags);
 
        TALLOC_FREE(smb_fname_tmp);
        return ret;
 }
 
-static int cap_chmod(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       mode_t mode)
-{
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       int ret;
-       int saved_errno;
-
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-
-       ret = SMB_VFS_NEXT_CHMOD(handle, cap_smb_fname, mode);
-       saved_errno = errno;
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(cap_smb_fname);
-       errno = saved_errno;
-       return ret;
-}
-
-static int cap_chown(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       uid_t uid,
-                       gid_t gid)
-{
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       int ret;
-       int saved_errno;
-
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-
-       ret = SMB_VFS_NEXT_CHOWN(handle, cap_smb_fname, uid, gid);
-       saved_errno = errno;
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(cap_smb_fname);
-       errno = saved_errno;
-       return ret;
-}
-
 static int cap_lchown(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        uid_t uid,
@@ -421,6 +377,7 @@ static int cap_lchown(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
@@ -454,6 +411,7 @@ static int cap_chdir(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
@@ -472,70 +430,77 @@ static int cap_chdir(vfs_handle_struct *handle,
        return ret;
 }
 
-static int cap_ntimes(vfs_handle_struct *handle,
-                     const struct smb_filename *smb_fname,
-                     struct smb_file_time *ft)
+static int cap_symlinkat(vfs_handle_struct *handle,
+                       const struct smb_filename *link_contents,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *new_smb_fname)
 {
-       struct smb_filename *smb_fname_tmp = NULL;
-       char *cappath = NULL;
+       struct smb_filename *full_fname = NULL;
+       char *capold = capencode(talloc_tos(), link_contents->base_name);
+       char *capnew = NULL;
+       struct smb_filename *new_link_target = NULL;
+       struct smb_filename *new_cap_smb_fname = NULL;
+       int saved_errno = 0;
        int ret;
 
-       cappath = capencode(talloc_tos(), smb_fname->base_name);
-
-       if (!cappath) {
+       if (capold == NULL) {
                errno = ENOMEM;
                return -1;
        }
 
-       /* Setup temporary smb_filename structs. */
-       smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
-       if (smb_fname_tmp == NULL) {
-               errno = ENOMEM;
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               dirfsp,
+                                               new_smb_fname);
+       if (full_fname == NULL) {
                return -1;
        }
 
-       smb_fname_tmp->base_name = cappath;
-
-       ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
-
-       TALLOC_FREE(smb_fname_tmp);
-       return ret;
-}
-
-
-static int cap_symlink(vfs_handle_struct *handle,
-                       const char *link_contents,
-                       const struct smb_filename *new_smb_fname)
-{
-       char *capold = capencode(talloc_tos(), link_contents);
-       char *capnew = capencode(talloc_tos(), new_smb_fname->base_name);
-       struct smb_filename *new_cap_smb_fname = NULL;
-       int saved_errno = 0;
-       int ret;
+       capnew = capencode(talloc_tos(), full_fname->base_name);
+       if (!capnew) {
+               TALLOC_FREE(full_fname);
+               errno = ENOMEM;
+               return -1;
+       }
 
-       if (!capold || !capnew) {
+       new_link_target = synthetic_smb_fname(talloc_tos(),
+                                             capold,
+                                             NULL,
+                                             NULL,
+                                             new_smb_fname->twrp,
+                                             new_smb_fname->flags);
+       if (new_link_target == NULL) {
+               TALLOC_FREE(full_fname);
+               TALLOC_FREE(capold);
+               TALLOC_FREE(capnew);
                errno = ENOMEM;
                return -1;
        }
+
        new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
                                        capnew,
                                        NULL,
                                        NULL,
+                                       new_smb_fname->twrp,
                                        new_smb_fname->flags);
        if (new_cap_smb_fname == NULL) {
+               TALLOC_FREE(full_fname);
                TALLOC_FREE(capold);
                TALLOC_FREE(capnew);
+               TALLOC_FREE(new_link_target);
                errno = ENOMEM;
                return -1;
        }
-       ret = SMB_VFS_NEXT_SYMLINK(handle,
-                       capold,
+       ret = SMB_VFS_NEXT_SYMLINKAT(handle,
+                       new_link_target,
+                       handle->conn->cwd_fsp,
                        new_cap_smb_fname);
        if (ret == -1) {
                saved_errno = errno;
        }
+       TALLOC_FREE(full_fname);
        TALLOC_FREE(capold);
        TALLOC_FREE(capnew);
+       TALLOC_FREE(new_link_target);
        TALLOC_FREE(new_cap_smb_fname);
        if (saved_errno != 0) {
                errno = saved_errno;
@@ -543,17 +508,28 @@ static int cap_symlink(vfs_handle_struct *handle,
        return ret;
 }
 
-static int cap_readlink(vfs_handle_struct *handle,
+static int cap_readlinkat(vfs_handle_struct *handle,
+                       const struct files_struct *dirfsp,
                        const struct smb_filename *smb_fname,
                        char *buf,
                        size_t bufsiz)
 {
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+       struct smb_filename *full_fname = NULL;
        struct smb_filename *cap_smb_fname = NULL;
+       char *cappath = NULL;
        int saved_errno = 0;
        int ret;
 
-       if (!cappath) {
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               dirfsp,
+                                               smb_fname);
+       if (full_fname == NULL) {
+               return -1;
+       }
+
+       cappath = capencode(talloc_tos(), full_fname->base_name);
+       if (cappath == NULL) {
+               TALLOC_FREE(full_fname);
                errno = ENOMEM;
                return -1;
        }
@@ -561,16 +537,23 @@ static int cap_readlink(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
+               TALLOC_FREE(full_fname);
                TALLOC_FREE(cappath);
                errno = ENOMEM;
                return -1;
        }
-       ret = SMB_VFS_NEXT_READLINK(handle, cap_smb_fname, buf, bufsiz);
+       ret = SMB_VFS_NEXT_READLINKAT(handle,
+                       handle->conn->cwd_fsp,
+                       cap_smb_fname,
+                       buf,
+                       bufsiz);
        if (ret == -1) {
                saved_errno = errno;
        }
+       TALLOC_FREE(full_fname);
        TALLOC_FREE(cappath);
        TALLOC_FREE(cap_smb_fname);
        if (saved_errno != 0) {
@@ -579,48 +562,77 @@ static int cap_readlink(vfs_handle_struct *handle,
        return ret;
 }
 
-static int cap_link(vfs_handle_struct *handle,
-                       const struct smb_filename *old_smb_fname,
-                       const struct smb_filename *new_smb_fname)
+static int cap_linkat(vfs_handle_struct *handle,
+               files_struct *srcfsp,
+               const struct smb_filename *old_smb_fname,
+               files_struct *dstfsp,
+               const struct smb_filename *new_smb_fname,
+               int flags)
 {
-       char *capold = capencode(talloc_tos(), old_smb_fname->base_name);
-       char *capnew = capencode(talloc_tos(), new_smb_fname->base_name);
+       struct smb_filename *old_full_fname = NULL;
+       struct smb_filename *new_full_fname = NULL;
+       char *capold = NULL;
+       char *capnew = NULL;
        struct smb_filename *old_cap_smb_fname = NULL;
        struct smb_filename *new_cap_smb_fname = NULL;
        int saved_errno = 0;
        int ret;
 
-       if (!capold || !capnew) {
-               errno = ENOMEM;
-               return -1;
-       }
+       /* Process 'old' name. */
+       old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               srcfsp,
+                                               old_smb_fname);
+        if (old_full_fname == NULL) {
+               goto nomem_out;
+        }
+       capold = capencode(talloc_tos(), old_full_fname->base_name);
+       if (capold == NULL) {
+               goto nomem_out;
+       }
+       TALLOC_FREE(old_full_fname);
        old_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
                                        capold,
                                        NULL,
                                        NULL,
+                                       old_smb_fname->twrp,
                                        old_smb_fname->flags);
        if (old_cap_smb_fname == NULL) {
-               TALLOC_FREE(capold);
-               TALLOC_FREE(capnew);
-               errno = ENOMEM;
-               return -1;
+               goto nomem_out;
        }
+
+       /* Process 'new' name. */
+       new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               dstfsp,
+                                               new_smb_fname);
+        if (new_full_fname == NULL) {
+               goto nomem_out;
+        }
+       capnew = capencode(talloc_tos(), new_full_fname->base_name);
+       if (capnew == NULL) {
+               goto nomem_out;
+       }
+       TALLOC_FREE(new_full_fname);
        new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
                                        capnew,
                                        NULL,
                                        NULL,
+                                       new_smb_fname->twrp,
                                        new_smb_fname->flags);
        if (new_cap_smb_fname == NULL) {
-               TALLOC_FREE(capold);
-               TALLOC_FREE(capnew);
-               TALLOC_FREE(old_cap_smb_fname);
-               errno = ENOMEM;
-               return -1;
+               goto nomem_out;
        }
-       ret = SMB_VFS_NEXT_LINK(handle, old_cap_smb_fname, new_cap_smb_fname);
+
+       ret = SMB_VFS_NEXT_LINKAT(handle,
+                       handle->conn->cwd_fsp,
+                       old_cap_smb_fname,
+                       handle->conn->cwd_fsp,
+                       new_cap_smb_fname,
+                       flags);
        if (ret == -1) {
                saved_errno = errno;
        }
+       TALLOC_FREE(old_full_fname);
+       TALLOC_FREE(old_full_fname);
        TALLOC_FREE(capold);
        TALLOC_FREE(capnew);
        TALLOC_FREE(old_cap_smb_fname);
@@ -629,19 +641,41 @@ static int cap_link(vfs_handle_struct *handle,
                errno = saved_errno;
        }
        return ret;
+
+  nomem_out:
+
+       TALLOC_FREE(old_full_fname);
+       TALLOC_FREE(old_full_fname);
+       TALLOC_FREE(capold);
+       TALLOC_FREE(capnew);
+       TALLOC_FREE(old_cap_smb_fname);
+       TALLOC_FREE(new_cap_smb_fname);
+       errno = ENOMEM;
+       return -1;
 }
 
-static int cap_mknod(vfs_handle_struct *handle,
+static int cap_mknodat(vfs_handle_struct *handle,
+               files_struct *dirfsp,
                const struct smb_filename *smb_fname,
                mode_t mode,
                SMB_DEV_T dev)
 {
+       struct smb_filename *full_fname = NULL;
        struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+       char *cappath = NULL;
        int ret;
        int saved_errno = 0;
 
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               dirfsp,
+                                               smb_fname);
+        if (full_fname == NULL) {
+                return -1;
+        }
+
+       cappath = capencode(talloc_tos(), full_fname->base_name);
        if (!cappath) {
+               TALLOC_FREE(full_fname);
                errno = ENOMEM;
                return -1;
        }
@@ -649,16 +683,23 @@ static int cap_mknod(vfs_handle_struct *handle,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
+               TALLOC_FREE(full_fname);
                TALLOC_FREE(cappath);
                errno = ENOMEM;
                return -1;
        }
-       ret = SMB_VFS_NEXT_MKNOD(handle, cap_smb_fname, mode, dev);
+       ret = SMB_VFS_NEXT_MKNODAT(handle,
+                       handle->conn->cwd_fsp,
+                       cap_smb_fname,
+                       mode,
+                       dev);
        if (ret == -1) {
                saved_errno = errno;
        }
+       TALLOC_FREE(full_fname);
        TALLOC_FREE(cappath);
        TALLOC_FREE(cap_smb_fname);
        if (saved_errno != 0) {
@@ -667,78 +708,33 @@ static int cap_mknod(vfs_handle_struct *handle,
        return ret;
 }
 
-static char *cap_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
+                       TALLOC_CTX *ctx,
+                       const struct smb_filename *smb_fname)
 {
         /* monyo need capencode'ed and capdecode'ed? */
-       char *cappath = capencode(talloc_tos(), path);
-
-       if (!cappath) {
-               errno = ENOMEM;
-               return NULL;
-       }
-       return SMB_VFS_NEXT_REALPATH(handle, cappath);
-}
-
-static int cap_chmod_acl(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       mode_t mode)
-{
        struct smb_filename *cap_smb_fname = NULL;
+       struct smb_filename *return_fname = NULL;
        char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       int ret;
-       int saved_errno;
-
-       /* If the underlying VFS doesn't have ACL support... */
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
-       }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-
-       ret = SMB_VFS_NEXT_CHMOD_ACL(handle, cap_smb_fname, mode);
-       saved_errno = errno;
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(cap_smb_fname);
-       errno = saved_errno;
-       return ret;
-}
-
-static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               SMB_ACL_TYPE_T type,
-                               TALLOC_CTX *mem_ctx)
-{
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       SMB_ACL_T ret;
        int saved_errno = 0;
 
        if (!cappath) {
                errno = ENOMEM;
-               return (SMB_ACL_T)NULL;
+               return NULL;
        }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
+       cap_smb_fname = synthetic_smb_fname(ctx,
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
                errno = ENOMEM;
-               return (SMB_ACL_T)NULL;
+               return NULL;
        }
-       ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cap_smb_fname,
-                               type, mem_ctx);
-       if (ret == NULL) {
+       return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
+       if (return_fname == NULL) {
                saved_errno = errno;
        }
        TALLOC_FREE(cappath);
@@ -746,122 +742,32 @@ static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle,
        if (saved_errno != 0) {
                errno = saved_errno;
        }
-       return ret;
+       return return_fname;
 }
 
-static int cap_sys_acl_set_file(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       SMB_ACL_TYPE_T acltype,
-                       SMB_ACL_T theacl)
+static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
 {
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       int ret;
-       int saved_errno = 0;
+       char *cappath = capencode(talloc_tos(), path);
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-       ret =  SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cap_smb_fname,
-                               acltype, theacl);
-       if (ret == -1) {
-               saved_errno = errno;
-       }
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(cap_smb_fname);
-       if (saved_errno != 0) {
-               errno = saved_errno;
-       }
-       return ret;
+        return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
 }
 
-static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname)
+static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
 {
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       int ret;
-       int saved_errno = 0;
+       char *cappath = capencode(talloc_tos(), path);
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cap_smb_fname);
-       if (ret == -1) {
-               saved_errno = errno;
-       }
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(cap_smb_fname);
-       if (saved_errno) {
-               errno = saved_errno;
-       }
-       return ret;
-}
-
-static ssize_t cap_getxattr(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       const char *name,
-                       void *value,
-                       size_t size)
-{
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       char *capname = capencode(talloc_tos(), name);
-       ssize_t ret;
-       int saved_errno = 0;
-
-       if (!cappath || !capname) {
-               errno = ENOMEM;
-               return -1;
-       }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               TALLOC_FREE(capname);
-               errno = ENOMEM;
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_GETXATTR(handle, cap_smb_fname,
-                       capname, value, size);
-       if (ret == -1) {
-               saved_errno = errno;
-       }
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(capname);
-       TALLOC_FREE(cap_smb_fname);
-       if (saved_errno) {
-               errno = saved_errno;
-       }
-       return ret;
+        return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
 }
 
-static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
+static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
 {
        char *cappath = capencode(talloc_tos(), path);
 
@@ -869,183 +775,122 @@ static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp
                errno = ENOMEM;
                return -1;
        }
-        return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
+        return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
 }
 
-static ssize_t cap_listxattr(vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               char *list,
-                               size_t size)
+static NTSTATUS cap_create_dfs_pathat(vfs_handle_struct *handle,
+                       files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       const struct referral *reflist,
+                       size_t referral_count)
 {
-       struct smb_filename *cap_smb_fname = NULL;
        char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       ssize_t ret;
-       int saved_errno = 0;
+       struct smb_filename *cap_smb_fname = NULL;
+       NTSTATUS status;
 
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
+       if (cappath == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
        cap_smb_fname = synthetic_smb_fname(talloc_tos(),
                                        cappath,
                                        NULL,
                                        NULL,
+                                       smb_fname->twrp,
                                        smb_fname->flags);
        if (cap_smb_fname == NULL) {
                TALLOC_FREE(cappath);
-               errno = ENOMEM;
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_LISTXATTR(handle, cap_smb_fname, list, size);
-       if (ret == -1) {
-               saved_errno = errno;
+               return NT_STATUS_NO_MEMORY;
        }
+       status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
+                       dirfsp,
+                       cap_smb_fname,
+                       reflist,
+                       referral_count);
        TALLOC_FREE(cappath);
        TALLOC_FREE(cap_smb_fname);
-       if (saved_errno) {
-               errno = saved_errno;
-       }
-       return ret;
+       return status;
 }
 
-static int cap_removexattr(vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               const char *name)
+static NTSTATUS cap_read_dfs_pathat(struct vfs_handle_struct *handle,
+                       TALLOC_CTX *mem_ctx,
+                       struct files_struct *dirfsp,
+                       struct smb_filename *smb_fname,
+                       struct referral **ppreflist,
+                       size_t *preferral_count)
 {
+       struct smb_filename *full_fname = NULL;
        struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       char *capname = capencode(talloc_tos(), name);
-       int ret;
-       int saved_errno = 0;
+       char *cappath = NULL;
+       NTSTATUS status;
 
-       if (!cappath || !capname) {
-               errno = ENOMEM;
-               return -1;
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                               dirfsp,
+                                               smb_fname);
+       if (full_fname == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       cappath = capencode(talloc_tos(), full_fname->base_name);
+       if (cappath == NULL) {
+               TALLOC_FREE(full_fname);
+               return NT_STATUS_NO_MEMORY;
        }
        cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
+                               cappath,
+                               NULL,
+                               NULL,
+                               smb_fname->twrp,
+                               smb_fname->flags);
        if (cap_smb_fname == NULL) {
+               TALLOC_FREE(full_fname);
                TALLOC_FREE(cappath);
-               TALLOC_FREE(capname);
-               errno = ENOMEM;
-               return -1;
-       }
-        ret = SMB_VFS_NEXT_REMOVEXATTR(handle, cap_smb_fname, capname);
-       if (ret == -1) {
-               saved_errno = errno;
+               return NT_STATUS_NO_MEMORY;
        }
-       TALLOC_FREE(cappath);
-       TALLOC_FREE(capname);
-       TALLOC_FREE(cap_smb_fname);
-       if (saved_errno) {
-               errno = saved_errno;
-       }
-       return ret;
-}
 
-static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
-{
-       char *cappath = capencode(talloc_tos(), path);
+       status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
+                       mem_ctx,
+                       handle->conn->cwd_fsp,
+                       cap_smb_fname,
+                       ppreflist,
+                       preferral_count);
 
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
+       if (NT_STATUS_IS_OK(status)) {
+               /* Return any stat(2) info. */
+               smb_fname->st = cap_smb_fname->st;
        }
-        return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
-}
 
-static int cap_setxattr(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       const char *name,
-                       const void *value,
-                       size_t size,
-                       int flags)
-{
-       struct smb_filename *cap_smb_fname = NULL;
-       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
-       char *capname = capencode(talloc_tos(), name);
-       int ret;
-       int saved_errno = 0;
-
-       if (!cappath || !capname) {
-               errno = ENOMEM;
-               return -1;
-       }
-       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
-                                       cappath,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-       if (cap_smb_fname == NULL) {
-               TALLOC_FREE(cappath);
-               TALLOC_FREE(capname);
-               errno = ENOMEM;
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_SETXATTR(handle, cap_smb_fname,
-                               capname, value, size, flags);
-       if (ret == -1) {
-               saved_errno = errno;
-       }
+       TALLOC_FREE(full_fname);
        TALLOC_FREE(cappath);
-       TALLOC_FREE(capname);
        TALLOC_FREE(cap_smb_fname);
-       if (saved_errno) {
-               errno = saved_errno;
-       }
-       return ret;
-}
-
-static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
-{
-       char *cappath = capencode(talloc_tos(), path);
-
-       if (!cappath) {
-               errno = ENOMEM;
-               return -1;
-       }
-        return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
+       return status;
 }
 
 static struct vfs_fn_pointers vfs_cap_fns = {
        .disk_free_fn = cap_disk_free,
        .get_quota_fn = cap_get_quota,
-       .opendir_fn = cap_opendir,
        .readdir_fn = cap_readdir,
-       .mkdir_fn = cap_mkdir,
-       .rmdir_fn = cap_rmdir,
-       .open_fn = cap_open,
-       .rename_fn = cap_rename,
+       .mkdirat_fn = cap_mkdirat,
+       .openat_fn = cap_openat,
+       .renameat_fn = cap_renameat,
        .stat_fn = cap_stat,
        .lstat_fn = cap_lstat,
-       .unlink_fn = cap_unlink,
-       .chmod_fn = cap_chmod,
-       .chown_fn = cap_chown,
+       .unlinkat_fn = cap_unlinkat,
        .lchown_fn = cap_lchown,
        .chdir_fn = cap_chdir,
-       .ntimes_fn = cap_ntimes,
-       .symlink_fn = cap_symlink,
-       .readlink_fn = cap_readlink,
-       .link_fn = cap_link,
-       .mknod_fn = cap_mknod,
+       .symlinkat_fn = cap_symlinkat,
+       .readlinkat_fn = cap_readlinkat,
+       .linkat_fn = cap_linkat,
+       .mknodat_fn = cap_mknodat,
        .realpath_fn = cap_realpath,
-       .chmod_acl_fn = cap_chmod_acl,
-       .sys_acl_get_file_fn = cap_sys_acl_get_file,
-       .sys_acl_set_file_fn = cap_sys_acl_set_file,
-       .sys_acl_delete_def_file_fn = cap_sys_acl_delete_def_file,
-       .getxattr_fn = cap_getxattr,
+       .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
+       .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
        .fgetxattr_fn = cap_fgetxattr,
-       .listxattr_fn = cap_listxattr,
-       .removexattr_fn = cap_removexattr,
        .fremovexattr_fn = cap_fremovexattr,
-       .setxattr_fn = cap_setxattr,
-       .fsetxattr_fn = cap_fsetxattr
+       .fsetxattr_fn = cap_fsetxattr,
+       .create_dfs_pathat_fn = cap_create_dfs_pathat,
+       .read_dfs_pathat_fn = cap_read_dfs_pathat
 };
 
-NTSTATUS vfs_cap_init(TALLOC_CTX *);
+static_decl_vfs;
 NTSTATUS vfs_cap_init(TALLOC_CTX *ctx)
 {
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",