#include "includes.h"
#include "smbd/smbd.h"
#include "system/filesys.h"
+#include "source3/smbd/dir.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
return true;
}
-static bool mark_file_valid(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
-{
- char buf = '1';
- int ret;
-
- DEBUG(10, ("marking file %s as valid\n", smb_fname->base_name));
-
- ret = SMB_VFS_FSETXATTR(smb_fname->fsp, SAMBA_XATTR_MARKER,
- &buf, sizeof(buf), 0);
-
- if (ret == -1) {
- DEBUG(10, ("SETXATTR failed: %s\n", strerror(errno)));
- return false;
- }
-
- return true;
-}
-
/*
* Return the root of the stream directory. Can be
* external to the share definition but by default
char *rootdir = NULL;
struct smb_filename *rootdir_fname = NULL;
struct smb_filename *tmp_fname = NULL;
- struct smb_filename *tmpref = NULL;
- const struct smb_filename *pathref = NULL;
int ret;
check_valid = lp_parm_bool(SNUM(handle->conn),
id = SMB_VFS_FILE_ID_CREATE(handle->conn, &base_sbuf_tmp);
- push_file_id_16((char *)id_buf, &id);
+ push_file_id_16(id_buf, &id);
hash = hash_fn(data_blob_const(id_buf, sizeof(id_buf)));
if ((ret != 0) && (errno != EEXIST)) {
goto fail;
}
- pathref = smb_fname;
- if (smb_fname->fsp == NULL) {
- NTSTATUS status;
- status = synthetic_pathref(talloc_tos(),
- handle->conn->cwd_fsp,
- smb_fname->base_name,
- NULL,
- NULL,
- smb_fname->twrp,
- smb_fname->flags,
- &tmpref);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
- pathref = tmpref;
- }
- if (check_valid && !mark_file_valid(handle, pathref)) {
- goto fail;
- }
- TALLOC_FREE(tmpref);
TALLOC_FREE(rootdir_fname);
TALLOC_FREE(rootdir);
TALLOC_FREE(tmp_fname);
return result;
fail:
- TALLOC_FREE(tmpref);
TALLOC_FREE(rootdir_fname);
TALLOC_FREE(rootdir);
TALLOC_FREE(tmp_fname);
* stream.
*/
static NTSTATUS stream_smb_fname(vfs_handle_struct *handle,
+ const struct stat_ex *base_sbuf,
const struct smb_filename *smb_fname,
struct smb_filename **smb_fname_out,
bool create_dir)
}
}
- dirname = stream_dir(handle, smb_fname, NULL, create_dir);
+ dirname = stream_dir(handle, smb_fname, base_sbuf, create_dir);
if (dirname == NULL) {
status = map_nt_error_from_unix(errno);
goto fail;
}
} else {
- /* Normalize the stream type to upercase. */
+ /* Normalize the stream type to uppercase. */
if (!strupper_m(strrchr_m(stream_fname, ':') + 1)) {
status = NT_STATUS_INVALID_PARAMETER;
goto fail;
struct smb_filename *dir_smb_fname = NULL;
struct smb_Dir *dir_hnd = NULL;
const char *dname = NULL;
- long offset = 0;
char *talloced = NULL;
NTSTATUS status;
return status;
}
- while ((dname = ReadDirName(dir_hnd, &offset, NULL, &talloced))
- != NULL)
- {
+ while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
if (ISDOT(dname) || ISDOTDOT(dname)) {
TALLOC_FREE(talloced);
continue;
}
/* Stat the actual stream now. */
- status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
- false);
+ status = stream_smb_fname(
+ handle, NULL, smb_fname, &smb_fname_stream, false);
if (!NT_STATUS_IS_OK(status)) {
ret = -1;
errno = map_errno_from_nt_status(status);
}
/* Stat the actual stream now. */
- status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
- false);
+ status = stream_smb_fname(
+ handle, NULL, smb_fname, &smb_fname_stream, false);
if (!NT_STATUS_IS_OK(status)) {
ret = -1;
errno = map_errno_from_nt_status(status);
const struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
struct files_struct *fsp,
- int flags,
- mode_t mode)
+ const struct vfs_open_how *how)
{
struct smb_filename *smb_fname_stream = NULL;
- struct smb_filename *smb_fname_base = NULL;
struct files_struct *fspcwd = NULL;
NTSTATUS status;
+ bool create_it;
int ret = -1;
if (!is_named_stream(smb_fname)) {
dirfsp,
smb_fname,
fsp,
- flags,
- mode);
+ how);
}
- SMB_ASSERT(fsp_is_alternate_stream(fsp));
-
- /*
- * For now assert this so the below SMB_VFS_STAT() is ok.
- */
- SMB_ASSERT(fsp_get_pathref_fd(dirfsp) == AT_FDCWD);
-
- /* Ensure the base file still exists. */
- smb_fname_base = synthetic_smb_fname(talloc_tos(),
- smb_fname->base_name,
- NULL,
- NULL,
- smb_fname->twrp,
- smb_fname->flags);
- if (smb_fname_base == NULL) {
- ret = -1;
- errno = ENOMEM;
- goto done;
+ if (how->resolve != 0) {
+ errno = ENOSYS;
+ return -1;
}
- ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
- if (ret == -1) {
- goto done;
- }
+ SMB_ASSERT(fsp_is_alternate_stream(fsp));
+ SMB_ASSERT(dirfsp == NULL);
+ SMB_ASSERT(VALID_STAT(fsp->base_fsp->fsp_name->st));
+
+ create_it = (how->flags & O_CREAT);
/* Determine the stream name, and then open it. */
- status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true);
+ status = stream_smb_fname(
+ handle,
+ &fsp->base_fsp->fsp_name->st,
+ fsp->fsp_name,
+ &smb_fname_stream,
+ create_it);
if (!NT_STATUS_IS_OK(status)) {
ret = -1;
errno = map_errno_from_nt_status(status);
goto done;
}
+ if (create_it) {
+ bool check_valid = lp_parm_bool(
+ SNUM(handle->conn),
+ "streams_depot",
+ "check_valid",
+ true);
+
+ if (check_valid) {
+ char buf = '1';
+
+ DBG_DEBUG("marking file %s as valid\n",
+ fsp->base_fsp->fsp_name->base_name);
+
+ ret = SMB_VFS_FSETXATTR(
+ fsp->base_fsp,
+ SAMBA_XATTR_MARKER,
+ &buf,
+ sizeof(buf),
+ 0);
+
+ if (ret == -1) {
+ DBG_DEBUG("FSETXATTR failed: %s\n",
+ strerror(errno));
+ goto done;
+ }
+ }
+ }
+
status = vfs_at_fspcwd(talloc_tos(), handle->conn, &fspcwd);
if (!NT_STATUS_IS_OK(status)) {
ret = -1;
fspcwd,
smb_fname_stream,
fsp,
- flags,
- mode);
+ how);
done:
TALLOC_FREE(smb_fname_stream);
- TALLOC_FREE(smb_fname_base);
TALLOC_FREE(fspcwd);
return ret;
}
struct smb_filename *smb_fname_stream = NULL;
NTSTATUS status;
- status = stream_smb_fname(handle, full_fname, &smb_fname_stream,
- false);
+ status = stream_smb_fname(
+ handle, NULL, full_fname, &smb_fname_stream, false);
TALLOC_FREE(full_fname);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto done;
}
- status = stream_smb_fname(handle, full_src, &smb_fname_src_stream,
- false);
+ status = stream_smb_fname(
+ handle, NULL, full_src, &smb_fname_src_stream, false);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto done;
}
- status = stream_smb_fname(handle, full_dst,
- &smb_fname_dst_stream, false);
+ status = stream_smb_fname(
+ handle, NULL, full_dst, &smb_fname_dst_stream, false);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto done;