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'))