diff options
Diffstat (limited to 'lib/util')
-rw-r--r-- | lib/util/charset/charcnv.c | 40 | ||||
-rw-r--r-- | lib/util/charset/charset.h | 9 | ||||
-rw-r--r-- | lib/util/charset/util_unistr.c | 3 |
3 files changed, 39 insertions, 13 deletions
diff --git a/lib/util/charset/charcnv.c b/lib/util/charset/charcnv.c index a479f44426..efdb3ed2b3 100644 --- a/lib/util/charset/charcnv.c +++ b/lib/util/charset/charcnv.c @@ -39,6 +39,7 @@ */ struct smb_iconv_convenience { + TALLOC_CTX *child_ctx; const char *unix_charset; const char *dos_charset; bool native_iconv; @@ -83,22 +84,45 @@ static int close_iconv_convenience(struct smb_iconv_convenience *data) return 0; } -_PUBLIC_ struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx, - const char *dos_charset, - const char *unix_charset, - bool native_iconv) +/* + the old_ic is passed in here as the smb_iconv_convenience structure + is used as a global pointer in some places (eg. python modules). We + don't want to invalidate those global pointers, but we do want to + update them with the right charset information when loadparm + runs. To do that we need to re-use the structure pointer, but + re-fill the elements in the structure with the updated values + */ +_PUBLIC_ struct smb_iconv_convenience *smb_iconv_convenience_reinit(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool native_iconv, + struct smb_iconv_convenience *old_ic) { - struct smb_iconv_convenience *ret = talloc_zero(mem_ctx, - struct smb_iconv_convenience); + struct smb_iconv_convenience *ret; + if (old_ic != NULL) { + ret = old_ic; + close_iconv_convenience(ret); + talloc_free(ret->child_ctx); + ZERO_STRUCTP(ret); + } else { + ret = talloc_zero(mem_ctx, struct smb_iconv_convenience); + } if (ret == NULL) { return NULL; } + /* we use a child context to allow us to free all ptrs without + freeing the structure itself */ + ret->child_ctx = talloc_new(ret); + if (ret->child_ctx == NULL) { + return NULL; + } + talloc_set_destructor(ret, close_iconv_convenience); - ret->dos_charset = talloc_strdup(ret, dos_charset); - ret->unix_charset = talloc_strdup(ret, unix_charset); + ret->dos_charset = talloc_strdup(ret->child_ctx, dos_charset); + ret->unix_charset = talloc_strdup(ret->child_ctx, unix_charset); ret->native_iconv = native_iconv; return ret; diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index 2c8aa41ad5..cc57b3eb54 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -163,10 +163,11 @@ codepoint_t tolower_m(codepoint_t val); int codepoint_cmpi(codepoint_t c1, codepoint_t c2); /* Iconv convenience functions */ -struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx, - const char *dos_charset, - const char *unix_charset, - bool native_iconv); +struct smb_iconv_convenience *smb_iconv_convenience_reinit(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool native_iconv, + struct smb_iconv_convenience *old_ic); bool convert_string_convenience(struct smb_iconv_convenience *ic, charset_t from, charset_t to, diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index f8207261c5..520ce05468 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -26,7 +26,8 @@ struct smb_iconv_convenience *global_iconv_convenience = NULL; static inline struct smb_iconv_convenience *get_iconv_convenience(void) { if (global_iconv_convenience == NULL) - global_iconv_convenience = smb_iconv_convenience_init(talloc_autofree_context(), "ASCII", "UTF-8", true); + global_iconv_convenience = smb_iconv_convenience_reinit(talloc_autofree_context(), + "ASCII", "UTF-8", true, NULL); return global_iconv_convenience; } |