summaryrefslogtreecommitdiff
path: root/source3/smbd/mangle.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-04-08 01:58:44 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-04-08 01:58:44 +0000
commitc21ff8f76209a1e7138ba06ce262a3e2c2880646 (patch)
treee33f991cbb4d2213267bb324b1b7c08551a6de37 /source3/smbd/mangle.c
parent0e6eb43e6b9a1dd57dea0b0f852db9240c0f2fde (diff)
downloadsamba-c21ff8f76209a1e7138ba06ce262a3e2c2880646.tar.gz
samba-c21ff8f76209a1e7138ba06ce262a3e2c2880646.tar.bz2
samba-c21ff8f76209a1e7138ba06ce262a3e2c2880646.zip
Reintroduce the 2.2 name mangling code, until we get are more flexible solution.
Even for a hash/cache setup, this code needs some more work, in particular it needs to use mangle_get_prefix() etc and to move to unicode internals. Andrew Bartlett (This used to be commit ad8aa470575c39fcbc7f1440bf1081d7ea31c0aa)
Diffstat (limited to 'source3/smbd/mangle.c')
-rw-r--r--source3/smbd/mangle.c1605
1 files changed, 785 insertions, 820 deletions
diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c
index cfa71e3cf4..9789f06e0c 100644
--- a/source3/smbd/mangle.c
+++ b/source3/smbd/mangle.c
@@ -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@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,66 +56,106 @@
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 TDB_CONTEXT *mangle_tdb;
+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
-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;
- }
+/* -------------------------------------------------------------------------- **
+ * External Variables...
+ */
- return True;
-}
+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. */
-/* 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);
- }
+NTSTATUS has_valid_chars(const smb_ucs2_t *s)
+{
+ if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
- src_len = strlen_w(src)* sizeof(smb_ucs2_t);
+ DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
- 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;
+ /* 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 (*src) {
- if (!isvalid83_w(*src) || *src == UCS2_CHAR('.')) *src = UCS2_CHAR('_');
- src++;
+ while (*s) {
+ if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
+ s++;
}
-}
+ return NT_STATUS_OK;
+}
/* return False if something fail and
* return 2 alloced unicode strings that contain prefix and extension
@@ -128,523 +191,18 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr
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)
-{
- 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)
+static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
{
smb_ucs2_t *str, *p;
NTSTATUS ret = NT_STATUS_OK;
@@ -703,296 +261,703 @@ NTSTATUS is_valid_name(const smb_ucs2_t *fname)
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)
-{
- 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)
+static NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
{
- 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 )
{
- smb_ucs2_t ucs2_name[2048];
- smb_ucs2_t *retstr;
- pstring unix_name;
+ 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;
+
+ 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)
+{
+ 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);
+ /* apply any name mappings */
+ map = lp_mangled_map(snum);
+
+ if (map && *map) {
+ do_fwd_mangled_map( OutName, map );
}
- 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;
+ /* check if it's already in 8.3 format */
+ if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) {
+ char *tmp = NULL;
- 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 (!lp_manglednames(snum)) {
+ return(False);
+ }
+
+ /* 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);
+ }
}
- 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);
-}
+ DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName));
+ SAFE_FREE(OutName_ucs2);
+ return(True);
+} /* name_map_mangle */
-#endif /* TEST_MANGLE_CODE */