From 6901b3c64a65d9745efac13f071225d5d2949f4d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 4 Dec 2007 01:51:44 +0100 Subject: r26278: Tallocify convenience table for iconv handles. (This used to be commit ad64b3baa4a5383c603d17ae75c33083af4690bb) --- source4/lib/charset/charcnv.c | 106 +++++++++++++++++++++++++++------------- source4/lib/charset/charset.h | 2 + source4/param/loadparm.c | 2 +- source4/smbd/process_standard.c | 4 +- source4/torture/masktest.c | 2 +- source4/torture/smbtorture.c | 6 +-- 6 files changed, 80 insertions(+), 42 deletions(-) diff --git a/source4/lib/charset/charcnv.c b/source4/lib/charset/charcnv.c index 6bb72af8e1..bbb8f05226 100644 --- a/source4/lib/charset/charcnv.c +++ b/source4/lib/charset/charcnv.c @@ -38,16 +38,26 @@ * @sa lib/iconv.c */ +struct smb_iconv_convenience { + const char *unix_charset; + const char *dos_charset; + const char *display_charset; + smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; +}; + +static struct smb_iconv_convenience *global_smb_iconv_convenience = NULL; + + /** * Return the name of a charset to give to iconv(). **/ -static const char *charset_name(struct loadparm_context *lp_ctx, charset_t ch) +static const char *charset_name(struct smb_iconv_convenience *ic, charset_t ch) { switch (ch) { case CH_UTF16: return "UTF-16LE"; - case CH_UNIX: return lp_unix_charset(lp_ctx); - case CH_DOS: return lp_dos_charset(lp_ctx); - case CH_DISPLAY: return lp_display_charset(lp_ctx); + case CH_UNIX: return ic->unix_charset; + case CH_DOS: return ic->dos_charset; + case CH_DISPLAY: return ic->display_charset; case CH_UTF8: return "UTF8"; case CH_UTF16BE: return "UTF-16BE"; default: @@ -55,31 +65,57 @@ static const char *charset_name(struct loadparm_context *lp_ctx, charset_t ch) } } -static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - /** re-initialize iconv conversion descriptors **/ -_PUBLIC_ void close_iconv(void) +static int close_iconv(struct smb_iconv_convenience *data) { unsigned c1, c2; for (c1=0;c1conv_handles[c1][c2] != NULL) { + if (data->conv_handles[c1][c2] != (smb_iconv_t)-1) { + smb_iconv_close(data->conv_handles[c1][c2]); } - conv_handles[c1][c2] = NULL; + data->conv_handles[c1][c2] = NULL; } } } + return 0; +} + +struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx) +{ + struct smb_iconv_convenience *ret = talloc_zero(mem_ctx, + struct smb_iconv_convenience); + + talloc_set_destructor(ret, close_iconv); + + ret->display_charset = talloc_strdup(ret, lp_display_charset(lp_ctx)); + ret->dos_charset = talloc_strdup(ret, lp_dos_charset(lp_ctx)); + ret->unix_charset = talloc_strdup(ret, lp_unix_charset(lp_ctx)); + + return ret; +} + + +_PUBLIC_ void reload_charcnv(void) +{ + talloc_free(global_smb_iconv_convenience); + global_smb_iconv_convenience = smb_iconv_convenience_init(talloc_autofree_context(), global_loadparm); +} + +static void free_global_smb_iconv_convenience(void) +{ + talloc_free(global_smb_iconv_convenience); } /* on-demand initialisation of conversion handles */ -static smb_iconv_t get_conv_handle(struct loadparm_context *lp_ctx, +static smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic, charset_t from, charset_t to) { const char *n1, *n2; @@ -98,34 +134,33 @@ static smb_iconv_t get_conv_handle(struct loadparm_context *lp_ctx, */ setlocale(LC_ALL, "C"); #endif - - atexit(close_iconv); + atexit(free_global_smb_iconv_convenience); } - if (conv_handles[from][to]) { - return conv_handles[from][to]; + if (ic->conv_handles[from][to]) { + return ic->conv_handles[from][to]; } - n1 = charset_name(lp_ctx, from); - n2 = charset_name(lp_ctx, to); + n1 = charset_name(ic, from); + n2 = charset_name(ic, to); - conv_handles[from][to] = smb_iconv_open(n2,n1); + ic->conv_handles[from][to] = smb_iconv_open(n2,n1); - if (conv_handles[from][to] == (smb_iconv_t)-1) { + if (ic->conv_handles[from][to] == (smb_iconv_t)-1) { if ((from == CH_DOS || to == CH_DOS) && - strcasecmp(charset_name(lp_ctx, CH_DOS), "ASCII") != 0) { + strcasecmp(charset_name(ic, CH_DOS), "ASCII") != 0) { DEBUG(0,("dos charset '%s' unavailable - using ASCII\n", - charset_name(lp_ctx, CH_DOS))); - lp_set_cmdline(lp_ctx, "dos charset", "ASCII"); + charset_name(ic, CH_DOS))); + ic->dos_charset = "ASCII"; - n1 = charset_name(lp_ctx, from); - n2 = charset_name(lp_ctx, to); + n1 = charset_name(ic, from); + n2 = charset_name(ic, to); - conv_handles[from][to] = smb_iconv_open(n2,n1); + ic->conv_handles[from][to] = smb_iconv_open(n2,n1); } } - return conv_handles[from][to]; + return ic->conv_handles[from][to]; } @@ -151,7 +186,7 @@ _PUBLIC_ ssize_t convert_string(charset_t from, charset_t to, if (srclen == (size_t)-1) srclen = strlen(inbuf)+1; - descriptor = get_conv_handle(global_loadparm, from, to); + descriptor = get_conv_handle(global_smb_iconv_convenience, from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, use as is */ @@ -173,12 +208,12 @@ _PUBLIC_ ssize_t convert_string(charset_t from, charset_t to, reason="No more room"; if (from == CH_UNIX) { DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n", - charset_name(global_loadparm, from), charset_name(global_loadparm, to), + charset_name(global_smb_iconv_convenience, from), charset_name(global_smb_iconv_convenience, to), (int)srclen, (int)destlen, (const char *)src)); } else { DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n", - charset_name(global_loadparm, from), charset_name(global_loadparm, to), + charset_name(global_smb_iconv_convenience, from), charset_name(global_smb_iconv_convenience, to), (int)srclen, (int)destlen)); } return -1; @@ -269,13 +304,13 @@ _PUBLIC_ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_ if (src == NULL || srclen == (size_t)-1 || srclen == 0) return (size_t)-1; - descriptor = get_conv_handle(global_loadparm, from, to); + descriptor = get_conv_handle(global_smb_iconv_convenience, from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, return -1*/ DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n", - charset_name(global_loadparm, from), - charset_name(global_loadparm, to))); + charset_name(global_smb_iconv_convenience, from), + charset_name(global_smb_iconv_convenience, to))); return -1; } @@ -631,7 +666,7 @@ _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size) ilen_orig = strnlen(str, 5); ilen = ilen_orig; - descriptor = get_conv_handle(global_loadparm, CH_UNIX, CH_UTF16); + descriptor = get_conv_handle(global_smb_iconv_convenience, CH_UNIX, CH_UTF16); if (descriptor == (smb_iconv_t)-1) { *size = 1; return INVALID_CODEPOINT; @@ -694,7 +729,8 @@ _PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c) return 1; } - descriptor = get_conv_handle(global_loadparm, CH_UTF16, CH_UNIX); + descriptor = get_conv_handle(global_smb_iconv_convenience, + CH_UTF16, CH_UNIX); if (descriptor == (smb_iconv_t)-1) { return -1; } diff --git a/source4/lib/charset/charset.h b/source4/lib/charset/charset.h index be2705100a..96762af85a 100644 --- a/source4/lib/charset/charset.h +++ b/source4/lib/charset/charset.h @@ -70,6 +70,8 @@ typedef struct smb_iconv_s { #define STR_TERMINATE_ASCII 128 /* only terminate if ascii */ #define STR_LEN_NOTERM 256 /* the length field is the unterminated length */ +struct loadparm_context; + #include "lib/charset/charset_proto.h" /* replace some string functions with multi-byte diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 9065a48113..9cd3cdbdc8 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -2471,7 +2471,7 @@ bool lp_load(const char *filename, struct loadparm_context **ret_lp) lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1"); } - close_iconv(); + reload_charcnv(); if (ret_lp != NULL) *ret_lp = lp_ctx; diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 1d254f3927..e013f9cd0e 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -195,9 +195,9 @@ _NORETURN_ static void standard_terminate(struct event_context *ev, const char * { DEBUG(2,("standard_terminate: reason[%s]\n",reason)); - /* this close_iconv() has the effect of freeing the iconv context memory, + /* this reload_charcnv() has the effect of freeing the iconv context memory, which makes leak checking easier */ - close_iconv(); + reload_charcnv(); /* the secrets db should really hang off the connection structure */ secrets_shutdown(); diff --git a/source4/torture/masktest.c b/source4/torture/masktest.c index 2455361e10..c2e3d7b1dd 100644 --- a/source4/torture/masktest.c +++ b/source4/torture/masktest.c @@ -310,7 +310,7 @@ static void usage(void) seed = time(NULL); - close_iconv(); + reload_charcnv(); while ((opt = getopt(argc, argv, "n:d:U:s:hm:f:aoW:M:vEl:")) != EOF) { switch (opt) { diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c index ef6484ebc9..33e80a4b97 100644 --- a/source4/torture/smbtorture.c +++ b/source4/torture/smbtorture.c @@ -50,7 +50,7 @@ static bool run_matching(struct torture_context *torture, for (o = torture_root->children; o; o = o->next) { if (gen_fnmatch(expr, o->name) == 0) { *matched = true; - close_iconv(); + reload_charcnv(); ret &= torture_run_suite(torture, o); continue; } @@ -67,7 +67,7 @@ static bool run_matching(struct torture_context *torture, if (gen_fnmatch(expr, name) == 0) { *matched = true; - close_iconv(); + reload_charcnv(); torture->active_testname = talloc_strdup(torture, prefix); ret &= torture_run_suite(torture, c); free(name); @@ -83,7 +83,7 @@ static bool run_matching(struct torture_context *torture, asprintf(&name, "%s-%s", prefix, t->name); if (gen_fnmatch(expr, name) == 0) { *matched = true; - close_iconv(); + reload_charcnv(); torture->active_testname = talloc_strdup(torture, prefix); ret &= torture_run_tcase(torture, t); talloc_free(torture->active_testname); -- cgit