/* Unix SMB/Netbios implementation. Version 3.0 Name mangling with persistent tdb Copyright (C) Simo Sorce 2001 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ /**************************************************************************** Rewritten from scrach in 2001 by Simo Sorce ****************************************************************************/ #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) { 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. */ 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) { 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; } /* 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: 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; } 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: 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; } BOOL is_8_3(const char *fname, BOOL check_case) { char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!fname || !*fname) return False; if ((f = strrchr(fname, '/')) == NULL) f = fname; 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: 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; } 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; if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */ 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; } 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) { 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; } 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); } #endif /* TEST_MANGLE_CODE */