diff -ru samba-3.0.7.orig/source/lib/util_str.c samba-3.0.7/source/lib/util_str.c --- samba-3.0.7.orig/source/lib/util_str.c 2004-09-12 06:47:17.000000000 +0300 +++ samba-3.0.7/source/lib/util_str.c 2004-11-16 13:21:03.000000000 +0200 @@ -202,6 +202,12 @@ ut = toupper(*pt); if (us == ut) continue; + + /* Beware of odd encodings which map to a multi-byte character for + the uppercase of some ASCII chars, e.g. Turkish (ISO-8859-9) */ + if ((us & 0x80) || (ut & 0x80)) + break; + else if (us < ut) return -1; else if (us > ut) @@ -1399,8 +1405,16 @@ (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = tolower((unsigned char)*s); - s++; + char c; + + /* Beware of odd encodings which map to a multi-byte + character for the lowercase of some ASCII characters, + e.g. Turkish (ISO-8859-9) */ + c = tolower((unsigned char)*s); + if (c & 0x80) + break; + + *s++ = c; } if (!*s) @@ -1433,8 +1447,16 @@ (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = toupper((unsigned char)*s); - s++; + char c; + + /* Beware of odd encodings which map to a multi-byte + character for the uppercase of some ASCII characters, + e.g. Turkish (ISO-8859-9) */ + c = toupper((unsigned char)*s); + if (c & 0x80) + break; + + *s++ = c; } if (!*s) diff -ru samba-3.0.7.orig/source/lib/util_unistr.c samba-3.0.7/source/lib/util_unistr.c --- samba-3.0.7.orig/source/lib/util_unistr.c 2004-05-25 17:09:32.000000000 +0300 +++ samba-3.0.7/source/lib/util_unistr.c 2004-11-16 13:25:34.000000000 +0200 @@ -31,6 +31,27 @@ static smb_ucs2_t *lowcase_table; static uint8 *valid_table; +/* Prototypes for case table hooks, see below. */ +static void turkic_hook(void); + +/* Structure used to handle the oddities of certain languages. It + incorporates case table hooks which will be called after loading + the case tables if the language being used matches against the + encoding or locale. */ +static const struct lang_oddity { + char *locale; + char *encoding; + void (*case_table_hook)(void); +} lang_oddities_list[] = { + { "tr_TR", "ISO-8859-9", turkic_hook }, + { "az_AZ", "ISO-8859-9E", turkic_hook }, + { "tr_CY", "ISO-8859-9", turkic_hook }, + { NULL, NULL, NULL } +}; + +/* Current oddity handler which has no effect if points to NULL. */ +static const struct lang_oddity *current_lang_oddity; + /** * This table says which Unicode characters are valid dos * characters. @@ -40,6 +61,15 @@ static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */ +/* Wrapper to encapsulate the underlying stuff. */ +void (* const get_current_lang_hook(void))(void) +{ + return (current_lang_oddity ? \ + current_lang_oddity->case_table_hook : \ + NULL); +} + + /** * Load or generate the case handling tables. * @@ -88,8 +118,121 @@ lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i); } } + + /* If exists, apply case table hooks for some language oddness. As a + * conservative approach, ensure first if we don't write to an mmaped + * area which would cause a nice segfault. */ + if (!lp_use_mmap()) { + void (*hook)(); + + hook = get_current_lang_hook(); + if (hook) + (*hook)(); + } +} + + +/* + * Modify case tables for the requirements of Turkic type languages. + * + * The oddity with Turkish is that the upper case of ASCII 'i' and + * the lower case of ASCII 'I' are all multi-byte characters which + * calls for modification in case tables accordingly. + */ +static void turkic_hook(void) +{ + if (upcase_table) { + smb_ucs2_t v; + + DEBUG(1,("turkic_hook: applying hooks on upper case tables\n")); + + /* Map the multi-byte uppercase value of 'i': i->V */ + SSVAL(&v, 0, (smb_ucs2_t) 0x0069); + upcase_table[v] = (smb_ucs2_t) 0x0130; + + /* Map the multi-byte lowercase value of ASCII 'I': v<-I */ + SSVAL(&v, 0, (smb_ucs2_t) 0x0131); + upcase_table[v] = (smb_ucs2_t) 0x0049; + } + + if (lowcase_table) { + smb_ucs2_t v; + + DEBUG(1,("turkic_hook: applying hooks on lower case tables\n")); + + /* Map the multi-byte uppercase value of 'i': i<-V */ + SSVAL(&v, 0, (smb_ucs2_t) 0x0130); + lowcase_table[v] = (smb_ucs2_t) 0x0069; + + /* Map the multi-byte lowercase value of ASCII 'I': I->v */ + SSVAL(&v, 0, (smb_ucs2_t) 0x0049); + lowcase_table[v] = (smb_ucs2_t) 0x0131; + } +} + + +/* + * Determine whether the current locale environment is an odd language. + */ +static void determine_lang_oddity(void) +{ + char *system_locale = NULL; + char *system_encoding = NULL; + + /* Always start by assuming an odd-free locale environment. */ + current_lang_oddity = NULL; + +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); + system_locale = setlocale(LC_CTYPE, NULL); + #if defined(HAVE_NL_LANGINFO) && defined(CODESET) + system_encoding = nl_langinfo(CODESET); + #endif +#endif + + /* Encoding should be honored first... */ + if (system_encoding) { + int i; + + for (i = 0; lang_oddities_list[i].encoding; i++) { + char *enc; + + enc = lang_oddities_list[i].locale; + if (strncmp(enc, system_encoding, strlen(enc)) == 0) { + current_lang_oddity = &lang_oddities_list[i]; + break; + } + } + } + + /* Locale comes second (will catch i.e. tr_TR.UTF-8) */ + if (system_locale && !current_lang_oddity) { + int i; + + if (*system_locale) + for (i = 0; lang_oddities_list[i].locale; i++) { + char *loc; + + loc = lang_oddities_list[i].locale; + if (strncmp(loc, system_locale, strlen(loc)) == 0) { + current_lang_oddity = &lang_oddities_list[i]; + break; + } + } + } } + +/** + * Init the case handling tables while taking care of language oddities. + **/ +void init_case_tables(void) +{ + determine_lang_oddity(); + load_case_tables(); +} + + /* see if a ucs2 character can be mapped correctly to a dos character and mapped back to the same character in ucs2 diff -ru samba-3.0.7.orig/source/param/loadparm.c samba-3.0.7/source/param/loadparm.c --- samba-3.0.7.orig/source/param/loadparm.c 2004-09-12 06:47:16.000000000 +0300 +++ samba-3.0.7/source/param/loadparm.c 2004-11-16 13:02:09.000000000 +0200 @@ -91,6 +91,11 @@ }; /* + * This flag signals if the globals have been initiated. + */ +static BOOL bGlobalsDone = False; + +/* * This structure describes global (ie., server-wide) parameters. */ typedef struct @@ -1529,6 +1534,8 @@ Globals.bDeferSharingViolations = True; string_set(&Globals.smb_ports, SMB_PORTS); + + bGlobalsDone = True; } static TALLOC_CTX *lp_talloc; @@ -1756,7 +1763,6 @@ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs) FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks) FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing) -FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap) FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions) FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) @@ -4333,3 +4339,27 @@ return; ServicePtrs[(snum)]->bStoreDosAttributes = val; } + +/*************************************************************************** + If we should use mmap +***************************************************************************/ + +BOOL lp_use_mmap(void) +{ + /* If we're going to modify case tables through a hook, ignore the + value whatever the global flag says, since I (at least) don't + know a reasonable method to modify a _shared_ mmapped area + without writing back to the readonly file being mmapped. -- ro */ + if (get_current_lang_hook()) + return False; + + /* Do not rely on an uninitiated global. */ + if (!bGlobalsDone) +#ifdef MMAP_BLACKLIST + Globals.bUseMmap = False; +#else + Globals.bUseMmap = True; +#endif + + return Globals.bUseMmap; +} diff -ru samba-3.0.7.orig/source/smbd/server.c samba-3.0.7/source/smbd/server.c --- samba-3.0.7.orig/source/smbd/server.c 2004-08-19 16:39:11.000000000 +0300 +++ samba-3.0.7/source/smbd/server.c 2004-11-16 13:02:09.000000000 +0200 @@ -700,7 +700,7 @@ sec_init(); - load_case_tables(); + init_case_tables(); set_remote_machine_name("smbd", False);