diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c index 0155c2ccc8d..e20ac4430ab 100644 --- a/source3/lib/adouble.c +++ b/source3/lib/adouble.c @@ -1072,6 +1072,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, status = string_replace_allocate(handle->conn, e->adx_name, string_replace_cmaps, + NULL, talloc_tos(), &mapped_name, vfs_translate_to_windows); @@ -1781,6 +1782,7 @@ static bool ad_collect_one_stream(struct vfs_handle_struct *handle, status = string_replace_allocate(handle->conn, e->adx_name, cmaps, + NULL, ad, &mapped_name, vfs_translate_to_unix); diff --git a/source3/lib/string_replace.c b/source3/lib/string_replace.c index 42022d78ab9..c3fbaa37629 100644 --- a/source3/lib/string_replace.c +++ b/source3/lib/string_replace.c @@ -138,6 +138,7 @@ struct char_mappings **string_replace_init_map(TALLOC_CTX *mem_ctx, NTSTATUS string_replace_allocate(connection_struct *conn, const char *name_in, struct char_mappings **cmaps, + struct char_mappings **term_cmaps, TALLOC_CTX *mem_ctx, char **mapped_name, enum vfs_translate_direction direction) @@ -170,6 +171,18 @@ NTSTATUS string_replace_allocate(connection_struct *conn, *ptr = map->entry[T_OFFSET((*ptr))][direction]; } + if (term_cmaps != NULL) { + /* ptr should now point at the terminating null. */ + if (ptr > tmpbuf) { + /* Move back to the last character. */ + ptr--; + map = term_cmaps[T_PICK((*ptr))]; + if (map != NULL) { + *ptr = map->entry[T_OFFSET((*ptr))][direction]; + } + } + } + ok = pull_ucs2_talloc(mem_ctx, mapped_name, tmpbuf, &converted_size); TALLOC_FREE(tmpbuf); diff --git a/source3/lib/string_replace.h b/source3/lib/string_replace.h index 012b1aa8f2e..f96b0d4bcd6 100644 --- a/source3/lib/string_replace.h +++ b/source3/lib/string_replace.h @@ -28,6 +28,7 @@ struct char_mappings **string_replace_init_map(TALLOC_CTX *mem_ctx, NTSTATUS string_replace_allocate(connection_struct *conn, const char *name_in, struct char_mappings **cmaps, + struct char_mappings **term_cmaps, TALLOC_CTX *mem_ctx, char **mapped_name, enum vfs_translate_direction direction); diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 355e1127998..12ddacd1d01 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -42,6 +42,7 @@ struct share_mapping_entry { int snum; struct share_mapping_entry *next; struct char_mappings **mappings; + struct char_mappings **term_mappings; }; struct catia_cache { @@ -71,7 +72,9 @@ static struct share_mapping_entry *get_srt(connection_struct *conn, return share; } -static struct share_mapping_entry *add_srt(int snum, const char **mappings) +static struct share_mapping_entry *add_srt(int snum, + const char **mappings, + const char **term_mappings) { struct share_mapping_entry *sme = NULL; @@ -83,13 +86,13 @@ static struct share_mapping_entry *add_srt(int snum, const char **mappings) sme->next = srt_head; srt_head = sme; - if (mappings == NULL) { - sme->mappings = NULL; - return sme; + if (mappings != NULL) { + sme->mappings = string_replace_init_map(sme, mappings); + } + if (term_mappings != NULL) { + sme->term_mappings = string_replace_init_map(sme, + term_mappings); } - - sme->mappings = string_replace_init_map(sme, mappings); - return sme; } @@ -97,6 +100,7 @@ static bool init_mappings(connection_struct *conn, struct share_mapping_entry **selected_out) { const char **mappings = NULL; + const char **term_mappings = NULL; struct share_mapping_entry *share_level = NULL; struct share_mapping_entry *global = NULL; @@ -104,31 +108,40 @@ static bool init_mappings(connection_struct *conn, share_level = get_srt(conn, &global); if (share_level) { *selected_out = share_level; - return (share_level->mappings != NULL); + return (share_level->mappings != NULL) || + (share_level->term_mappings != NULL); } /* see if we have a global setting */ if (!global) { /* global setting */ mappings = lp_parm_string_list(-1, "catia", "mappings", NULL); - global = add_srt(GLOBAL_SECTION_SNUM, mappings); + term_mappings = lp_parm_string_list(-1, + "catia", + "terminating mappings", + NULL); + global = add_srt(GLOBAL_SECTION_SNUM, mappings, term_mappings); } /* no global setting - what about share level ? */ mappings = lp_parm_string_list(SNUM(conn), "catia", "mappings", NULL); - share_level = add_srt(SNUM(conn), mappings); + term_mappings = lp_parm_string_list(SNUM(conn), + "catia", + "terminating mappings", + NULL); + share_level = add_srt(SNUM(conn), mappings, term_mappings); - if (share_level->mappings) { + if (share_level->mappings || share_level->term_mappings) { (*selected_out) = share_level; - return True; + return true; } - if (global->mappings) { + if (global->mappings || global->term_mappings) { share_level->mappings = global->mappings; (*selected_out) = share_level; - return True; + return true; } - return False; + return false; } static NTSTATUS catia_string_replace_allocate(connection_struct *conn, @@ -152,6 +165,7 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn, status = string_replace_allocate(conn, name_in, selected->mappings, + selected->term_mappings, talloc_tos(), mapped_name, direction);