diff --git a/source3/modules/string_replace.c b/source3/modules/string_replace.c new file mode 100644 index 00000000000..88b53fbbf4a --- /dev/null +++ b/source3/modules/string_replace.c @@ -0,0 +1,178 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Volker Lendecke, 2005 + * Copyright (C) Aravind Srinivasan, 2009 + * Copyright (C) Guenter Kukkukk, 2013 + * Copyright (C) Ralph Boehme, 2017 + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "smbd/smbd.h" +#include "string_replace.h" + +#define MAP_SIZE 0xFF +#define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */ +#define T_OFFSET(_v_) ((_v_ % MAP_SIZE)) +#define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE)) +#define T_PICK(_v_) ((_v_ / MAP_SIZE)) + +struct char_mappings { + smb_ucs2_t entry[MAP_SIZE][2]; +}; + +static bool build_table(struct char_mappings **cmaps, int value) +{ + int i; + int start = T_START(value); + + (*cmaps) = talloc_zero(NULL, struct char_mappings); + + if (!*cmaps) + return False; + + for (i = 0; i < MAP_SIZE;i++) { + (*cmaps)->entry[i][vfs_translate_to_unix] = start + i; + (*cmaps)->entry[i][vfs_translate_to_windows] = start + i; + } + + return True; +} + +static void set_tables(struct char_mappings **cmaps, + long unix_map, + long windows_map) +{ + int i; + + /* set unix -> windows */ + i = T_OFFSET(unix_map); + cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map; + + /* set windows -> unix */ + i = T_OFFSET(windows_map); + cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map; +} + +static bool build_ranges(struct char_mappings **cmaps, + long unix_map, + long windows_map) +{ + + if (!cmaps[T_PICK(unix_map)]) { + if (!build_table(&cmaps[T_PICK(unix_map)], unix_map)) + return False; + } + + if (!cmaps[T_PICK(windows_map)]) { + if (!build_table(&cmaps[T_PICK(windows_map)], windows_map)) + return False; + } + + set_tables(cmaps, unix_map, windows_map); + + return True; +} + +struct char_mappings **string_replace_init_map(const char **mappings) +{ + int i; + char *tmp; + fstring mapping; + long unix_map, windows_map; + struct char_mappings **cmaps = NULL; + + if (mappings == NULL) { + return NULL; + } + + cmaps = TALLOC_ZERO(NULL, MAP_NUM * sizeof(struct char_mappings *)); + if (cmaps == NULL) { + return NULL; + } + + /* + * catia mappings are of the form : + * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex) + * + * multiple mappings are comma separated in smb.conf + */ + + for (i = 0; mappings[i]; i++) { + fstrcpy(mapping, mappings[i]); + unix_map = strtol(mapping, &tmp, 16); + if (unix_map == 0 && errno == EINVAL) { + DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping)); + continue; + } + windows_map = strtol(++tmp, NULL, 16); + if (windows_map == 0 && errno == EINVAL) { + DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping)); + continue; + } + + if (!build_ranges(cmaps, unix_map, windows_map)) { + DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping)); + continue; + } + } + + return cmaps; +} + +NTSTATUS string_replace_allocate(connection_struct *conn, + const char *name_in, + struct char_mappings **cmaps, + TALLOC_CTX *mem_ctx, + char **mapped_name, + enum vfs_translate_direction direction) +{ + static smb_ucs2_t *tmpbuf = NULL; + smb_ucs2_t *ptr = NULL; + struct char_mappings *map = NULL; + size_t converted_size; + bool ok; + + ok = push_ucs2_talloc(talloc_tos(), &tmpbuf, name_in, + &converted_size); + if (!ok) { + return map_nt_error_from_unix(errno); + } + + for (ptr = tmpbuf; *ptr; ptr++) { + if (*ptr == 0) { + break; + } + if (cmaps == NULL) { + continue; + } + map = cmaps[T_PICK((*ptr))]; + if (map == NULL) { + /* nothing to do */ + continue; + } + + *ptr = map->entry[T_OFFSET((*ptr))][direction]; + } + + ok = pull_ucs2_talloc(mem_ctx, mapped_name, tmpbuf, + &converted_size); + TALLOC_FREE(tmpbuf); + if (!ok) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; +} diff --git a/source3/modules/string_replace.h b/source3/modules/string_replace.h new file mode 100644 index 00000000000..d7c9b52c85c --- /dev/null +++ b/source3/modules/string_replace.h @@ -0,0 +1,32 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Volker Lendecke, 2005 + * Copyright (C) Aravind Srinivasan, 2009 + * Copyright (C) Guenter Kukkukk, 2013 + * Copyright (C) Ralph Boehme, 2017 + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +struct char_mappings; + +struct char_mappings **string_replace_init_map(const char **mappings); + +NTSTATUS string_replace_allocate(connection_struct *conn, + const char *name_in, + struct char_mappings **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 c47b64d8657..ce760ceefda 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -31,23 +31,13 @@ #include "smbd/smbd.h" #include "lib/util/tevent_unix.h" #include "lib/util/tevent_ntstatus.h" +#include "string_replace.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 -#define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */ -#define T_OFFSET(_v_) ((_v_ % MAP_SIZE)) -#define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE)) -#define T_PICK(_v_) ((_v_ / MAP_SIZE)) - -struct char_mappings { - smb_ucs2_t entry[MAP_SIZE][2]; -}; - struct share_mapping_entry { int snum; struct share_mapping_entry *next; @@ -65,66 +55,13 @@ struct catia_cache { struct share_mapping_entry *srt_head = NULL; -static bool build_table(struct char_mappings **cmaps, int value) -{ - int i; - int start = T_START(value); - - (*cmaps) = talloc_zero(NULL, struct char_mappings); - - if (!*cmaps) - return False; - - for (i = 0; i < MAP_SIZE;i++) { - (*cmaps)->entry[i][vfs_translate_to_unix] = start + i; - (*cmaps)->entry[i][vfs_translate_to_windows] = start + i; - } - - return True; -} - -static void set_tables(struct char_mappings **cmaps, - long unix_map, - long windows_map) -{ - int i; - - /* set unix -> windows */ - i = T_OFFSET(unix_map); - cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map; - - /* set windows -> unix */ - i = T_OFFSET(windows_map); - cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map; -} - -static bool build_ranges(struct char_mappings **cmaps, - long unix_map, - long windows_map) -{ - - if (!cmaps[T_PICK(unix_map)]) { - if (!build_table(&cmaps[T_PICK(unix_map)], unix_map)) - return False; - } - - if (!cmaps[T_PICK(windows_map)]) { - if (!build_table(&cmaps[T_PICK(windows_map)], windows_map)) - return False; - } - - set_tables(cmaps, unix_map, windows_map); - - return True; -} - static struct share_mapping_entry *get_srt(connection_struct *conn, struct share_mapping_entry **global) { struct share_mapping_entry *share; for (share = srt_head; share != NULL; share = share->next) { - if (share->snum == GLOBAL_SNUM) + if (share->snum == GLOBAL_SECTION_SNUM) (*global) = share; if (share->snum == SNUM(conn)) @@ -136,61 +73,24 @@ static struct share_mapping_entry *get_srt(connection_struct *conn, static struct share_mapping_entry *add_srt(int snum, const char **mappings) { + struct share_mapping_entry *sme = NULL; - char *tmp; - fstring mapping; - int i; - long unix_map, windows_map; - struct share_mapping_entry *ret = NULL; + sme = TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry)); + if (sme == NULL) + return sme; - ret = (struct share_mapping_entry *) - TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry) + - (mappings ? (MAP_NUM * sizeof(struct char_mappings *)) : 0)); + sme->snum = snum; + sme->next = srt_head; + srt_head = sme; - if (!ret) - return ret; - - ret->snum = snum; - - ret->next = srt_head; - srt_head = ret; - - if (mappings) { - ret->mappings = (struct char_mappings**) ((unsigned char*) ret + - sizeof(struct share_mapping_entry)); - memset(ret->mappings, 0, - MAP_NUM * sizeof(struct char_mappings *)); - } else { - ret->mappings = NULL; - return ret; + if (mappings == NULL) { + sme->mappings = NULL; + return sme; } - /* - * catia mappings are of the form : - * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex) - * - * multiple mappings are comma separated in smb.conf - */ - for (i=0;mappings[i];i++) { - fstrcpy(mapping, mappings[i]); - unix_map = strtol(mapping, &tmp, 16); - if (unix_map == 0 && errno == EINVAL) { - DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping)); - continue; - } - windows_map = strtol(++tmp, NULL, 16); - if (windows_map == 0 && errno == EINVAL) { - DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping)); - continue; - } + sme->mappings = string_replace_init_map(mappings); - if (!build_ranges(ret->mappings, unix_map, windows_map)) { - DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping)); - continue; - } - } - - return ret; + return sme; } static bool init_mappings(connection_struct *conn, @@ -211,7 +111,7 @@ static bool init_mappings(connection_struct *conn, if (!global) { /* global setting */ mappings = lp_parm_string_list(-1, "catia", "mappings", NULL); - global = add_srt(GLOBAL_SNUM, mappings); + global = add_srt(GLOBAL_SECTION_SNUM, mappings); } /* no global setting - what about share level ? */ @@ -236,12 +136,8 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn, char **mapped_name, enum vfs_translate_direction direction) { - static smb_ucs2_t *tmpbuf = NULL; - smb_ucs2_t *ptr; struct share_mapping_entry *selected; - struct char_mappings *map = NULL; - size_t converted_size; - TALLOC_CTX *ctx = talloc_tos(); + NTSTATUS status; if (!init_mappings(conn, &selected)) { /* No mappings found. Just use the old name */ @@ -253,30 +149,13 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn, return NT_STATUS_OK; } - if ((push_ucs2_talloc(ctx, &tmpbuf, name_in, - &converted_size)) == false) { - return map_nt_error_from_unix(errno); - } - ptr = tmpbuf; - for(;*ptr;ptr++) { - if (*ptr == 0) - break; - map = selected->mappings[T_PICK((*ptr))]; - - /* nothing to do */ - if (!map) - continue; - - *ptr = map->entry[T_OFFSET((*ptr))][direction]; - } - - if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf, - &converted_size)) == false) { - TALLOC_FREE(tmpbuf); - return map_nt_error_from_unix(errno); - } - TALLOC_FREE(tmpbuf); - return NT_STATUS_OK; + status = string_replace_allocate(conn, + name_in, + selected->mappings, + talloc_tos(), + mapped_name, + direction); + return status; } static DIR *catia_opendir(vfs_handle_struct *handle, diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index 58aaf2e99d9..810dc4cd6be 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -29,6 +29,9 @@ bld.SAMBA3_SUBSYSTEM('OFFLOAD_TOKEN', source='offload_token.c', deps='samba-util') +bld.SAMBA3_SUBSYSTEM('STRING_REPLACE', + source='string_replace.c') + bld.SAMBA3_MODULE('vfs_default', subsystem='vfs', source='vfs_default.c', @@ -239,7 +242,7 @@ bld.SAMBA3_MODULE('vfs_tru64acl', bld.SAMBA3_MODULE('vfs_catia', subsystem='vfs', source='vfs_catia.c', - deps='samba-util', + deps='samba-util STRING_REPLACE', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_catia'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_catia'))