*/
#include "includes.h"
+#include "smbd/smbd.h"
+#include "system/filesys.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
* an option to put in a special ACL entry for a non-existing group.
*/
-#define SAMBA_XATTR_MARKER "user.SAMBA_STREAMS"
-
static bool file_is_valid(vfs_handle_struct *handle, const char *path,
bool check_valid)
{
*smb_fname_out = NULL;
+ stype = strchr_m(smb_fname->stream_name + 1, ':');
+
+ if (stype) {
+ if (StrCaseCmp(stype, ":$DATA") != 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
dirname = stream_dir(handle, smb_fname, NULL, create_dir);
if (dirname == NULL) {
goto fail;
}
- stype = strchr_m(smb_fname->stream_name + 1, ':');
-
stream_fname = talloc_asprintf(talloc_tos(), "%s/%s", dirname,
smb_fname->stream_name);
return status;
}
-/*
- * XXX: This function should be removed after the other vfs ops take
- * smb_filename structs
- */
-static char *stream_name(vfs_handle_struct *handle, const char *fname,
- bool create_dir)
-{
- struct smb_filename *smb_fname = NULL;
- struct smb_filename *smb_fname_stream = NULL;
- char *sname = NULL;
- NTSTATUS status;
-
- status = create_synthetic_smb_fname_split(talloc_tos(), fname,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
-
- status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
- create_dir);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
-
- status = get_full_smb_filename(talloc_tos(), smb_fname_stream,
- &sname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
- out:
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(smb_fname_stream);
-
- return sname;
-}
-
static NTSTATUS walk_streams(vfs_handle_struct *handle,
struct smb_filename *smb_fname_base,
char **pdirname,
{
char *dirname;
SMB_STRUCT_DIR *dirhandle = NULL;
- char *dirent;
+ const char *dirent = NULL;
+ char *talloced = NULL;
dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st,
false);
return map_nt_error_from_unix(errno);
}
- while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL)) != NULL) {
+ while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL,
+ &talloced)) != NULL) {
if (ISDOT(dirent) || ISDOTDOT(dirent)) {
+ TALLOC_FREE(talloced);
continue;
}
DEBUG(10, ("walk_streams: dirent=%s\n", dirent));
if (!fn(dirname, dirent, private_data)) {
+ TALLOC_FREE(talloced);
break;
}
+ TALLOC_FREE(talloced);
}
SMB_VFS_NEXT_CLOSEDIR(handle, dirhandle);
return ret;
}
-static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname)
+static int streams_depot_unlink(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
struct smb_filename *smb_fname_base = NULL;
NTSTATUS status;
int ret = -1;
- DEBUG(10, ("streams_depot_unlink called for %s\n", fname));
+ DEBUG(10, ("streams_depot_unlink called for %s\n",
+ smb_fname_str_dbg(smb_fname)));
- if (is_ntfs_stream_name(fname)) {
- char *stream_fname;
+ /* If there is a valid stream, just unlink the stream and return. */
+ if (is_ntfs_stream_smb_fname(smb_fname) &&
+ !is_ntfs_default_stream_smb_fname(smb_fname)) {
+ struct smb_filename *smb_fname_stream = NULL;
- stream_fname = stream_name(handle, fname, false);
- if (stream_fname == NULL) {
+ status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
+ false);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
return -1;
}
- ret = SMB_VFS_NEXT_UNLINK(handle, stream_fname);
+ ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_stream);
- TALLOC_FREE(stream_fname);
+ TALLOC_FREE(smb_fname_stream);
return ret;
}
* We potentially need to delete the per-inode streams directory
*/
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
- &smb_fname_base);
+ status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
+ NULL, NULL, &smb_fname_base);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
TALLOC_FREE(dirname);
}
- TALLOC_FREE(smb_fname_base);
+ ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
- return SMB_VFS_NEXT_UNLINK(handle, fname);
+ TALLOC_FREE(smb_fname_base);
+ return ret;
}
static int streams_depot_rename(vfs_handle_struct *handle,
{
struct smb_filename *smb_fname_src_stream = NULL;
struct smb_filename *smb_fname_dst_stream = NULL;
- struct smb_filename *smb_fname_dst_mod = NULL;
bool src_is_stream, dst_is_stream;
NTSTATUS status;
int ret = -1;
goto done;
}
- /*
- * Handle passing in a stream name without the base file. This is
- * exercised by the NTRENAME streams rename path.
- */
- if (StrCaseCmp(smb_fname_dst->base_name, "./") == 0) {
- status = create_synthetic_smb_fname(talloc_tos(),
- smb_fname_src->base_name,
- smb_fname_dst->stream_name,
- NULL, &smb_fname_dst_mod);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto done;
- }
- }
-
- status = stream_smb_fname(handle, (smb_fname_dst_mod ?
- smb_fname_dst_mod : smb_fname_dst),
+ status = stream_smb_fname(handle, smb_fname_dst,
&smb_fname_dst_stream, false);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
done:
TALLOC_FREE(smb_fname_src_stream);
TALLOC_FREE(smb_fname_dst_stream);
- TALLOC_FREE(smb_fname_dst_mod);
return ret;
}
}
if ((fsp != NULL) && (fsp->fh->fd != -1)) {
- if (is_ntfs_stream_name(fsp->fsp_name)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &smb_fname_base->st);
}
else {
- if (is_ntfs_stream_name(fname)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
if (lp_posix_pathnames()) {
ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
} else {
return status;
}
-static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle,
+ enum timestamp_set_resolution *p_ts_res)
{
- return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+ return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS;
}
-/* VFS operations structure */
-
-static vfs_op_tuple streams_depot_ops[] = {
- {SMB_VFS_OP(streams_depot_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_open), SMB_VFS_OP_OPEN,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_stat), SMB_VFS_OP_STAT,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_lstat), SMB_VFS_OP_LSTAT,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_unlink), SMB_VFS_OP_UNLINK,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_rename), SMB_VFS_OP_RENAME,
- SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(streams_depot_streaminfo), SMB_VFS_OP_STREAMINFO,
- SMB_VFS_LAYER_OPAQUE},
- {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+static struct vfs_fn_pointers vfs_streams_depot_fns = {
+ .fs_capabilities = streams_depot_fs_capabilities,
+ .open = streams_depot_open,
+ .stat = streams_depot_stat,
+ .lstat = streams_depot_lstat,
+ .unlink = streams_depot_unlink,
+ .rename = streams_depot_rename,
+ .streaminfo = streams_depot_streaminfo,
};
NTSTATUS vfs_streams_depot_init(void);
NTSTATUS vfs_streams_depot_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "streams_depot",
- streams_depot_ops);
+ &vfs_streams_depot_fns);
}