r24453: Remove the read and write bmpx calls
[samba.git] / source3 / smbd / mangle.c
index b83168712f0e74ea0ddaba5ddc2e711e8b0803c7..fce86903f2427b99ef6f04ed7b7e2683a68ce2d3 100644 (file)
@@ -1,12 +1,11 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 3.0
-   Name mangling with persistent tdb
-   Copyright (C) Simo Sorce 2001
+   Unix SMB/CIFS implementation.
+   Name mangling interface
+   Copyright (C) Andrew Tridgell 2002
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-/****************************************************************************
-  Rewritten from scrach in 2001 by Simo Sorce <idra@samba.org>
- ****************************************************************************/
-
 #include "includes.h"
 
-
-/* -------------------------------------------------------------------------- **
- * External Variables...
- */
-
-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. */
-
-char magic_char = '~';
-
-/* -------------------------------------------------------------------- */
-
-#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 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 */
-
-       /* 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;
-       }
-
-       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)
-{
-       int src_len, ret;
-
-       if (dest_len == -1) {
-               dest_len = sizeof(pstring);
-       }
-
-       src_len = strlen_w(src)* sizeof(smb_ucs2_t);
-       
-       ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len);
-       if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
-
-       return ret;
-}
-
-/* trasform in a string that contain only valid chars for win filenames,
- not including a '.' */
-static void strvalid(smb_ucs2_t *src)
-{
-       if (!src || !*src) return;
-
-       while (*src) {
-               if (!isvalid83_w(*src) || *src == UCS2_CHAR('.')) *src = UCS2_CHAR('_');
-               src++;
-       }
-}
-
-
-/* return False if something fail and
- * return 2 alloced unicode strings that contain prefix and extension
- */
-static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension)
-{
-       size_t ext_len;
-       smb_ucs2_t *p;
-
-       *extension = 0;
-       *prefix = strdup_w(ucs2_string);
-       if (!*prefix)
-       {
-               DEBUG(0,("mangle_get_prefix: out of memory!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-       if ((p = strrchr_w(*prefix, UCS2_CHAR('.'))))
-       {
-               ext_len = strlen_w(p+1);
-               if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
-                   (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */
-               {
-                       *p = 0;
-                       *extension = strdup_w(p+1);
-                       if (!*extension)
-                       {
-                               DEBUG(0,("mangle_get_prefix: out of memory!\n"));
-                               SAFE_FREE(*prefix);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-       }
-       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)
+static struct mangle_fns *mangle_fns;
+
+/* this allows us to add more mangling backends */
+static const struct {
+       const char *name;
+       struct mangle_fns *(*init_fn)(void);
+} mangle_backends[] = {
+       { "hash", mangle_hash_init },
+       { "hash2", mangle_hash2_init },
+       { "posix", posix_mangle_init },
+       /*{ "tdb", mangle_tdb_init }, */
+       { NULL, NULL }
+};
+
+/*
+  initialise the mangling subsystem
+*/
+static void mangle_init(void)
 {
-       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;
-       }
+       int i;
+       const char *method;
 
-       if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext)))
-               return NULL;
+       if (mangle_fns)
+               return;
 
-       /* 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;
-       }
+       method = lp_mangling_method();
 
-       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;
+       /* find the first mangling method that manages to initialise and
+          matches the "mangling method" parameter */
+       for (i=0; mangle_backends[i].name && !mangle_fns; i++) {
+               if (!method || !*method || strcmp(method, mangle_backends[i].name) == 0) {
+                       mangle_fns = mangle_backends[i].init_fn();
                }
-               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;
-               }
 
+       if (!mangle_fns) {
+               DEBUG(0,("Failed to initialise mangling system '%s'\n", method));
+               exit_server("mangling init failed");
        }
-
-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.
- */
 
-smb_ucs2_t *mangle(const smb_ucs2_t *unmangled)
+/*
+  reset the cache. This is called when smb.conf has been reloaded
+*/
+void mangle_reset_cache(void)
 {
-       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)
-                       {
-                               DEBUG(0, ("mangle: unable to mangle file name!\n"));
-                               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)
-                       {
-                               DEBUG(0, ("mangle: database store error: %s\n",
-                                       tdb_errorstr(mangle_tdb)));
-                               goto done;
-                       }
-               }
-
-               /* lock the mangle counter for this prefix */           
-               if (tdb_chainlock(mangle_tdb, klock))
-               {
-                       DEBUG(0,("mangle: failed to lock database\n!"));
-                       goto done;
-               }
-               tclock = True;
-
-               data = tdb_fetch(mangle_tdb, klock);
-               if (!data.dptr)
-               {
-                       DEBUG(0, ("mangle: database retrieval error: %s\n",
-                                       tdb_errorstr(mangle_tdb)));
-                       goto done;
-               }
-               c = *((uint32 *)data.dptr);
-               c++;
-               
-               if (c > MANGLE_COUNTER_MAX)
-               {
-                       DEBUG(0, ("mangle: error, counter overflow!\n"));
-                       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)
-               {
-                       DEBUG(0, ("mangle: darn, logic error aborting!\n"));
-                       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)
-               {
-                       DEBUG(0, ("mangle: database store error: %s\n",
-                                       tdb_errorstr(mangle_tdb)));
-                       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)
-               {
-                       DEBUG(0, ("mangle: database store failed: %s\n",
-                                       tdb_errorstr(mangle_tdb)));
-
-                       /* 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)
-               {
-                       DEBUG(0, ("mangle: database store failed: %s\n",
-                                       tdb_errorstr(mangle_tdb)));
-                       /* 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: out of memory!\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;
+       mangle_init();
+       mangle_fns->reset();
 }
 
-
-/* non unicode compatibility functions */
-
-char *dos_mangle(const char *dos_unmangled)
+void mangle_change_to_posix(void)
 {
-       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: out of memory!\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: out of memory!\n"));
-               goto done;
-       }
-
-done:
-       SAFE_FREE(in);
-       SAFE_FREE(out);
-       return dos_mangled;
+       mangle_fns = NULL;
+       lp_set_mangling_method("posix");
+       mangle_reset_cache();
 }
 
-char *dos_unmangle(const char *dos_mangled)
+/*
+  see if a filename has come out of our mangling code
+*/
+BOOL mangle_is_mangled(const char *s, const struct share_params *p)
 {
-       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: out of memory!\n"));
-               return NULL;
-       }
-
-       out = mangle(in);
-       if (!out)
-       {
-               SAFE_FREE(in);
-               return NULL;
-       }
-
-       dos_unmangled = acnv_u2dos(out);
-       if (!dos_unmangled)
-       {
-               DEBUG(0,("dos_unmangle: out of memory!\n"));
-               goto done;
-       }
-
-done:
-       SAFE_FREE(in);
-       SAFE_FREE(out);
-       return dos_unmangled;
+       return mangle_fns->is_mangled(s, p);
 }
 
-BOOL is_8_3(const char *fname, BOOL check_case)
+/*
+  see if a filename matches the rules of a 8.3 filename
+*/
+BOOL mangle_is_8_3(const char *fname, BOOL check_case,
+                  const struct share_params *p)
 {
-       smb_ucs2_t *ucs2name;
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
-       if (!fname || !*fname) return False;
-
-       DEBUG(10,("is_8_3: testing [%s]\n", fname));
-
-       if (strlen(fname) > 12) return False;
-       
-       ucs2name = acnv_uxu2(fname);
-       if (!ucs2name)
-       {
-               DEBUG(0,("is_8_3: out of memory!\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;
+       return mangle_fns->is_8_3(fname, check_case, False, p);
 }
 
-NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
+BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case,
+                            const struct share_params *p)
 {
-       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;
+       return mangle_fns->is_8_3(fname, check_case, True, p);
 }
 
-NTSTATUS has_valid_chars(const smb_ucs2_t *s)
+/*
+  try to reverse map a 8.3 name to the original filename. This doesn't have to 
+  always succeed, as the directory handling code in smbd will scan the directory
+  looking for a matching name if it doesn't. It should succeed most of the time
+  or there will be a huge performance penalty
+*/
+BOOL mangle_check_cache(char *s, size_t maxlen,
+                       const struct share_params *p)
 {
-       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;
+       return mangle_fns->check_cache(s, maxlen, p);
 }
 
-NTSTATUS is_valid_name(const smb_ucs2_t *fname)
+BOOL mangle_check_cache_alloc(const char *name, char **presult,
+                             const struct share_params *p)
 {
-       smb_ucs2_t *str, *p;
-       NTSTATUS ret = NT_STATUS_OK;
-
-       if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
-
-       DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */
+       pstring tmp;
+       char *result;
+       pstrcpy(tmp, name);
 
-       if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL;
-       
-       ret = has_valid_chars(fname);
-       if (NT_STATUS_IS_ERR(ret)) return ret;
-
-       str = strdup_w(fname);
-       p = strchr_w(str, UCS2_CHAR('.'));
-       if (p) *p = 0;
-       strupper_w(str);
-       p = &(str[1]);
-
-       switch(str[0])
-       {
-       case UCS2_CHAR('A'):
-               if(strcmp_wa(p, "UX") == 0)
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               break;
-       case UCS2_CHAR('C'):
-               if((strcmp_wa(p, "LOCK$") == 0)
-               || (strcmp_wa(p, "ON") == 0)
-               || (strcmp_wa(p, "OM1") == 0)
-               || (strcmp_wa(p, "OM2") == 0)
-               || (strcmp_wa(p, "OM3") == 0)
-               || (strcmp_wa(p, "OM4") == 0)
-               )
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               break;
-       case UCS2_CHAR('L'):
-               if((strcmp_wa(p, "PT1") == 0)
-               || (strcmp_wa(p, "PT2") == 0)
-               || (strcmp_wa(p, "PT3") == 0)
-               )
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               break;
-       case UCS2_CHAR('N'):
-               if(strcmp_wa(p, "UL") == 0)
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               break;
-       case UCS2_CHAR('P'):
-               if(strcmp_wa(p, "RN") == 0)
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               break;
-       default:
-               break;
-       }
-
-       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: out of memory!\n"));
-               return ret;
+       if (!mangle_check_cache(tmp, sizeof(pstring)-1, p)
+           || !(result = SMB_STRDUP(tmp))) {
+               return False;
        }
-
-       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;
+       *presult = result;
+       return True;
 }
 
-NTSTATUS is_mangled_w(const smb_ucs2_t *s)
-{
-       smb_ucs2_t *res;
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       
-       res = unmangle(s);
-       if (res) ret = NT_STATUS_OK;
-       SAFE_FREE(res);
-       return ret;
-}
+/* 
+   map a long filename to a 8.3 name. 
+ */
 
-NTSTATUS path_has_mangled(const smb_ucs2_t *s)
+void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
+               const struct share_params *p)
 {
-       smb_ucs2_t *p, *f, *b;
-       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;
+       /* name mangling can be disabled for speed, in which case
+          we just truncate the string */
+       if (!lp_manglednames(p)) {
+               if (need83) {
+                       string_truncate(OutName, 12);
                }
-               f = b + 1;
-       }
-done:
-       SAFE_FREE(p);
-       return ret;
-}
-
-/* backward compatibility functions */
-
-void reset_mangled_cache(void)
-{
-       DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n"));
-}
-
-BOOL check_mangled_cache(char *s)
-{
-       smb_ucs2_t *u2, *res;
-       BOOL ret = False;
-
-       DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n"));
-       DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s));
-
-       if (!s || !*s) return False;
-
-       u2 = acnv_dosu2(s);
-       if (!u2)
-       {
-               DEBUG(0,("check_mangled_cache: out of memory!\n"));
-               return ret;
-       }
-
-       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"));
-       return ret;
-}
-
-void mangle_name_83(char *s)
-{
-       smb_ucs2_t *u2, *res;
-
-       DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n"));
-       DEBUG(10,("mangle_name_83: testing -> [%s]\n", s));
-
-       if (!s || !*s) return;
-       
-       u2 = acnv_dosu2(s);
-       if (!u2)
-       {
-               DEBUG(0,("mangle_name_83: out of memory!\n"));
                return;
        }
 
-       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);
-}
-
-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"));
-
-       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*/
-
-       mangle_name_83(OutName);
-       return True;
-}
-
-
-
-#if 0 /* TEST_MANGLE_CODE */
-
-#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                ""
-
-static void unmangle_test (char *name, char *ext)
-{
-       smb_ucs2_t ucs2_name[2048];
-       smb_ucs2_t *retstr;
-       pstring unix_name;      
-
-       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);
-       }
-       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);
-}
-
-static void mangle_test (char *name, char *ext)
-{
-       smb_ucs2_t ucs2_name[2048];
-       smb_ucs2_t *retstr;
-       pstring unix_name;      
-
-       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);
-       }
-       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();
-
-       /* unmangle every */
-       printf("Unmangle test 1:\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 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);
+       /* invoke the inane "mangled map" code */
+       mangle_map_filename(OutName, p);
+       mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
 }
-
-#endif /* TEST_MANGLE_CODE */