*
* Copyright (C) Volker Lendecke, 2005
* Copyright (C) Aravind Srinivasan, 2009
+ * Copyright (C) Guenter Kukkukk, 2013
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "includes.h"
+#include "smbd/smbd.h"
+
+static int vfs_catia_debug_level = DBGC_VFS;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS vfs_catia_debug_level
#define GLOBAL_SNUM 0xFFFFFFF
#define MAP_SIZE 0xFF
* catia mappings are of the form :
* UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
*
- * multiple mappings are comma seperated in smb.conf
+ * multiple mappings are comma separated in smb.conf
*/
for (i=0;mappings[i];i++) {
fstrcpy(mapping, mappings[i]);
if (share_level->mappings) {
(*selected_out) = share_level;
return True;
- } else if (global->mappings) {
+ }
+ if (global->mappings) {
share_level->mappings = global->mappings;
(*selected_out) = share_level;
return True;
static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
const char *name_in,
char **mapped_name,
- int direction)
+ enum vfs_translate_direction direction)
{
static smb_ucs2_t *tmpbuf = NULL;
smb_ucs2_t *ptr;
size_t converted_size;
TALLOC_CTX *ctx = talloc_tos();
- if (!init_mappings(conn, &selected))
+ if (!init_mappings(conn, &selected)) {
+ /* No mappings found. Just use the old name */
+ *mapped_name = talloc_strdup(NULL, name_in);
+ if (!*mapped_name) {
+ errno = ENOMEM;
+ return NT_STATUS_NO_MEMORY;
+ }
return NT_STATUS_OK;
+ }
if ((push_ucs2_talloc(ctx, &tmpbuf, name_in,
- &converted_size)) == -1) {
+ &converted_size)) == false) {
return map_nt_error_from_unix(errno);
}
ptr = tmpbuf;
}
if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf,
- &converted_size)) == -1) {
+ &converted_size)) == false) {
TALLOC_FREE(tmpbuf);
return map_nt_error_from_unix(errno);
}
return NT_STATUS_OK;
}
-static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
- const char *fname,
- const char *mask,
- uint32 attr)
+static DIR *catia_opendir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ const char *mask,
+ uint32_t attr)
{
char *name_mapped = NULL;
NTSTATUS status;
- SMB_STRUCT_DIR *ret;
+ DIR *ret;
+ struct smb_filename *mapped_smb_fname = NULL;
- status = catia_string_replace_allocate(handle->conn, fname,
- &name_mapped, vfs_translate_to_unix);
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
+ &name_mapped,
+ vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return NULL;
}
- ret = SMB_VFS_NEXT_OPENDIR(handle, name_mapped, mask, attr);
+ mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
+ name_mapped,
+ NULL,
+ NULL);
+ if (mapped_smb_fname == NULL) {
+ TALLOC_FREE(mapped_smb_fname);
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ret = SMB_VFS_NEXT_OPENDIR(handle, mapped_smb_fname, mask, attr);
+
TALLOC_FREE(name_mapped);
+ TALLOC_FREE(mapped_smb_fname);
return ret;
}
* TRANSLATE_NAME call which converts the given name to
* "WINDOWS displayable" name
*/
-static NTSTATUS catia_translate_name(vfs_handle_struct *handle,
- char **mapped_name,
- enum vfs_translate_direction direction)
+static NTSTATUS catia_translate_name(struct vfs_handle_struct *handle,
+ const char *orig_name,
+ enum vfs_translate_direction direction,
+ TALLOC_CTX *mem_ctx,
+ char **pmapped_name)
{
char *name = NULL;
- NTSTATUS ret;
+ char *mapped_name;
+ NTSTATUS status, ret;
/*
* Copy the supplied name and free the memory for mapped_name,
* We will be allocating new memory for mapped_name in
* catia_string_replace_allocate
*/
- name = talloc_strdup(talloc_tos(), *mapped_name);
+ name = talloc_strdup(talloc_tos(), orig_name);
if (!name) {
errno = ENOMEM;
return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(*mapped_name);
- ret = catia_string_replace_allocate(handle->conn, name,
- mapped_name, direction);
+ status = catia_string_replace_allocate(handle->conn, name,
+ &mapped_name, direction);
TALLOC_FREE(name);
- if (!NT_STATUS_IS_OK(ret)) {
- return ret;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction);
+ ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction,
+ mem_ctx, pmapped_name);
+
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+ *pmapped_name = talloc_move(mem_ctx, &mapped_name);
+ /* we need to return the former translation result here */
+ ret = status;
+ } else {
+ TALLOC_FREE(mapped_name);
+ }
return ret;
}
}
/* Setup temporary smb_filename structs. */
- status = copy_smb_filename(ctx, smb_fname_src, &smb_fname_src_tmp);
-
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_fname_src_tmp = cp_smb_filename(ctx, smb_fname_src);
+ if (smb_fname_src_tmp == NULL) {
+ errno = ENOMEM;
goto out;
}
- status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
+ if (smb_fname_dst_tmp == NULL) {
+ errno = ENOMEM;
goto out;
}
}
/* Setup temporary smb_filename structs. */
- status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
+ if (smb_fname_tmp == NULL) {
+ errno = ENOMEM;
return -1;
}
return ret;
}
+static int catia_chmod(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ mode_t mode)
+{
+ char *name = NULL;
+ NTSTATUS status;
+ int ret;
+ int saved_errno;
+ struct smb_filename *catia_smb_fname = NULL;
+
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
+ &name,
+ vfs_translate_to_unix);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+ catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+ name,
+ NULL,
+ NULL);
+ if (catia_smb_fname == NULL) {
+ TALLOC_FREE(name);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = SMB_VFS_NEXT_CHMOD(handle, catia_smb_fname, mode);
+ saved_errno = errno;
+ TALLOC_FREE(name);
+ TALLOC_FREE(catia_smb_fname);
+ errno = saved_errno;
+ return ret;
+}
+
static int catia_rmdir(vfs_handle_struct *handle,
- const char *path)
+ const struct smb_filename *smb_fname)
{
char *name = NULL;
NTSTATUS status;
int ret;
+ struct smb_filename *catia_smb_fname = NULL;
- status = catia_string_replace_allocate(handle->conn, path,
- &name, vfs_translate_to_unix);
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
+ &name,
+ vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
}
+ catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+ name,
+ NULL,
+ NULL);
+ if (catia_smb_fname == NULL) {
+ TALLOC_FREE(name);
+ errno = ENOMEM;
+ return -1;
+ }
- ret = SMB_VFS_NEXT_RMDIR(handle, name);
+ ret = SMB_VFS_NEXT_RMDIR(handle, catia_smb_fname);
TALLOC_FREE(name);
+ TALLOC_FREE(catia_smb_fname);
return ret;
}
static int catia_mkdir(vfs_handle_struct *handle,
- const char *path,
+ const struct smb_filename *smb_fname,
mode_t mode)
{
char *name = NULL;
NTSTATUS status;
int ret;
+ struct smb_filename *catia_smb_fname = NULL;
- status = catia_string_replace_allocate(handle->conn, path,
- &name, vfs_translate_to_unix);
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
+ &name,
+ vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
}
+ catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+ name,
+ NULL,
+ NULL);
+ if (catia_smb_fname == NULL) {
+ TALLOC_FREE(name);
+ errno = ENOMEM;
+ return -1;
+ }
- ret = SMB_VFS_NEXT_MKDIR(handle, name, mode);
+ ret = SMB_VFS_NEXT_MKDIR(handle, catia_smb_fname, mode);
TALLOC_FREE(name);
+ TALLOC_FREE(catia_smb_fname);
return ret;
}
return -1;
}
- status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
+ if (smb_fname_tmp == NULL) {
+ errno = ENOMEM;
return -1;
}
}
static char *
-catia_realpath(vfs_handle_struct *handle, const char *path,
- char *resolved_path)
+catia_realpath(vfs_handle_struct *handle, const char *path)
{
char *mapped_name = NULL;
NTSTATUS status;
return NULL;
}
- ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name, resolved_path);
+ ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name);
TALLOC_FREE(mapped_name);
return ret;
struct files_struct *fsp,
const char *path,
TALLOC_CTX *mem_ctx,
- unsigned int *num_streams,
- struct stream_struct **streams)
+ unsigned int *_num_streams,
+ struct stream_struct **_streams)
{
char *mapped_name = NULL;
NTSTATUS status;
+ int i;
+ unsigned int num_streams = 0;
+ struct stream_struct *streams = NULL;
+
+ *_num_streams = 0;
+ *_streams = NULL;
status = catia_string_replace_allocate(handle->conn, path,
&mapped_name, vfs_translate_to_unix);
}
status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, mapped_name,
- mem_ctx, num_streams,streams);
+ mem_ctx, &num_streams, &streams);
TALLOC_FREE(mapped_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- return status;
+ /*
+ * Translate stream names just like the base names
+ */
+ for (i = 0; i < num_streams; i++) {
+ /*
+ * Strip ":" prefix and ":$DATA" suffix to get a
+ * "pure" stream name and only translate that.
+ */
+ void *old_ptr = streams[i].name;
+ char *stream_name = streams[i].name + 1;
+ char *stream_type = strrchr_m(stream_name, ':');
+
+ if (stream_type != NULL) {
+ *stream_type = '\0';
+ stream_type += 1;
+ }
+
+ status = catia_string_replace_allocate(handle->conn, stream_name,
+ &mapped_name, vfs_translate_to_windows);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(streams);
+ return status;
+ }
+
+ if (stream_type != NULL) {
+ streams[i].name = talloc_asprintf(streams, ":%s:%s",
+ mapped_name, stream_type);
+ } else {
+ streams[i].name = talloc_asprintf(streams, ":%s",
+ mapped_name);
+ }
+ TALLOC_FREE(mapped_name);
+ TALLOC_FREE(old_ptr);
+ if (streams[i].name == NULL) {
+ TALLOC_FREE(streams);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ *_num_streams = num_streams;
+ *_streams = streams;
+ return NT_STATUS_OK;
}
static NTSTATUS
catia_get_nt_acl(struct vfs_handle_struct *handle,
- const char *path,
- uint32 security_info,
+ const struct smb_filename *smb_fname,
+ uint32_t security_info,
+ TALLOC_CTX *mem_ctx,
struct security_descriptor **ppdesc)
{
char *mapped_name = NULL;
+ const char *path = smb_fname->base_name;
+ struct smb_filename *mapped_smb_fname = NULL;
NTSTATUS status;
status = catia_string_replace_allocate(handle->conn,
errno = map_errno_from_nt_status(status);
return status;
}
- status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_name,
- security_info, ppdesc);
+ mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
+ mapped_name,
+ NULL,
+ NULL);
+ if (mapped_smb_fname == NULL) {
+ TALLOC_FREE(mapped_name);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_smb_fname,
+ security_info, mem_ctx, ppdesc);
TALLOC_FREE(mapped_name);
+ TALLOC_FREE(mapped_smb_fname);
return status;
}
static int
catia_chmod_acl(vfs_handle_struct *handle,
- const char *path,
+ const struct smb_filename *smb_fname,
mode_t mode)
{
char *mapped_name = NULL;
+ struct smb_filename *mapped_smb_fname = NULL;
NTSTATUS status;
int ret;
+ int saved_errno;
status = catia_string_replace_allocate(handle->conn,
- path, &mapped_name, vfs_translate_to_unix);
+ smb_fname->base_name,
+ &mapped_name,
+ vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
}
- ret = SMB_VFS_NEXT_CHMOD_ACL(handle, mapped_name, mode);
+ mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
+ mapped_name,
+ NULL,
+ NULL);
+ if (mapped_smb_fname == NULL) {
+ TALLOC_FREE(mapped_name);
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = SMB_VFS_NEXT_CHMOD_ACL(handle, mapped_smb_fname, mode);
+ saved_errno = errno;
TALLOC_FREE(mapped_name);
+ TALLOC_FREE(mapped_smb_fname);
+ errno = saved_errno;
return ret;
}
static SMB_ACL_T
catia_sys_acl_get_file(vfs_handle_struct *handle,
const char *path,
- SMB_ACL_TYPE_T type)
+ SMB_ACL_TYPE_T type,
+ TALLOC_CTX *mem_ctx)
{
char *mapped_name = NULL;
NTSTATUS status;
return NULL;
}
- ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_name, type);
+ ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_name, type, mem_ctx);
TALLOC_FREE(mapped_name);
return ret;
return ret;
}
-static ssize_t
-catia_lgetxattr(vfs_handle_struct *handle, const char *path,
- const char *name, void *value, size_t size)
-{
- char *mapped_name = NULL;
- NTSTATUS status;
- ssize_t ret;
-
- status = catia_string_replace_allocate(handle->conn,
- name, &mapped_name, vfs_translate_to_unix);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
-
- ret = SMB_VFS_NEXT_LGETXATTR(handle, path, mapped_name, value, size);
- TALLOC_FREE(mapped_name);
-
- return ret;
-}
-
static ssize_t
catia_listxattr(vfs_handle_struct *handle, const char *path,
char *list, size_t size)
return ret;
}
-static ssize_t
-catia_llistxattr(vfs_handle_struct *handle, const char *path,
- char *list, size_t size)
-{
- char *mapped_name = NULL;
- NTSTATUS status;
- ssize_t ret;
-
- status = catia_string_replace_allocate(handle->conn,
- path, &mapped_name, vfs_translate_to_unix);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
-
- ret = SMB_VFS_NEXT_LLISTXATTR(handle, mapped_name, list, size);
- TALLOC_FREE(mapped_name);
-
- return ret;
-}
-
static int
catia_removexattr(vfs_handle_struct *handle, const char *path,
const char *name)
return ret;
}
-static int
-catia_lremovexattr(vfs_handle_struct *handle, const char *path,
- const char *name)
-{
- char *mapped_name = NULL;
- NTSTATUS status;
- ssize_t ret;
-
- status = catia_string_replace_allocate(handle->conn,
- name, &mapped_name, vfs_translate_to_unix);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
-
- ret = SMB_VFS_NEXT_LREMOVEXATTR(handle, path, mapped_name);
- TALLOC_FREE(mapped_name);
-
- return ret;
-}
-
static int
catia_setxattr(vfs_handle_struct *handle, const char *path,
const char *name, const void *value, size_t size,
return ret;
}
-static int
-catia_lsetxattr(vfs_handle_struct *handle, const char *path,
- const char *name, const void *value, size_t size,
- int flags)
-{
- char *mapped_name = NULL;
- NTSTATUS status;
- ssize_t ret;
-
- status = catia_string_replace_allocate(handle->conn,
- name, &mapped_name, vfs_translate_to_unix);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
-
- ret = SMB_VFS_NEXT_LSETXATTR(handle, path, mapped_name, value, size, flags);
- TALLOC_FREE(mapped_name);
-
- return ret;
-}
-
static struct vfs_fn_pointers vfs_catia_fns = {
- .mkdir = catia_mkdir,
- .rmdir = catia_rmdir,
- .opendir = catia_opendir,
- .open = catia_open,
- .rename = catia_rename,
- .stat = catia_stat,
- .lstat = catia_lstat,
- .unlink = catia_unlink,
- .chown = catia_chown,
- .lchown = catia_lchown,
- .chdir = catia_chdir,
- .ntimes = catia_ntimes,
- .realpath = catia_realpath,
- .chflags = catia_chflags,
- .streaminfo = catia_streaminfo,
- .translate_name = catia_translate_name,
- .get_nt_acl = catia_get_nt_acl,
- .chmod_acl = catia_chmod_acl,
- .sys_acl_get_file = catia_sys_acl_get_file,
- .sys_acl_set_file = catia_sys_acl_set_file,
- .sys_acl_delete_def_file = catia_sys_acl_delete_def_file,
- .getxattr = catia_getxattr,
- .lgetxattr = catia_lgetxattr,
- .listxattr = catia_listxattr,
- .llistxattr = catia_llistxattr,
- .removexattr = catia_removexattr,
- .lremovexattr = catia_lremovexattr,
- .setxattr = catia_setxattr,
- .lsetxattr = catia_lsetxattr,
+ .mkdir_fn = catia_mkdir,
+ .rmdir_fn = catia_rmdir,
+ .opendir_fn = catia_opendir,
+ .open_fn = catia_open,
+ .rename_fn = catia_rename,
+ .stat_fn = catia_stat,
+ .lstat_fn = catia_lstat,
+ .unlink_fn = catia_unlink,
+ .chown_fn = catia_chown,
+ .lchown_fn = catia_lchown,
+ .chmod_fn = catia_chmod,
+ .chdir_fn = catia_chdir,
+ .ntimes_fn = catia_ntimes,
+ .realpath_fn = catia_realpath,
+ .chflags_fn = catia_chflags,
+ .streaminfo_fn = catia_streaminfo,
+ .translate_name_fn = catia_translate_name,
+ .get_nt_acl_fn = catia_get_nt_acl,
+ .chmod_acl_fn = catia_chmod_acl,
+ .sys_acl_get_file_fn = catia_sys_acl_get_file,
+ .sys_acl_set_file_fn = catia_sys_acl_set_file,
+ .sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
+ .getxattr_fn = catia_getxattr,
+ .listxattr_fn = catia_listxattr,
+ .removexattr_fn = catia_removexattr,
+ .setxattr_fn = catia_setxattr,
};
+static_decl_vfs;
NTSTATUS vfs_catia_init(void)
{
- return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
+ NTSTATUS ret;
+
+ ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
&vfs_catia_fns);
+ if (!NT_STATUS_IS_OK(ret))
+ return ret;
+
+ vfs_catia_debug_level = debug_add_class("catia");
+ if (vfs_catia_debug_level == -1) {
+ vfs_catia_debug_level = DBGC_VFS;
+ DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
+ "class!\n"));
+ } else {
+ DEBUG(10, ("vfs_catia: Debug class number of "
+ "'catia': %d\n", vfs_catia_debug_level));
+ }
+
+ return ret;
+
}