VFS: Modify chmod_acl to take a const struct smb_filename * instead of const char *
[nivanova/samba-autobuild/.git] / source3 / modules / vfs_catia.c
index 652c3caf1fc7541b6aba249650446ef8a5753161..e142ccef8ef09218e56f3a5b93757babc96c3c4c 100644 (file)
@@ -155,7 +155,7 @@ static struct share_mapping_entry *add_srt(int snum, const char **mappings)
         * 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]);
@@ -210,7 +210,8 @@ static bool init_mappings(connection_struct *conn,
        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;
@@ -222,7 +223,7 @@ static bool init_mappings(connection_struct *conn,
 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;
@@ -268,23 +269,38 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
 }
 
 static DIR *catia_opendir(vfs_handle_struct *handle,
-                                    const char *fname,
-                                    const char *mask,
-                                    uint32 attr)
+                       const struct smb_filename *smb_fname,
+                       const char *mask,
+                       uint32_t attr)
 {
        char *name_mapped = NULL;
        NTSTATUS status;
        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;
 }
@@ -491,9 +507,9 @@ static int catia_unlink(vfs_handle_struct *handle,
        }
 
        /* 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;
        }
 
@@ -549,43 +565,105 @@ static int catia_lchown(vfs_handle_struct *handle,
        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;
 }
@@ -627,9 +705,9 @@ static int catia_ntimes(vfs_handle_struct *handle,
                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;
        }
 
@@ -686,11 +764,17 @@ catia_streaminfo(struct vfs_handle_struct *handle,
                 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);
@@ -700,20 +784,66 @@ catia_streaminfo(struct vfs_handle_struct *handle,
        }
 
        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,
@@ -722,31 +852,57 @@ catia_get_nt_acl(struct vfs_handle_struct *handle,
                errno = map_errno_from_nt_status(status);
                return status;
        }
-       status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_name,
+       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;
 }
 
@@ -917,6 +1073,7 @@ static struct vfs_fn_pointers vfs_catia_fns = {
        .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,
@@ -934,6 +1091,7 @@ static struct vfs_fn_pointers vfs_catia_fns = {
        .setxattr_fn = catia_setxattr,
 };
 
+static_decl_vfs;
 NTSTATUS vfs_catia_init(void)
 {
        NTSTATUS ret;