*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "onefs.h"
#include "onefs_config.h"
#include <sys/isi_enc.h>
-/*
- * OneFS stores streams without the explicit :$DATA at the end, so this strips
- * it off. All onefs_stream functions must call through this instead of
- * split_ntfs_stream_name directly.
- */
-NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
- char **pbase, char **pstream)
-{
- NTSTATUS status;
- char *stream;
-
- status = split_ntfs_stream_name(mem_ctx, fname, pbase, pstream);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* Default $DATA stream. */
- if (pstream == NULL || *pstream == NULL) {
- return NT_STATUS_OK;
- }
-
- /* Strip off the $DATA. */
- stream = strrchr_m(*pstream, ':');
- SMB_ASSERT(stream);
- stream[0] = '\0';
-
- return NT_STATUS_OK;
-}
-
NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx,
const struct smb_filename *smb_fname_in,
struct smb_filename **smb_fname_out)
/* Strip off the :$DATA if one exists. */
str_tmp = strrchr_m(stream_name, ':');
if (str_tmp) {
+ if (strcasecmp_m(str_tmp, ":$DATA") != 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
str_tmp[0] = '\0';
}
}
stream_name, &smb_fname_in->st,
smb_fname_out);
TALLOC_FREE(stream_name);
- return status;
-}
-int onefs_is_stream(const char *path, char **pbase, char **pstream,
- bool *is_stream)
-{
- (*is_stream) = is_ntfs_stream_name(path);
-
- if (!(*is_stream)) {
- return 0;
- }
-
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
- pbase, pstream))) {
- DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
- errno = ENOMEM;
- return -1;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5, ("Failed to prep stream name for %s: %s\n",
+ *smb_fname_out ?
+ smb_fname_str_dbg(*smb_fname_out) : "NULL",
+ nt_errstr(status)));
}
-
- return 0;
+ return status;
}
int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp)
int dir_fd;
int saved_errno;
+ DEBUG(10, ("Getting stream directory fd: %s (%d)\n", base,
+ base_fdp ? *base_fdp : -1));
+
/* If a valid base_fdp was given, use it. */
if (base_fdp && *base_fdp >= 0) {
base_fd = *base_fdp;
0,
NULL);
if (base_fd < 0) {
+ DEBUG(5, ("Failed getting base fd: %s\n",
+ strerror(errno)));
return -1;
}
}
*base_fdp = base_fd;
}
+ if (dir_fd < 0) {
+ DEBUG(5, ("Failed getting stream directory fd: %s\n",
+ strerror(errno)));
+ }
+
return dir_fd;
}
/* For now don't allow renames from or to the default stream. */
if (is_ntfs_default_stream_smb_fname(smb_fname_src) ||
is_ntfs_default_stream_smb_fname(smb_fname_dst)) {
+ DEBUG(3, ("Unable to rename to/from a default stream: %s -> "
+ "%s\n", smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_dst)));
errno = ENOSYS;
goto done;
}
/* Stat the stream. */
ret = onefs_sys_fstat_at(dir_fd, stream, sbuf, flags);
if (ret != -1) {
+ DEBUG(10, ("stat of stream '%s' failed: %s\n", stream,
+ strerror(errno)));
+ } else {
/* Now stat the base file and merge the results. */
ret = onefs_sys_fstat(base_fd, &base_sbuf);
if (ret != -1) {
}
}
- onefs_adjust_stat_time(handle->conn, fsp->fsp_name, sbuf);
+ onefs_adjust_stat_time(handle->conn, fsp->fsp_name->base_name, sbuf);
return ret;
}
}
int onefs_unlink(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
+ const struct smb_filename *smb_fname)
{
struct smb_filename *smb_fname_onefs = NULL;
int ret;
- bool is_stream;
- char *base = NULL;
- char *stream = NULL;
int dir_fd, saved_errno;
+ NTSTATUS status;
/* Not a stream. */
if (!is_ntfs_stream_smb_fname(smb_fname)) {
START_PROFILE(syscall_ntimes);
- ret = onefs_is_stream(fname, &base, &stream, &is_stream);
- if (ret)
- return ret;
-
if (!is_ntfs_stream_smb_fname(smb_fname)) {
ret = vtimes(smb_fname->base_name, times, flags);
return ret;
static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
struct stream_struct **streams,
- const char *name, SMB_OFF_T size,
- SMB_OFF_T alloc_size)
+ const char *name, off_t size,
+ off_t alloc_size)
{
struct stream_struct *tmp;
- tmp = TALLOC_REALLOC_ARRAY(mem_ctx, *streams, struct stream_struct,
+ tmp = talloc_realloc(mem_ctx, *streams, struct stream_struct,
(*num_streams)+1);
if (tmp == NULL) {
return false;
int dir_fd = -1;
int stream_fd = -1;
int ret;
- SMB_STRUCT_DIR *dirp = NULL;
- SMB_STRUCT_DIRENT *dp = NULL;
+ DIR *dirp = NULL;
+ struct dirent *dp = NULL;
files_struct fake_fs;
struct fd_handle fake_fh;
SMB_STRUCT_STAT stream_sbuf;
fake_fs.conn = conn;
fake_fs.fh = &fake_fh;
- fake_fs.fsp_name = SMB_STRDUP(fname);
+ status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
+ &fake_fs.fsp_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
/* Iterate over the streams in the ADS directory. */
while ((dp = SMB_VFS_READDIR(conn, dirp, NULL)) != NULL) {
close(base_fd);
}
- SAFE_FREE(fake_fs.fsp_name);
+ TALLOC_FREE(fake_fs.fsp_name);
return status;
}
return map_nt_error_from_unix(errno);
}
- state.streams = NULL;
- state.num_streams = 0;
+ state.streams = *pstreams;
+ state.num_streams = *pnum_streams;
if (lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) {
goto out;
}
- /* Add the default stream. */
- if (S_ISREG(sbuf.st_ex_mode)) {
- if (!add_one_stream(mem_ctx,
- &state.num_streams, &state.streams,
- "", sbuf.st_ex_size,
- SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp,
- &sbuf))) {
- return NT_STATUS_NO_MEMORY;
- }
- }
-
state.mem_ctx = mem_ctx;
state.handle = handle;
state.status = NT_STATUS_OK;
out:
*num_streams = state.num_streams;
*streams = state.streams;
- return NT_STATUS_OK;
+ return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams);
}