vfs_streams_depot: implement SMB_VFS_OPENAT()
authorRalph Boehme <slow@samba.org>
Wed, 20 May 2020 21:07:20 +0000 (23:07 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 21 May 2020 20:38:33 +0000 (20:38 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_streams_depot.c

index e408cbdc492231c8d9f59bcf54b5801983e3479c..7a3402606d1514daa9de661967a59d12674a91b7 100644 (file)
@@ -661,6 +661,80 @@ static int streams_depot_open(vfs_handle_struct *handle,
        return ret;
 }
 
+static int streams_depot_openat(struct vfs_handle_struct *handle,
+                               const struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct files_struct *fsp,
+                               int flags,
+                               mode_t mode)
+{
+       struct smb_filename *smb_fname_stream = NULL;
+       struct smb_filename *smb_fname_base = NULL;
+       struct files_struct *fspcwd = NULL;
+       NTSTATUS status;
+       int ret = -1;
+
+       /*
+        * For now assert this so the below SMB_VFS_STAT() is ok.
+        */
+       SMB_ASSERT(dirfsp->fh->fd == AT_FDCWD);
+
+       if (!is_named_stream(smb_fname)) {
+               return SMB_VFS_NEXT_OPENAT(handle,
+                                          dirfsp,
+                                          smb_fname,
+                                          fsp,
+                                          flags,
+                                          mode);
+       }
+
+       /* Ensure the base file still exists. */
+       smb_fname_base = synthetic_smb_fname(talloc_tos(),
+                                       smb_fname->base_name,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->twrp,
+                                       smb_fname->flags);
+       if (smb_fname_base == NULL) {
+               ret = -1;
+               errno = ENOMEM;
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
+       if (ret == -1) {
+               goto done;
+       }
+
+       /* Determine the stream name, and then open it. */
+       status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
+               goto done;
+       }
+
+       status = vfs_at_fspcwd(talloc_tos(), handle->conn, &fspcwd);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_OPENAT(handle,
+                                 fspcwd,
+                                 smb_fname_stream,
+                                 fsp,
+                                 flags,
+                                 mode);
+
+ done:
+       TALLOC_FREE(smb_fname_stream);
+       TALLOC_FREE(smb_fname_base);
+       TALLOC_FREE(fspcwd);
+       return ret;
+}
+
 static int streams_depot_unlink_internal(vfs_handle_struct *handle,
                                struct files_struct *dirfsp,
                                const struct smb_filename *smb_fname,
@@ -1094,6 +1168,7 @@ static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle,
 static struct vfs_fn_pointers vfs_streams_depot_fns = {
        .fs_capabilities_fn = streams_depot_fs_capabilities,
        .open_fn = streams_depot_open,
+       .openat_fn = streams_depot_openat,
        .stat_fn = streams_depot_stat,
        .lstat_fn = streams_depot_lstat,
        .unlinkat_fn = streams_depot_unlinkat,