1/* 2 Unix SMB/CIFS implementation. 3 Name mapping code 4 Copyright (C) Jeremy Allison 1998 5 Copyright (C) Andrew Tridgell 2002 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#include "includes.h" 23 24 25/* ************************************************************************** ** 26 * Used only in do_fwd_mangled_map(), below. 27 * ************************************************************************** ** 28 */ 29static char *map_filename( char *s, /* This is null terminated */ 30 const char *pattern, /* This isn't. */ 31 int len ) /* This is the length of pattern. */ 32 { 33 static pstring matching_bit; /* The bit of the string which matches */ 34 /* a * in pattern if indeed there is a * */ 35 char *sp; /* Pointer into s. */ 36 char *pp; /* Pointer into p. */ 37 char *match_start; /* Where the matching bit starts. */ 38 pstring pat; 39 40 StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ 41 pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ 42 pp = pat; /* Initialize the pointers. */ 43 sp = s; 44 45 if( strequal(s, ".") || strequal(s, "..")) 46 { 47 return NULL; /* Do not map '.' and '..' */ 48 } 49 50 if( (len == 1) && (*pattern == '*') ) 51 { 52 return NULL; /* Impossible, too ambiguous for */ 53 } /* words! */ 54 55 while( (*sp) /* Not the end of the string. */ 56 && (*pp) /* Not the end of the pattern. */ 57 && (*sp == *pp) /* The two match. */ 58 && (*pp != '*') ) /* No wildcard. */ 59 { 60 sp++; /* Keep looking. */ 61 pp++; 62 } 63 64 if( !*sp && !*pp ) /* End of pattern. */ 65 return( matching_bit ); /* Simple match. Return empty string. */ 66 67 if( *pp == '*' ) 68 { 69 pp++; /* Always interrested in the chacter */ 70 /* after the '*' */ 71 if( !*pp ) /* It is at the end of the pattern. */ 72 { 73 StrnCpy( matching_bit, s, sp-s ); 74 return( matching_bit ); 75 } 76 else 77 { 78 /* The next character in pattern must match a character further */ 79 /* along s than sp so look for that character. */ 80 match_start = sp; 81 while( (*sp) /* Not the end of s. */ 82 && (*sp != *pp) ) /* Not the same */ 83 sp++; /* Keep looking. */ 84 if( !*sp ) /* Got to the end without a match. */ 85 { 86 return( NULL ); 87 } /* Still hope for a match. */ 88 else 89 { 90 /* Now sp should point to a matching character. */ 91 StrnCpy(matching_bit, match_start, sp-match_start); 92 /* Back to needing a stright match again. */ 93 while( (*sp) /* Not the end of the string. */ 94 && (*pp) /* Not the end of the pattern. */ 95 && (*sp == *pp) ) /* The two match. */ 96 { 97 sp++; /* Keep looking. */ 98 pp++; 99 } 100 if( !*sp && !*pp ) /* Both at end so it matched */ 101 return( matching_bit ); 102 else 103 return( NULL ); 104 } 105 } 106 } 107 return( NULL ); /* No match. */ 108 } /* map_filename */ 109 110 111/* ************************************************************************** ** 112 * MangledMap is a series of name pairs in () separated by spaces. 113 * If s matches the first of the pair then the name given is the 114 * second of the pair. A * means any number of any character and if 115 * present in the second of the pair as well as the first the 116 * matching part of the first string takes the place of the * in the 117 * second. 118 * 119 * I wanted this so that we could have RCS files which can be used 120 * by UNIX and DOS programs. My mapping string is (RCS rcs) which 121 * converts the UNIX RCS file subdirectory to lowercase thus 122 * preventing mangling. 123 * 124 * See 'mangled map' in smb.conf(5). 125 * 126 * ************************************************************************** ** 127 */ 128static void mangled_map(char *s, const char *MangledMap) 129{ 130 const char *start=MangledMap; /* Use this to search for mappings. */ 131 const char *end; /* Used to find the end of strings. */ 132 char *match_string; 133 pstring new_string; /* Make up the result here. */ 134 char *np; /* Points into new_string. */ 135 136 DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); 137 while( *start ) { 138 while( (*start) && (*start != '(') ) 139 start++; 140 if( !*start ) 141 continue; /* Always check for the end. */ 142 start++; /* Skip the ( */ 143 end = start; /* Search for the ' ' or a ')' */ 144 DEBUG( 5, ("Start of first in pair '%s'\n", start) ); 145 while( (*end) && !((*end == ' ') || (*end == ')')) ) 146 end++; 147 if( !*end ) { 148 start = end; 149 continue; /* Always check for the end. */ 150 } 151 DEBUG( 5, ("End of first in pair '%s'\n", end) ); 152 if( (match_string = map_filename( s, start, end-start )) ) { 153 int size_left = sizeof(new_string) - 1; 154 DEBUG( 5, ("Found a match\n") ); 155 /* Found a match. */ 156 start = end + 1; /* Point to start of what it is to become. */ 157 DEBUG( 5, ("Start of second in pair '%s'\n", start) ); 158 end = start; 159 np = new_string; 160 while( (*end && size_left > 0) /* Not the end of string. */ 161 && (*end != ')') /* Not the end of the pattern. */ 162 && (*end != '*') ) { /* Not a wildcard. */ 163 *np++ = *end++; 164 size_left--; 165 } 166 167 if( !*end ) { 168 start = end; 169 continue; /* Always check for the end. */ 170 } 171 if( *end == '*' ) { 172 if (size_left > 0 ) 173 safe_strcpy( np, match_string, size_left ); 174 np += strlen( match_string ); 175 size_left -= strlen( match_string ); 176 end++; /* Skip the '*' */ 177 while ((*end && size_left > 0) /* Not the end of string. */ 178 && (*end != ')') /* Not the end of the pattern. */ 179 && (*end != '*')) { /* Not a wildcard. */ 180 *np++ = *end++; 181 size_left--; 182 } 183 } 184 if (!*end) { 185 start = end; 186 continue; /* Always check for the end. */ 187 } 188 if (size_left > 0) 189 *np++ = '\0'; /* NULL terminate it. */ 190 DEBUG(5,("End of second in pair '%s'\n", end)); 191 new_string[sizeof(new_string)-1] = '\0'; 192 pstrcpy( s, new_string ); /* Substitute with the new name. */ 193 DEBUG( 5, ("s is now '%s'\n", s) ); 194 } 195 start = end; /* Skip a bit which cannot be wanted anymore. */ 196 start++; 197 } 198} 199 200/* 201 front end routine to the mangled map code 202 personally I think that the whole idea of "mangled map" is completely bogus 203*/ 204void mangle_map_filename(fstring fname, const struct share_params *p) 205{ 206 char *map; 207 208 map = lp_mangled_map(p); 209 if (!map || !*map) return; 210 211 mangled_map(fname, map); 212} 213