vfs: Add SMB_VFS_GET_REAL_FILENAME_AT
[bbaumbach/samba-autobuild/.git] / source3 / modules / vfs_default.c
index aa7dfe3192f8fcca88c198a9d448b8b4550d48ca..ca928ded260a002f95117eccd27b3c412c2167de 100644 (file)
@@ -1314,6 +1314,33 @@ static int vfswrap_lstat(vfs_handle_struct *handle,
        return result;
 }
 
+static int vfswrap_fstatat(
+       struct vfs_handle_struct *handle,
+       const struct files_struct *dirfsp,
+       const struct smb_filename *smb_fname,
+       SMB_STRUCT_STAT *sbuf,
+       int flags)
+{
+       int result = -1;
+
+       START_PROFILE(syscall_fstatat);
+
+       if (is_named_stream(smb_fname)) {
+               errno = ENOENT;
+               goto out;
+       }
+
+       result = sys_fstatat(
+               fsp_get_pathref_fd(dirfsp),
+               smb_fname->base_name,
+               sbuf,
+               flags,
+               lp_fake_directory_create_times(SNUM(handle->conn)));
+ out:
+       END_PROFILE(syscall_fstatat);
+       return result;
+}
+
 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
                                       const char *name,
                                       enum vfs_translate_direction direction,
@@ -1326,7 +1353,7 @@ static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
 /**
  * Return allocated parent directory and basename of path
  *
- * Note: if requesting name, it is returned as talloc child of the
+ * Note: if requesting atname, it is returned as talloc child of the
  * parent. Freeing the parent is thus sufficient to free both.
  */
 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
@@ -1340,12 +1367,11 @@ static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
        struct smb_filename *name = NULL;
        char *p = NULL;
 
-       parent = cp_smb_filename(frame, smb_fname_in);
+       parent = cp_smb_filename_nostream(frame, smb_fname_in);
        if (parent == NULL) {
                TALLOC_FREE(frame);
                return NT_STATUS_NO_MEMORY;
        }
-       TALLOC_FREE(parent->stream_name);
        SET_STAT_INVALID(parent->st);
 
        p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
@@ -1785,6 +1811,14 @@ static struct tevent_req *vfswrap_get_dos_attributes_send(
                .smb_fname = smb_fname,
        };
 
+       if (!lp_store_dos_attributes(SNUM(dir_fsp->conn))) {
+               DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
+                       "\"store dos attributes\" is disabled\n",
+                       dir_fsp->conn->connectpath);
+               tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+               return tevent_req_post(req, ev);
+       }
+
        subreq = SMB_VFS_GETXATTRAT_SEND(state,
                                         ev,
                                         dir_fsp,
@@ -1990,6 +2024,8 @@ static struct tevent_req *vfswrap_offload_read_send(
 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
                                          struct vfs_handle_struct *handle,
                                          TALLOC_CTX *mem_ctx,
+                                         uint32_t *flags,
+                                         uint64_t *xferlen,
                                          DATA_BLOB *token)
 {
        struct vfswrap_offload_read_state *state = tevent_req_data(
@@ -2001,6 +2037,8 @@ static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
                return status;
        }
 
+       *flags = 0;
+       *xferlen = 0;
        token->length = state->token.length;
        token->data = talloc_move(mem_ctx, &state->token.data);
 
@@ -2214,10 +2252,11 @@ static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
        NTSTATUS status;
        bool same_file;
        bool ok;
+       static bool try_copy_file_range = true;
 
-#ifndef USE_COPY_FILE_RANGE
-       return NT_STATUS_MORE_PROCESSING_REQUIRED;
-#endif
+       if (!try_copy_file_range) {
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
 
        same_file = file_id_equal(&state->src_fsp->file_id,
                                  &state->dst_fsp->file_id);
@@ -2230,8 +2269,8 @@ static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
                return NT_STATUS_MORE_PROCESSING_REQUIRED;
        }
 
-       if (is_named_stream(state->src_fsp->fsp_name) ||
-           is_named_stream(state->dst_fsp->fsp_name))
+       if (fsp_is_alternate_stream(state->src_fsp) ||
+           fsp_is_alternate_stream(state->dst_fsp))
        {
                return NT_STATUS_MORE_PROCESSING_REQUIRED;
        }
@@ -2241,6 +2280,7 @@ static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
                                state->src_off,
                                state->remaining,
                                READ_LOCK,
+                               lp_posix_cifsu_locktype(state->src_fsp),
                                &lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
@@ -2260,6 +2300,7 @@ static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
                                state->dst_off,
                                state->remaining,
                                WRITE_LOCK,
+                               lp_posix_cifsu_locktype(state->dst_fsp),
                                &lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
@@ -2286,6 +2327,11 @@ static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
                                  (intmax_t)state->remaining,
                                  strerror(errno));
                        switch (errno) {
+                       case EOPNOTSUPP:
+                       case ENOSYS:
+                               try_copy_file_range = false;
+                               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+                               break;
                        case EXDEV:
                                status = NT_STATUS_MORE_PROCESSING_REQUIRED;
                                break;
@@ -2349,6 +2395,7 @@ static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
                                state->src_off,
                                state->next_io_size,
                                READ_LOCK,
+                               lp_posix_cifsu_locktype(state->src_fsp),
                                &read_lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
@@ -2412,6 +2459,7 @@ static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
                                state->dst_off,
                                state->next_io_size,
                                WRITE_LOCK,
+                               lp_posix_cifsu_locktype(state->dst_fsp),
                                &write_lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
@@ -2748,7 +2796,7 @@ static int vfswrap_fntimes(vfs_handle_struct *handle,
 
        START_PROFILE(syscall_fntimes);
 
-       if (is_named_stream(fsp->fsp_name)) {
+       if (fsp_is_alternate_stream(fsp)) {
                errno = ENOENT;
                goto out;
        }
@@ -3009,13 +3057,13 @@ static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, o
        return result;
 }
 
-static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
-                               uint32_t share_access, uint32_t access_mask)
+static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
+                                       files_struct *fsp,
+                                       uint32_t share_access,
+                                       uint32_t access_mask)
 {
-       START_PROFILE(syscall_kernel_flock);
-       kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
-       END_PROFILE(syscall_kernel_flock);
-       return 0;
+       errno = ENOTSUP;
+       return -1;
 }
 
 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
@@ -3246,10 +3294,6 @@ static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
 {
        uint64_t file_id;
 
-       if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
-               return psbuf->st_ex_file_id;
-       }
-
        if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
                return (uint64_t)psbuf->st_ex_ino;
        }
@@ -3314,18 +3358,31 @@ static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
-static int vfswrap_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 vfswrap_get_real_filename(struct vfs_handle_struct *handle,
+                                         const struct smb_filename *path,
+                                         const char *name,
+                                         TALLOC_CTX *mem_ctx,
+                                         char **found_name)
 {
        /*
         * Don't fall back to get_real_filename so callers can differentiate
         * between a full directory scan and an actual case-insensitive stat.
         */
-       errno = EOPNOTSUPP;
-       return -1;
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_get_real_filename_at(
+       struct vfs_handle_struct *handle,
+       struct files_struct *dirfsp,
+       const char *name,
+       TALLOC_CTX *mem_ctx,
+       char **found_name)
+{
+       /*
+        * Don't fall back to get_real_filename so callers can differentiate
+        * between a full directory scan and an actual case-insensitive stat.
+        */
+       return NT_STATUS_NOT_SUPPORTED;
 }
 
 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
@@ -3609,11 +3666,7 @@ static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
 {
        struct vfswrap_getxattrat_state *state = tevent_req_data(
                req, struct vfswrap_getxattrat_state);
-       struct files_struct *fsp = state->smb_fname->fsp;
-
-       if (fsp->base_fsp != NULL) {
-               fsp = fsp->base_fsp;
-       }
+       struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
 
        state->xattr_size = vfswrap_fgetxattr(state->handle,
                                              fsp,
@@ -3636,11 +3689,7 @@ static void vfswrap_getxattrat_do_async(void *private_data)
        struct timespec start_time;
        struct timespec end_time;
        int ret;
-       struct files_struct *fsp = state->smb_fname->fsp;
-
-       if (fsp->base_fsp != NULL) {
-               fsp = fsp->base_fsp;
-       }
+       struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
 
        PROFILE_TIMESTAMP(&start_time);
        SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
@@ -3955,6 +4004,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .stat_fn = vfswrap_stat,
        .fstat_fn = vfswrap_fstat,
        .lstat_fn = vfswrap_lstat,
+       .fstatat_fn = vfswrap_fstatat,
        .get_alloc_size_fn = vfswrap_get_alloc_size,
        .unlinkat_fn = vfswrap_unlinkat,
        .fchmod_fn = vfswrap_fchmod,
@@ -3966,7 +4016,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .ftruncate_fn = vfswrap_ftruncate,
        .fallocate_fn = vfswrap_fallocate,
        .lock_fn = vfswrap_lock,
-       .kernel_flock_fn = vfswrap_kernel_flock,
+       .filesystem_sharemode_fn = vfswrap_filesystem_sharemode,
        .fcntl_fn = vfswrap_fcntl,
        .linux_setlease_fn = vfswrap_linux_setlease,
        .getlock_fn = vfswrap_getlock,
@@ -3980,6 +4030,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .fs_file_id_fn = vfswrap_fs_file_id,
        .fstreaminfo_fn = vfswrap_fstreaminfo,
        .get_real_filename_fn = vfswrap_get_real_filename,
+       .get_real_filename_at_fn = vfswrap_get_real_filename_at,
        .connectpath_fn = vfswrap_connectpath,
        .brl_lock_windows_fn = vfswrap_brl_lock_windows,
        .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,