vfs: remove SMB_VFS_OPEN()
[amitay/samba.git] / source3 / modules / vfs_streams_xattr.c
index 580ecd0e5fff1044ec8cd0e109e7710b3b40bd58..2e4105fec496ee76d79e8135f694fb20f28b6f08 100644 (file)
@@ -24,9 +24,9 @@
 #include "includes.h"
 #include "smbd/smbd.h"
 #include "system/filesys.h"
-#include "../lib/crypto/md5.h"
 #include "lib/util/tevent_unix.h"
 #include "librpc/gen_ndr/ioctl.h"
+#include "hash_inode.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -45,39 +45,6 @@ struct stream_io {
        vfs_handle_struct *handle;
 };
 
-static SMB_INO_T stream_inode(const SMB_STRUCT_STAT *sbuf, const char *sname)
-{
-       MD5_CTX ctx;
-        unsigned char hash[16];
-       SMB_INO_T result;
-       char *upper_sname;
-
-       DEBUG(10, ("stream_inode called for %lu/%lu [%s]\n",
-                  (unsigned long)sbuf->st_ex_dev,
-                  (unsigned long)sbuf->st_ex_ino, sname));
-
-       upper_sname = talloc_strdup_upper(talloc_tos(), sname);
-       SMB_ASSERT(upper_sname != NULL);
-
-        MD5Init(&ctx);
-        MD5Update(&ctx, (const unsigned char *)&(sbuf->st_ex_dev),
-                 sizeof(sbuf->st_ex_dev));
-        MD5Update(&ctx, (const unsigned char *)&(sbuf->st_ex_ino),
-                 sizeof(sbuf->st_ex_ino));
-        MD5Update(&ctx, (unsigned char *)upper_sname,
-                 talloc_get_size(upper_sname)-1);
-        MD5Final(hash, &ctx);
-
-       TALLOC_FREE(upper_sname);
-
-        /* Hopefully all the variation is in the lower 4 (or 8) bytes! */
-       memcpy(&result, hash, sizeof(result));
-
-       DEBUG(10, ("stream_inode returns %lu\n", (unsigned long)result));
-
-       return result;
-}
-
 static ssize_t get_xattr_size(connection_struct *conn,
                                const struct smb_filename *smb_fname,
                                const char *xattr_name)
@@ -190,16 +157,21 @@ static bool streams_xattr_recheck(struct stream_io *sio)
        TALLOC_FREE(sio->base);
        sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp),
                                        xattr_name);
-        sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp),
-                                  sio->fsp->fsp_name->base_name);
-       sio->fsp_name_ptr = sio->fsp->fsp_name;
-
+       if (sio->xattr_name == NULL) {
+               DBG_DEBUG("sio->xattr_name==NULL\n");
+               return false;
+       }
        TALLOC_FREE(xattr_name);
 
-       if ((sio->xattr_name == NULL) || (sio->base == NULL)) {
+       sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp),
+                                 sio->fsp->fsp_name->base_name);
+       if (sio->base == NULL) {
+               DBG_DEBUG("sio->base==NULL\n");
                return false;
        }
 
+       sio->fsp_name_ptr = sio->fsp->fsp_name;
+
        return true;
 }
 
@@ -247,6 +219,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
                                        io->base,
                                        NULL,
                                        NULL,
+                                       fsp->fsp_name->twrp,
                                        fsp->fsp_name->flags);
        if (smb_fname_base == NULL) {
                errno = ENOMEM;
@@ -275,8 +248,9 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
 
        DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size));
 
-       sbuf->st_ex_ino = stream_inode(sbuf, io->xattr_name);
+       sbuf->st_ex_ino = hash_inode(sbuf, io->xattr_name);
        sbuf->st_ex_mode &= ~S_IFMT;
+       sbuf->st_ex_mode &= ~S_IFDIR;
         sbuf->st_ex_mode |= S_IFREG;
         sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
 
@@ -291,20 +265,15 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
        int result = -1;
        char *xattr_name = NULL;
 
-       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+       if (!is_named_stream(smb_fname)) {
                return SMB_VFS_NEXT_STAT(handle, smb_fname);
        }
 
        /* Note if lp_posix_paths() is true, we can never
-        * get here as is_ntfs_stream_smb_fname() is
+        * get here as is_named_stream() is
         * always false. So we never need worry about
         * not following links here. */
 
-       /* If the default stream is requested, just stat the base file. */
-       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
-               return streams_xattr_stat_base(handle, smb_fname, true);
-       }
-
        /* Populate the stat struct with info from the base file. */
        if (streams_xattr_stat_base(handle, smb_fname, true) == -1) {
                return -1;
@@ -329,8 +298,9 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
                goto fail;
        }
 
-       smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name);
+       smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, xattr_name);
        smb_fname->st.st_ex_mode &= ~S_IFMT;
+       smb_fname->st.st_ex_mode &= ~S_IFDIR;
         smb_fname->st.st_ex_mode |= S_IFREG;
         smb_fname->st.st_ex_blocks =
            smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
@@ -348,15 +318,10 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
        int result = -1;
        char *xattr_name = NULL;
 
-       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+       if (!is_named_stream(smb_fname)) {
                return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        }
 
-       /* If the default stream is requested, just stat the base file. */
-       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
-               return streams_xattr_stat_base(handle, smb_fname, false);
-       }
-
        /* Populate the stat struct with info from the base file. */
        if (streams_xattr_stat_base(handle, smb_fname, false) == -1) {
                return -1;
@@ -381,7 +346,7 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
                goto fail;
        }
 
-       smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name);
+       smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, xattr_name);
        smb_fname->st.st_ex_mode &= ~S_IFMT;
         smb_fname->st.st_ex_mode |= S_IFREG;
         smb_fname->st.st_ex_blocks =
@@ -394,9 +359,12 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
        return result;
 }
 
-static int streams_xattr_open(vfs_handle_struct *handle,
-                             struct smb_filename *smb_fname,
-                             files_struct *fsp, int flags, mode_t mode)
+static int streams_xattr_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)
 {
        NTSTATUS status;
        struct streams_xattr_config *config = NULL;
@@ -405,30 +373,27 @@ static int streams_xattr_open(vfs_handle_struct *handle,
        char *xattr_name = NULL;
        int pipe_fds[2];
        int fakefd = -1;
+       bool set_empty_xattr = false;
        int ret;
 
+       /*
+        * For now assert this, so the below SMB_VFS_SETXATTR() works.
+        */
+       SMB_ASSERT(dirfsp->fh->fd == AT_FDCWD);
+
        SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
                                return -1);
 
        DEBUG(10, ("streams_xattr_open called for %s with flags 0x%x\n",
                   smb_fname_str_dbg(smb_fname), flags));
 
-       if (!is_ntfs_stream_smb_fname(smb_fname)) {
-               return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-       }
-
-       /* If the default stream is requested, just open the base file. */
-       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
-               char *tmp_stream_name;
-
-               tmp_stream_name = smb_fname->stream_name;
-               smb_fname->stream_name = NULL;
-
-               ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-
-               smb_fname->stream_name = tmp_stream_name;
-
-               return ret;
+       if (!is_named_stream(smb_fname)) {
+               return SMB_VFS_NEXT_OPENAT(handle,
+                                          dirfsp,
+                                          smb_fname,
+                                          fsp,
+                                          flags,
+                                          mode);
        }
 
        status = streams_xattr_get_name(handle, talloc_tos(),
@@ -438,39 +403,37 @@ static int streams_xattr_open(vfs_handle_struct *handle,
                goto fail;
        }
 
-       /*
-        * Return a valid fd, but ensure any attempt to use it returns an error
-        * (EPIPE).
-        */
-       ret = pipe(pipe_fds);
-       if (ret != 0) {
-               goto fail;
-       }
-
-       close(pipe_fds[1]);
-       pipe_fds[1] = -1;
-       fakefd = pipe_fds[0];
-
        status = get_ea_value(talloc_tos(), handle->conn, NULL,
                              smb_fname, xattr_name, &ea);
 
        DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
 
-       if (!NT_STATUS_IS_OK(status)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-               /*
-                * The base file is not there. This is an error even if we got
-                * O_CREAT, the higher levels should have created the base
-                * file for us.
-                */
-               DEBUG(10, ("streams_xattr_open: base file %s not around, "
-                          "returning ENOENT\n", smb_fname->base_name));
-               errno = ENOENT;
-               goto fail;
+       if (!NT_STATUS_IS_OK(status)) {
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+                       /*
+                        * The base file is not there. This is an error even if
+                        * we got O_CREAT, the higher levels should have created
+                        * the base file for us.
+                        */
+                       DBG_DEBUG("streams_xattr_open: base file %s not around, "
+                                 "returning ENOENT\n", smb_fname->base_name);
+                       errno = ENOENT;
+                       goto fail;
+               }
+
+               if (!(flags & O_CREAT)) {
+                       errno = ENOATTR;
+                       goto fail;
+               }
+
+               set_empty_xattr = true;
+       }
+
+       if (flags & O_TRUNC) {
+               set_empty_xattr = true;
        }
 
-       if ((!NT_STATUS_IS_OK(status) && (flags & O_CREAT)) ||
-           (flags & O_TRUNC)) {
+       if (set_empty_xattr) {
                /*
                 * The attribute does not exist or needs to be truncated
                 */
@@ -493,6 +456,19 @@ static int streams_xattr_open(vfs_handle_struct *handle,
                }
        }
 
+       /*
+        * Return a valid fd, but ensure any attempt to use it returns an error
+        * (EPIPE).
+        */
+       ret = pipe(pipe_fds);
+       if (ret != 0) {
+               goto fail;
+       }
+
+       close(pipe_fds[1]);
+       pipe_fds[1] = -1;
+       fakefd = pipe_fds[0];
+
         sio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct stream_io, NULL);
         if (sio == NULL) {
                 errno = ENOMEM;
@@ -501,6 +477,11 @@ static int streams_xattr_open(vfs_handle_struct *handle,
 
         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
                                        xattr_name);
+       if (sio->xattr_name == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
        /*
         * so->base needs to be a copy of fsp->fsp_name->base_name,
         * making it identical to streams_xattr_recheck(). If the
@@ -510,15 +491,15 @@ static int streams_xattr_open(vfs_handle_struct *handle,
         */
         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
                                  fsp->fsp_name->base_name);
-       sio->fsp_name_ptr = fsp->fsp_name;
-       sio->handle = handle;
-       sio->fsp = fsp;
-
-       if ((sio->xattr_name == NULL) || (sio->base == NULL)) {
+       if (sio->base == NULL) {
                errno = ENOMEM;
                goto fail;
        }
 
+       sio->fsp_name_ptr = fsp->fsp_name;
+       sio->handle = handle;
+       sio->fsp = fsp;
+
        return fakefd;
 
  fail:
@@ -530,31 +511,41 @@ static int streams_xattr_open(vfs_handle_struct *handle,
        return -1;
 }
 
-static int streams_xattr_unlink(vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname)
+static int streams_xattr_close(vfs_handle_struct *handle,
+                              files_struct *fsp)
 {
-       NTSTATUS status;
-       int ret = -1;
-       char *xattr_name = NULL;
+       int ret;
+       int fd;
+
+       fd = fsp->fh->fd;
 
-       if (!is_ntfs_stream_smb_fname(smb_fname)) {
-               return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+       DBG_DEBUG("streams_xattr_close called [%s] fd [%d]\n",
+                       smb_fname_str_dbg(fsp->fsp_name), fd);
+
+       if (!is_named_stream(fsp->fsp_name)) {
+               return SMB_VFS_NEXT_CLOSE(handle, fsp);
        }
 
-       /* If the default stream is requested, just open the base file. */
-       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
-               struct smb_filename *smb_fname_base = NULL;
+       ret = close(fd);
+       fsp->fh->fd = -1;
 
-               smb_fname_base = cp_smb_filename(talloc_tos(), smb_fname);
-               if (smb_fname_base == NULL) {
-                       errno = ENOMEM;
-                       return -1;
-               }
+       return ret;
+}
 
-               ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_base);
+static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       int flags)
+{
+       NTSTATUS status;
+       int ret = -1;
+       char *xattr_name = NULL;
 
-               TALLOC_FREE(smb_fname_base);
-               return ret;
+       if (!is_named_stream(smb_fname)) {
+               return SMB_VFS_NEXT_UNLINKAT(handle,
+                                       dirfsp,
+                                       smb_fname,
+                                       flags);
        }
 
        status = streams_xattr_get_name(handle, talloc_tos(),
@@ -578,8 +569,30 @@ static int streams_xattr_unlink(vfs_handle_struct *handle,
        return ret;
 }
 
-static int streams_xattr_rename(vfs_handle_struct *handle,
+static int streams_xattr_unlinkat(vfs_handle_struct *handle,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       int flags)
+{
+       int ret;
+       if (flags & AT_REMOVEDIR) {
+               ret = SMB_VFS_NEXT_UNLINKAT(handle,
+                               dirfsp,
+                               smb_fname,
+                               flags);
+       } else {
+               ret = streams_xattr_unlink_internal(handle,
+                               dirfsp,
+                               smb_fname,
+                               flags);
+       }
+       return ret;
+}
+
+static int streams_xattr_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)
 {
        NTSTATUS status;
@@ -595,8 +608,11 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
        dst_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
 
        if (!src_is_stream && !dst_is_stream) {
-               return SMB_VFS_NEXT_RENAME(handle, smb_fname_src,
-                                          smb_fname_dst);
+               return SMB_VFS_NEXT_RENAMEAT(handle,
+                                       srcfsp,
+                                       smb_fname_src,
+                                       dstfsp,
+                                       smb_fname_dst);
        }
 
        /* For now don't allow renames from or to the default stream. */
@@ -937,6 +953,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
                                        sio->base,
                                        NULL,
                                        NULL,
+                                       fsp->fsp_name->twrp,
                                        fsp->fsp_name->flags);
        if (smb_fname_base == NULL) {
                errno = ENOMEM;
@@ -1007,6 +1024,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
                                        sio->base,
                                        NULL,
                                        NULL,
+                                       fsp->fsp_name->twrp,
                                        fsp->fsp_name->flags);
        if (smb_fname_base == NULL) {
                errno = ENOMEM;
@@ -1224,6 +1242,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
                                        sio->base,
                                        NULL,
                                        NULL,
+                                       fsp->fsp_name->twrp,
                                        fsp->fsp_name->flags);
        if (smb_fname_base == NULL) {
                errno = ENOMEM;
@@ -1321,18 +1340,6 @@ static int streams_xattr_fchmod(vfs_handle_struct *handle,
        return 0;
 }
 
-static int streams_xattr_fsync(vfs_handle_struct *handle, files_struct *fsp)
-{
-       struct stream_io *sio =
-               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
-       if (sio == NULL) {
-               return SMB_VFS_NEXT_FSYNC(handle, fsp);
-       }
-
-       return 0;
-}
-
 static ssize_t streams_xattr_fgetxattr(struct vfs_handle_struct *handle,
                                       struct files_struct *fsp,
                                       const char *name,
@@ -1400,20 +1407,6 @@ static int streams_xattr_fsetxattr(struct vfs_handle_struct *handle,
        return -1;
 }
 
-static int streams_xattr_fchmod_acl(vfs_handle_struct *handle,
-                                   files_struct *fsp,
-                                   mode_t mode)
-{
-       struct stream_io *sio =
-               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
-       if (sio == NULL) {
-               return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
-       }
-
-       return 0;
-}
-
 static SMB_ACL_T streams_xattr_sys_acl_get_fd(vfs_handle_struct *handle,
                                              files_struct *fsp,
                                              TALLOC_CTX *mem_ctx)
@@ -1477,8 +1470,12 @@ static NTSTATUS streams_xattr_fget_nt_acl(vfs_handle_struct *handle,
                                                mem_ctx, ppdesc);
        }
 
-       return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp->base_fsp->fsp_name,
-                                      security_info, mem_ctx, ppdesc);
+       return SMB_VFS_NEXT_GET_NT_ACL_AT(handle,
+                                       handle->conn->cwd_fsp,
+                                       fsp->base_fsp->fsp_name,
+                                       security_info,
+                                       mem_ctx,
+                                       ppdesc);
 }
 
 static NTSTATUS streams_xattr_fset_nt_acl(vfs_handle_struct *handle,
@@ -1609,7 +1606,7 @@ static bool streams_xattr_getlock(vfs_handle_struct *handle,
 
 static int streams_xattr_kernel_flock(vfs_handle_struct *handle,
                                      files_struct *fsp,
-                                     uint32_t share_mode,
+                                     uint32_t share_access,
                                      uint32_t access_mask)
 {
        struct stream_io *sio =
@@ -1617,7 +1614,7 @@ static int streams_xattr_kernel_flock(vfs_handle_struct *handle,
 
        if (sio == NULL) {
                return SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp,
-                                                share_mode, access_mask);
+                                                share_access, access_mask);
        }
 
        return 0;
@@ -1654,7 +1651,8 @@ static bool streams_xattr_strict_lock_check(struct vfs_handle_struct *handle,
 static struct vfs_fn_pointers vfs_streams_xattr_fns = {
        .fs_capabilities_fn = streams_xattr_fs_capabilities,
        .connect_fn = streams_xattr_connect,
-       .open_fn = streams_xattr_open,
+       .openat_fn = streams_xattr_openat,
+       .close_fn = streams_xattr_close,
        .stat_fn = streams_xattr_stat,
        .fstat_fn = streams_xattr_fstat,
        .lstat_fn = streams_xattr_lstat,
@@ -1664,8 +1662,8 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = {
        .pread_recv_fn = streams_xattr_pread_recv,
        .pwrite_send_fn = streams_xattr_pwrite_send,
        .pwrite_recv_fn = streams_xattr_pwrite_recv,
-       .unlink_fn = streams_xattr_unlink,
-       .rename_fn = streams_xattr_rename,
+       .unlinkat_fn = streams_xattr_unlinkat,
+       .renameat_fn = streams_xattr_renameat,
        .ftruncate_fn = streams_xattr_ftruncate,
        .fallocate_fn = streams_xattr_fallocate,
        .streaminfo_fn = streams_xattr_streaminfo,
@@ -1681,15 +1679,12 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = {
 
        .fchown_fn = streams_xattr_fchown,
        .fchmod_fn = streams_xattr_fchmod,
-       .fsync_fn = streams_xattr_fsync,
 
        .fgetxattr_fn = streams_xattr_fgetxattr,
        .flistxattr_fn = streams_xattr_flistxattr,
        .fremovexattr_fn = streams_xattr_fremovexattr,
        .fsetxattr_fn = streams_xattr_fsetxattr,
 
-       .fchmod_acl_fn = streams_xattr_fchmod_acl,
-
        .sys_acl_get_fd_fn = streams_xattr_sys_acl_get_fd,
        .sys_acl_blob_get_fd_fn = streams_xattr_sys_acl_blob_get_fd,
        .sys_acl_set_fd_fn = streams_xattr_sys_acl_set_fd,