vfs_handle_struct *handle;
};
-static ssize_t get_xattr_size(connection_struct *conn,
- const struct smb_filename *smb_fname,
- const char *xattr_name)
+static ssize_t get_xattr_size_fsp(struct files_struct *fsp,
+ const char *xattr_name)
{
NTSTATUS status;
struct ea_struct ea;
ssize_t result;
- status = get_ea_value(talloc_tos(), conn, NULL, smb_fname,
- xattr_name, &ea);
-
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp,
+ xattr_name,
+ &ea);
if (!NT_STATUS_IS_OK(status)) {
return -1;
}
const char *stream_name,
char **xattr_name)
{
- char *sname;
+ size_t stream_name_len = strlen(stream_name);
char *stype;
struct streams_xattr_config *config;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return NT_STATUS_UNSUCCESSFUL);
- sname = talloc_strdup(ctx, stream_name + 1);
- if (sname == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ SMB_ASSERT(stream_name[0] == ':');
+ stream_name += 1;
/*
* With vfs_fruit option "fruit:encoding = native" we're
* In check_path_syntax() we've already ensured the streamname
* we got from the client is valid.
*/
- stype = strrchr_m(sname, ':');
+ stype = strrchr_m(stream_name, ':');
if (stype) {
/*
* We only support one stream type: "$DATA"
*/
if (strcasecmp_m(stype, ":$DATA") != 0) {
- talloc_free(sname);
return NT_STATUS_INVALID_PARAMETER;
}
/* Split name and type */
- stype[0] = '\0';
+ stream_name_len = (stype - stream_name);
}
- *xattr_name = talloc_asprintf(ctx, "%s%s%s",
+ *xattr_name = talloc_asprintf(ctx, "%s%.*s%s",
config->prefix,
- sname,
+ (int)stream_name_len,
+ stream_name,
config->store_stream_type ? ":$DATA" : "");
if (*xattr_name == NULL) {
- talloc_free(sname);
return NT_STATUS_NO_MEMORY;
}
DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
stream_name));
- talloc_free(sname);
return NT_STATUS_OK;
}
return true;
}
-/**
- * Helper to stat/lstat the base file of an smb_fname.
- */
-static int streams_xattr_stat_base(vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- bool follow_links)
-{
- char *tmp_stream_name;
- int result;
-
- tmp_stream_name = smb_fname->stream_name;
- smb_fname->stream_name = NULL;
- if (follow_links) {
- result = SMB_VFS_NEXT_STAT(handle, smb_fname);
- } else {
- result = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
- }
- smb_fname->stream_name = tmp_stream_name;
- return result;
-}
-
static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
SMB_STRUCT_STAT *sbuf)
{
- struct smb_filename *smb_fname_base = NULL;
int ret = -1;
struct stream_io *io = (struct stream_io *)
VFS_FETCH_FSP_EXTENSION(handle, fsp);
- if (io == NULL || fsp->base_fsp == NULL) {
+ if (io == NULL || !fsp_is_alternate_stream(fsp)) {
return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
}
return -1;
}
- /* Create an smb_filename with stream_name == NULL. */
- smb_fname_base = synthetic_smb_fname(talloc_tos(),
- io->base,
- NULL,
- NULL,
- fsp->fsp_name->twrp,
- fsp->fsp_name->flags);
- if (smb_fname_base == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- if (smb_fname_base->flags & SMB_FILENAME_POSIX_PATH) {
- ret = SMB_VFS_LSTAT(handle->conn, smb_fname_base);
- } else {
- ret = SMB_VFS_STAT(handle->conn, smb_fname_base);
- }
- *sbuf = smb_fname_base->st;
-
+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp->base_fsp, sbuf);
if (ret == -1) {
- TALLOC_FREE(smb_fname_base);
return -1;
}
- sbuf->st_ex_size = get_xattr_size(handle->conn,
- smb_fname_base, io->xattr_name);
+ sbuf->st_ex_size = get_xattr_size_fsp(fsp->base_fsp,
+ io->xattr_name);
if (sbuf->st_ex_size == -1) {
- TALLOC_FREE(smb_fname_base);
SET_STAT_INVALID(*sbuf);
return -1;
}
sbuf->st_ex_mode |= S_IFREG;
sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
- TALLOC_FREE(smb_fname_base);
return 0;
}
NTSTATUS status;
int result = -1;
char *xattr_name = NULL;
+ char *tmp_stream_name = NULL;
+ struct smb_filename *pathref = NULL;
+ struct files_struct *fsp = smb_fname->fsp;
if (!is_named_stream(smb_fname)) {
return SMB_VFS_NEXT_STAT(handle, smb_fname);
* not following links here. */
/* Populate the stat struct with info from the base file. */
- if (streams_xattr_stat_base(handle, smb_fname, true) == -1) {
+ tmp_stream_name = smb_fname->stream_name;
+ smb_fname->stream_name = NULL;
+ result = SMB_VFS_NEXT_STAT(handle, smb_fname);
+ smb_fname->stream_name = tmp_stream_name;
+
+ if (result == -1) {
return -1;
}
}
/* Augment the base file's stat information before returning. */
- smb_fname->st.st_ex_size = get_xattr_size(handle->conn,
- smb_fname,
- xattr_name);
+ if (fsp == NULL) {
+ status = synthetic_pathref(talloc_tos(),
+ handle->conn->cwd_fsp,
+ smb_fname->base_name,
+ NULL,
+ NULL,
+ smb_fname->twrp,
+ smb_fname->flags,
+ &pathref);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(xattr_name);
+ SET_STAT_INVALID(smb_fname->st);
+ errno = ENOENT;
+ return -1;
+ }
+ fsp = pathref->fsp;
+ } else {
+ fsp = fsp->base_fsp;
+ }
+
+ smb_fname->st.st_ex_size = get_xattr_size_fsp(fsp,
+ xattr_name);
if (smb_fname->st.st_ex_size == -1) {
+ TALLOC_FREE(xattr_name);
+ TALLOC_FREE(pathref);
SET_STAT_INVALID(smb_fname->st);
errno = ENOENT;
- result = -1;
- goto fail;
+ return -1;
}
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;
- result = 0;
- fail:
TALLOC_FREE(xattr_name);
- return result;
+ TALLOC_FREE(pathref);
+ return 0;
}
static int streams_xattr_lstat(vfs_handle_struct *handle,
struct smb_filename *smb_fname)
{
- NTSTATUS status;
- int result = -1;
- char *xattr_name = NULL;
-
- if (!is_named_stream(smb_fname)) {
- return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
- }
-
- /* Populate the stat struct with info from the base file. */
- if (streams_xattr_stat_base(handle, smb_fname, false) == -1) {
- return -1;
- }
-
- /* Derive the xattr name to lookup. */
- status = streams_xattr_get_name(handle, talloc_tos(),
- smb_fname->stream_name, &xattr_name);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- /* Augment the base file's stat information before returning. */
- smb_fname->st.st_ex_size = get_xattr_size(handle->conn,
- smb_fname,
- xattr_name);
- if (smb_fname->st.st_ex_size == -1) {
+ if (is_named_stream(smb_fname)) {
+ /*
+ * There can never be EA's on a symlink.
+ * Windows will never see a symlink, and
+ * in SMB_FILENAME_POSIX_PATH mode we don't
+ * allow EA's on a symlink.
+ */
SET_STAT_INVALID(smb_fname->st);
errno = ENOENT;
- result = -1;
- goto fail;
+ return -1;
}
-
- 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 =
- smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
-
- result = 0;
-
- fail:
- TALLOC_FREE(xattr_name);
- return result;
+ return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
}
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)
+ const struct vfs_open_how *how)
{
NTSTATUS status;
struct streams_xattr_config *config = NULL;
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));
+ DBG_DEBUG("called for %s with flags 0x%x\n",
+ smb_fname_str_dbg(smb_fname),
+ how->flags);
if (!is_named_stream(smb_fname)) {
return SMB_VFS_NEXT_OPENAT(handle,
dirfsp,
smb_fname,
fsp,
- flags,
- mode);
+ how);
}
- /*
- * For now assert this, so the below SMB_VFS_SETXATTR() works.
- */
- SMB_ASSERT(dirfsp->fh->fd == AT_FDCWD);
+ if (how->resolve != 0) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ SMB_ASSERT(fsp_is_alternate_stream(fsp));
+ SMB_ASSERT(dirfsp == NULL);
status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname->stream_name, &xattr_name);
goto fail;
}
- status = get_ea_value(talloc_tos(), handle->conn, NULL,
- smb_fname, xattr_name, &ea);
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp->base_fsp,
+ xattr_name,
+ &ea);
- DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
+ DBG_DEBUG("get_ea_value_fsp returned %s\n", nt_errstr(status));
if (!NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
goto fail;
}
- if (!(flags & O_CREAT)) {
+ if (!(how->flags & O_CREAT)) {
errno = ENOATTR;
goto fail;
}
set_empty_xattr = true;
}
- if (flags & O_TRUNC) {
+ if (how->flags & O_TRUNC) {
set_empty_xattr = true;
}
DEBUG(10, ("creating or truncating attribute %s on file %s\n",
xattr_name, smb_fname->base_name));
- ret = SMB_VFS_SETXATTR(fsp->conn,
- smb_fname,
+ ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
xattr_name,
&null, sizeof(null),
- flags & O_EXCL ? XATTR_CREATE : 0);
+ how->flags & O_EXCL ? XATTR_CREATE : 0);
if (ret != 0) {
goto fail;
}
fail:
if (fakefd >= 0) {
- close(fakefd);
+ vfs_fake_fd_close(fakefd);
fakefd = -1;
}
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)) {
+ if (!fsp_is_alternate_stream(fsp)) {
return SMB_VFS_NEXT_CLOSE(handle, fsp);
}
- ret = close(fd);
+ ret = vfs_fake_fd_close(fd);
fsp_set_fd(fsp, -1);
return ret;
}
-static int streams_xattr_unlink_internal(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)
NTSTATUS status;
int ret = -1;
char *xattr_name = NULL;
+ struct smb_filename *pathref = NULL;
+ struct files_struct *fsp = smb_fname->fsp;
if (!is_named_stream(smb_fname)) {
return SMB_VFS_NEXT_UNLINKAT(handle,
flags);
}
+ /* A stream can never be rmdir'ed */
+ SMB_ASSERT((flags & AT_REMOVEDIR) == 0);
+
status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- ret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname, xattr_name);
+ if (fsp == NULL) {
+ status = synthetic_pathref(talloc_tos(),
+ handle->conn->cwd_fsp,
+ smb_fname->base_name,
+ NULL,
+ NULL,
+ smb_fname->twrp,
+ smb_fname->flags,
+ &pathref);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = ENOENT;
+ goto fail;
+ }
+ fsp = pathref->fsp;
+ } else {
+ SMB_ASSERT(fsp_is_alternate_stream(smb_fname->fsp));
+ fsp = fsp->base_fsp;
+ }
+
+ ret = SMB_VFS_FREMOVEXATTR(fsp, xattr_name);
if ((ret == -1) && (errno == ENOATTR)) {
errno = ENOENT;
fail:
TALLOC_FREE(xattr_name);
- return ret;
-}
-
-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);
- }
+ TALLOC_FREE(pathref);
return ret;
}
ssize_t oret;
ssize_t nret;
struct ea_struct ea;
+ struct smb_filename *pathref_src = NULL;
+ struct smb_filename *pathref_dst = NULL;
+ struct smb_filename *full_src = NULL;
+ struct smb_filename *full_dst = NULL;
src_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
dst_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
goto fail;
}
- /* read the old stream */
- status = get_ea_value(talloc_tos(), handle->conn, NULL,
- smb_fname_src, src_xattr_name, &ea);
+ full_src = full_path_from_dirfsp_atname(talloc_tos(),
+ srcfsp,
+ smb_fname_src);
+ if (full_src == NULL) {
+ errno = ENOMEM;
+ goto fail;
+ }
+ full_dst = full_path_from_dirfsp_atname(talloc_tos(),
+ dstfsp,
+ smb_fname_dst);
+ if (full_dst == NULL) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
+ /* Get a pathref for full_src (base file, no stream name). */
+ status = synthetic_pathref(talloc_tos(),
+ handle->conn->cwd_fsp,
+ full_src->base_name,
+ NULL,
+ NULL,
+ full_src->twrp,
+ full_src->flags,
+ &pathref_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = ENOENT;
+ goto fail;
+ }
+
+ /* Read the old stream from the base file fsp. */
+ status = get_ea_value_fsp(talloc_tos(),
+ pathref_src->fsp,
+ src_xattr_name,
+ &ea);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ goto fail;
+ }
+
+ /* Get a pathref for full_dst (base file, no stream name). */
+ status = synthetic_pathref(talloc_tos(),
+ handle->conn->cwd_fsp,
+ full_dst->base_name,
+ NULL,
+ NULL,
+ full_dst->twrp,
+ full_dst->flags,
+ &pathref_dst);
if (!NT_STATUS_IS_OK(status)) {
errno = ENOENT;
goto fail;
}
- /* (over)write the new stream */
- nret = SMB_VFS_SETXATTR(handle->conn, smb_fname_src,
- dst_xattr_name, ea.value.data, ea.value.length,
- 0);
+ /* (Over)write the new stream on the base file fsp. */
+ nret = SMB_VFS_FSETXATTR(
+ pathref_dst->fsp,
+ dst_xattr_name,
+ ea.value.data,
+ ea.value.length,
+ 0);
if (nret < 0) {
if (errno == ENOATTR) {
errno = ENOENT;
goto fail;
}
- /* remove the old stream */
- oret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname_src,
- src_xattr_name);
+ /*
+ * Remove the old stream from the base file fsp.
+ */
+ oret = SMB_VFS_FREMOVEXATTR(pathref_src->fsp,
+ src_xattr_name);
if (oret < 0) {
if (errno == ENOATTR) {
errno = ENOENT;
errno = 0;
ret = 0;
fail:
+ TALLOC_FREE(pathref_src);
+ TALLOC_FREE(pathref_dst);
+ TALLOC_FREE(full_src);
+ TALLOC_FREE(full_dst);
TALLOC_FREE(src_xattr_name);
TALLOC_FREE(dst_xattr_name);
return ret;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return NT_STATUS_UNSUCCESSFUL);
- status = get_ea_names_from_file(talloc_tos(),
- handle->conn,
- fsp,
- smb_fname,
+ status = get_ea_names_from_fsp(talloc_tos(),
+ smb_fname->fsp,
&names,
&num_names);
if (!NT_STATUS_IS_OK(status)) {
continue;
}
- status = get_ea_value(names,
- handle->conn,
- NULL,
- smb_fname,
- names[i],
- &ea);
+ status = get_ea_value_fsp(names,
+ smb_fname->fsp,
+ names[i],
+ &ea);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Could not get ea %s for file %s: %s\n",
names[i],
return true;
}
-static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
+static NTSTATUS streams_xattr_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;
- int ret;
NTSTATUS status;
struct streaminfo_state state;
- ret = vfs_stat_smb_basename(handle->conn, smb_fname, &sbuf);
- if (ret == -1) {
- return map_nt_error_from_unix(errno);
- }
-
state.streams = *pstreams;
state.num_streams = *pnum_streams;
state.mem_ctx = mem_ctx;
state.handle = handle;
state.status = NT_STATUS_OK;
- if (S_ISLNK(sbuf.st_ex_mode)) {
- /*
- * Currently we do't have SMB_VFS_LLISTXATTR
- * inside the VFS which means there's no way
- * to cope with a symlink when lp_posix_pathnames().
- * returns true. For now ignore links.
- * FIXME - by adding SMB_VFS_LLISTXATTR. JRA.
- */
- status = NT_STATUS_OK;
- } else {
- status = walk_xattr_streams(handle, fsp, smb_fname,
- collect_one_stream, &state);
- }
+ status = walk_xattr_streams(handle,
+ fsp,
+ fsp->fsp_name,
+ collect_one_stream,
+ &state);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(state.streams);
*pnum_streams = state.num_streams;
*pstreams = state.streams;
- return SMB_VFS_NEXT_STREAMINFO(handle,
+ return SMB_VFS_NEXT_FSTREAMINFO(handle,
fsp,
- smb_fname,
mem_ctx,
pnum_streams,
pstreams);
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct ea_struct ea;
NTSTATUS status;
- struct smb_filename *smb_fname_base = NULL;
int ret;
DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n));
return -1;
}
- /* Create an smb_filename with stream_name == NULL. */
- smb_fname_base = synthetic_smb_fname(talloc_tos(),
- sio->base,
- NULL,
- NULL,
- fsp->fsp_name->twrp,
- fsp->fsp_name->flags);
- if (smb_fname_base == NULL) {
- errno = ENOMEM;
+ if ((offset + n) >= lp_smbd_max_xattr_size(SNUM(handle->conn))) {
+ /*
+ * Requested write is beyond what can be read based on
+ * samba configuration.
+ * ReFS returns STATUS_FILESYSTEM_LIMITATION, which causes
+ * entire file to be skipped by File Explorer. VFAT returns
+ * NT_STATUS_OBJECT_NAME_COLLISION causes user to be prompted
+ * to skip writing metadata, but copy data.
+ */
+ DBG_ERR("Write to xattr [%s] on file [%s] exceeds maximum "
+ "supported extended attribute size. "
+ "Depending on filesystem type and operating system "
+ "(OS) specifics, this value may be increased using "
+ "the value of the parameter: "
+ "smbd max xattr size = <bytes>. Consult OS and "
+ "filesystem manpages prior to increasing this limit.\n",
+ sio->xattr_name, sio->base);
+ errno = EOVERFLOW;
return -1;
}
- status = get_ea_value(talloc_tos(), handle->conn, NULL,
- smb_fname_base, sio->xattr_name, &ea);
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp->base_fsp,
+ sio->xattr_name,
+ &ea);
if (!NT_STATUS_IS_OK(status)) {
return -1;
}
memcpy(ea.value.data + offset, data, n);
- ret = SMB_VFS_SETXATTR(fsp->conn,
- fsp->fsp_name,
- sio->xattr_name,
- ea.value.data, ea.value.length, 0);
+ ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+ sio->xattr_name,
+ ea.value.data,
+ ea.value.length,
+ 0);
TALLOC_FREE(ea.value.data);
if (ret == -1) {
struct ea_struct ea;
NTSTATUS status;
size_t length, overlap;
- struct smb_filename *smb_fname_base = NULL;
DEBUG(10, ("streams_xattr_pread: offset=%d, size=%d\n",
(int)offset, (int)n));
return -1;
}
- /* Create an smb_filename with stream_name == NULL. */
- smb_fname_base = synthetic_smb_fname(talloc_tos(),
- sio->base,
- NULL,
- NULL,
- fsp->fsp_name->twrp,
- fsp->fsp_name->flags);
- if (smb_fname_base == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- status = get_ea_value(talloc_tos(), handle->conn, NULL,
- smb_fname_base, sio->xattr_name, &ea);
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp->base_fsp,
+ sio->xattr_name,
+ &ea);
if (!NT_STATUS_IS_OK(status)) {
return -1;
}
length = ea.value.length-1;
- DEBUG(10, ("streams_xattr_pread: get_ea_value returned %d bytes\n",
- (int)length));
+ DBG_DEBUG("get_ea_value_fsp returned %d bytes\n",
+ (int)length);
/* Attempt to read past EOF. */
if (length <= offset) {
NTSTATUS status;
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
- struct smb_filename *smb_fname_base = NULL;
DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
fsp_str_dbg(fsp), (double)offset));
return -1;
}
- /* Create an smb_filename with stream_name == NULL. */
- smb_fname_base = synthetic_smb_fname(talloc_tos(),
- sio->base,
- NULL,
- NULL,
- fsp->fsp_name->twrp,
- fsp->fsp_name->flags);
- if (smb_fname_base == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- status = get_ea_value(talloc_tos(), handle->conn, NULL,
- smb_fname_base, sio->xattr_name, &ea);
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp->base_fsp,
+ sio->xattr_name,
+ &ea);
if (!NT_STATUS_IS_OK(status)) {
return -1;
}
ea.value.length = offset + 1;
ea.value.data[offset] = 0;
- ret = SMB_VFS_SETXATTR(fsp->conn,
- fsp->fsp_name,
- sio->xattr_name,
- ea.value.data, ea.value.length, 0);
+ ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+ sio->xattr_name,
+ ea.value.data,
+ ea.value.length,
+ 0);
+
TALLOC_FREE(ea.value.data);
if (ret == -1) {
return -1;
}
-static SMB_ACL_T streams_xattr_sys_acl_get_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- TALLOC_CTX *mem_ctx)
-{
- struct stream_io *sio =
- (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
- if (sio == NULL) {
- return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
- }
-
- return SMB_VFS_NEXT_SYS_ACL_GET_FILE(
- handle, fsp->base_fsp->fsp_name,
- SMB_ACL_TYPE_ACCESS, mem_ctx);
-}
-
-static int streams_xattr_sys_acl_set_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- SMB_ACL_T theacl)
-{
- struct stream_io *sio =
- (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
- if (sio == NULL) {
- return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
- }
-
- return 0;
-}
-
-static int streams_xattr_sys_acl_blob_get_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- TALLOC_CTX *mem_ctx,
- char **blob_description,
- DATA_BLOB *blob)
-{
- struct stream_io *sio =
- (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
- if (sio == NULL) {
- return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx,
- blob_description, blob);
- }
-
- return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(
- handle, fsp->base_fsp->fsp_name, mem_ctx,
- blob_description, blob);
-}
-
-static NTSTATUS streams_xattr_fget_nt_acl(vfs_handle_struct *handle,
- files_struct *fsp,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
-{
- struct stream_io *sio =
- (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
- if (sio == NULL) {
- return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, 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,
- files_struct *fsp,
- uint32_t security_info_sent,
- const struct security_descriptor *psd)
-{
- struct stream_io *sio =
- (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
-
- if (sio == NULL) {
- return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp,
- security_info_sent, psd);
- }
-
- return NT_STATUS_OK;
-}
-
struct streams_xattr_fsync_state {
int ret;
struct vfs_aio_state vfs_aio_state;
return false;
}
-static int streams_xattr_kernel_flock(vfs_handle_struct *handle,
- files_struct *fsp,
- uint32_t share_access,
- uint32_t access_mask)
+static int streams_xattr_filesystem_sharemode(vfs_handle_struct *handle,
+ files_struct *fsp,
+ uint32_t share_access,
+ uint32_t access_mask)
{
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
if (sio == NULL) {
- return SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp,
- share_access, access_mask);
+ return SMB_VFS_NEXT_FILESYSTEM_SHAREMODE(handle,
+ fsp,
+ share_access,
+ access_mask);
}
return 0;
return true;
}
+static int streams_xattr_fcntl(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int cmd,
+ va_list cmd_arg)
+{
+ va_list dup_cmd_arg;
+ void *arg;
+ int ret;
+
+ if (fsp_is_alternate_stream(fsp)) {
+ switch (cmd) {
+ case F_GETFL:
+ case F_SETFL:
+ break;
+ default:
+ DBG_ERR("Unsupported fcntl() cmd [%d] on [%s]\n",
+ cmd, fsp_str_dbg(fsp));
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ va_copy(dup_cmd_arg, cmd_arg);
+ arg = va_arg(dup_cmd_arg, void *);
+
+ ret = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
+
+ va_end(dup_cmd_arg);
+
+ return ret;
+}
+
static struct vfs_fn_pointers vfs_streams_xattr_fns = {
.fs_capabilities_fn = streams_xattr_fs_capabilities,
.connect_fn = streams_xattr_connect,
.renameat_fn = streams_xattr_renameat,
.ftruncate_fn = streams_xattr_ftruncate,
.fallocate_fn = streams_xattr_fallocate,
- .streaminfo_fn = streams_xattr_streaminfo,
+ .fstreaminfo_fn = streams_xattr_fstreaminfo,
.fsync_send_fn = streams_xattr_fsync_send,
.fsync_recv_fn = streams_xattr_fsync_recv,
.lock_fn = streams_xattr_lock,
.getlock_fn = streams_xattr_getlock,
- .kernel_flock_fn = streams_xattr_kernel_flock,
+ .filesystem_sharemode_fn = streams_xattr_filesystem_sharemode,
.linux_setlease_fn = streams_xattr_linux_setlease,
.strict_lock_check_fn = streams_xattr_strict_lock_check,
+ .fcntl_fn = streams_xattr_fcntl,
.fchown_fn = streams_xattr_fchown,
.fchmod_fn = streams_xattr_fchmod,
.flistxattr_fn = streams_xattr_flistxattr,
.fremovexattr_fn = streams_xattr_fremovexattr,
.fsetxattr_fn = streams_xattr_fsetxattr,
-
- .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,
-
- .fget_nt_acl_fn = streams_xattr_fget_nt_acl,
- .fset_nt_acl_fn = streams_xattr_fset_nt_acl,
};
static_decl_vfs;