#include "lib/pthreadpool/pthreadpool_tevent.h"
#include "librpc/gen_ndr/ndr_ioctl.h"
#include "offload_token.h"
+#include "util_reparse.h"
+#include "lib/util/string_wrappers.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
{
- return 0; /* Return >= 0 for success */
+ handle->conn->have_proc_fds = sys_have_proc_fds();
+ return 0; /* Return >= 0 for success */
}
static void vfswrap_disconnect(vfs_handle_struct *handle)
int ret;
char *msdfs_link = NULL;
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
/* Form the msdfs_link contents */
msdfs_link = msdfs_link_string(frame,
reflist,
}
ret = symlinkat(msdfs_link,
- dirfsp->fh->fd,
+ fsp_get_pathref_fd(dirfsp),
smb_fname->base_name);
if (ret == 0) {
status = NT_STATUS_OK;
static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct files_struct *dirfsp,
- const struct smb_filename *smb_fname,
+ struct smb_filename *smb_fname,
struct referral **ppreflist,
size_t *preferral_count)
{
#else
char link_target_buf[7];
#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;
+ }
if (ppreflist == NULL && preferral_count == NULL) {
/*
}
}
- referral_len = readlinkat(dirfsp->fh->fd,
+ referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
smb_fname->base_name,
link_target,
bufsize - 1);
status = NT_STATUS_OBJECT_TYPE_MISMATCH;
} else {
status = map_nt_error_from_unix(errno);
- DBG_ERR("Error reading "
- "msdfs link %s: %s\n",
- smb_fname->base_name,
- strerror(errno));
+ if (errno == ENOENT) {
+ DBG_NOTICE("Error reading "
+ "msdfs link %s: %s\n",
+ smb_fname->base_name,
+ strerror(errno));
+ } else {
+ DBG_ERR("Error reading "
+ "msdfs link %s: %s\n",
+ smb_fname->base_name,
+ strerror(errno));
+ }
}
goto err;
}
goto err;
}
+ 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;
+ }
+
if (ppreflist == NULL && preferral_count == NULL) {
/* Early return for checking if this is a DFS link. */
return NT_STATUS_OK;
DIR *result;
START_PROFILE(syscall_fdopendir);
- result = sys_fdopendir(fsp->fh->fd);
+ result = sys_fdopendir(fsp_get_io_fd(fsp));
END_PROFILE(syscall_fdopendir);
return result;
}
static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
- DIR *dirp,
- SMB_STRUCT_STAT *sbuf)
+ struct files_struct *dirfsp,
+ DIR *dirp,
+ SMB_STRUCT_STAT *sbuf)
{
struct dirent *result;
+ bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
+ int flags = AT_SYMLINK_NOFOLLOW;
+ SMB_STRUCT_STAT st;
+ int ret;
START_PROFILE(syscall_readdir);
+
result = readdir(dirp);
END_PROFILE(syscall_readdir);
- if (sbuf) {
- /* Default Posix readdir() does not give us stat info.
- * Set to invalid to indicate we didn't return this info. */
- SET_STAT_INVALID(*sbuf);
-#if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
- if (result != NULL) {
- /* See if we can efficiently return this. */
- struct stat st;
- int flags = AT_SYMLINK_NOFOLLOW;
- int ret = fstatat(dirfd(dirp),
- result->d_name,
- &st,
- flags);
- /*
- * As this is an optimization,
- * ignore it if we stat'ed a
- * symlink. Make the caller
- * do it again as we don't
- * know if they wanted the link
- * info, or its target info.
- */
- if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
- init_stat_ex_from_stat(sbuf,
- &st,
- lp_fake_directory_create_times(
- SNUM(handle->conn)));
- }
- }
-#endif
+
+ if (sbuf == NULL) {
+ return result;
+ }
+ if (result == NULL) {
+ return NULL;
}
+
+ /*
+ * Default Posix readdir() does not give us stat info.
+ * Set to invalid to indicate we didn't return this info.
+ */
+ SET_STAT_INVALID(*sbuf);
+
+ ret = sys_fstatat(dirfd(dirp),
+ result->d_name,
+ &st,
+ flags,
+ fake_ctime);
+ if (ret != 0) {
+ return result;
+ }
+
+ /*
+ * As this is an optimization, ignore it if we stat'ed a
+ * symlink for non-POSIX context. Make the caller do it again
+ * as we don't know if they wanted the link info, or its
+ * target info.
+ */
+ if (S_ISLNK(st.st_ex_mode) &&
+ !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
+ {
+ return result;
+ }
+ *sbuf = st;
+
return result;
}
-static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
- const struct smb_filename *fname,
- TALLOC_CTX *mem_ctx,
- struct readdir_attr_data **attr_data)
+static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ TALLOC_CTX *mem_ctx,
+ struct readdir_attr_data **attr_data)
{
return NT_STATUS_NOT_SUPPORTED;
}
mode_t mode)
{
int result;
- struct smb_filename *parent = NULL;
- bool ok;
START_PROFILE(syscall_mkdirat);
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
- if (lp_inherit_acls(SNUM(handle->conn))) {
- ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
- if (ok && directory_has_default_acl(handle->conn,
- dirfsp,
- parent))
- {
- mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
- }
- }
-
- TALLOC_FREE(parent);
-
- result = mkdirat(dirfsp->fh->fd, smb_fname->base_name, mode);
+ result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
END_PROFILE(syscall_mkdirat);
return result;
/* File operations */
-static int vfswrap_open(vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- files_struct *fsp, int flags, mode_t mode)
+static int vfswrap_openat(vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ files_struct *fsp,
+ int flags,
+ mode_t mode)
{
- int result = -1;
+ bool have_opath = false;
+ bool became_root = false;
+ int result;
- START_PROFILE(syscall_open);
+ START_PROFILE(syscall_openat);
if (is_named_stream(smb_fname)) {
errno = ENOENT;
+ result = -1;
goto out;
}
- result = open(smb_fname->base_name, flags, mode);
- out:
- END_PROFILE(syscall_open);
+#ifdef O_PATH
+ have_opath = true;
+ if (fsp->fsp_flags.is_pathref) {
+ flags |= O_PATH;
+ }
+#endif
+
+ if (fsp->fsp_flags.is_pathref && !have_opath) {
+ become_root();
+ became_root = true;
+ }
+
+ result = openat(fsp_get_pathref_fd(dirfsp),
+ smb_fname->base_name,
+ flags,
+ mode);
+
+ if (became_root) {
+ unbecome_root();
+ }
+
+ fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
+
+out:
+ END_PROFILE(syscall_openat);
return result;
}
-
static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
struct smb_request *req,
- uint16_t root_dir_fid,
struct smb_filename *smb_fname,
uint32_t access_mask,
uint32_t share_access,
const struct smb2_create_blobs *in_context_blobs,
struct smb2_create_blobs *out_context_blobs)
{
- return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
+ return create_file_default(handle->conn, req, smb_fname,
access_mask, share_access,
create_disposition, create_options,
file_attributes, oplock_request, lease,
#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
START_PROFILE_BYTES(syscall_pread, n);
- result = sys_pread_full(fsp->fh->fd, data, n, offset);
+ result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
END_PROFILE_BYTES(syscall_pread);
if (result == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be seeked (sought?) on. */
- result = sys_read(fsp->fh->fd, data, n);
- fsp->fh->pos = 0;
+ result = sys_read(fsp_get_io_fd(fsp), data, n);
+ fh_set_pos(fsp->fh, 0);
}
#else /* HAVE_PREAD */
#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
START_PROFILE_BYTES(syscall_pwrite, n);
- result = sys_pwrite_full(fsp->fh->fd, data, n, offset);
+ result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
END_PROFILE_BYTES(syscall_pwrite);
if (result == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be sought on. */
- result = sys_write(fsp->fh->fd, data, n);
+ result = sys_write(fsp_get_io_fd(fsp), data, n);
}
#else /* HAVE_PWRITE */
}
state->ret = -1;
- state->fd = fsp->fh->fd;
+ state->fd = fsp_get_io_fd(fsp);
state->buf = data;
state->count = n;
state->offset = offset;
}
state->ret = -1;
- state->fd = fsp->fh->fd;
+ state->fd = fsp_get_io_fd(fsp);
state->buf = data;
state->count = n;
state->offset = offset;
PROFILE_TIMESTAMP(&start_time);
- do {
- state->ret = pwrite(state->fd, state->buf, state->count,
- state->offset);
- } while ((state->ret == -1) && (errno == EINTR));
+ state->ret = sys_pwrite_full(state->fd,
+ state->buf,
+ state->count,
+ state->offset);
if (state->ret == -1) {
state->vfs_aio_state.error = errno;
}
state->ret = -1;
- state->fd = fsp->fh->fd;
+ state->fd = fsp_get_io_fd(fsp);
SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
state->profile_bytes, 0);
START_PROFILE(syscall_lseek);
- result = lseek(fsp->fh->fd, offset, whence);
+ result = lseek(fsp_get_io_fd(fsp), offset, whence);
/*
* We want to maintain the fiction that we can seek
* on a fifo for file system purposes. This allows
ssize_t result;
START_PROFILE_BYTES(syscall_sendfile, n);
- result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
+ result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
END_PROFILE_BYTES(syscall_sendfile);
return result;
}
ssize_t result;
START_PROFILE_BYTES(syscall_recvfile, n);
- result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
+ result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
END_PROFILE_BYTES(syscall_recvfile);
return result;
}
goto out;
}
- result = renameat(srcfsp->fh->fd,
+ result = renameat(fsp_get_pathref_fd(srcfsp),
smb_fname_src->base_name,
- dstfsp->fh->fd,
+ fsp_get_pathref_fd(dstfsp),
smb_fname_dst->base_name);
out:
int result;
START_PROFILE(syscall_fstat);
- result = sys_fstat(fsp->fh->fd,
+ result = sys_fstat(fsp_get_pathref_fd(fsp),
sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
END_PROFILE(syscall_fstat);
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 NT_STATUS_NONE_MAPPED;
}
+/**
+ * Return allocated parent directory and basename of path
+ *
+ * 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,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct smb_filename *parent = NULL;
+ struct smb_filename *name = NULL;
+ char *p = NULL;
+
+ parent = cp_smb_filename_nostream(frame, smb_fname_in);
+ if (parent == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ SET_STAT_INVALID(parent->st);
+
+ p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
+ if (p == NULL) {
+ TALLOC_FREE(parent->base_name);
+ parent->base_name = talloc_strdup(parent, ".");
+ if (parent->base_name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ p = smb_fname_in->base_name;
+ } else {
+ *p = '\0';
+ p++;
+ }
+
+ if (atname_out == NULL) {
+ *parent_dir_out = talloc_move(mem_ctx, &parent);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+ }
+
+ name = cp_smb_filename(frame, smb_fname_in);
+ if (name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ TALLOC_FREE(name->base_name);
+
+ name->base_name = talloc_strdup(name, p);
+ if (name->base_name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ *parent_dir_out = talloc_move(mem_ctx, &parent);
+ *atname_out = talloc_move(*parent_dir_out, &name);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
/*
* Implement the default fsctl operation.
*/
case FSCTL_GET_REPARSE_POINT:
{
- /* Fail it with STATUS_NOT_A_REPARSE_POINT */
- DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
- "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
- return NT_STATUS_NOT_A_REPARSE_POINT;
+ status = fsctl_get_reparse_point(
+ fsp, ctx, out_data, max_out_len, out_len);
+ return status;
}
case FSCTL_SET_REPARSE_POINT:
{
- /* Fail it with STATUS_NOT_A_REPARSE_POINT */
- DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
- "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
- return NT_STATUS_NOT_A_REPARSE_POINT;
+ status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
+ return status;
+ }
+
+ case FSCTL_DELETE_REPARSE_POINT:
+ {
+ status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
+ return status;
}
case FSCTL_GET_SHADOW_COPY_DATA:
static bool vfswrap_is_offline(struct connection_struct *conn,
const struct smb_filename *fname);
-static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- uint32_t *dosmode)
-{
- bool offline;
-
- offline = vfswrap_is_offline(handle->conn, smb_fname);
- if (offline) {
- *dosmode |= FILE_ATTRIBUTE_OFFLINE;
- }
-
- return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
-}
-
struct vfswrap_get_dos_attributes_state {
struct vfs_aio_state aio_state;
connection_struct *conn;
.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,
*dosmode |= FILE_ATTRIBUTE_OFFLINE;
}
- return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
-}
-
-static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- uint32_t dosmode)
-{
- return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
+ return fget_ea_dos_attribute(fsp, dosmode);
}
static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
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);
off_t dst_off;
off_t to_copy;
off_t remaining;
+ off_t copied;
size_t next_io_size;
};
state->dst_fsp = NULL;
}
+static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
static struct tevent_req *vfswrap_offload_write_send(
return tevent_req_post(req, ev);
}
+ status = vfswrap_offload_copy_file_range(req);
+ if (NT_STATUS_IS_OK(status)) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+
state->buf = talloc_array(state, uint8_t, num);
if (tevent_req_nomem(state->buf, req)) {
return tevent_req_post(req, ev);
return req;
}
+static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
+{
+ struct vfswrap_offload_write_state *state = tevent_req_data(
+ req, struct vfswrap_offload_write_state);
+ struct lock_struct lck;
+ ssize_t nwritten;
+ NTSTATUS status;
+ bool same_file;
+ bool ok;
+ static bool try_copy_file_range = true;
+
+ 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);
+ if (same_file &&
+ sys_io_ranges_overlap(state->remaining,
+ state->src_off,
+ state->remaining,
+ state->dst_off))
+ {
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if (fsp_is_alternate_stream(state->src_fsp) ||
+ fsp_is_alternate_stream(state->dst_fsp))
+ {
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ init_strict_lock_struct(state->src_fsp,
+ state->src_fsp->op->global->open_persistent_id,
+ 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->src_fsp,
+ &lck);
+ if (!ok) {
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ ok = change_to_user_and_service_by_fsp(state->dst_fsp);
+ if (!ok) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ init_strict_lock_struct(state->dst_fsp,
+ state->dst_fsp->op->global->open_persistent_id,
+ 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,
+ state->dst_fsp,
+ &lck);
+ if (!ok) {
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ while (state->remaining > 0) {
+ nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
+ &state->src_off,
+ fsp_get_io_fd(state->dst_fsp),
+ &state->dst_off,
+ state->remaining,
+ 0);
+ if (nwritten == -1) {
+ DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
+ "n [%jd] failed: %s\n",
+ fsp_str_dbg(state->src_fsp),
+ (intmax_t)state->src_off,
+ fsp_str_dbg(state->dst_fsp),
+ (intmax_t)state->dst_off,
+ (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;
+ default:
+ status = map_nt_error_from_unix(errno);
+ if (NT_STATUS_EQUAL(
+ status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED))
+ {
+ /* Avoid triggering the fallback */
+ status = NT_STATUS_INTERNAL_ERROR;
+ }
+ break;
+ }
+ return status;
+ }
+
+ if (state->remaining < nwritten) {
+ DBG_DEBUG("copy_file_range src [%s] dst [%s] "
+ "n [%jd] remaining [%jd]\n",
+ fsp_str_dbg(state->src_fsp),
+ fsp_str_dbg(state->dst_fsp),
+ (intmax_t)nwritten,
+ (intmax_t)state->remaining);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ if (nwritten == 0) {
+ break;
+ }
+ state->copied += nwritten;
+ state->remaining -= nwritten;
+ }
+
+ /*
+ * Tell the req cleanup function there's no need to call
+ * change_to_user_and_service_by_fsp() on the dst handle.
+ */
+ state->dst_fsp = NULL;
+ return NT_STATUS_OK;
+}
+
static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
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,
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,
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
+ state->copied += nwritten;
state->remaining -= nwritten;
if (state->remaining == 0) {
tevent_req_done(req);
return status;
}
- *copied = state->to_copy;
+ *copied = state->copied;
DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
tevent_req_received(req);
return NT_STATUS_OK;
}
-static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
+static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
- struct smb_filename *smb_fname,
uint16_t *_compression_fmt)
{
return NT_STATUS_INVALID_DEVICE_REQUEST;
START_PROFILE(syscall_unlinkat);
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
if (is_named_stream(smb_fname)) {
errno = ENOENT;
goto out;
}
- result = unlinkat(dirfsp->fh->fd,
+ result = unlinkat(fsp_get_pathref_fd(dirfsp),
smb_fname->base_name,
flags);
return result;
}
-static int vfswrap_chmod(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- mode_t mode)
-{
- int result;
-
- START_PROFILE(syscall_chmod);
- result = chmod(smb_fname->base_name, mode);
- END_PROFILE(syscall_chmod);
- return result;
-}
-
static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
{
int result;
START_PROFILE(syscall_fchmod);
-#if defined(HAVE_FCHMOD)
- result = fchmod(fsp->fh->fd, mode);
-#else
- result = -1;
- errno = ENOSYS;
-#endif
+
+ if (!fsp->fsp_flags.is_pathref) {
+ result = fchmod(fsp_get_io_fd(fsp), mode);
+ END_PROFILE(syscall_fchmod);
+ return result;
+ }
+
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ const char *p = NULL;
+ char buf[PATH_MAX];
+
+ p = sys_proc_fd_path(fd, buf, sizeof(buf));
+ if (p != NULL) {
+ result = chmod(p, mode);
+ } else {
+ result = -1;
+ }
+ END_PROFILE(syscall_fchmod);
+ return result;
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ result = chmod(fsp->fsp_name->base_name, mode);
END_PROFILE(syscall_fchmod);
return result;
int result;
START_PROFILE(syscall_fchown);
- result = fchown(fsp->fh->fd, uid, gid);
+ if (!fsp->fsp_flags.is_pathref) {
+ result = fchown(fsp_get_io_fd(fsp), uid, gid);
+ END_PROFILE(syscall_fchown);
+ return result;
+ }
+
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ const char *p = NULL;
+ char buf[PATH_MAX];
+
+ p = sys_proc_fd_path(fd, buf, sizeof(buf));
+ if (p != NULL) {
+ result = chown(p, uid, gid);
+ } else {
+ result = -1;
+ }
+ END_PROFILE(syscall_fchown);
+ return result;
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ result = chown(fsp->fsp_name->base_name, uid, gid);
END_PROFILE(syscall_fchown);
return result;
#else
system will support.
**********************************************************************/
-static int vfswrap_ntimes(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct smb_file_time *ft)
+static int vfswrap_fntimes(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct smb_file_time *ft)
{
int result = -1;
+ struct timespec ts[2];
+ struct timespec *times = NULL;
- START_PROFILE(syscall_ntimes);
+ START_PROFILE(syscall_fntimes);
- if (is_named_stream(smb_fname)) {
+ if (fsp_is_alternate_stream(fsp)) {
errno = ENOENT;
goto out;
}
if (ft != NULL) {
if (is_omit_timespec(&ft->atime)) {
- ft->atime= smb_fname->st.st_ex_atime;
+ ft->atime = fsp->fsp_name->st.st_ex_atime;
}
if (is_omit_timespec(&ft->mtime)) {
- ft->mtime = smb_fname->st.st_ex_mtime;
+ ft->mtime = fsp->fsp_name->st.st_ex_mtime;
}
if (!is_omit_timespec(&ft->create_time)) {
- set_create_timespec_ea(handle->conn,
- smb_fname,
+ set_create_timespec_ea(fsp,
ft->create_time);
}
if ((timespec_compare(&ft->atime,
- &smb_fname->st.st_ex_atime) == 0) &&
+ &fsp->fsp_name->st.st_ex_atime) == 0) &&
(timespec_compare(&ft->mtime,
- &smb_fname->st.st_ex_mtime) == 0)) {
- return 0;
+ &fsp->fsp_name->st.st_ex_mtime) == 0)) {
+ result = 0;
+ goto out;
}
- }
-#if defined(HAVE_UTIMENSAT)
- if (ft != NULL) {
- struct timespec ts[2];
ts[0] = ft->atime;
ts[1] = ft->mtime;
- result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
+ times = ts;
} else {
- result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
+ times = NULL;
}
- if (!((result == -1) && (errno == ENOSYS))) {
- goto out;
- }
-#endif
-#if defined(HAVE_UTIMES)
- if (ft != NULL) {
- struct timeval tv[2];
- tv[0] = convert_timespec_to_timeval(ft->atime);
- tv[1] = convert_timespec_to_timeval(ft->mtime);
- result = utimes(smb_fname->base_name, tv);
- } else {
- result = utimes(smb_fname->base_name, NULL);
- }
- if (!((result == -1) && (errno == ENOSYS))) {
+
+ if (!fsp->fsp_flags.is_pathref) {
+ result = futimens(fsp_get_io_fd(fsp), times);
goto out;
}
-#endif
-#if defined(HAVE_UTIME)
- if (ft != NULL) {
- struct utimbuf times;
- times.actime = convert_timespec_to_time_t(ft->atime);
- times.modtime = convert_timespec_to_time_t(ft->mtime);
- result = utime(smb_fname->base_name, ×);
- } else {
- result = utime(smb_fname->base_name, NULL);
- }
- if (!((result == -1) && (errno == ENOSYS))) {
+
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ const char *p = NULL;
+ char buf[PATH_MAX];
+
+ p = sys_proc_fd_path(fd, buf, sizeof(buf));
+ if (p != NULL) {
+ /*
+ * The dirfd argument of utimensat is ignored when
+ * pathname is an absolute path
+ */
+ result = utimensat(AT_FDCWD, p, times, 0);
+ } else {
+ result = -1;
+ }
+
goto out;
}
-#endif
- errno = ENOSYS;
- result = -1;
- out:
- END_PROFILE(syscall_ntimes);
+ /*
+ * The fd is a pathref (opened with O_PATH) and there isn't fd to
+ * path translation mechanism. Fallback to path based call.
+ */
+ result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
+
+out:
+ END_PROFILE(syscall_fntimes);
+
return result;
}
+
/*********************************************************************
A version of ftruncate that will write the space on disk if strict
allocate is set.
/* Shrink - just ftruncate. */
if (pst->st_ex_size > len)
- return ftruncate(fsp->fh->fd, len);
+ return ftruncate(fsp_get_io_fd(fsp), len);
space_to_write = len - pst->st_ex_size;
expansion and some that don't! On Linux fat can't do
ftruncate extend but ext2 can. */
- result = ftruncate(fsp->fh->fd, len);
+ result = ftruncate(fsp_get_io_fd(fsp), len);
/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
extend a file with ftruncate. Provide alternate implementation
START_PROFILE(syscall_fallocate);
if (mode == 0) {
- result = sys_posix_fallocate(fsp->fh->fd, offset, len);
+ result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
/*
* posix_fallocate returns 0 on success, errno on error
* and doesn't set errno. Make it behave like fallocate()
}
} else {
/* sys_fallocate handles filtering of unsupported mode flags */
- result = sys_fallocate(fsp->fh->fd, mode, offset, len);
+ result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
}
END_PROFILE(syscall_fallocate);
return result;
op = map_process_lock_to_ofd_lock(op);
}
- result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
+ result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
END_PROFILE(syscall_fcntl_lock);
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->fh->fd, 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,
case F_SET_FILE_RW_HINT:
#endif
argp = va_arg(dup_cmd_arg, void *);
- result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
+ result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
break;
default:
val = va_arg(dup_cmd_arg, int);
- result = sys_fcntl_int(fsp->fh->fd, cmd, val);
+ result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
}
va_end(dup_cmd_arg);
op = map_process_lock_to_ofd_lock(op);
}
- result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
+ result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
END_PROFILE(syscall_fcntl_getlock);
return result;
}
START_PROFILE(syscall_linux_setlease);
#ifdef HAVE_KERNEL_OPLOCKS_LINUX
- result = linux_setlease(fsp->fh->fd, leasetype);
+ result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
#else
errno = ENOSYS;
#endif
START_PROFILE(syscall_symlinkat);
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
result = symlinkat(link_target->base_name,
- dirfsp->fh->fd,
+ fsp_get_pathref_fd(dirfsp),
new_smb_fname->base_name);
END_PROFILE(syscall_symlinkat);
return result;
}
static int vfswrap_readlinkat(vfs_handle_struct *handle,
- files_struct *dirfsp,
+ const struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
char *buf,
size_t bufsiz)
START_PROFILE(syscall_readlinkat);
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
- result = readlinkat(dirfsp->fh->fd,
+ result = readlinkat(fsp_get_pathref_fd(dirfsp),
smb_fname->base_name,
buf,
bufsiz);
START_PROFILE(syscall_linkat);
- SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
- SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
-
- result = linkat(srcfsp->fh->fd,
+ result = linkat(fsp_get_pathref_fd(srcfsp),
old_smb_fname->base_name,
- dstfsp->fh->fd,
+ fsp_get_pathref_fd(dstfsp),
new_smb_fname->base_name,
flags);
START_PROFILE(syscall_mknodat);
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
- result = sys_mknodat(dirfsp->fh->fd,
+ result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
smb_fname->base_name,
mode,
dev);
return result_fname;
}
-static int vfswrap_chflags(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
+static int vfswrap_fchflags(vfs_handle_struct *handle,
+ struct files_struct *fsp,
unsigned int flags)
{
-#ifdef HAVE_CHFLAGS
- return chflags(smb_fname->base_name, flags);
+#ifdef HAVE_FCHFLAGS
+ int fd = fsp_get_pathref_fd(fsp);
+
+ if (!fsp->fsp_flags.is_pathref) {
+ return fchflags(fd, flags);
+ }
+
+ 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 chflags(p, flags);
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ return chflags(fsp->fsp_name->base_name, flags);
#else
errno = ENOSYS;
return -1;
{
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 file_id;
}
-static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
+static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
struct files_struct *fsp,
- const struct smb_filename *smb_fname,
TALLOC_CTX *mem_ctx,
unsigned int *pnum_streams,
struct stream_struct **pstreams)
{
- SMB_STRUCT_STAT sbuf;
struct stream_struct *tmp_streams = NULL;
- int ret;
+ unsigned int num_streams = *pnum_streams;
+ struct stream_struct *streams = *pstreams;
+ NTSTATUS status;
- if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
+ if (fsp->fsp_flags.is_directory) {
/*
* No default streams on directories
*/
goto done;
}
-
- if ((fsp != NULL) && (fsp->fh->fd != -1)) {
- ret = SMB_VFS_FSTAT(fsp, &sbuf);
- }
- else {
- struct smb_filename *smb_fname_cp = NULL;
-
- smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
- if (smb_fname_cp == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
- ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
- } else {
- ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
- }
- sbuf = smb_fname_cp->st;
- TALLOC_FREE(smb_fname_cp);
- }
-
- if (ret == -1) {
- return map_nt_error_from_unix(errno);
+ status = vfs_stat_fsp(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- if (S_ISDIR(sbuf.st_ex_mode)) {
- goto done;
+ if (num_streams + 1 < 1) {
+ /* Integer wrap. */
+ return NT_STATUS_INVALID_PARAMETER;
}
- tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
- (*pnum_streams) + 1);
+ tmp_streams = talloc_realloc(mem_ctx,
+ streams,
+ struct stream_struct,
+ num_streams + 1);
if (tmp_streams == NULL) {
return NT_STATUS_NO_MEMORY;
}
- tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
- if (tmp_streams[*pnum_streams].name == NULL) {
+ tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
+ if (tmp_streams[num_streams].name == NULL) {
return NT_STATUS_NO_MEMORY;
}
- tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
- tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
+ tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
+ tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
+ handle->conn,
+ fsp,
+ &fsp->fsp_name->st);
+ num_streams += 1;
- *pnum_streams += 1;
+ *pnum_streams = num_streams;
*pstreams = tmp_streams;
done:
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,
return result;
}
-static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
- struct files_struct *dirfsp,
- const struct smb_filename *smb_fname,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
-{
- NTSTATUS result;
-
- START_PROFILE(get_nt_acl_at);
-
- SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
- result = posix_get_nt_acl(handle->conn,
- smb_fname,
- security_info,
- mem_ctx,
- ppdesc);
- END_PROFILE(get_nt_acl_at);
- return result;
-}
-
static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
{
NTSTATUS result;
return NT_STATUS_OK; /* Nothing to do here ... */
}
-static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- SMB_ACL_TYPE_T type,
- TALLOC_CTX *mem_ctx)
-{
- return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
-}
-
static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
files_struct *fsp,
+ SMB_ACL_TYPE_T type,
TALLOC_CTX *mem_ctx)
{
- return sys_acl_get_fd(handle, fsp, mem_ctx);
+ return sys_acl_get_fd(handle, fsp, type, mem_ctx);
}
-static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- SMB_ACL_TYPE_T acltype,
- SMB_ACL_T theacl)
+static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
{
- return sys_acl_set_file(handle, smb_fname, acltype, theacl);
+ return sys_acl_set_fd(handle, fsp, type, theacl);
}
-static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
+static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
+ files_struct *fsp)
{
- return sys_acl_set_fd(handle, fsp, theacl);
-}
-
-static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
-{
- return sys_acl_delete_def_file(handle, smb_fname);
+ return sys_acl_delete_def_fd(handle, fsp);
}
/****************************************************************
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;
- struct tevent_req *req;
/*
* The following variables are talloced off "state" which is protected
}
*state = (struct vfswrap_getxattrat_state) {
.ev = ev,
+ .handle = handle,
.dir_fsp = dir_fsp,
.smb_fname = smb_fname,
- .req = req,
};
max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
state->profile_bytes, 0);
- if (dir_fsp->fh->fd == -1) {
+ if (fsp_get_pathref_fd(dir_fsp) == -1) {
DBG_ERR("Need a valid directory fd\n");
tevent_req_error(req, EINVAL);
return tevent_req_post(req, ev);
{
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(state->dir_fsp->fh->fd);
- 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)
+static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
{
- return fgetxattr(fsp->fh->fd, name, value, size);
-}
+ int fd = fsp_get_pathref_fd(fsp);
-static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- char *list,
- size_t size)
-{
- return listxattr(smb_fname->base_name, list, size);
-}
+ if (!fsp->fsp_flags.is_pathref) {
+ return flistxattr(fd, list, size);
+ }
-static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
-{
- return flistxattr(fsp->fh->fd, list, size);
-}
+ if (fsp->fsp_flags.have_proc_fds) {
+ const char *p = NULL;
+ char buf[PATH_MAX];
-static int vfswrap_removexattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *name)
-{
- return removexattr(smb_fname->base_name, name);
+ p = sys_proc_fd_path(fd, buf, sizeof(buf));
+ if (p == NULL) {
+ return -1;
+ }
+
+ return listxattr(p, list, size);
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ return listxattr(fsp->fsp_name->base_name, list, size);
}
static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
{
- return fremovexattr(fsp->fh->fd, name);
-}
+ int fd = fsp_get_pathref_fd(fsp);
-static int vfswrap_setxattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *name,
- const void *value,
- size_t size,
- int flags)
-{
- return setxattr(smb_fname->base_name, name, value, size, flags);
+ if (!fsp->fsp_flags.is_pathref) {
+ return fremovexattr(fd, name);
+ }
+
+ 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 removexattr(p, name);
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ return removexattr(fsp->fsp_name->base_name, name);
}
static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
{
- return fsetxattr(fsp->fh->fd, name, value, size, flags);
+ int fd = fsp_get_pathref_fd(fsp);
+
+ if (!fsp->fsp_flags.is_pathref) {
+ return fsetxattr(fd, name, value, size, flags);
+ }
+
+ 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 setxattr(p, name, value, size, flags);
+ }
+
+ /*
+ * This is no longer a handle based call.
+ */
+ return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
}
static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
.fdopendir_fn = vfswrap_fdopendir,
.readdir_fn = vfswrap_readdir,
- .readdir_attr_fn = vfswrap_readdir_attr,
+ .freaddir_attr_fn = vfswrap_freaddir_attr,
.seekdir_fn = vfswrap_seekdir,
.telldir_fn = vfswrap_telldir,
.rewind_dir_fn = vfswrap_rewinddir,
/* File operations */
- .open_fn = vfswrap_open,
+ .openat_fn = vfswrap_openat,
.create_file_fn = vfswrap_create_file,
.close_fn = vfswrap_close,
.pread_fn = vfswrap_pread,
.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,
- .chmod_fn = vfswrap_chmod,
.fchmod_fn = vfswrap_fchmod,
.fchown_fn = vfswrap_fchown,
.lchown_fn = vfswrap_lchown,
.chdir_fn = vfswrap_chdir,
.getwd_fn = vfswrap_getwd,
- .ntimes_fn = vfswrap_ntimes,
+ .fntimes_fn = vfswrap_fntimes,
.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,
.linkat_fn = vfswrap_linkat,
.mknodat_fn = vfswrap_mknodat,
.realpath_fn = vfswrap_realpath,
- .chflags_fn = vfswrap_chflags,
+ .fchflags_fn = vfswrap_fchflags,
.file_id_create_fn = vfswrap_file_id_create,
.fs_file_id_fn = vfswrap_fs_file_id,
- .streaminfo_fn = vfswrap_streaminfo,
+ .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,
.strict_lock_check_fn = vfswrap_strict_lock_check,
.translate_name_fn = vfswrap_translate_name,
+ .parent_pathname_fn = vfswrap_parent_pathname,
.fsctl_fn = vfswrap_fsctl,
- .set_dos_attributes_fn = vfswrap_set_dos_attributes,
.fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
- .get_dos_attributes_fn = vfswrap_get_dos_attributes,
.get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
.get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
.fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
.offload_read_recv_fn = vfswrap_offload_read_recv,
.offload_write_send_fn = vfswrap_offload_write_send,
.offload_write_recv_fn = vfswrap_offload_write_recv,
- .get_compression_fn = vfswrap_get_compression,
+ .fget_compression_fn = vfswrap_fget_compression,
.set_compression_fn = vfswrap_set_compression,
/* NT ACL operations. */
.fget_nt_acl_fn = vfswrap_fget_nt_acl,
- .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
.fset_nt_acl_fn = vfswrap_fset_nt_acl,
.audit_file_fn = vfswrap_audit_file,
/* POSIX ACL operations. */
- .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
.sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
- .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
.sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
- .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
.sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
- .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
+ .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,
- .listxattr_fn = vfswrap_listxattr,
.flistxattr_fn = vfswrap_flistxattr,
- .removexattr_fn = vfswrap_removexattr,
.fremovexattr_fn = vfswrap_fremovexattr,
- .setxattr_fn = vfswrap_setxattr,
.fsetxattr_fn = vfswrap_fsetxattr,
/* aio operations */