[PATCH] Fix Name mangling in HEAD
Simo Sorce
idra at samba.org
Mon Mar 25 03:12:11 GMT 2002
On Mon, 2002-03-25 at 11:52, Simo Sorce wrote:
> Sorry Andrew but reverting back to 2.2 code is not the way to go on my
> opinion, I made that code to solve many problems and bugs that apperead
> in 2.2. code. The way to go is that me and tridge discussed on IRC, eg:
>
> change the code to use a hash instead of numbering as windows (2k at
> least) does after a few similar entries (five).
> eg:
> averylongname[1-10].txt
>
> windows do this:
> averyl~1.txt
> averyl~2.txt
> averyl~3.txt
> averyl~4.txt
> averyl~5.txt
> aERWF4~1.txt
> aehw64~1.txt
> .
> .
Sorry, my mistake, windows use a little different scheme!
averyl~1.txt
averyl~2.txt
averyl~3.txt
averyl~4.txt
averyl~5.txt
avA4BD~1.txt
avA4FC~1.txt
avF3D6~1.txt
avAB5F~1.txt
avAB54~1.txt
windows use a week 16 bit number as hash and put it as a hex number in
the file name after the first 2 letters of the original name.
>
> we would do this:
>
> aRtf6e~9.txt
> aWE456~3.txt
> ...
>
> the number of letters that will be used will be based on a configurable
> option (1 to 7).
>
> We need to keep the a tdb as base but make an in meory cache to spead up
> things.
>
> And above all move everything to VFS and merge in also the case
> sensitivity handling.
>
>
> Simo.
>
> On Mon, 2002-03-25 at 09:41, Andrew Bartlett wrote:
> > Attached is a partial, unfinished (but apparently functional) name
> > mangling patch for HEAD.
> > This patch reintroduces hash (rather that db/counter) based mangling.
> >
> > This fixes the issue that samba gets very slow when more than 99 files
> > exist on the server with the same 5 chars in their name. This
> > particular bug also causes MS word to leave temporay files behind.
> >
> > When I get more time, I'll fix this to use more unicode and the
> > mangle_get_prefix() function.
> >
> > Andrew Bartlett
> >
> > --
> > Andrew Bartlett abartlet at pcug.org.au
> > Manager, Authentication Subsystems, Samba Team abartlet at samba.org
> > Student Network Administrator, Hawker College abartlet at hawkerc.net
> > http://samba.org http://build.samba.org http://hawkerc.net
> > ----
> >
>
> > Index: smbd/filename.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/filename.c,v
> > retrieving revision 1.46
> > diff -u -r1.46 filename.c
> > --- smbd/filename.c 2002/01/30 06:08:38 1.46
> > +++ smbd/filename.c 2002/03/25 08:24:41
> > @@ -75,6 +75,17 @@
> > ****************************************************************************/
> > static BOOL mangled_equal(char *name1, char *name2)
> > {
> > +#if 1
> > + pstring tmpname;
> > + if (is_8_3(name2, True)) {
> > + return False;
> > + }
> > +
> > + pstrcpy(tmpname, name2);
> > + mangle_name_83(tmpname);
> > +
> > + return strequal(name1, tmpname);
> > +#else
> > char *tmpname;
> > BOOL ret = False;
> >
> > @@ -86,6 +97,8 @@
> > SAFE_FREE(tmpname);
> > }
> > return ret;
> > +#endif
> > +
> > }
> >
> >
> > @@ -116,7 +129,7 @@
> > for nlinks = 0, which can never be true for any file).
> > ****************************************************************************/
> >
> > -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
> > +BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component,
> > BOOL *bad_path, SMB_STRUCT_STAT *pst)
> > {
> > SMB_STRUCT_STAT st;
> > Index: smbd/mangle.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/mangle.c,v
> > retrieving revision 1.66
> > diff -u -r1.66 mangle.c
> > --- smbd/mangle.c 2002/03/14 22:52:19 1.66
> > +++ smbd/mangle.c 2002/03/25 08:24:43
> > @@ -1,6 +1,7 @@
> > /*
> > Unix SMB/CIFS implementation.
> > - Name mangling with persistent tdb
> > + Name mangling
> > + Copyright (C) Andrew Tridgell 1992-1998
> > Copyright (C) Simo Sorce 2001
> > Copyright (C) Andrew Bartlett 2002
> >
> > @@ -19,9 +20,31 @@
> > Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> > */
> >
> > -/****************************************************************************
> > - Rewritten from scrach in 2001 by Simo Sorce <idra at samba.org>
> > - ****************************************************************************/
> > +/* -------------------------------------------------------------------------- **
> > + * Notable problems...
> > + *
> > + * March/April 1998 CRH
> > + * - Many of the functions in this module overwrite string buffers passed to
> > + * them. This causes a variety of problems and is, generally speaking,
> > + * dangerous and scarry. See the kludge notes in name_map_mangle()
> > + * below.
> > + * - It seems that something is calling name_map_mangle() twice. The
> > + * first call is probably some sort of test. Names which contain
> > + * illegal characters are being doubly mangled. I'm not sure, but
> > + * I'm guessing the problem is in server.c.
> > + *
> > + * -------------------------------------------------------------------------- **
> > + */
> > +
> > +/* -------------------------------------------------------------------------- **
> > + * History...
> > + *
> > + * March/April 1998 CRH
> > + * Updated a bit. Rewrote is_mangled() to be a bit more selective.
> > + * Rewrote the mangled name cache. Added comments here and there.
> > + * &c.
> > + * -------------------------------------------------------------------------- **
> > + */
> >
> > #include "includes.h"
> >
> > @@ -33,36 +56,88 @@
> > extern int case_default; /* Are conforming 8.3 names all upper or lower? */
> > extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
> >
> > +/* -------------------------------------------------------------------------- **
> > + * Other stuff...
> > + *
> > + * magic_char - This is the magic char used for mangling. It's
> > + * global. There is a call to lp_magicchar() in server.c
> > + * that is used to override the initial value.
> > + *
> > + * MANGLE_BASE - This is the number of characters we use for name mangling.
> > + *
> > + * basechars - The set characters used for name mangling. This
> > + * is static (scope is this file only).
> > + *
> > + * mangle() - Macro used to select a character from basechars (i.e.,
> > + * mangle(n) will return the nth digit, modulo MANGLE_BASE).
> > + *
> > + * chartest - array 0..255. The index range is the set of all possible
> > + * values of a byte. For each byte value, the content is a
> > + * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK,
> > + * below.
> > + *
> > + * ct_initialized - False until the chartest array has been initialized via
> > + * a call to init_chartest().
> > + *
> > + * BASECHAR_MASK - Masks the upper nibble of a one-byte value.
> > + *
> > + * ILLEGAL_MASK - Masks the lower nibble of a one-byte value.
> > + *
> > + * isbasecahr() - Given a character, check the chartest array to see
> > + * if that character is in the basechars set. This is
> > + * faster than using strchr_m().
> > + *
> > + * isillegal() - Given a character, check the chartest array to see
> > + * if that character is in the illegal characters set.
> > + * This is faster than using strchr_m().
> > + *
> > + * mangled_cache - Cache header used for storing mangled -> original
> > + * reverse maps.
> > + *
> > + * mc_initialized - False until the mangled_cache structure has been
> > + * initialized via a call to reset_mangled_cache().
> > + *
> > + * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
> > + * cache. A value of 0 indicates "infinite".
> > + *
> > + * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the
> > + * cache. When the cache was kept as an array of 256
> > + * byte strings, the default cache size was 50 entries.
> > + * This required a fixed 12.5Kbytes of memory. The
> > + * mangled stack parameter is no longer used (though
> > + * this might change). We're now using a fixed 16Kbyte
> > + * maximum cache size. This will probably be much more
> > + * than 50 entries.
> > + */
> > +
> > char magic_char = '~';
> >
> > -/* -------------------------------------------------------------------- */
> > +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
> > +#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1)
> >
> > -#define MANGLE_TDB_VERSION "20010927"
> > -#define MANGLE_TDB_FILE_NAME "mangle.tdb"
> > -#define MANGLED_PREFIX "MANGLED_"
> > -#define LONG_PREFIX "LONG_"
> > -#define COUNTER_PREFIX "COUNTER_"
> > -#define MANGLE_COUNTER_MAX 99
> > -#define MANGLE_SUFFIX_SIZE 3 /* "~XX" */
> > +static unsigned char chartest[256] = { 0 };
> > +static BOOL ct_initialized = False;
> >
> > +#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
> > +#define BASECHAR_MASK 0xf0
> > +#define ILLEGAL_MASK 0x0f
> > +#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
> > +#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
> > +
> > +static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
> > +static BOOL mc_initialized = False;
> > +#define MANGLED_CACHE_MAX_ENTRIES 0
> > +#define MANGLED_CACHE_MAX_MEMORY 16384
> >
> > -static TDB_CONTEXT *mangle_tdb;
> >
> > -BOOL init_mangle_tdb(void)
> > -{
> > - char *tdbfile;
> > -
> > - tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */
> > +/* -------------------------------------------------------------------------- **
> > + * External Variables...
> > + */
> >
> > - /* Open tdb */
> > - if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
> > - {
> > - DEBUG(0, ("Unable to open Mangle TDB\n"));
> > - return False;
> > - }
> > +extern int case_default; /* Are conforming 8.3 names all upper or lower? */
> > +extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
> >
> > - return True;
> > -}
> > +/* -------------------------------------------------------------------- */
> >
> > /* trasform a unicode string into a dos charset string */
> > static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len)
> > @@ -81,6 +156,24 @@
> > return ret;
> > }
> >
> > +NTSTATUS has_valid_chars(const smb_ucs2_t *s)
> > +{
> > + if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > +
> > + DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
> > +
> > + /* CHECK: this should not be necessary if the ms wild chars
> > + are not valid in valid.dat --- simo */
> > + if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
> > +
> > + while (*s) {
> > + if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
> > + s++;
> > + }
> > +
> > + return NT_STATUS_OK;
> > +}
> > +
> > /* trasform in a string that contain only valid chars for win filenames,
> > not including a '.' */
> > static void strvalid(smb_ucs2_t *src)
> > @@ -128,524 +221,19 @@
> > return NT_STATUS_OK;
> > }
> >
> > -
> > -/* mangled must contain only the file name, not a path.
> > - and MUST be ZERO terminated */
> > -smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
> > -{
> > - TDB_DATA data, key;
> > - fstring keystr;
> > - fstring mufname;
> > - smb_ucs2_t *pref, *ext, *retstr;
> > - size_t long_len, ext_len, muf_len;
> > -
> > - if (strlen_w(mangled) > 12) return NULL;
> > - if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL;
> > -
> > - /* if it is a path refuse to proceed */
> > - if (strchr_w(mangled, UCS2_CHAR('/'))) {
> > - DEBUG(10, ("unmangle: cannot unmangle a path\n"));
> > - return NULL;
> > - }
> > -
> > - if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext)))
> > - return NULL;
> > -
> > - /* mangled names are stored lowercase only */
> > - strlower_w(pref);
> > - /* set search key */
> > - muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname));
> > - SAFE_FREE(pref);
> > - if (!muf_len) return NULL;
> > -
> > - slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > -
> > - /* get the record */
> > - data = tdb_fetch(mangle_tdb, key);
> > -
> > - if (!data.dptr) /* not found */
> > - {
> > - DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb)));
> > - retstr = NULL;
> > - goto done;
> > - }
> > -
> > - if (ext)
> > - {
> > - long_len = (data.dsize / 2) - 1;
> > - ext_len = strlen_w(ext);
> > - retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t));
> > - if (!retstr)
> > - {
> > - DEBUG(0, ("unamngle: out of memory!\n"));
> > - goto done;
> > - }
> > - strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len);
> > - retstr[long_len] = UCS2_CHAR('.');
> > - retstr[long_len + 1] = 0;
> > - strncat_w(retstr, ext, ext_len);
> > - }
> > - else
> > - {
> > - retstr = strdup_w((smb_ucs2_t *)data.dptr);
> > - if (!retstr)
> > - {
> > - DEBUG(0, ("unamngle: out of memory!\n"));
> > - goto done;
> > - }
> > -
> > - }
> > -
> > -done:
> > - SAFE_FREE(data.dptr);
> > - SAFE_FREE(pref);
> > - SAFE_FREE(ext);
> > -
> > - return retstr;
> > -}
> > -
> > -/* unmangled must contain only the file name, not a path.
> > - and MUST be ZERO terminated.
> > - return a new allocated string if the name is yet valid 8.3
> > - or is mangled successfully.
> > - return null on error.
> > +/* ************************************************************************** **
> > + * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name.
> > + *
> > + * Input: fname - String containing the name to be tested.
> > + *
> > + * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names.
> > + *
> > + * Notes: This is a static function called by is_8_3(), below.
> > + *
> > + * ************************************************************************** **
> > */
> > -
> > -smb_ucs2_t *mangle(const smb_ucs2_t *unmangled)
> > -{
> > - TDB_DATA data, key, klock;
> > - pstring keystr;
> > - pstring longname;
> > - fstring keylock;
> > - fstring mufname;
> > - fstring prefix;
> > - BOOL tclock = False;
> > - char suffix[7];
> > - smb_ucs2_t *mangled = NULL;
> > - smb_ucs2_t *umpref, *ext, *p = NULL;
> > - size_t pref_len, ext_len, ud83_len;
> > -
> > - /* if it is a path refuse to proceed */
> > - if (strchr_w(unmangled, UCS2_CHAR('/'))) {
> > - DEBUG(10, ("mangle: cannot mangle a path\n"));
> > - return NULL;
> > - }
> > -
> > - /* if it is a valid 8_3 do not mangle again */
> > - if (NT_STATUS_IS_OK(is_8_3_w(unmangled)))
> > - return NULL;
> > -
> > - if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext)))
> > - return NULL;
> > -
> > - /* test if the same is yet mangled */
> > -
> > - /* set search key */
> > - pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > - key.dptr = keystr;
> > - key.dsize = strlen(keystr) + 1;
> > -
> > - /* get the record */
> > - data = tdb_fetch (mangle_tdb, key);
> > - if (!data.dptr) /* not found */
> > - {
> > - smb_ucs2_t temp[9];
> > - size_t c, pos;
> > -
> > - if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST)
> > - {
> > - DEBUG(0, ("mangle: database retrieval error: %s\n",
> > - tdb_errorstr(mangle_tdb)));
> > - goto done;
> > - }
> > -
> > - /* if not find the first free possibile mangled name */
> > -
> > - pos = strlen_w(umpref);
> > - if ((8 - MANGLE_SUFFIX_SIZE) < pos)
> > - pos = 8 - MANGLE_SUFFIX_SIZE;
> > - pos++;
> > - do
> > - {
> > - pos--;
> > - if (pos == 0)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0, ("mangle: unable to mangle file name (%s)!\n",unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > - strncpy_w(temp, umpref, pos);
> > - temp[pos] = 0;
> > - strlower_w(temp);
> > -
> > - /* convert any invalid char into '_' */
> > - strvalid(temp);
> > - ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix));
> > - if (!ud83_len) goto done;
> > - }
> > - while (ud83_len > 8 - MANGLE_SUFFIX_SIZE);
> > -
> > - slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix);
> > - klock.dptr = keylock;
> > - klock.dsize = strlen(keylock) + 1;
> > -
> > - c = 0;
> > - data.dptr = (char *)&c;
> > - data.dsize = sizeof(uint32);
> > - /* try to insert a new counter prefix, if it exist the call will
> > - fail (correct) otherwise it will create a new entry with counter set
> > - to 0
> > - */
> > - if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS)
> > - {
> > - if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > - DEBUG(0, ("mangle: database store error: %s for filename: %s\n",
> > - tdb_errorstr(mangle_tdb), unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > - }
> > -
> > - /* lock the mangle counter for this prefix */
> > - if (tdb_chainlock(mangle_tdb, klock))
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0,("mangle: failed to lock database for filename %s\n!", unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > - tclock = True;
> > -
> > - data = tdb_fetch(mangle_tdb, klock);
> > - if (!data.dptr)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0, ("mangle: database retrieval error: %s for filename: %s\n",
> > - tdb_errorstr(mangle_tdb), unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > - c = *((uint32 *)data.dptr);
> > - c++;
> > -
> > - if (c > MANGLE_COUNTER_MAX)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0, ("mangle: error, counter overflow (max=%d, counter=%d) for file: [%s] prefix (dos charset): [%s]!\n", MANGLE_COUNTER_MAX, c, unmangled_unix, prefix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > -
> > - temp[pos] = UCS2_CHAR('~');
> > - temp[pos+1] = 0;
> > - snprintf(suffix, 7, "%.6d", c);
> > - strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE);
> > -
> > - ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname));
> > - if (!ud83_len) goto done;
> > - if (ud83_len > 8)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0, ("mangle: darn, logic error aborting! Filename was %s\n", unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > -
> > - /* store the long entry with mangled key */
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > - data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t);
> > - data.dptr = (void *)umpref;
> > -
> > - if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > - DEBUG(0, ("mangle: database store error: %s for filename: %s\n",
> > - tdb_errorstr(mangle_tdb), unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - goto done;
> > - }
> > -
> > - /* store the mangled entry with long key*/
> > - pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > - data.dsize = strlen(mufname) + 1;
> > - data.dptr = mufname;
> > - if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > - DEBUG(0, ("mangle: database store failed: %s for filename: %s\n",
> > - tdb_errorstr(mangle_tdb), unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > -
> > - /* try to delete the mangled key entry to avoid later inconsistency */
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > - if (!tdb_delete(mangle_tdb, key))
> > - {
> > - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > - }
> > - goto done;
> > - }
> > -
> > - p = strdup_w(temp);
> > - if (!p)
> > - {
> > - DEBUG(0,("mangle: out of memory!\n"));
> > - goto done;
> > - }
> > -
> > - data.dptr = (char *)&c;
> > - data.dsize = sizeof(uint32);
> > - /* store the counter */
> > - if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS)
> > - {
> > - char *unmangled_unix = acnv_u2ux(unmangled);
> > - DEBUG(0, ("mangle: database store failed: %s for filename: %s\n",
> > - tdb_errorstr(mangle_tdb), unmangled_unix));
> > - SAFE_FREE(unmangled_unix);
> > - /* try to delete the mangled and long key entry to avoid later inconsistency */
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > - if (!tdb_delete(mangle_tdb, key))
> > - {
> > - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > - }
> > - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > - key.dptr = keystr;
> > - key.dsize = strlen (keystr) + 1;
> > - if (!tdb_delete(mangle_tdb, key))
> > - {
> > - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > - }
> > - goto done;
> > - }
> > -
> > - tclock = False;
> > - tdb_chainunlock(mangle_tdb, klock);
> > - }
> > - else /* FOUND */
> > - {
> > - p = acnv_dosu2(data.dptr);
> > - if (!p)
> > - {
> > - DEBUG(0,("mangle: internal error acnv_dosu2() failed!\n"));
> > - goto done;
> > - }
> > - }
> > -
> > - if (ext)
> > - {
> > - pref_len = strlen_w(p);
> > - ext_len = strlen_w(ext);
> > - mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t));
> > - if (!mangled)
> > - {
> > - DEBUG(0,("mangle: out of memory!\n"));
> > - goto done;
> > - }
> > - strncpy_w (mangled, p, pref_len);
> > - mangled[pref_len] = UCS2_CHAR('.');
> > - mangled[pref_len + 1] = 0;
> > - strncat_w (mangled, ext, ext_len);
> > - }
> > - else
> > - {
> > - mangled = strdup_w(p);
> > - if (!mangled)
> > - {
> > - DEBUG(0,("mangle: out of memory!\n"));
> > - goto done;
> > - }
> > - }
> > -
> > - /* mangled name are returned in upper or lower case depending on
> > - case_default value */
> > - strnorm_w(mangled);
> > -
> > -done:
> > - if (tclock) tdb_chainunlock(mangle_tdb, klock);
> > - SAFE_FREE(p);
> > - SAFE_FREE(umpref);
> > - SAFE_FREE(ext);
> > -
> > - return mangled;
> > -}
> > -
> > -
> > -/* non unicode compatibility functions */
> > -
> > -char *dos_mangle(const char *dos_unmangled)
> > -{
> > - smb_ucs2_t *in, *out;
> > - char *dos_mangled;
> > -
> > - if (!dos_unmangled || !*dos_unmangled) return NULL;
> > -
> > - in = acnv_dosu2(dos_unmangled);
> > - if (!in)
> > - {
> > - DEBUG(0,("dos_mangle: internal error acnv_dosu2() failed!\n"));
> > - return NULL;
> > - }
> > -
> > - out = mangle(in);
> > - if (!out)
> > - {
> > - SAFE_FREE(in);
> > - return NULL;
> > - }
> > -
> > - dos_mangled = acnv_u2dos(out);
> > - if (!dos_mangled)
> > - {
> > - DEBUG(0,("dos_mangle: internal error acnv_u2dos() failed!\n"));
> > - goto done;
> > - }
> > -
> > -done:
> > - SAFE_FREE(in);
> > - SAFE_FREE(out);
> > - return dos_mangled;
> > -}
> > -
> > -char *dos_unmangle(const char *dos_mangled)
> > -{
> > - smb_ucs2_t *in, *out;
> > - char *dos_unmangled;
> > -
> > - if (!dos_mangled || !*dos_mangled) return NULL;
> > -
> > - in = acnv_dosu2(dos_mangled);
> > - if (!in)
> > - {
> > - DEBUG(0,("dos_unmangle: internal error acnv_dosu2() failed!\n"));
> > - return NULL;
> > - }
> > -
> > - out = unmangle(in);
> > - if (!out)
> > - {
> > - SAFE_FREE(in);
> > - return NULL;
> > - }
> > -
> > - dos_unmangled = acnv_u2dos(out);
> > - if (!dos_unmangled)
> > - {
> > - DEBUG(0,("dos_unmangle: internal error acnv_u2dos failed!\n"));
> > - goto done;
> > - }
> > -
> > -done:
> > - SAFE_FREE(in);
> > - SAFE_FREE(out);
> > - return dos_unmangled;
> > -}
> > -
> > -BOOL is_8_3(const char *fname, BOOL check_case)
> > +static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
> > {
> > - const char *f;
> > - smb_ucs2_t *ucs2name;
> > - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -
> > - if (!fname || !*fname) return False;
> > - if ((f = strrchr(fname, '/')) == NULL) f = fname;
> > - else f++;
> > -
> > - DEBUG(10,("is_8_3: testing [%s]\n", f));
> > -
> > - if (strlen(f) > 12) return False;
> > -
> > - ucs2name = acnv_uxu2(f);
> > - if (!ucs2name)
> > - {
> > - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
> > - goto done;
> > - }
> > -
> > - ret = is_8_3_w(ucs2name);
> > -
> > -done:
> > - SAFE_FREE(ucs2name);
> > -
> > - DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
> > -
> > - if (NT_STATUS_IS_ERR(ret)) return False;
> > - else return True;
> > -}
> > -
> > -NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
> > -{
> > - smb_ucs2_t *pref = 0, *ext = 0;
> > - size_t plen;
> > - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -
> > - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
> > -
> > - DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
> > -
> > - if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
> > -
> > - if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
> > - return NT_STATUS_OK;
> > -
> > - if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
> > -
> > - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
> > - plen = strlen_w(pref);
> > -
> > - if (strchr_wa(pref, '.')) goto done;
> > - if (plen < 1 || plen > 8) goto done;
> > - if (ext) if (strlen_w(ext) > 3) goto done;
> > -
> > - ret = NT_STATUS_OK;
> > -
> > -done:
> > - SAFE_FREE(pref);
> > - SAFE_FREE(ext);
> > - return ret;
> > -}
> > -
> > -NTSTATUS has_valid_chars(const smb_ucs2_t *s)
> > -{
> > - NTSTATUS ret = NT_STATUS_OK;
> > -
> > - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > -
> > - DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
> > -
> > - /* CHECK: this should not be necessary if the ms wild chars
> > - are not valid in valid.dat --- simo */
> > - if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
> > -
> > - while (*s) {
> > - if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
> > - s++;
> > - }
> > -
> > - return ret;
> > -}
> > -
> > -NTSTATUS is_valid_name(const smb_ucs2_t *fname)
> > -{
> > smb_ucs2_t *str, *p;
> > NTSTATUS ret = NT_STATUS_OK;
> >
> > @@ -702,297 +290,712 @@
> > SAFE_FREE(str);
> > return ret;
> > }
> > -
> > -BOOL is_mangled(const char *s)
> > -{
> > - smb_ucs2_t *u2, *res;
> > - BOOL ret = False;
> > -
> > - DEBUG(10,("is_mangled: testing [%s]\n", s));
> > -
> > - if (!s || !*s) return False;
> > - if ((strlen(s) > 12) || (!strchr(s, '~'))) return False;
> > -
> > - u2 = acnv_dosu2(s);
> > - if (!u2)
> > - {
> > - DEBUG(0,("is_mangled: internal error acnv_dosu2() failed!!\n"));
> > - return ret;
> > - }
> > -
> > - res = unmangle(u2);
> > - if (res) ret = True;
> > - SAFE_FREE(res);
> > - SAFE_FREE(u2);
> > - DEBUG(10,("is_mangled: returning [%s]\n", ret?"True":"False"));
> > - return ret;
> > -}
> >
> > -NTSTATUS is_mangled_w(const smb_ucs2_t *s)
> > +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
> > {
> > - smb_ucs2_t *res;
> > - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -
> > - res = unmangle(s);
> > - if (res) ret = NT_STATUS_OK;
> > - SAFE_FREE(res);
> > - return ret;
> > -}
> > -
> > -NTSTATUS path_has_mangled(const smb_ucs2_t *s)
> > -{
> > - smb_ucs2_t *p, *f, *b;
> > + smb_ucs2_t *pref = 0, *ext = 0;
> > + size_t plen;
> > NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> >
> > - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > -
> > - p = strdup_w(s);
> > - if (!p) return NT_STATUS_NO_MEMORY;
> > - trim_string_wa(p, "/", "/");
> > - f = b = p;
> > - while (b) {
> > - b = strchr_w(f, UCS2_CHAR('/'));
> > - if (b) *b = 0;
> > - if (NT_STATUS_IS_OK(is_mangled_w(f))) {
> > - ret = NT_STATUS_OK;
> > - goto done;
> > - }
> > - f = b + 1;
> > - }
> > -done:
> > - SAFE_FREE(p);
> > - return ret;
> > -}
> > + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
> >
> > -/* backward compatibility functions */
> > + DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
> >
> > -void reset_mangled_cache(void)
> > -{
> > - DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n"));
> > -}
> > + if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
> > +
> > + if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
> > + return NT_STATUS_OK;
> >
> > -BOOL check_mangled_cache(char *s)
> > -{
> > - smb_ucs2_t *u2, *res;
> > - BOOL ret = False;
> > + if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
> >
> > - DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n"));
> > - DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s));
> > + if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
> > + plen = strlen_w(pref);
> >
> > - if (!s || !*s) return False;
> > + if (strchr_wa(pref, '.')) goto done;
> > + if (plen < 1 || plen > 8) goto done;
> > + if (ext) if (strlen_w(ext) > 3) goto done;
> >
> > - u2 = acnv_dosu2(s);
> > - if (!u2)
> > - {
> > - DEBUG(0,("check_mangled_cache: out of memory!\n"));
> > - return ret;
> > - }
> > + ret = NT_STATUS_OK;
> >
> > - res = unmangle(u2);
> > - if (res)
> > - {
> > -
> > - ucs2_to_dos (s, res, PSTRING_LEN);
> > - /* We MUST change this brainded interface,
> > - we do not know how many chars will be used
> > - in dos so i guess they will be no more than
> > - double the size of the unicode string
> > - ---simo */
> > - DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s));
> > - ret = True;
> > - }
> > - SAFE_FREE(res);
> > - SAFE_FREE(u2);
> > - DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False"));
> > +done:
> > + SAFE_FREE(pref);
> > + SAFE_FREE(ext);
> > return ret;
> > }
> >
> > -void mangle_name_83(char *s)
> > +BOOL is_8_3(const char *fname, BOOL check_case)
> > {
> > - smb_ucs2_t *u2, *res;
> > + const char *f;
> > + smb_ucs2_t *ucs2name;
> > + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> >
> > - DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n"));
> > - DEBUG(10,("mangle_name_83: testing -> [%s]\n", s));
> > + if (!fname || !*fname) return False;
> > + if ((f = strrchr(fname, '/')) == NULL) f = fname;
> > + else f++;
> >
> > - if (!s || !*s) return;
> > + DEBUG(10,("is_8_3: testing [%s]\n", f));
> > +
> > + if (strlen(f) > 12) return False;
> >
> > - u2 = acnv_dosu2(s);
> > - if (!u2)
> > + ucs2name = acnv_uxu2(f);
> > + if (!ucs2name)
> > {
> > - DEBUG(0,("mangle_name_83: internal error acnv_dosu2() failed!\n"));
> > - return;
> > + DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
> > + goto done;
> > }
> >
> > - res = mangle(u2);
> > - if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */
> > - DEBUG(10,("mangle_name_83: returning -> [%s]\n", s));
> > - SAFE_FREE(res);
> > - SAFE_FREE(u2);
> > -}
> > + ret = is_8_3_w(ucs2name);
> >
> > -BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
> > -{
> > - DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n"));
> > +done:
> > + SAFE_FREE(ucs2name);
> >
> > - if (!need83) return True;
> > - /* if (is_8_3(OutName, True)) return True; */
> > - /* Warning: we should check for invalid chars in file name and mangle
> > - if invalid chars found --simo*/
> > + DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
> >
> > - mangle_name_83(OutName);
> > + if (!NT_STATUS_IS_OK(ret)) {
> > + return False;
> > + }
> > +
> > return True;
> > }
> >
> >
> >
> > -#if 0 /* TEST_MANGLE_CODE */
> > +/* -------------------------------------------------------------------------- **
> > + * Functions...
> > + */
> >
> > -#define LONG "this_is_a_long_file_name"
> > -#define LONGM "this_~01"
> > -#define SHORT "short"
> > -#define SHORTM "short~01"
> > -#define EXT1 "ex1"
> > -#define EXT2 "e2"
> > -#define EXT3 "3"
> > -#define EXTFAIL "longext"
> > -#define EXTNULL ""
> > +/* ************************************************************************** **
> > + * Initialize the static character test array.
> > + *
> > + * Input: none
> > + *
> > + * Output: none
> > + *
> > + * Notes: This function changes (loads) the contents of the <chartest>
> > + * array. The scope of <chartest> is this file.
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void init_chartest( void )
> > + {
> > + char *illegalchars = "*\\/?<>|\":";
> > + unsigned char *s;
> > +
> > + memset( (char *)chartest, '\0', 256 );
> > +
> > + for( s = (unsigned char *)illegalchars; *s; s++ )
> > + chartest[*s] = ILLEGAL_MASK;
> > +
> > + for( s = (unsigned char *)basechars; *s; s++ )
> > + chartest[*s] |= BASECHAR_MASK;
> > +
> > + ct_initialized = True;
> > + } /* init_chartest */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Return True if the name *could be* a mangled name.
> > + *
> > + * Input: s - A path name - in UNIX pathname format.
> > + *
> > + * Output: True if the name matches the pattern described below in the
> > + * notes, else False.
> > + *
> > + * Notes: The input name is *not* tested for 8.3 compliance. This must be
> > + * done separately. This function returns true if the name contains
> > + * a magic character followed by excactly two characters from the
> > + * basechars list (above), which in turn are followed either by the
> > + * nul (end of string) byte or a dot (extension) or by a '/' (end of
> > + * a directory name).
> > + *
> > + * ************************************************************************** **
> > + */
> > +BOOL is_mangled( char *s )
> > + {
> > + char *magic;
> > +
> > + if( !ct_initialized )
> > + init_chartest();
> > +
> > + magic = strchr_m( s, magic_char );
> > + while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */
> > + {
> > + if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */
> > + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */
> > + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */
> > + return( True ); /* If all above, then true, */
> > + magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */
> > + }
> > + return( False );
> > + } /* is_mangled */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Compare two cache keys and return a value indicating their ordinal
> > + * relationship.
> > + *
> > + * Input: ItemPtr - Pointer to a comparison key. In this case, this will
> > + * be a mangled name string.
> > + * NodePtr - Pointer to a node in the cache. The node structure
> > + * will be followed in memory by a mangled name string.
> > + *
> > + * Output: A signed integer, as follows:
> > + * (x < 0) <==> Key1 less than Key2
> > + * (x == 0) <==> Key1 equals Key2
> > + * (x > 0) <==> Key1 greater than Key2
> > + *
> > + * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for
> > + * more info.
> > + *
> > + * ************************************************************************** **
> > + */
> > +static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
> > + {
> > + char *Key1 = (char *)ItemPtr;
> > + char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
> > +
> > + return( StrCaseCmp( Key1, Key2 ) );
> > + } /* cache_compare */
> > +
> > +/* ************************************************************************** **
> > + * Free a cache entry.
> > + *
> > + * Input: WarrenZevon - Pointer to the entry that is to be returned to
> > + * Nirvana.
> > + * Output: none.
> > + *
> > + * Notes: This function gets around the possibility that the standard
> > + * free() function may be implemented as a macro, or other evil
> > + * subversions (oh, so much fun).
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void cache_free_entry( ubi_trNodePtr WarrenZevon )
> > + {
> > + ZERO_STRUCTP(WarrenZevon);
> > + SAFE_FREE( WarrenZevon );
> > + } /* cache_free_entry */
> > +
> > +/* ************************************************************************** **
> > + * Initializes or clears the mangled cache.
> > + *
> > + * Input: none.
> > + * Output: none.
> > + *
> > + * Notes: There is a section below that is commented out. It shows how
> > + * one might use lp_ calls to set the maximum memory and entry size
> > + * of the cache. You might also want to remove the constants used
> > + * in ubi_cacheInit() and replace them with lp_ calls. If so, then
> > + * the calls to ubi_cacheSetMax*() would be moved into the else
> > + * clause. Another option would be to pass in the max_entries and
> > + * max_memory values as parameters. crh 09-Apr-1998.
> > + *
> > + * ************************************************************************** **
> > + */
> > +void reset_mangled_cache( void )
> > + {
> > + if( !mc_initialized )
> > + {
> > + (void)ubi_cacheInit( mangled_cache,
> > + cache_compare,
> > + cache_free_entry,
> > + MANGLED_CACHE_MAX_ENTRIES,
> > + MANGLED_CACHE_MAX_MEMORY );
> > + mc_initialized = True;
> > + }
> > + else
> > + {
> > + (void)ubi_cacheClear( mangled_cache );
> > + }
> > +
> > + /*
> > + (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
> > + (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
> > + */
> > + } /* reset_mangled_cache */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Add a mangled name into the cache.
> > + *
> > + * Notes: If the mangled cache has not been initialized, then the
> > + * function will simply fail. It could initialize the cache,
> > + * but that's not the way it was done before I changed the
> > + * cache mechanism, so I'm sticking with the old method.
> > + *
> > + * If the extension of the raw name maps directly to the
> > + * extension of the mangled name, then we'll store both names
> > + * *without* extensions. That way, we can provide consistent
> > + * reverse mangling for all names that match. The test here is
> > + * a bit more careful than the one done in earlier versions of
> > + * mangle.c:
> > + *
> > + * - the extension must exist on the raw name,
> > + * - it must be all lower case
> > + * - it must match the mangled extension (to prove that no
> > + * mangling occurred).
> > + *
> > + * crh 07-Apr-1998
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void cache_mangled_name( char *mangled_name, char *raw_name )
> > + {
> > + ubi_cacheEntryPtr new_entry;
> > + char *s1;
> > + char *s2;
> > + size_t mangled_len;
> > + size_t raw_len;
> > + size_t i;
> > +
> > + /* If the cache isn't initialized, give up. */
> > + if( !mc_initialized )
> > + return;
> > +
> > + /* Init the string lengths. */
> > + mangled_len = strlen( mangled_name );
> > + raw_len = strlen( raw_name );
> > +
> > + /* See if the extensions are unmangled. If so, store the entry
> > + * without the extension, thus creating a "group" reverse map.
> > + */
> > + s1 = strrchr( mangled_name, '.' );
> > + if( s1 && (s2 = strrchr( raw_name, '.' )) )
> > + {
> > + i = 1;
> > + while( s1[i] && (tolower( s1[1] ) == s2[i]) )
> > + i++;
> > + if( !s1[i] && !s2[i] )
> > + {
> > + mangled_len -= i;
> > + raw_len -= i;
> > + }
> > + }
> > +
> > + /* Allocate a new cache entry. If the allocation fails, just return. */
> > + i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
> > + new_entry = malloc( i );
> > + if( !new_entry )
> > + return;
> > +
> > + /* Fill the new cache entry, and add it to the cache. */
> > + s1 = (char *)(new_entry + 1);
> > + s2 = (char *)&(s1[mangled_len + 1]);
> > + (void)StrnCpy( s1, mangled_name, mangled_len );
> > + (void)StrnCpy( s2, raw_name, raw_len );
> > + ubi_cachePut( mangled_cache, i, new_entry, s1 );
> > + } /* cache_mangled_name */
> > +
> > +/* ************************************************************************** **
> > + * Check for a name on the mangled name stack
> > + *
> > + * Input: s - Input *and* output string buffer.
> > + *
> > + * Output: True if the name was found in the cache, else False.
> > + *
> > + * Notes: If a reverse map is found, the function will overwrite the string
> > + * space indicated by the input pointer <s>. This is frightening.
> > + * It should be rewritten to return NULL if the long name was not
> > + * found, and a pointer to the long name if it was found.
> > + *
> > + * ************************************************************************** **
> > + */
> >
> > -static void unmangle_test (char *name, char *ext)
> > +BOOL check_mangled_cache( char *s )
> > +{
> > + ubi_cacheEntryPtr FoundPtr;
> > + char *ext_start = NULL;
> > + char *found_name;
> > + char *saved_ext = NULL;
> > +
> > + /* If the cache isn't initialized, give up. */
> > + if( !mc_initialized )
> > + return( False );
> > +
> > + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
> > +
> > + /* If we didn't find the name *with* the extension, try without. */
> > + if( !FoundPtr )
> > + {
> > + ext_start = strrchr( s, '.' );
> > + if( ext_start )
> > + {
> > + if((saved_ext = strdup(ext_start)) == NULL)
> > + return False;
> > +
> > + *ext_start = '\0';
> > + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
> > + /*
> > + * At this point s is the name without the
> > + * extension. We re-add the extension if saved_ext
> > + * is not null, before freeing saved_ext.
> > + */
> > + }
> > + }
> > +
> > + /* Okay, if we haven't found it we're done. */
> > + if( !FoundPtr )
> > + {
> > + if(saved_ext)
> > + {
> > + /* Replace the saved_ext as it was truncated. */
> > + (void)pstrcat( s, saved_ext );
> > + SAFE_FREE(saved_ext);
> > + }
> > + return( False );
> > + }
> > +
> > + /* If we *did* find it, we need to copy it into the string buffer. */
> > + found_name = (char *)(FoundPtr + 1);
> > + found_name += (strlen( found_name ) + 1);
> > +
> > + DEBUG( 3, ("Found %s on mangled stack ", s) );
> > +
> > + (void)pstrcpy( s, found_name );
> > + if( saved_ext )
> > + {
> > + /* Replace the saved_ext as it was truncated. */
> > + (void)pstrcat( s, saved_ext );
> > + SAFE_FREE(saved_ext);
> > + }
> > +
> > + DEBUG( 3, ("as %s\n", s) );
> > +
> > + return( True );
> > +} /* check_mangled_cache */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Used only in do_fwd_mangled_map(), below.
> > + * ************************************************************************** **
> > + */
> > +static char *map_filename( char *s, /* This is null terminated */
> > + char *pattern, /* This isn't. */
> > + int len ) /* This is the length of pattern. */
> > + {
> > + static pstring matching_bit; /* The bit of the string which matches */
> > + /* a * in pattern if indeed there is a * */
> > + char *sp; /* Pointer into s. */
> > + char *pp; /* Pointer into p. */
> > + char *match_start; /* Where the matching bit starts. */
> > + pstring pat;
> > +
> > + StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */
> > + pstrcpy( matching_bit, "" ); /* Match but no star gets this. */
> > + pp = pat; /* Initialize the pointers. */
> > + sp = s;
> > +
> > + if( strequal(s, ".") || strequal(s, ".."))
> > + {
> > + return NULL; /* Do not map '.' and '..' */
> > + }
> > +
> > + if( (len == 1) && (*pattern == '*') )
> > + {
> > + return NULL; /* Impossible, too ambiguous for */
> > + } /* words! */
> > +
> > + while( (*sp) /* Not the end of the string. */
> > + && (*pp) /* Not the end of the pattern. */
> > + && (*sp == *pp) /* The two match. */
> > + && (*pp != '*') ) /* No wildcard. */
> > + {
> > + sp++; /* Keep looking. */
> > + pp++;
> > + }
> > +
> > + if( !*sp && !*pp ) /* End of pattern. */
> > + return( matching_bit ); /* Simple match. Return empty string. */
> > +
> > + if( *pp == '*' )
> > + {
> > + pp++; /* Always interrested in the chacter */
> > + /* after the '*' */
> > + if( !*pp ) /* It is at the end of the pattern. */
> > + {
> > + StrnCpy( matching_bit, s, sp-s );
> > + return( matching_bit );
> > + }
> > + else
> > + {
> > + /* The next character in pattern must match a character further */
> > + /* along s than sp so look for that character. */
> > + match_start = sp;
> > + while( (*sp) /* Not the end of s. */
> > + && (*sp != *pp) ) /* Not the same */
> > + sp++; /* Keep looking. */
> > + if( !*sp ) /* Got to the end without a match. */
> > + {
> > + return( NULL );
> > + } /* Still hope for a match. */
> > + else
> > + {
> > + /* Now sp should point to a matching character. */
> > + StrnCpy(matching_bit, match_start, sp-match_start);
> > + /* Back to needing a stright match again. */
> > + while( (*sp) /* Not the end of the string. */
> > + && (*pp) /* Not the end of the pattern. */
> > + && (*sp == *pp) ) /* The two match. */
> > + {
> > + sp++; /* Keep looking. */
> > + pp++;
> > + }
> > + if( !*sp && !*pp ) /* Both at end so it matched */
> > + return( matching_bit );
> > + else
> > + return( NULL );
> > + }
> > + }
> > + }
> > + return( NULL ); /* No match. */
> > + } /* map_filename */
> > +
> > +
> > +/* ************************************************************************** **
> > + * MangledMap is a series of name pairs in () separated by spaces.
> > + * If s matches the first of the pair then the name given is the
> > + * second of the pair. A * means any number of any character and if
> > + * present in the second of the pair as well as the first the
> > + * matching part of the first string takes the place of the * in the
> > + * second.
> > + *
> > + * I wanted this so that we could have RCS files which can be used
> > + * by UNIX and DOS programs. My mapping string is (RCS rcs) which
> > + * converts the UNIX RCS file subdirectory to lowercase thus
> > + * preventing mangling.
> > + *
> > + * (I think Andrew wrote the above, but I'm not sure. -- CRH)
> > + *
> > + * See 'mangled map' in smb.conf(5).
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void do_fwd_mangled_map(char *s, char *MangledMap)
> > + {
> > + char *start=MangledMap; /* Use this to search for mappings. */
> > + char *end; /* Used to find the end of strings. */
> > + char *match_string;
> > + pstring new_string; /* Make up the result here. */
> > + char *np; /* Points into new_string. */
> > +
> > + DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) );
> > + while( *start )
> > + {
> > + while( (*start) && (*start != '(') )
> > + start++;
> > + if( !*start )
> > + continue; /* Always check for the end. */
> > + start++; /* Skip the ( */
> > + end = start; /* Search for the ' ' or a ')' */
> > + DEBUG( 5, ("Start of first in pair '%s'\n", start) );
> > + while( (*end) && !((*end == ' ') || (*end == ')')) )
> > + end++;
> > + if( !*end )
> > + {
> > + start = end;
> > + continue; /* Always check for the end. */
> > + }
> > + DEBUG( 5, ("End of first in pair '%s'\n", end) );
> > + if( (match_string = map_filename( s, start, end-start )) )
> > + {
> > + DEBUG( 5, ("Found a match\n") );
> > + /* Found a match. */
> > + start = end + 1; /* Point to start of what it is to become. */
> > + DEBUG( 5, ("Start of second in pair '%s'\n", start) );
> > + end = start;
> > + np = new_string;
> > + while( (*end) /* Not the end of string. */
> > + && (*end != ')') /* Not the end of the pattern. */
> > + && (*end != '*') ) /* Not a wildcard. */
> > + *np++ = *end++;
> > + if( !*end )
> > + {
> > + start = end;
> > + continue; /* Always check for the end. */
> > + }
> > + if( *end == '*' )
> > + {
> > + pstrcpy( np, match_string );
> > + np += strlen( match_string );
> > + end++; /* Skip the '*' */
> > + while( (*end) /* Not the end of string. */
> > + && (*end != ')') /* Not the end of the pattern. */
> > + && (*end != '*') ) /* Not a wildcard. */
> > + *np++ = *end++;
> > + }
> > + if( !*end )
> > + {
> > + start = end;
> > + continue; /* Always check for the end. */
> > + }
> > + *np++ = '\0'; /* NULL terminate it. */
> > + DEBUG(5,("End of second in pair '%s'\n", end));
> > + pstrcpy( s, new_string ); /* Substitute with the new name. */
> > + DEBUG( 5, ("s is now '%s'\n", s) );
> > + }
> > + start = end; /* Skip a bit which cannot be wanted anymore. */
> > + start++;
> > + }
> > + } /* do_fwd_mangled_map */
> > +
> > +/*****************************************************************************
> > + * do the actual mangling to 8.3 format
> > + * the buffer must be able to hold 13 characters (including the null)
> > + *****************************************************************************
> > + */
> > +void mangle_name_83( char *s)
> > + {
> > + int csum;
> > + char *p;
> > + char extension[4];
> > + char base[9];
> > + int baselen = 0;
> > + int extlen = 0;
> > + int skip;
> > +
> > + extension[0] = 0;
> > + base[0] = 0;
> > +
> > + p = strrchr(s,'.');
> > + if( p && (strlen(p+1) < (size_t)4) )
> > + {
> > + BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
> > +
> > + if( all_normal && p[1] != 0 )
> > + {
> > + *p = 0;
> > + csum = str_checksum( s );
> > + *p = '.';
> > + }
> > + else
> > + csum = str_checksum(s);
> > + }
> > + else
> > + csum = str_checksum(s);
> > +
> > + strupper( s );
> > +
> > + DEBUG( 5, ("Mangling name %s to ",s) );
> > +
> > + if( p )
> > + {
> > + if( p == s )
> > + safe_strcpy( extension, "___", 3 );
> > + else
> > + {
> > + *p++ = 0;
> > + while( *p && extlen < 3 )
> > + {
> > + if ( *p != '.') {
> > + extension[extlen++] = p[0];
> > + }
> > + p++;
> > + }
> > + extension[extlen] = 0;
> > + }
> > + }
> > +
> > + p = s;
> > +
> > + while( *p && baselen < 5 )
> > + {
> > + if (*p != '.') {
> > + base[baselen++] = p[0];
> > + }
> > + p++;
> > + }
> > + base[baselen] = 0;
> > +
> > + csum = csum % (MANGLE_BASE*MANGLE_BASE);
> > +
> > + (void)slprintf(s, 12, "%s%c%c%c",
> > + base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
> > +
> > + if( *extension )
> > + {
> > + (void)pstrcat( s, "." );
> > + (void)pstrcat( s, extension );
> > + }
> > +
> > + DEBUG( 5, ( "%s\n", s ) );
> > +
> > + } /* mangle_name_83 */
> > +
> > +/*****************************************************************************
> > + * Convert a filename to DOS format. Return True if successful.
> > + *
> > + * Input: OutName - Source *and* destination buffer.
> > + *
> > + * NOTE that OutName must point to a memory space that
> > + * is at least 13 bytes in size!
> > + *
> > + * need83 - If False, name mangling will be skipped unless the
> > + * name contains illegal characters. Mapping will still
> > + * be done, if appropriate. This is probably used to
> > + * signal that a client does not require name mangling,
> > + * thus skipping the name mangling even on shares which
> > + * have name-mangling turned on.
> > + * cache83 - If False, the mangled name cache will not be updated.
> > + * This is usually used to prevent that we overwrite
> > + * a conflicting cache entry prematurely, i.e. before
> > + * we know whether the client is really interested in the
> > + * current name. (See PR#13758). UKD.
> > + * snum - Share number. This identifies the share in which the
> > + * name exists.
> > + *
> > + * Output: Returns False only if the name wanted mangling but the share does
> > + * not have name mangling turned on.
> > + *
> > + * ****************************************************************************
> > + */
> > +BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
> > {
> > - smb_ucs2_t ucs2_name[2048];
> > - smb_ucs2_t *retstr;
> > - pstring unix_name;
> > + char *map;
> > + smb_ucs2_t *OutName_ucs2;
> > + DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName,
> > + need83 ? "True" : "False", cache83 ? "True" : "False", snum));
> > +
> > + if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) {
> > + DEBUG(0, ("push_ucs2_allocate failed!\n"));
> > + return False;
> > + }
> >
> > - push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
> > - if (ext)
> > - {
> > - strncat_wa(ucs2_name, ".", 1);
> > - strncat_wa(ucs2_name, ext, strlen(ext) + 1);
> > +#ifdef MANGLE_LONG_FILENAMES
> > +
> > + if( !need83 && !NT_STATUS_IS_OK(has_valid_chars(OutName_ucs2 ))) {
> > + need83 = True;
> > }
> > - retstr = unmangle(ucs2_name);
> > - if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
> > - else unix_name[0] = 0;
> > - if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
> > - else printf ("[%s] ---> [%s]\n", name, unix_name);
> > - SAFE_FREE(retstr);
> > -}
> > +#endif
> >
> > -static void mangle_test (char *name, char *ext)
> > -{
> > - smb_ucs2_t ucs2_name[2048];
> > - smb_ucs2_t *retstr;
> > - pstring unix_name;
> > + /* apply any name mappings */
> > + map = lp_mangled_map(snum);
> >
> > - push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
> > - if (ext)
> > - {
> > - strncat_wa(ucs2_name, ".", 1);
> > - strncat_wa(ucs2_name, ext, strlen(ext) + 1);
> > + if (map && *map) {
> > + do_fwd_mangled_map( OutName, map );
> > }
> > - retstr = mangle(ucs2_name);
> > - if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
> > - else unix_name[0] = 0;
> > - if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
> > - else printf ("[%s] ---> [%s]\n", name, unix_name);
> > - SAFE_FREE(retstr);
> > -}
> >
> > -void mangle_test_code(void)
> > -{
> > - init_mangle_tdb();
> > + /* check if it's already in 8.3 format */
> > + if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) {
> > + char *tmp = NULL;
> >
> > - /* unmangle every */
> > - printf("Unmangle test 1:\n");
> > + if (!lp_manglednames(snum)) {
> > + return(False);
> > + }
> >
> > - unmangle_test (LONG, NULL);
> > - unmangle_test (LONG, EXT1);
> > - unmangle_test (LONG, EXT2);
> > - unmangle_test (LONG, EXT3);
> > - unmangle_test (LONG, EXTFAIL);
> > - unmangle_test (LONG, EXTNULL);
> > -
> > - unmangle_test (LONGM, NULL);
> > - unmangle_test (LONGM, EXT1);
> > - unmangle_test (LONGM, EXT2);
> > - unmangle_test (LONGM, EXT3);
> > - unmangle_test (LONGM, EXTFAIL);
> > - unmangle_test (LONGM, EXTNULL);
> > -
> > - unmangle_test (SHORT, NULL);
> > - unmangle_test (SHORT, EXT1);
> > - unmangle_test (SHORT, EXT2);
> > - unmangle_test (SHORT, EXT3);
> > - unmangle_test (SHORT, EXTFAIL);
> > - unmangle_test (SHORT, EXTNULL);
> > -
> > - unmangle_test (SHORTM, NULL);
> > - unmangle_test (SHORTM, EXT1);
> > - unmangle_test (SHORTM, EXT2);
> > - unmangle_test (SHORTM, EXT3);
> > - unmangle_test (SHORTM, EXTFAIL);
> > - unmangle_test (SHORTM, EXTNULL);
> > -
> > - /* mangle every */
> > - printf("Mangle test\n");
> > -
> > - mangle_test (LONG, NULL);
> > - mangle_test (LONG, EXT1);
> > - mangle_test (LONG, EXT2);
> > - mangle_test (LONG, EXT3);
> > - mangle_test (LONG, EXTFAIL);
> > - mangle_test (LONG, EXTNULL);
> > -
> > - mangle_test (LONGM, NULL);
> > - mangle_test (LONGM, EXT1);
> > - mangle_test (LONGM, EXT2);
> > - mangle_test (LONGM, EXT3);
> > - mangle_test (LONGM, EXTFAIL);
> > - mangle_test (LONGM, EXTNULL);
> > -
> > - mangle_test (SHORT, NULL);
> > - mangle_test (SHORT, EXT1);
> > - mangle_test (SHORT, EXT2);
> > - mangle_test (SHORT, EXT3);
> > - mangle_test (SHORT, EXTFAIL);
> > - mangle_test (SHORT, EXTNULL);
> > -
> > - mangle_test (SHORTM, NULL);
> > - mangle_test (SHORTM, EXT1);
> > - mangle_test (SHORTM, EXT2);
> > - mangle_test (SHORTM, EXT3);
> > - mangle_test (SHORTM, EXTFAIL);
> > - mangle_test (SHORTM, EXTNULL);
> > -
> > - /* unmangle again every */
> > - printf("Unmangle test 2:\n");
> > -
> > - unmangle_test (LONG, NULL);
> > - unmangle_test (LONG, EXT1);
> > - unmangle_test (LONG, EXT2);
> > - unmangle_test (LONG, EXT3);
> > - unmangle_test (LONG, EXTFAIL);
> > - unmangle_test (LONG, EXTNULL);
> > -
> > - unmangle_test (LONGM, NULL);
> > - unmangle_test (LONGM, EXT1);
> > - unmangle_test (LONGM, EXT2);
> > - unmangle_test (LONGM, EXT3);
> > - unmangle_test (LONGM, EXTFAIL);
> > - unmangle_test (LONGM, EXTNULL);
> > -
> > - unmangle_test (SHORT, NULL);
> > - unmangle_test (SHORT, EXT1);
> > - unmangle_test (SHORT, EXT2);
> > - unmangle_test (SHORT, EXT3);
> > - unmangle_test (SHORT, EXTFAIL);
> > - unmangle_test (SHORT, EXTNULL);
> > -
> > - unmangle_test (SHORTM, NULL);
> > - unmangle_test (SHORTM, EXT1);
> > - unmangle_test (SHORTM, EXT2);
> > - unmangle_test (SHORTM, EXT3);
> > - unmangle_test (SHORTM, EXTFAIL);
> > - unmangle_test (SHORTM, EXTNULL);
> > -}
> > + /* mangle it into 8.3 */
> > + if (cache83)
> > + tmp = strdup(OutName);
> > +
> > + mangle_name_83(OutName);
> > +
> > + if(tmp != NULL) {
> > + cache_mangled_name(OutName, tmp);
> > + SAFE_FREE(tmp);
> > + }
> > + }
> > +
> > + DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName));
> > + SAFE_FREE(OutName_ucs2);
> > + return(True);
> > +} /* name_map_mangle */
> >
> > -#endif /* TEST_MANGLE_CODE */
> > Index: smbd/reply.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/reply.c,v
> > retrieving revision 1.376
> > diff -u -r1.376 reply.c
> > --- smbd/reply.c 2002/03/23 02:57:43 1.376
> > +++ smbd/reply.c 2002/03/25 08:24:47
> > @@ -3054,10 +3054,10 @@
> > * Tine Smukavec <valentin.smukavec at hermes.si>.
> > */
> >
> > -#if 0
> > +#if 1
> > if (!rc && is_mangled(mask))
> > check_mangled_cache( mask );
> > -#endif
> > +#else
> > if (!rc)
> > {
> > char *unmangled;
> > @@ -3068,6 +3068,7 @@
> >
> > SAFE_FREE(unmangled);
> > }
> > +#endif
> >
> > has_wild = ms_has_wild(mask);
> >
> > @@ -3470,10 +3471,10 @@
> > * Tine Smukavec <valentin.smukavec at hermes.si>.
> > */
> >
> > -#if 0
> > +#if 1
> > if (!rc && is_mangled(mask))
> > check_mangled_cache( mask );
> > -#endif
> > +#else
> > if (!rc)
> > {
> > char *unmangled;
> > @@ -3484,7 +3485,7 @@
> >
> > SAFE_FREE(unmangled);
> > }
> > -
> > +#endif
> >
> > has_wild = ms_has_wild(mask);
> >
> > Index: smbd/server.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/server.c,v
> > retrieving revision 1.369
> > diff -u -r1.369 server.c
> > --- smbd/server.c 2002/03/14 02:15:08 1.369
> > +++ smbd/server.c 2002/03/25 08:24:48
> > @@ -882,10 +882,6 @@
> > if (!init_oplocks())
> > exit(1);
> >
> > - /* Setup mangle */
> > - if (!init_mangle_tdb())
> > - exit(1);
> > -
> > /* Setup change notify */
> > if (!init_change_notify())
> > exit(1);
> --
> Simo Sorce
> ----------
> Una scelta di liberta': Software Libero.
> A choice of freedom: Free Software.
> http://www.softwarelibero.it
>
--
Simo Sorce
----------
Una scelta di liberta': Software Libero.
A choice of freedom: Free Software.
http://www.softwarelibero.it
More information about the samba-technical
mailing list