/* * All modifications in this file to the original code are * (C) Copyright 1992, ..., 2004 the "DOSEMU-Development-Team". * * for details see file COPYING in the DOSEMU distribution */ /* Unix SMB/Netbios implementation. Version 1.9. Copyright (C) Andrew Tridgell 1992,1993,1994 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. */ /* Modified by O.V.Zhirov, July 1998 */ #ifdef DOSEMU #include "config.h" #include "utilities.h" #include "mangle.h" #include "mfs.h" #include "dos2linux.h" #include "emu.h" #ifdef HAVE_UNICODE_TRANSLATION #include "translate.h" #include #endif #else #include "includes.h" #include "loadparm.h" #endif /**************************************************************************** provide a checksum on a string ****************************************************************************/ static int str_checksum(char *s) { int res = 0; int c; int i=0; while (*s) { c = *s; res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); s++; i++; } return(res); } /**************************************************************************** check if a name is a special msdos reserved name: the name is either a full Unix name or an 8 character candidate ****************************************************************************/ unsigned long is_dos_device(const char *fname) { char *p; unsigned char *dev; unsigned long devfar; int i; /* * LPTx e.t.c. is reserved no matter the path (e.g. .\LPT1 _is_ reserved), * but mfs.c sends an entire path. * -- Rob Clark 2000/05/09 */ if (fname[0] == '/') { d_printf("MFS: is_msdos_device %s\n", fname); p = strrchr(fname,'/'); if (p) fname = p+1; /* strip the directory part */ } else { d_printf("MFS: is_msdos_device %.8s\n", fname); } /* * The below (now #ifdef'ed out) code strips the extension off for checking. * But the assumption, that file names with a reserved basename remain * reserved even if they have an extension, seems not to be true. * For example CLIPPER-programs _are_ using file names such as * 'LPTx.PRN' for internal spooling purposes. * -- Bernd Schueler b.schueler@gmx.de 2001/02/23 * well, as far as I know the extension can be stripped off; * most likely the bug was somewhere else - we must not strip * the extension off for further processing Bart 2002/08/12 */ /* walk the chain of DOS devices; see also FreeDOS kernel code */ dev = &lol[lol_nuldev_off]; devfar = (((unsigned long)dev - 0x26) << 12) | 0x26; do { for (i = 0; i < 8; i++) { char c1 = fname[i]; /* hopefully no device names with cyrillic characters exist ... */ if ((unsigned char)c1 >= 128) break; if ((unsigned char)dev[0xa + i] >= 128) break; if (c1 == '.' || c1 == '\0') { /* check if remainder of device name consists of spaces or nulls */ for (; i < 8; i++) { char c2 = dev[0xa + i]; if (c2 != ' ' && c2 != '\0') break; } break; } if (toupper(c1) != toupper(dev[0xa + i])) break; } if (i == 8) return devfar; if (dev[0] == 0xff || dev[1] == 0xff) return 0; memcpy(&devfar, dev, 4); dev = (char *)((((dev[3] << 8) | dev[2]) << 4) + ((dev[1] << 8) | dev[0])); } while (1); } BOOL valid_dos_char[256]; /**************************************************************************** initialise the valid dos char array ****************************************************************************/ static void valid_initialise(void) { static BOOL initialised = False; int i; if (initialised) return; for (i=0;i<256;i++) valid_dos_char[i] = is_valid_DOS_char(i); initialised = True; } /**************************************************************************** return True if a name is in 8.3 dos format ****************************************************************************/ static BOOL is_8_3(char *fname) { int len = strlen(fname); char *dot_pos = strchr(fname,'.'); int l; DEBUG(5,("checking %s for 8.3\n",fname)); /* can't be longer than 12 chars */ if (len == 0 || len > 12) return(False); /* can't contain invalid dos chars */ /* Windows use the ANSI charset. But filenames are translated in the PC charset. This Translation may be more or less relaxed depending the Windows application. */ /* %%% A nice improvment to name mangling would be to translate filename to ANSI charset on the smb server host */ { char *p = fname; valid_initialise(); #ifdef KANJI dot_pos = 0; while (*p) { if (is_shift_jis (*p)) { p += 2; } else if (is_kana (*p)) { p ++; } else { if (*p == '.' && !dot_pos) dot_pos = (char *) p; if (!VALID_DOS_PCHAR(p)) return(False); p++; } } #else while (*p) { if (!VALID_DOS_PCHAR(p)) return(False); p++; } #endif /* KANJI */ } /* no dot and less than 9 means OK */ if (!dot_pos) return(len <= 8); l = PTR_DIFF(dot_pos,fname); /* base must be at least 1 char except special cases . and .. */ if (l == 0) return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); /* base can't be greater than 8 */ if (l > 8) return(False); if (lp_strip_dot() && len - l == 1 && !strchr(dot_pos+1,'.')) { *dot_pos = 0; return(True); } /* extension must be between 1 and 3 */ if ( (len - l < 2 ) || (len - l > 4) ) return(False); /* extension can't have a dot */ if (strchr(dot_pos+1,'.')) return(False); /* must be in 8.3 format */ return(True); } /* keep a stack of name mangling results - just so file moves and copies have a chance of working */ fstring *mangled_stack = NULL; int mangled_stack_size = 0; int mangled_stack_len = 0; /**************************************************************************** create the mangled stack ****************************************************************************/ static void create_mangled_stack(int size) { if (mangled_stack) { free(mangled_stack); mangled_stack_size = 0; mangled_stack_len = 0; } if (size > 0) mangled_stack = (fstring *)malloc(sizeof(fstring)*size); if (mangled_stack) mangled_stack_size = size; } /**************************************************************************** push a mangled name onto the stack ****************************************************************************/ static void push_mangled_name(char *s) { int i; char *p; if (!mangled_stack) { create_mangled_stack(MANGLED_STACK); if (!mangled_stack) return; } for (i=0;i