#endif
int ret;
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
if (is_named_stream(smb_fname)) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
goto err;
}
}
- referral_len = readlinkat(fsp_get_io_fd(dirfsp),
+ referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
smb_fname->base_name,
link_target,
bufsize - 1);
goto err;
}
- ret = sys_lstat(smb_fname->base_name,
- &smb_fname->st,
- lp_fake_directory_create_times(SNUM(handle->conn)));
+ ret = sys_fstatat(fsp_get_pathref_fd(dirfsp),
+ smb_fname->base_name,
+ &smb_fname->st,
+ AT_SYMLINK_NOFOLLOW,
+ lp_fake_directory_create_times(SNUM(handle->conn)));
if (ret < 0) {
status = map_nt_error_from_unix(errno);
goto err;
SMB_STRUCT_STAT *sbuf)
{
struct dirent *result;
- bool do_stat = false;
bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
int flags = AT_SYMLINK_NOFOLLOW;
- struct stat st;
+ SMB_STRUCT_STAT st;
int ret;
START_PROFILE(syscall_readdir);
-#if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
- do_stat = true;
-#endif
-
result = readdir(dirp);
END_PROFILE(syscall_readdir);
*/
SET_STAT_INVALID(*sbuf);
- /* See if we can efficiently return this. */
- if (!do_stat) {
- return result;
- }
-
- ret = fstatat(dirfd(dirp),
+ ret = sys_fstatat(dirfd(dirp),
result->d_name,
&st,
- flags);
+ flags,
+ fake_ctime);
if (ret != 0) {
return result;
}
* as we don't know if they wanted the link info, or its
* target info.
*/
- if (S_ISLNK(st.st_mode) &&
+ if (S_ISLNK(st.st_ex_mode) &&
!(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
{
return result;
}
- init_stat_ex_from_stat(sbuf, &st, fake_ctime);
+ *sbuf = st;
return result;
}
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,
/**
* 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,
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 */
.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,
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(
return status;
}
+ *flags = 0;
+ *xferlen = 0;
token->length = state->token.length;
token->data = talloc_move(mem_ctx, &state->token.data);
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);
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;
}
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,
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,
}
while (state->remaining > 0) {
- nwritten = copy_file_range(fsp_get_pathref_fd(state->src_fsp),
+ nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
&state->src_off,
- fsp_get_pathref_fd(state->dst_fsp),
+ fsp_get_io_fd(state->dst_fsp),
&state->dst_off,
state->remaining,
0);
(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;
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,
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,
START_PROFILE(syscall_fntimes);
- if (is_named_stream(fsp->fsp_name)) {
+ if (fsp_is_alternate_stream(fsp)) {
errno = ENOENT;
goto out;
}
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,
{
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;
}
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,
Extended attribute operations.
*****************************************************************/
-static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *name,
- void *value,
- size_t size)
+static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ const char *name,
+ void *value,
+ size_t size)
{
- return getxattr(smb_fname->base_name, name, value, size);
+ int fd = fsp_get_pathref_fd(fsp);
+
+ if (!fsp->fsp_flags.is_pathref) {
+ return fgetxattr(fd, name, value, size);
+ }
+
+ if (fsp->fsp_flags.have_proc_fds) {
+ const char *p = NULL;
+ char buf[PATH_MAX];
+
+ p = sys_proc_fd_path(fd, buf, sizeof(buf));
+ if (p == NULL) {
+ return -1;
+ }
+
+ return getxattr(p, name, value, size);
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ return getxattr(fsp->fsp_name->base_name, name, value, size);
}
struct vfswrap_getxattrat_state {
struct tevent_context *ev;
+ struct vfs_handle_struct *handle;
files_struct *dir_fsp;
const struct smb_filename *smb_fname;
}
*state = (struct vfswrap_getxattrat_state) {
.ev = ev,
+ .handle = handle,
.dir_fsp = dir_fsp,
.smb_fname = smb_fname,
};
{
struct vfswrap_getxattrat_state *state = tevent_req_data(
req, struct vfswrap_getxattrat_state);
- char *path = NULL;
- char *tofree = NULL;
- char pathbuf[PATH_MAX+1];
- ssize_t pathlen;
- int err;
+ struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
- pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
- state->smb_fname->base_name,
- pathbuf,
- sizeof(pathbuf),
- &path,
- &tofree);
- if (pathlen == -1) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- state->xattr_size = getxattr(path,
- state->xattr_name,
- state->xattr_value,
- talloc_array_length(state->xattr_value));
- err = errno;
- TALLOC_FREE(tofree);
+ state->xattr_size = vfswrap_fgetxattr(state->handle,
+ fsp,
+ state->xattr_name,
+ state->xattr_value,
+ talloc_array_length(state->xattr_value));
if (state->xattr_size == -1) {
- tevent_req_error(req, err);
+ tevent_req_error(req, errno);
return;
}
struct timespec start_time;
struct timespec end_time;
int ret;
+ struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
PROFILE_TIMESTAMP(&start_time);
SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
goto end_profile;
}
- ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
- if (ret == -1) {
- state->xattr_size = -1;
- state->vfs_aio_state.error = errno;
- goto end_profile;
- }
-
- state->xattr_size = getxattr(state->name,
- state->xattr_name,
- state->xattr_value,
- talloc_array_length(state->xattr_value));
+ state->xattr_size = vfswrap_fgetxattr(state->handle,
+ fsp,
+ state->xattr_name,
+ state->xattr_value,
+ talloc_array_length(state->xattr_value));
if (state->xattr_size == -1) {
state->vfs_aio_state.error = errno;
}
return xattr_size;
}
-static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- const char *name,
- void *value,
- size_t size)
-{
- int fd = fsp_get_pathref_fd(fsp);
-
- if (!fsp->fsp_flags.is_pathref) {
- return fgetxattr(fd, name, value, size);
- }
-
- if (fsp->fsp_flags.have_proc_fds) {
- const char *p = NULL;
- char buf[PATH_MAX];
-
- p = sys_proc_fd_path(fd, buf, sizeof(buf));
- if (p == NULL) {
- return -1;
- }
-
- return getxattr(p, name, value, size);
- }
-
- /*
- * This is no longer a handle based call.
- */
- return getxattr(fsp->fsp_name->base_name, name, value, size);
-}
-
static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
{
int fd = fsp_get_pathref_fd(fsp);
.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,
.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,
.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,
.sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
/* EA operations. */
- .getxattr_fn = vfswrap_getxattr,
.getxattrat_send_fn = vfswrap_getxattrat_send,
.getxattrat_recv_fn = vfswrap_getxattrat_recv,
.fgetxattr_fn = vfswrap_fgetxattr,