From 0922615405838af7430ef39490ee578711866320 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 07:40:06 +0000 Subject: more splitting of server.c created dosmode.c and filename.c (This used to be commit 534a90ca44641417c21f6ed6d4b94b1de60f808d) --- source3/smbd/filename.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 source3/smbd/filename.c (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c new file mode 100644 index 0000000000..a6a9e7e7f0 --- /dev/null +++ b/source3/smbd/filename.c @@ -0,0 +1,380 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + filename handling routines + Copyright (C) Andrew Tridgell 1992-1998 + + 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. +*/ + +#include "includes.h" + +extern int DEBUGLEVEL; +extern BOOL case_sensitive; +extern BOOL case_preserve; +extern BOOL short_case_preserve; +extern fstring remote_machine; +extern BOOL use_mangled_map; + +/**************************************************************************** +check if two filenames are equal + +this needs to be careful about whether we are case sensitive +****************************************************************************/ +BOOL fname_equal(char *name1, char *name2) +{ + int l1 = strlen(name1); + int l2 = strlen(name2); + + /* handle filenames ending in a single dot */ + if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name1[l1-1] = 0; + ret = fname_equal(name1,name2); + name1[l1-1] = '.'; + return(ret); + } + + if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name2[l2-1] = 0; + ret = fname_equal(name1,name2); + name2[l2-1] = '.'; + return(ret); + } + + /* now normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + + return(strequal(name1,name2)); +} + + +/**************************************************************************** +mangle the 2nd name and check if it is then equal to the first name +****************************************************************************/ +BOOL mangled_equal(char *name1, char *name2) +{ + pstring tmpname; + + if (is_8_3(name2, True)) + return(False); + + pstrcpy(tmpname,name2); + mangle_name_83(tmpname,sizeof(tmpname)); + + return(strequal(name1,tmpname)); +} + +/**************************************************************************** +This routine is called to convert names from the dos namespace to unix +namespace. It needs to handle any case conversions, mangling, format +changes etc. + +We assume that we have already done a chdir() to the right "root" directory +for this service. + +The function will return False if some part of the name except for the last +part cannot be resolved + +If the saved_last_component != 0, then the unmodified last component +of the pathname is returned there. This is used in an exceptional +case in reply_mv (so far). If saved_last_component == 0 then nothing +is returned there. + +The bad_path arg is set to True if the filename walk failed. This is +used to pick the correct error code to return between ENOENT and ENOTDIR +as Windows applications depend on ERRbadpath being returned if a component +of a pathname does not exist. +****************************************************************************/ +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) +{ + struct stat st; + char *start, *end; + pstring dirpath; + int saved_errno; + + *dirpath = 0; + *bad_path = False; + + if(saved_last_component) + *saved_last_component = 0; + + /* convert to basic unix format - removing \ chars and cleaning it up */ + unix_format(name); + unix_clean_name(name); + + /* names must be relative to the root of the service - trim any leading /. + also trim trailing /'s */ + trim_string(name,"/","/"); + + /* + * Ensure saved_last_component is valid even if file exists. + */ + if(saved_last_component) { + end = strrchr(name, '/'); + if(end) + pstrcpy(saved_last_component, end + 1); + else + pstrcpy(saved_last_component, name); + } + + if (!case_sensitive && + (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) + strnorm(name); + + /* check if it's a printer file */ + if (conn->printer) + { + if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) + { + char *s; + fstring name2; + slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); + /* sanitise the name */ + for (s=name2 ; *s ; s++) + if (!issafe(*s)) *s = '_'; + pstrcpy(name,(char *)mktemp(name2)); + } + return(True); + } + + /* stat the name - if it exists then we are all done! */ + if (sys_stat(name,&st) == 0) + return(True); + + saved_errno = errno; + + DEBUG(5,("unix_convert(%s)\n",name)); + + /* a special case - if we don't have any mangling chars and are case + sensitive then searching won't help */ + if (case_sensitive && !is_mangled(name) && + !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) + return(False); + + /* now we need to recursively match the name against the real + directory structure */ + + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + /* now match each part of the path name separately, trying the names + as is first, then trying to scan the directory for matching names */ + for (;start;start = (end?end+1:(char *)NULL)) + { + /* pinpoint the end of this section of the filename */ + end = strchr(start, '/'); + + /* chop the name at this point */ + if (end) *end = 0; + + if(saved_last_component != 0) + pstrcpy(saved_last_component, end ? end + 1 : start); + + /* check if the name exists up to this point */ + if (sys_stat(name, &st) == 0) + { + /* it exists. it must either be a directory or this must be + the last part of the path for it to be OK */ + if (end && !(st.st_mode & S_IFDIR)) + { + /* an intermediate part of the name isn't a directory */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + } + else + { + pstring rest; + + *rest = 0; + + /* remember the rest of the pathname so it can be restored + later */ + if (end) pstrcpy(rest,end+1); + + /* try to find this part of the path in the directory */ + if (strchr(start,'?') || strchr(start,'*') || + !scan_directory(dirpath, start, conn, end?True:False)) + { + if (end) + { + /* an intermediate part of the name can't be found */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + /* We need to return the fact that the intermediate + name resolution failed. This is used to return an + error of ERRbadpath rather than ERRbadfile. Some + Windows applications depend on the difference between + these two errors. + */ + *bad_path = True; + return(False); + } + + /* just the last part of the name doesn't exist */ + /* we may need to strupper() or strlower() it in case + this conversion is being used for file creation + purposes */ + /* if the filename is of mixed case then don't normalise it */ + if (!case_preserve && + (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* check on the mangled stack to see if we can recover the + base of the filename */ + if (is_mangled(start)) + check_mangled_cache( start ); + + DEBUG(5,("New file %s\n",start)); + return(True); + } + + /* restore the rest of the string */ + if (end) + { + pstrcpy(start+strlen(start)+1,rest); + end = start + strlen(start); + } + } + + /* add to the dirpath that we have resolved so far */ + if (*dirpath) pstrcat(dirpath,"/"); + pstrcat(dirpath,start); + + /* restore the / that we wiped out earlier */ + if (end) *end = '/'; + } + + /* the name has been resolved */ + DEBUG(5,("conversion finished %s\n",name)); + return(True); +} + + +/**************************************************************************** +check a filename - possibly caling reducename + +This is called by every routine before it allows an operation on a filename. +It does any final confirmation necessary to ensure that the filename is +a valid one for the user to access. +****************************************************************************/ +BOOL check_name(char *name,connection_struct *conn) +{ + BOOL ret; + + errno = 0; + + if (IS_VETO_PATH(conn, name)) { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } + + ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); + + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ + +#ifdef S_ISLNK + if (!lp_symlinks(SNUM(conn))) + { + struct stat statbuf; + if ( (sys_lstat(name,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) + { + DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + ret=0; + } + } +#endif + + if (!ret) + DEBUG(5,("check_name on %s failed\n",name)); + + return(ret); +} + + +/**************************************************************************** +scan a directory to find a filename, matching without case sensitivity + +If the name looks like a mangled name then try via the mangling functions +****************************************************************************/ +BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +{ + void *cur_dir; + char *dname; + BOOL mangled; + pstring name2; + + mangled = is_mangled(name); + + /* handle null paths */ + if (*path == 0) + path = "."; + + if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { + pstrcpy(name, dname); + return(True); + } + + /* + * The incoming name can be mangled, and if we de-mangle it + * here it will not compare correctly against the filename (name2) + * read from the directory and then mangled by the name_map_mangle() + * call. We need to mangle both names or neither. + * (JRA). + */ + if (mangled) + mangled = !check_mangled_cache( name ); + + /* open the directory */ + if (!(cur_dir = OpenDir(conn, path, True))) + { + DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + return(False); + } + + /* now scan for matching names */ + while ((dname = ReadDirName(cur_dir))) + { + if (*dname == '.' && + (strequal(dname,".") || strequal(dname,".."))) + continue; + + pstrcpy(name2,dname); + if (!name_map_mangle(name2,False,SNUM(conn))) continue; + + if ((mangled && mangled_equal(name,name2)) + || fname_equal(name, name2)) + { + /* we've found the file, change it's name and return */ + if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); + } + } + + CloseDir(cur_dir); + return(False); +} -- cgit From 12de4034c72ea5054d716bf848c2b16bef7a4d89 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Aug 1998 01:49:34 +0000 Subject: Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes. include/includes.h: Added nterr.h. locking/locking.c: Moved blocking lock code into smbd/blocking.c for link purposes. smbd/close.c: Added blocking lock removal to file close. smbd/filename.c: Tidied up unix_convert() so I could read it (:-) in preparation for the stat_cache code. smbd/nttrans.c: Added WRITE_ATTRIBUTES check. smbd/reply.c: Fixed multibyte char problem in wildcard mask. Jeremy. (This used to be commit 148eaba3dadb1d0bd3ac3ef53da3d9811636e89a) --- source3/smbd/filename.c | 254 +++++++++++++++++++++++++++++------------------- 1 file changed, 152 insertions(+), 102 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a6a9e7e7f0..ab5851fb5e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -102,6 +102,7 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ + BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) { struct stat st; @@ -115,17 +116,24 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(saved_last_component) *saved_last_component = 0; - /* convert to basic unix format - removing \ chars and cleaning it up */ + /* + * Convert to basic unix format - removing \ chars and cleaning it up. + */ + unix_format(name); unix_clean_name(name); - /* names must be relative to the root of the service - trim any leading /. - also trim trailing /'s */ + /* + * Names must be relative to the root of the service - trim any leading /. + * also trim trailing /'s. + */ + trim_string(name,"/","/"); /* * Ensure saved_last_component is valid even if file exists. */ + if(saved_last_component) { end = strrchr(name, '/'); if(end) @@ -138,23 +146,30 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* check if it's a printer file */ - if (conn->printer) - { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) - { - char *s; - fstring name2; - slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); - /* sanitise the name */ - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); - } - return(True); - } + /* + * Check if it's a printer file. + */ + if (conn->printer) { + if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { + char *s; + fstring name2; + slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); + + /* + * Sanitise the name. + */ + + for (s=name2 ; *s ; s++) + if (!issafe(*s)) *s = '_'; + pstrcpy(name,(char *)mktemp(name2)); + } + return(True); + } + + /* + * stat the name - if it exists then we are all done! + */ - /* stat the name - if it exists then we are all done! */ if (sys_stat(name,&st) == 0) return(True); @@ -162,109 +177,144 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, DEBUG(5,("unix_convert(%s)\n",name)); - /* a special case - if we don't have any mangling chars and are case - sensitive then searching won't help */ + /* + * A special case - if we don't have any mangling chars and are case + * sensitive then searching won't help. + */ + if (case_sensitive && !is_mangled(name) && !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) return(False); - /* now we need to recursively match the name against the real - directory structure */ + /* + * Now we need to recursively match the name against the real + * directory structure. + */ start = name; while (strncmp(start,"./",2) == 0) start += 2; - /* now match each part of the path name separately, trying the names - as is first, then trying to scan the directory for matching names */ - for (;start;start = (end?end+1:(char *)NULL)) - { - /* pinpoint the end of this section of the filename */ + /* + * Match each part of the path name separately, trying the names + * as is first, then trying to scan the directory for matching names. + */ + + for (;start;start = (end?end+1:(char *)NULL)) { + /* + * Pinpoint the end of this section of the filename. + */ end = strchr(start, '/'); - /* chop the name at this point */ - if (end) *end = 0; + /* + * Chop the name at this point. + */ + if (end) + *end = 0; if(saved_last_component != 0) pstrcpy(saved_last_component, end ? end + 1 : start); - /* check if the name exists up to this point */ - if (sys_stat(name, &st) == 0) - { - /* it exists. it must either be a directory or this must be - the last part of the path for it to be OK */ - if (end && !(st.st_mode & S_IFDIR)) - { - /* an intermediate part of the name isn't a directory */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - } - else - { - pstring rest; - - *rest = 0; - - /* remember the rest of the pathname so it can be restored - later */ - if (end) pstrcpy(rest,end+1); - - /* try to find this part of the path in the directory */ - if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, conn, end?True:False)) - { - if (end) - { - /* an intermediate part of the name can't be found */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - /* We need to return the fact that the intermediate - name resolution failed. This is used to return an - error of ERRbadpath rather than ERRbadfile. Some - Windows applications depend on the difference between - these two errors. - */ - *bad_path = True; - return(False); - } + /* + * Check if the name exists up to this point. + */ + if (sys_stat(name, &st) == 0) { + /* + * It exists. it must either be a directory or this must be + * the last part of the path for it to be OK. + */ + if (end && !(st.st_mode & S_IFDIR)) { + /* + * An intermediate part of the name isn't a directory. + */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + } else { + pstring rest; + + *rest = 0; + + /* + * Remember the rest of the pathname so it can be restored + * later. + */ + + if (end) + pstrcpy(rest,end+1); + + /* + * Try to find this part of the path in the directory. + */ + if (strchr(start,'?') || strchr(start,'*') || + !scan_directory(dirpath, start, conn, end?True:False)) { + if (end) { + /* + * An intermediate part of the name can't be found. + */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + *bad_path = True; + return(False); + } - /* just the last part of the name doesn't exist */ - /* we may need to strupper() or strlower() it in case - this conversion is being used for file creation - purposes */ - /* if the filename is of mixed case then don't normalise it */ - if (!case_preserve && - (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* check on the mangled stack to see if we can recover the - base of the filename */ - if (is_mangled(start)) - check_mangled_cache( start ); - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* restore the rest of the string */ - if (end) - { - pstrcpy(start+strlen(start)+1,rest); - end = start + strlen(start); - } - } + /* + * Just the last part of the name doesn't exist. + * We may need to strupper() or strlower() it in case + * this conversion is being used for file creation + * purposes. If the filename is of mixed case then + * don't normalise it. + */ + + if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* + * check on the mangled stack to see if we can recover the + * base of the filename. + */ + + if (is_mangled(start)) + check_mangled_cache( start ); + + DEBUG(5,("New file %s\n",start)); + return(True); + } - /* add to the dirpath that we have resolved so far */ - if (*dirpath) pstrcat(dirpath,"/"); + /* + * Restore the rest of the string. + */ + if (end) { + pstrcpy(start+strlen(start)+1,rest); + end = start + strlen(start); + } + } /* end else */ + + /* + * Add to the dirpath that we have resolved so far. + */ + if (*dirpath) pstrcat(dirpath,"/"); pstrcat(dirpath,start); - /* restore the / that we wiped out earlier */ - if (end) *end = '/'; - } + /* + * Restore the / that we wiped out earlier. + */ + if (end) + *end = '/'; + } - /* the name has been resolved */ + /* + * The name has been resolved. + */ DEBUG(5,("conversion finished %s\n",name)); return(True); } -- cgit From 5e5e320d361afcb4d9503354b3912b4c7a672197 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Aug 1998 20:38:53 +0000 Subject: This is the stat cache code - seems to work fine (needs heavy NetBench testing though.... :-). Attempts to efficiently reduce the number of stat() calls Samba does. Jeremy. (This used to be commit d0e48a2d8072c3e77a57ac6a2fb5044c05f03b41) --- source3/smbd/filename.c | 290 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 273 insertions(+), 17 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ab5851fb5e..8ef2eef96a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -29,10 +29,10 @@ extern fstring remote_machine; extern BOOL use_mangled_map; /**************************************************************************** -check if two filenames are equal - -this needs to be careful about whether we are case sensitive + Check if two filenames are equal. + This needs to be careful about whether we are case sensitive. ****************************************************************************/ + BOOL fname_equal(char *name1, char *name2) { int l1 = strlen(name1); @@ -66,8 +66,9 @@ BOOL fname_equal(char *name1, char *name2) /**************************************************************************** -mangle the 2nd name and check if it is then equal to the first name + Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ + BOOL mangled_equal(char *name1, char *name2) { pstring tmpname; @@ -81,6 +82,215 @@ BOOL mangled_equal(char *name1, char *name2) return(strequal(name1,tmpname)); } +/**************************************************************************** + Stat cache code used in unix_convert. +*****************************************************************************/ + +static int global_stat_cache_lookups; +static int global_stat_cache_misses; +static int global_stat_cache_hits; + +/**************************************************************************** + Stat cache statistics code. +*****************************************************************************/ + +void print_stat_cache_statistics(void) +{ + double eff = ((double)global_stat_cache_lookups/100.0)*(double)global_stat_cache_hits; + + DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ +stat cache was %f%% effective.\n", global_stat_cache_lookups, + global_stat_cache_hits, global_stat_cache_misses, eff )); +} + +typedef struct { + ubi_dlNode link; + int name_len; + pstring orig_name; + pstring translated_name; +} stat_cache_entry; + +#define MAX_STAT_CACHE_SIZE 50 + +static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; + +/**************************************************************************** + Compare two names in the stat cache. +*****************************************************************************/ + +static BOOL stat_name_equal( char *s1, char *s2) +{ + return (case_sensitive ? (strcmp( s1, s2) == 0) : (StrCaseCmp(s1, s2) == 0)); +} + +/**************************************************************************** + Compare two names in the stat cache. +*****************************************************************************/ + +static BOOL stat_name_equal_len( char *s1, char *s2, int len) +{ + return (case_sensitive ? (strncmp( s1, s2, len) == 0) : + (StrnCaseCmp(s1, s2, len) == 0)); +} + +/**************************************************************************** + Add an entry into the stat cache. +*****************************************************************************/ + +static void stat_cache_add( char *full_orig_name, char *orig_translated_path) +{ + stat_cache_entry *scp; + pstring orig_name; + pstring translated_path; + int namelen = strlen(orig_translated_path); + + /* + * Don't cache trivial valid directory entries. + */ + if(strequal(full_orig_name, ".") || strequal(full_orig_name, "..")) + return; + + /* + * If we are in case insentive mode, we need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + pstrcpy(translated_path, orig_translated_path); + if(translated_path[namelen-1] == '/') { + translated_path[namelen-1] = '\0'; + namelen--; + } + + /* + * We will only replace namelen characters + * of full_orig_name. + * StrnCpy always null terminates. + */ + + StrnCpy(orig_name, full_orig_name, namelen); + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; + scp = (stat_cache_entry *)ubi_dlNext( scp )) { + if(stat_name_equal( scp->orig_name, orig_name) && + (strcmp( scp->translated_name, translated_path) == 0)) { + /* + * Name does exist - promote it. + */ + if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) { + ubi_dlRemThis( &stat_cache, scp); + ubi_dlAddHead( &stat_cache, scp); + } + return; + } + } + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + + pstrcpy(scp->orig_name, orig_name); + pstrcpy(scp->translated_name, translated_path); + scp->name_len = namelen; + + ubi_dlAddHead( &stat_cache, scp); + + DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); + + if(ubi_dlCount(&stat_cache) > MAX_STAT_CACHE_SIZE) { + scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); + free((char *)scp); + return; + } +} + +/**************************************************************************** + Look through the stat cache for an entry - promote it to the top if found. + Return True if we translated (and did a scuccessful stat on) the entire name. +*****************************************************************************/ + +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct stat *pst) +{ + stat_cache_entry *scp; + stat_cache_entry *longest_hit = NULL; + int namelen = strlen(name); + + *start = name; + global_stat_cache_lookups++; + + /* + * Don't lookup trivial valid directory entries. + */ + if(strequal(name, ".") || strequal(name, "..")) { + global_stat_cache_misses++; + return False; + } + + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; + scp = (stat_cache_entry *)ubi_dlNext( scp )) { + if(scp->name_len <= namelen) { + if(stat_name_equal_len(scp->orig_name, name, scp->name_len)) { + if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) + longest_hit = scp; + } + } + } + + if(longest_hit == NULL) { + DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name)); + global_stat_cache_misses++; + return False; + } + + global_stat_cache_hits++; + + DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n", + name, longest_hit->orig_name, longest_hit->translated_name )); + + /* + * longest_hit is the longest match we got in the list. + * Check it exists - if so, overwrite the original name + * and then promote it to the top. + */ + + if(sys_stat( longest_hit->translated_name, pst) != 0) { + /* + * Discard this entry. + */ + ubi_dlRemThis( &stat_cache, longest_hit); + free((char *)longest_hit); + return False; + } + + memcpy(name, longest_hit->translated_name, longest_hit->name_len); + if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) { + ubi_dlRemThis( &stat_cache, longest_hit); + ubi_dlAddHead( &stat_cache, longest_hit); + } + + *start = &name[longest_hit->name_len]; + if(**start == '/') + ++*start; + + StrnCpy( dirpath, longest_hit->translated_name, name - (*start)); + + return (namelen == longest_hit->name_len); +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -103,15 +313,21 @@ as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, + BOOL *bad_path, struct stat *pst) { struct stat st; - char *start, *end; + char *start, *end, *orig_start; pstring dirpath; + pstring orig_path; int saved_errno; + BOOL component_was_mangled = False; + BOOL name_has_wildcard = False; *dirpath = 0; *bad_path = False; + if(pst) + memset( (char *)pst, '\0', sizeof(struct stat)); if(saved_last_component) *saved_last_component = 0; @@ -166,16 +382,34 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, return(True); } + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + pstrcpy(orig_path, name); + + if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(pst) + *pst = st; + return True; + } + /* * stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) + if (sys_stat(name,&st) == 0) { + stat_cache_add(orig_path, name); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + if(pst) + *pst = st; return(True); + } saved_errno = errno; - DEBUG(5,("unix_convert(%s)\n",name)); + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", + name, dirpath, start)); /* * A special case - if we don't have any mangling chars and are case @@ -186,21 +420,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) return(False); + if(strchr(start,'?') || strchr(start,'*')) + name_has_wildcard = True; + /* * Now we need to recursively match the name against the real * directory structure. */ - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - /* * Match each part of the path name separately, trying the names * as is first, then trying to scan the directory for matching names. */ - for (;start;start = (end?end+1:(char *)NULL)) { + for (orig_start = start; start ; start = (end?end+1:(char *)NULL)) { /* * Pinpoint the end of this section of the filename. */ @@ -231,6 +464,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *end = '/'; return(False); } + } else { pstring rest; @@ -247,6 +481,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Try to find this part of the path in the directory. */ + if (strchr(start,'?') || strchr(start,'*') || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { @@ -283,8 +518,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * base of the filename. */ - if (is_mangled(start)) + if (is_mangled(start)) { + component_was_mangled = True; check_mangled_cache( start ); + } DEBUG(5,("New file %s\n",start)); return(True); @@ -302,8 +539,18 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) pstrcat(dirpath,"/"); - pstrcat(dirpath,start); + if (*dirpath) + pstrcat(dirpath,"/"); + + pstrcat(dirpath,start); + + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, dirpath); /* * Restore the / that we wiped out earlier. @@ -312,10 +559,19 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *end = '/'; } + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); + /* * The name has been resolved. */ - DEBUG(5,("conversion finished %s\n",name)); + + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); return(True); } -- cgit From d0cfc1f04192bd22ce750e076d81d8be64504adc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Aug 1998 20:51:12 +0000 Subject: Fixed stat cache statistics calculation. Oops. Jeremy. (This used to be commit d6a9087e7e626e6e07503dba38854b136fe70c23) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8ef2eef96a..de4fef5189 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -96,7 +96,7 @@ static int global_stat_cache_hits; void print_stat_cache_statistics(void) { - double eff = ((double)global_stat_cache_lookups/100.0)*(double)global_stat_cache_hits; + double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ stat cache was %f%% effective.\n", global_stat_cache_lookups, -- cgit From 38142a1ebbe860778e26eaff68585726061c05e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Aug 1998 21:46:29 +0000 Subject: This checking fixes the statcache bug that stopped NetBench from running correctly. Added new parameter "stat cache size" - set to 50 by default. I now declare the statcache code officially "open" for business :-). It gets a hit rate of 97% with a NetBench run and seems to make using a case insensitive run as efficient as a case sensitive run. Also tidied up our sys_select usage - added a maxfd parameter and also added an implementation of select in terms of poll(), for systems where poll() is much faster. This is disabled by default. Jeremy. (This used to be commit 779b924ec1f6c81ff578d22295b20fece698d1fc) --- source3/smbd/filename.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index de4fef5189..9112828092 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -115,7 +115,8 @@ typedef struct { static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; /**************************************************************************** - Compare two names in the stat cache. + Compare two names in the stat cache - to check if we already have such an + entry. *****************************************************************************/ static BOOL stat_name_equal( char *s1, char *s2) @@ -124,13 +125,20 @@ static BOOL stat_name_equal( char *s1, char *s2) } /**************************************************************************** - Compare two names in the stat cache. + Compare a pathname to a name in the stat cache - of a given length. + Note - this code always checks that the next character in the pathname + is either a '/' character, or a '\0' character - to ensure we only + match *full* pathname components. *****************************************************************************/ -static BOOL stat_name_equal_len( char *s1, char *s2, int len) +static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { - return (case_sensitive ? (strncmp( s1, s2, len) == 0) : - (StrnCaseCmp(s1, s2, len) == 0)); + BOOL matched = (case_sensitive ? (strncmp( stat_name, orig_name, len) == 0) : + (StrnCaseCmp(stat_name, orig_name, len) == 0)); + if(orig_name[len] != '/' && orig_name[len] != '\0') + return False; + + return matched; } /**************************************************************************** @@ -211,7 +219,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); - if(ubi_dlCount(&stat_cache) > MAX_STAT_CACHE_SIZE) { + if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) { scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); free((char *)scp); return; -- cgit From 18556274139cc5a00593471bd745354d98a35303 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Sep 1998 20:11:54 +0000 Subject: More abstraction of file system data types, to move to a 64 bit file interface for the NT SMB's. Created a new define, SMB_STRUCT_STAT that currently is defined to be struct stat - this wil change to a user defined type containing 64 bit info when the correct wrappers are written for 64 bit stat(), fstat() and lstat() calls. Also changed all sys_xxxx() calls that were previously just wrappers to the same call prefixed by a dos_to_unix() call into dos_xxxx() calls. This makes it explicit when a pathname translation is being done, and when it is not. Now, all sys_xxx() calls are meant to be wrappers to mask OS differences, and not silently converting filenames on the fly. Jeremy. (This used to be commit 28aa182dbffaa4ffd86047e608400de4b26e80eb) --- source3/smbd/filename.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9112828092..3bc69210b9 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -231,7 +231,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct stat *pst) +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -275,7 +275,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct s * and then promote it to the top. */ - if(sys_stat( longest_hit->translated_name, pst) != 0) { + if(dos_stat( longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -322,9 +322,9 @@ of a pathname does not exist. ****************************************************************************/ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, struct stat *pst) + BOOL *bad_path, SMB_STRUCT_STAT *pst) { - struct stat st; + SMB_STRUCT_STAT st; char *start, *end, *orig_start; pstring dirpath; pstring orig_path; @@ -335,7 +335,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; if(pst) - memset( (char *)pst, '\0', sizeof(struct stat)); + memset( (char *)pst, '\0', sizeof(SMB_STRUCT_STAT)); if(saved_last_component) *saved_last_component = 0; @@ -406,7 +406,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) { + if (dos_stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -459,7 +459,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (sys_stat(name, &st) == 0) { + if (dos_stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -611,8 +611,8 @@ BOOL check_name(char *name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { - struct stat statbuf; - if ( (sys_lstat(name,&statbuf) != -1) && + SMB_STRUCT_STAT statbuf; + if ( (dos_lstat(name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); -- cgit From 0b5cc173099c7fd5ea4865ef4197739ec87e4c35 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Sep 1998 03:14:31 +0000 Subject: fixed a bug in the name mangling code. It implicitly assumed that mangling a name can't increase it's size which isn't true. (imagine a file called "L B" which mangles to "LB~XX") The symptoms were that users couldn't run batch files from short directory names that contained non 8.3 characters (such as spaces). (This used to be commit c319d8ea3f8b42bb3a8e501642971ed0bdb21583) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3bc69210b9..656bb8997c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -77,7 +77,7 @@ BOOL mangled_equal(char *name1, char *name2) return(False); pstrcpy(tmpname,name2); - mangle_name_83(tmpname,sizeof(tmpname)); + mangle_name_83(tmpname); return(strequal(name1,tmpname)); } -- cgit From e9ea36e4d2270bd7d32da12ef6d6e2299641582d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:07:05 +0000 Subject: tridge the destroyer returns! prompted by the interpret_security() dead code that Jean-Francois pointed out I added a make target "finddead" that finds potentially dead (ie. unused) code. It spat out 304 function names ... I went through these are deleted many of them, making others static (finddead also reports functions that are used only in the local file). in doing this I have almost certainly deleted some useful code. I may have even prevented compilation with some compile options. I apologise. I decided it was better to get rid of this code now and add back the one or two functions that are needed than to keep all this baggage. So, if I have done a bit too much "destroying" then let me know. Keep the swearing to a minimum :) One bit I didn't do is the ubibt code. Chris, can you look at that? Heaps of unused functions there. Can they be made static? (This used to be commit 2204475c87f3024ea8fd1fbd7385b2def617a46f) --- source3/smbd/filename.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 656bb8997c..115ff699c7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -28,12 +28,13 @@ extern BOOL short_case_preserve; extern fstring remote_machine; extern BOOL use_mangled_map; +static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); + /**************************************************************************** Check if two filenames are equal. This needs to be careful about whether we are case sensitive. ****************************************************************************/ - -BOOL fname_equal(char *name1, char *name2) +static BOOL fname_equal(char *name1, char *name2) { int l1 = strlen(name1); int l2 = strlen(name2); @@ -68,8 +69,7 @@ BOOL fname_equal(char *name1, char *name2) /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ - -BOOL mangled_equal(char *name1, char *name2) +static BOOL mangled_equal(char *name1, char *name2) { pstring tmpname; @@ -633,7 +633,7 @@ scan a directory to find a filename, matching without case sensitivity If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; -- cgit From f6044c87c021342d68d614d59bc8dacd32d223b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 13:24:20 +0000 Subject: some cleanups to use ZERO_STRUCT() and friends (This used to be commit 7b154dc4313324dfad6cf0117b8ce246bf12bf16) --- source3/smbd/filename.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 115ff699c7..8b81d6df2a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -334,8 +334,9 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; - if(pst) - memset( (char *)pst, '\0', sizeof(SMB_STRUCT_STAT)); + if(pst) { + ZERO_STRUCTP(pst); + } if(saved_last_component) *saved_last_component = 0; -- cgit From fd33412fa0ebd7de6c8749caeb111bdf4390dd47 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 15:31:10 +0000 Subject: fixed a stat cache bug (the one found by Matthew Geier). The fix I used is a very conservative fix. I'll leave it up to Jeremy to put in a better fix. The problem was the detection of mangled names. (This used to be commit c96b5fde5ae12bd0d4d6bcff095cf090738c92a4) --- source3/smbd/filename.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8b81d6df2a..ee9ce3f835 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -331,6 +331,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; + extern char magic_char; *dirpath = 0; *bad_path = False; @@ -432,6 +433,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(strchr(start,'?') || strchr(start,'*')) name_has_wildcard = True; + /* this is an extremely conservative test for mangled names. */ + if (strchr(start,magic_char)) + component_was_mangled = True; + /* * Now we need to recursively match the name against the real * directory structure. @@ -528,7 +533,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, */ if (is_mangled(start)) { - component_was_mangled = True; check_mangled_cache( start ); } -- cgit From 4fc5a74ffa491d52afc373abcdd4257a4f105aa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 6 Sep 1998 01:37:14 +0000 Subject: add a "stat cache" boolean smb.conf option. (defaults to on) I think we need this so we can rule out stat cache bugs when dealing with bug reports. If we ask a user to disable the stat cache and the problem persists then we know it isn't a stat cache bug. The stat cache code is sufficiently complicated that it can be pretty hard to tell if it is causing problems or not. (This used to be commit c83f3775cd8a7aad13571926cdd5949a07538771) --- source3/smbd/filename.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ee9ce3f835..a88829de9d 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,11 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) stat_cache_entry *scp; pstring orig_name; pstring translated_path; - int namelen = strlen(orig_translated_path); + int namelen; + + if (!lp_stat_cache()) return; + + namelen = strlen(orig_translated_path); /* * Don't cache trivial valid directory entries. @@ -235,8 +239,12 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; - int namelen = strlen(name); + int namelen; + + if (!lp_stat_cache()) return False; + namelen = strlen(name); + *start = name; global_stat_cache_lookups++; -- cgit From 6e0c276ec8b918165a19b3dfc86bc7bef6d1f706 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Sep 1998 19:21:04 +0000 Subject: Added back groupname map stuff removed by Andrew's "slash 'n' burn" tactics :-). Protected by #ifdef until used. Fixed bug in fd_attempt_close() where a pointer to potentially free'd memory was returned. I hate that. Added "blocking locks" as a per-share option for performance testing. Changed is_mangled() so it will return true if called with a pathname and any component of the pathname was mangled (it was already attempting to do this, but not checking for a '/' as end-of-mangle). This should be a better fix for the wierd stat cache bug Andrew identified. Jeremy. (This used to be commit 0de01f45980c7bc261248a9cead972a8d8cbd594) --- source3/smbd/filename.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a88829de9d..0910e03ee3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -339,7 +339,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; +#if 0 + /* Andrew's conservative code... JRA. */ extern char magic_char; +#endif *dirpath = 0; *bad_path = False; @@ -441,9 +444,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(strchr(start,'?') || strchr(start,'*')) name_has_wildcard = True; + /* + * is_mangled() was changed to look at an entire pathname, not + * just a component. JRA. + */ + + if(is_mangled(start)) + component_was_mangled = True; + +#if 0 + /* Keep Andrew's conservative code around, just in case. JRA. */ /* this is an extremely conservative test for mangled names. */ if (strchr(start,magic_char)) component_was_mangled = True; +#endif /* * Now we need to recursively match the name against the real -- cgit From aab0323d294770f80c6514389e5f84d3abf82429 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Sep 1998 00:35:10 +0000 Subject: Improved stat cache code by uppercasing any search name that gets added to it if we're in case insensitive mode, and then doing a memcmp rather than a StrnCaseCmp (which is *horribly* slow) on every lookup. Fixed bug with refusing NT SMB's (use *brackets* where needed :-). Jeremy. (This used to be commit 02b3fddce33a58a4db2102670b502fc0c6f45fab) --- source3/smbd/filename.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 0910e03ee3..caba4064d7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -114,27 +114,18 @@ typedef struct { static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; -/**************************************************************************** - Compare two names in the stat cache - to check if we already have such an - entry. -*****************************************************************************/ - -static BOOL stat_name_equal( char *s1, char *s2) -{ - return (case_sensitive ? (strcmp( s1, s2) == 0) : (StrCaseCmp(s1, s2) == 0)); -} - /**************************************************************************** Compare a pathname to a name in the stat cache - of a given length. Note - this code always checks that the next character in the pathname is either a '/' character, or a '\0' character - to ensure we only - match *full* pathname components. + match *full* pathname components. Note we don't need to handle case + here, if we're case insensitive the stat cache orig names are all upper + case. *****************************************************************************/ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { - BOOL matched = (case_sensitive ? (strncmp( stat_name, orig_name, len) == 0) : - (StrnCaseCmp(stat_name, orig_name, len) == 0)); + BOOL matched = (memcmp( stat_name, orig_name, len) == 0); if(orig_name[len] != '/' && orig_name[len] != '\0') return False; @@ -159,7 +150,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) /* * Don't cache trivial valid directory entries. */ - if(strequal(full_orig_name, ".") || strequal(full_orig_name, "..")) + if((strcmp(full_orig_name, ".") == 0) || (strcmp(full_orig_name, "..") == 0)) return; /* @@ -189,6 +180,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) */ StrnCpy(orig_name, full_orig_name, namelen); + if(!case_sensitive) + strupper( orig_name ); /* * Check this name doesn't exist in the cache before we @@ -197,7 +190,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if(stat_name_equal( scp->orig_name, orig_name) && + if((strcmp( scp->orig_name, orig_name) == 0) && (strcmp( scp->translated_name, translated_path) == 0)) { /* * Name does exist - promote it. @@ -239,6 +232,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; + pstring chk_name; int namelen; if (!lp_stat_cache()) return False; @@ -251,15 +245,19 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU /* * Don't lookup trivial valid directory entries. */ - if(strequal(name, ".") || strequal(name, "..")) { + if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { global_stat_cache_misses++; return False; } + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; scp = (stat_cache_entry *)ubi_dlNext( scp )) { if(scp->name_len <= namelen) { - if(stat_name_equal_len(scp->orig_name, name, scp->name_len)) { + if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) { if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) longest_hit = scp; } -- cgit From fc82bd2914c5687c0d03636ed05280c3506cea0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Sep 1998 03:34:12 +0000 Subject: Small bit of paranioa. Ensure that if the incoming name to unix_convert() was a single '\' (the base directory of the service) that it gets translated to a '.', not a '\0'. Jeremy. (This used to be commit f74f39f45fa55c1768d6622a52c494328f22f50b) --- source3/smbd/filename.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index caba4064d7..7cbb3392cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) /* * Don't cache trivial valid directory entries. */ - if((strcmp(full_orig_name, ".") == 0) || (strcmp(full_orig_name, "..") == 0)) + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) return; /* @@ -245,7 +246,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU /* * Don't lookup trivial valid directory entries. */ - if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { global_stat_cache_misses++; return False; } @@ -365,6 +366,17 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache. + */ + + if(!*name) { + name[0] = '.'; + name[1] = '\0'; + } + /* * Ensure saved_last_component is valid even if file exists. */ -- cgit From 95f99e80b4d0bf23e9e638f3024ae9d074482f57 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 25 Sep 1998 03:52:29 +0000 Subject: I've disabled the conversion of null filenames to "." until we solve the win95 printing problem. I suspect it is a smbgetatr() problem with a null name (which requires special behaviour). This is an interim solution. (This used to be commit 0a69e091a2ec75bce89760d69ea1488941108740) --- source3/smbd/filename.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7cbb3392cb..685725f096 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -366,6 +366,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* I've disabled this till we fix printing (probably a getatr problem) (tridge) */ +#if TRIM_NULL_NAMES /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid @@ -376,6 +378,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, name[0] = '.'; name[1] = '\0'; } +#endif /* * Ensure saved_last_component is valid even if file exists. -- cgit From a377543cc0af26ddcaf58aa4bc368afd70bca5ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Sep 1998 03:49:25 +0000 Subject: Fixed the problem with reply_getatr() being passed a "" name in reply_getatr, replaced the paranoid code in smbd/filename.c that replaces a "" with a ".". I am starting to think this code may well be needed. Jeremy. (This used to be commit bdc3d9f52fbded4b1483af8be0059decfd4bad34) --- source3/smbd/filename.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 685725f096..7cbb3392cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -366,8 +366,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); - /* I've disabled this till we fix printing (probably a getatr problem) (tridge) */ -#if TRIM_NULL_NAMES /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid @@ -378,7 +376,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, name[0] = '.'; name[1] = '\0'; } -#endif /* * Ensure saved_last_component is valid even if file exists. -- cgit From cf3a9741dc7427efb97eff09a3c197a906ce6767 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Sep 1998 21:43:48 +0000 Subject: Changes to test in configure if capabilities are enabled on a system. Changes to get Samba to compile cleanly with the IRIX compiler with the options : -fullwarn -woff 1209,1174 (the -woff options are to turn off warnings about unused function parameters and controlling loop expressions being constants). Split prototype generation as we hit a limit in IRIX nawk. Removed "." code in smbd/filename.c (yet again :-). Jeremy. (This used to be commit e0567433bd72aec17bf5a54cc292701095d25f09) --- source3/smbd/filename.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7cbb3392cb..ff4d682747 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -332,7 +332,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; - char *start, *end, *orig_start; + char *start, *end; pstring dirpath; pstring orig_path; int saved_errno; @@ -366,17 +366,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); - /* - * If we trimmed down to a single '\0' character - * then we should use the "." directory to avoid - * searching the cache. - */ - - if(!*name) { - name[0] = '.'; - name[1] = '\0'; - } - /* * Ensure saved_last_component is valid even if file exists. */ @@ -413,6 +402,15 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, return(True); } + /* + * If we trimmed down to a single '\0' character + * then we will be using the "." directory. + * As we know this is valid we can return true here. + */ + + if(!*name) + return(True); + start = name; while (strncmp(start,"./",2) == 0) start += 2; @@ -479,7 +477,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * as is first, then trying to scan the directory for matching names. */ - for (orig_start = start; start ; start = (end?end+1:(char *)NULL)) { + for (; start ; start = (end?end+1:(char *)NULL)) { /* * Pinpoint the end of this section of the filename. */ -- cgit From 4c2b041e78ccac4a71b368e6998644cab3140ff7 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 9 Oct 1998 06:47:22 +0000 Subject: Add a DEBUG to unix_convert (This used to be commit ac61a102473c7f23938368f9bfea494cd56344a1) --- source3/smbd/filename.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ff4d682747..d311d56b99 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -343,6 +343,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + *dirpath = 0; *bad_path = False; if(pst) { -- cgit From 7c45b3c25c665d65cfdb503724efe094b5172c12 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 9 Oct 1998 10:03:19 +0000 Subject: Added code to convert empty file names to "." so we avoid searching the cache, but only if we are not on a print share. This code is known to work on at least one site! (This used to be commit a2898af463132147cbe19b18585c793960cb39ee) --- source3/smbd/filename.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d311d56b99..1b4f7f8c77 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -368,6 +368,18 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache, but not if we are in a + * printing share. + */ + + if (!*name && (!conn -> printer)) { + name[0] = '.'; + name[1] = '\0'; + } + /* * Ensure saved_last_component is valid even if file exists. */ -- cgit From bb5fab7b553dc18d8b0c03f6a65ee92586752955 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Nov 1998 01:26:18 +0000 Subject: formatting change (This used to be commit 94fc7fe3afa1dc5547050248738eb697c1eeef59) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1b4f7f8c77..83e6fe092e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -411,7 +411,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); + pstrcpy(name,(char *)mktemp(name2)); } return(True); } -- cgit From 6d5ef2e92995df1cbf5cd3d7c6a33fe55cedb311 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 06:25:13 +0000 Subject: Use VFS operations for file I/O. (This used to be commit cfddbdb62485256a947a30e04c753200451cbe1c) --- source3/smbd/filename.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 83e6fe092e..913d0b367e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -441,7 +441,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (dos_stat(name,&st) == 0) { + if (conn->vfs_ops.stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -509,7 +509,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (dos_stat(name, &st) == 0) { + + if (conn->vfs_ops.stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -661,7 +662,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (dos_lstat(name,&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); -- cgit From a4194191ce87cc630e34fe65ac8f207cc4330cae Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 05:18:44 +0000 Subject: Use VFS I/O for stat_cache_lookup() (This used to be commit 5ece1fcffbc5a5062c02edf6f2ecb405c2a2f43e) --- source3/smbd/filename.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 913d0b367e..fb2f57339b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -229,7 +229,9 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, + char *dirpath, char **start, + SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -282,7 +284,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU * and then promote it to the top. */ - if(dos_stat( longest_hit->translated_name, pst) != 0) { + if(conn->vfs_ops.stat(longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -431,7 +433,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); - if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { if(pst) *pst = st; return True; -- cgit From 939f6d6794e1dc0677624ac67d1f00950417b713 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Jul 1999 20:44:24 +0000 Subject: more dfs stuff. this looks like it's going to be more appropriate to use the vfs tables. at the moment, i replaced all calls to unix_convert() with unix_dfs_convert(). this does the job, but it's not very nice. (This used to be commit 00d4aebce9f268a737ef9df9bdbe59f8fe831979) --- source3/smbd/filename.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fb2f57339b..1d9c5ef754 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,6 +26,7 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; extern fstring remote_machine; +extern pstring global_myname; extern BOOL use_mangled_map; static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); @@ -308,6 +309,35 @@ static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, return (namelen == longest_hit->name_len); } +/**************************************************************************** + this routine converts from the dos and dfs namespace to the unix namespace. +****************************************************************************/ +BOOL unix_dfs_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) +{ + pstring local_path; + + DEBUG(10,("unix_dfs_convert: %s\n", name)); + + if (name != NULL && + under_dfs(conn, name, local_path, sizeof(local_path))) + { + DEBUG(10,("%s is in dfs map.\n", name)); + + /* check for our own name */ + if (StrCaseCmp(global_myname, name+1) > 0) + { + return False; + } + + pstrcpy(name, local_path); + + DEBUG(10,("removed name: %s\n", name)); + } + return unix_convert(name, conn, saved_last_component, bad_path, pst); +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -329,9 +359,9 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ - -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) +BOOL unix_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; -- cgit From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/smbd/filename.c | 68 ++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 49 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1d9c5ef754..64f63805f3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,7 +26,6 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; extern fstring remote_machine; -extern pstring global_myname; extern BOOL use_mangled_map; static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); @@ -97,7 +96,12 @@ static int global_stat_cache_hits; void print_stat_cache_statistics(void) { - double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; + double eff; + + if(global_stat_cache_lookups == 0) + return; + + eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ stat cache was %f%% effective.\n", global_stat_cache_lookups, @@ -230,9 +234,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, - char *dirpath, char **start, - SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -285,7 +287,7 @@ static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, * and then promote it to the top. */ - if(conn->vfs_ops.stat(longest_hit->translated_name, pst) != 0) { + if(dos_stat( longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -309,35 +311,6 @@ static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, return (namelen == longest_hit->name_len); } -/**************************************************************************** - this routine converts from the dos and dfs namespace to the unix namespace. -****************************************************************************/ -BOOL unix_dfs_convert(char *name,connection_struct *conn, - char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) -{ - pstring local_path; - - DEBUG(10,("unix_dfs_convert: %s\n", name)); - - if (name != NULL && - under_dfs(conn, name, local_path, sizeof(local_path))) - { - DEBUG(10,("%s is in dfs map.\n", name)); - - /* check for our own name */ - if (StrCaseCmp(global_myname, name+1) > 0) - { - return False; - } - - pstrcpy(name, local_path); - - DEBUG(10,("removed name: %s\n", name)); - } - return unix_convert(name, conn, saved_last_component, bad_path, pst); -} - /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -359,15 +332,14 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn, - char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) + +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; pstring dirpath; pstring orig_path; - int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; #if 0 @@ -443,7 +415,7 @@ BOOL unix_convert(char *name,connection_struct *conn, for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); + pstrcpy(name,(char *)smbd_mktemp(name2)); } return(True); } @@ -463,7 +435,7 @@ BOOL unix_convert(char *name,connection_struct *conn, pstrcpy(orig_path, name); - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(stat_cache_lookup( name, dirpath, &start, &st)) { if(pst) *pst = st; return True; @@ -473,7 +445,7 @@ BOOL unix_convert(char *name,connection_struct *conn, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(name,&st) == 0) { + if (dos_stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -481,8 +453,6 @@ BOOL unix_convert(char *name,connection_struct *conn, return(True); } - saved_errno = errno; - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); @@ -492,7 +462,7 @@ BOOL unix_convert(char *name,connection_struct *conn, */ if (case_sensitive && !is_mangled(name) && - !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) + !lp_strip_dot() && !use_mangled_map) return(False); if(strchr(start,'?') || strchr(start,'*')) @@ -541,8 +511,7 @@ BOOL unix_convert(char *name,connection_struct *conn, /* * Check if the name exists up to this point. */ - - if (conn->vfs_ops.stat(name, &st) == 0) { + if (dos_stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -694,7 +663,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && + if ( (dos_lstat(name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); @@ -758,7 +727,8 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d continue; pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,SNUM(conn))) continue; + if (!name_map_mangle(name2,False,True,SNUM(conn))) + continue; if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) -- cgit From ace4006c9f7ac16b3c09b1b2222f607bccfa040e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2000 21:25:35 +0000 Subject: Added hash-based stat cache code from Ying Chen. Jeremy. (This used to be commit b62a1bd6328f5894ae1a2fef3ef6fc66304ade52) --- source3/smbd/filename.c | 173 +++++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 81 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 64f63805f3..2f8e92d98e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -3,6 +3,8 @@ Version 1.9. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Ying Chen 2000 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 @@ -19,6 +21,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * New hash table stat cache code added by Ying Chen. + */ + #include "includes.h" extern int DEBUGLEVEL; @@ -109,15 +115,12 @@ stat cache was %f%% effective.\n", global_stat_cache_lookups, } typedef struct { - ubi_dlNode link; int name_len; - pstring orig_name; - pstring translated_name; + char names[2]; /* This is extended via malloc... */ } stat_cache_entry; -#define MAX_STAT_CACHE_SIZE 50 - -static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; +#define INIT_STAT_CACHE_SIZE 512 +static hash_table stat_cache; /**************************************************************************** Compare a pathname to a name in the stat cache - of a given length. @@ -144,9 +147,11 @@ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) static void stat_cache_add( char *full_orig_name, char *orig_translated_path) { stat_cache_entry *scp; + stat_cache_entry *found_scp; pstring orig_name; pstring translated_path; int namelen; + hash_element *hash_elem; if (!lp_stat_cache()) return; @@ -194,39 +199,39 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) * add it. */ - for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; - scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if((strcmp( scp->orig_name, orig_name) == 0) && - (strcmp( scp->translated_name, translated_path) == 0)) { - /* - * Name does exist - promote it. - */ - if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) { - ubi_dlRemThis( &stat_cache, scp); - ubi_dlAddHead( &stat_cache, scp); - } + if (hash_elem = hash_lookup(&stat_cache, orig_name)) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { return; + } else { + hash_remove(&stat_cache, hash_elem); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy((scp->names+namelen+1), translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); } - } - - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); return; - } - - pstrcpy(scp->orig_name, orig_name); - pstrcpy(scp->translated_name, translated_path); - scp->name_len = namelen; - - ubi_dlAddHead( &stat_cache, scp); + } else { - DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); + /* + * New entry. + */ - if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) { - scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); - free((char *)scp); - return; + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy(scp->names+namelen+1, translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); } + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); } /**************************************************************************** @@ -238,10 +243,14 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; + char *trans_name; pstring chk_name; int namelen; + hash_element *hash_elem; + char *sp; - if (!lp_stat_cache()) return False; + if (!lp_stat_cache()) + return False; namelen = strlen(name); @@ -260,55 +269,44 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU if(!case_sensitive) strupper( chk_name ); - for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; - scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if(scp->name_len <= namelen) { - if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) { - if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) - longest_hit = scp; + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + global_stat_cache_misses++; + return False; } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + global_stat_cache_hits++; + trans_name = scp->names+scp->name_len+1; + if(dos_stat( trans_name, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, trans_name, scp->name_len); + *start = &name[scp->name_len]; + if(**start == '/') + ++*start; + StrnCpy( dirpath, trans_name, name - (*start)); + return (namelen == scp->name_len); } } - - if(longest_hit == NULL) { - DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name)); - global_stat_cache_misses++; - return False; - } - - global_stat_cache_hits++; - - DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n", - name, longest_hit->orig_name, longest_hit->translated_name )); - - /* - * longest_hit is the longest match we got in the list. - * Check it exists - if so, overwrite the original name - * and then promote it to the top. - */ - - if(dos_stat( longest_hit->translated_name, pst) != 0) { - /* - * Discard this entry. - */ - ubi_dlRemThis( &stat_cache, longest_hit); - free((char *)longest_hit); - return False; - } - - memcpy(name, longest_hit->translated_name, longest_hit->name_len); - if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) { - ubi_dlRemThis( &stat_cache, longest_hit); - ubi_dlAddHead( &stat_cache, longest_hit); - } - - *start = &name[longest_hit->name_len]; - if(**start == '/') - ++*start; - - StrnCpy( dirpath, longest_hit->translated_name, name - (*start)); - - return (namelen == longest_hit->name_len); } /**************************************************************************** @@ -352,7 +350,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; if(pst) { - ZERO_STRUCTP(pst); + ZERO_STRUCTP(pst); } if(saved_last_component) @@ -744,3 +742,16 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d CloseDir(cur_dir); return(False); } + +/*************************************************************************** ** + * Initializes or clears the stat cache. + * + * Input: none. + * Output: none. + * + * ************************************************************************** ** + */ +BOOL reset_stat_cache( void ) +{ + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); +} /* reset_stat_cache */ -- cgit From 16bb009dbbe6302febf3848cee61e9927eeb0fb5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 05:17:25 +0000 Subject: Mega-VFS merge. Yeah baby! Synopsis: change every disk access function to work through a vfs_ops structure contained in the connection_struct. (This used to be commit 3aad500c0fb61232ed3431ff4b743b5d18ec852f) --- source3/smbd/filename.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2f8e92d98e..b1550e5c73 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -239,7 +239,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, + char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -294,7 +295,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU scp = (stat_cache_entry *)(hash_elem->value); global_stat_cache_hits++; trans_name = scp->names+scp->name_len+1; - if(dos_stat( trans_name, pst) != 0) { + if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; @@ -433,7 +434,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); - if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { if(pst) *pst = st; return True; @@ -443,7 +444,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (dos_stat(name,&st) == 0) { + if (conn->vfs_ops.stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -509,7 +510,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (dos_stat(name, &st) == 0) { + + if (conn->vfs_ops.stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -661,7 +663,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (dos_lstat(name,&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); -- cgit From ae7696117e81bb469fa71f9bc880f6b5aac0724e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 23:08:24 +0000 Subject: Put back lots of missing calls to dos_to_unix(). Thanks to aono@cc.osaka-kyoiku.ac.jp (Tomoki AONO) (This used to be commit 176c405d2702a4245561ff56c8eac3c754a0dea3) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b1550e5c73..85055f676a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -444,7 +444,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(name,&st) == 0) { + if (conn->vfs_ops.stat(dos_to_unix(name,False),&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -511,7 +511,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(name, &st) == 0) { + if (conn->vfs_ops.stat(dos_to_unix(name,False), &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. -- cgit From 3b6298b001467ff3d700624cf2bae5b1dc963a4c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 4 Feb 2000 05:18:06 +0000 Subject: Fix some compile warnings. (This used to be commit ccbd936211d4bfc8687cef78405ae58127289d13) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 85055f676a..b0c44d503a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -199,7 +199,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) * add it. */ - if (hash_elem = hash_lookup(&stat_cache, orig_name)) { + if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { found_scp = (stat_cache_entry *)(hash_elem->value); if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { return; -- cgit From 427a3baa9ccb942b82832f255e09acc87afca166 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Feb 2000 00:41:58 +0000 Subject: Fix some more compile warnings. (This used to be commit 507624dbc0a1a9e1df72a6b8de45038e86a9e5b1) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b0c44d503a..729ef8c809 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -131,6 +131,7 @@ static hash_table stat_cache; case. *****************************************************************************/ +#if 0 /* This function unused?? */ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { BOOL matched = (memcmp( stat_name, orig_name, len) == 0); @@ -139,6 +140,7 @@ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) return matched; } +#endif /**************************************************************************** Add an entry into the stat cache. @@ -243,7 +245,6 @@ static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - stat_cache_entry *longest_hit = NULL; char *trans_name; pstring chk_name; int namelen; -- cgit From 689ec46450a3f373b583ebe98d124ab4a99ce3ef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 13:05:23 +0000 Subject: the bulk of the changes to get rid of fd_ptr and move print open handling to printing/printing.c most of this was just replacing things like fsp->fd_ptr->fd with fsp->fd the changes in open.c are quite dramatic. Most of it is removing all the functions that handled the fd multiplexing (This used to be commit d1827a3648009fd0a0d165055015d9aeda7a1037) --- source3/smbd/filename.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 729ef8c809..7afa9e9986 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -347,6 +347,12 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + if (conn->printer) { + /* we don't ever use the filenames on a printer share as a + filename - so don't convert them */ + return True; + } + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); *dirpath = 0; -- cgit From 700f72453ed8dfd356a5591b9447127b5066ac4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 11:04:28 +0000 Subject: - removed all our old wildcard matching code and replaced it with a call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much (This used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e) --- source3/smbd/filename.c | 259 +----------------------------------------------- 1 file changed, 2 insertions(+), 257 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7afa9e9986..ed1a1c3f63 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -88,228 +88,6 @@ static BOOL mangled_equal(char *name1, char *name2) return(strequal(name1,tmpname)); } -/**************************************************************************** - Stat cache code used in unix_convert. -*****************************************************************************/ - -static int global_stat_cache_lookups; -static int global_stat_cache_misses; -static int global_stat_cache_hits; - -/**************************************************************************** - Stat cache statistics code. -*****************************************************************************/ - -void print_stat_cache_statistics(void) -{ - double eff; - - if(global_stat_cache_lookups == 0) - return; - - eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; - - DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ -stat cache was %f%% effective.\n", global_stat_cache_lookups, - global_stat_cache_hits, global_stat_cache_misses, eff )); -} - -typedef struct { - int name_len; - char names[2]; /* This is extended via malloc... */ -} stat_cache_entry; - -#define INIT_STAT_CACHE_SIZE 512 -static hash_table stat_cache; - -/**************************************************************************** - Compare a pathname to a name in the stat cache - of a given length. - Note - this code always checks that the next character in the pathname - is either a '/' character, or a '\0' character - to ensure we only - match *full* pathname components. Note we don't need to handle case - here, if we're case insensitive the stat cache orig names are all upper - case. -*****************************************************************************/ - -#if 0 /* This function unused?? */ -static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) -{ - BOOL matched = (memcmp( stat_name, orig_name, len) == 0); - if(orig_name[len] != '/' && orig_name[len] != '\0') - return False; - - return matched; -} -#endif - -/**************************************************************************** - Add an entry into the stat cache. -*****************************************************************************/ - -static void stat_cache_add( char *full_orig_name, char *orig_translated_path) -{ - stat_cache_entry *scp; - stat_cache_entry *found_scp; - pstring orig_name; - pstring translated_path; - int namelen; - hash_element *hash_elem; - - if (!lp_stat_cache()) return; - - namelen = strlen(orig_translated_path); - - /* - * Don't cache trivial valid directory entries. - */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) - return; - - /* - * If we are in case insentive mode, we need to - * store names that need no translation - else, it - * would be a waste. - */ - - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) - return; - - /* - * Remove any trailing '/' characters from the - * translated path. - */ - - pstrcpy(translated_path, orig_translated_path); - if(translated_path[namelen-1] == '/') { - translated_path[namelen-1] = '\0'; - namelen--; - } - - /* - * We will only replace namelen characters - * of full_orig_name. - * StrnCpy always null terminates. - */ - - StrnCpy(orig_name, full_orig_name, namelen); - if(!case_sensitive) - strupper( orig_name ); - - /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { - return; - } else { - hash_remove(&stat_cache, hash_elem); - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy((scp->names+namelen+1), translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - return; - } else { - - /* - * New entry. - */ - - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy(scp->names+namelen+1, translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); -} - -/**************************************************************************** - Look through the stat cache for an entry - promote it to the top if found. - Return True if we translated (and did a scuccessful stat on) the entire name. -*****************************************************************************/ - -static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, - char **start, SMB_STRUCT_STAT *pst) -{ - stat_cache_entry *scp; - char *trans_name; - pstring chk_name; - int namelen; - hash_element *hash_elem; - char *sp; - - if (!lp_stat_cache()) - return False; - - namelen = strlen(name); - - *start = name; - global_stat_cache_lookups++; - - /* - * Don't lookup trivial valid directory entries. - */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - global_stat_cache_misses++; - return False; - } - - pstrcpy(chk_name, name); - if(!case_sensitive) - strupper( chk_name ); - - while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { - /* - * Didn't find it - remove last component for next try. - */ - sp = strrchr(chk_name, '/'); - if (sp) { - *sp = '\0'; - } else { - /* - * We reached the end of the name - no match. - */ - global_stat_cache_misses++; - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - global_stat_cache_misses++; - return False; - } - } else { - scp = (stat_cache_entry *)(hash_elem->value); - global_stat_cache_hits++; - trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); - return False; - } - memcpy(name, trans_name, scp->name_len); - *start = &name[scp->name_len]; - if(**start == '/') - ++*start; - StrnCpy( dirpath, trans_name, name - (*start)); - return (namelen == scp->name_len); - } - } -} /**************************************************************************** This routine is called to convert names from the dos namespace to unix @@ -406,26 +184,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* - * Check if it's a printer file. - */ - if (conn->printer) { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { - char *s; - fstring name2; - slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); - - /* - * Sanitise the name. - */ - - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)smbd_mktemp(name2)); - } - return(True); - } - /* * If we trimmed down to a single '\0' character * then we will be using the "." directory. @@ -471,8 +229,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, !lp_strip_dot() && !use_mangled_map) return(False); - if(strchr(start,'?') || strchr(start,'*')) - name_has_wildcard = True; + name_has_wildcard = ms_has_wild(start); /* * is_mangled() was changed to look at an entire pathname, not @@ -549,7 +306,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Try to find this part of the path in the directory. */ - if (strchr(start,'?') || strchr(start,'*') || + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* @@ -752,15 +509,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d return(False); } -/*************************************************************************** ** - * Initializes or clears the stat cache. - * - * Input: none. - * Output: none. - * - * ************************************************************************** ** - */ -BOOL reset_stat_cache( void ) -{ - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); -} /* reset_stat_cache */ -- cgit From 49a0e6d5989656c1b3c9c063a20308ca4ee5d73b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 10:41:59 +0000 Subject: more merging voodoo this adds "#define OLD_NTDOMAIN 1" in lots of places. Don't panic - this isn't permanent, it should go after another few merge steps have been done (This used to be commit 92109d7b3c06f240452d39f669ecb8c9c86ab610) --- source3/smbd/filename.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ed1a1c3f63..294e80250a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -509,3 +511,5 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d return(False); } + +#undef OLD_NTDOMAIN -- cgit From b43b2e4f8a4be30e3f7aca6f570f5376fd508e3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Sep 2000 19:09:59 +0000 Subject: Restructuring of the code to remove dos_ChDir/dos_GetWd and re-vector them through the VFS. All file access/directory access code in smbd should now go via the vfs. Added vfs_chown/vfs_chmod calls. Still looking at vfs_get_nt_acl() vfs_set_nt_acl() call API design. Jeremy. (This used to be commit f96625ec124adb6e110dc54632e006b3620a962b) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 294e80250a..67fa85d9cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -419,7 +419,7 @@ BOOL check_name(char *name,connection_struct *conn) return(0); } - ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); + ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc -- cgit From 636f146abf0a75cd3b21a57b50627ee149a635ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:21:49 +0000 Subject: Restructuring of vfs layer to include a "this" pointer - can be an fsp or a conn struct depending on the call. We need this to have a clean NT ACL call interface. This will break any existing VFS libraries (that's why this is pre-release code). Andrew gets credit for this one :-) :-). In addition - added Herb's WITH_PROFILE changes - Herb - please examine the changes I've made to the smbd/reply.c code you added. The original code was very ugly and I have replaced it with a START_PROFILE(x)/END_PROFILE(x) pair using the preprocessor. Please check this compiles ok with the --with-profile switch. Jeremy. (This used to be commit b07611f8159b0b3f42e7e02611be9f4d56de96f5) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 67fa85d9cb..9ac82386f9 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -211,7 +211,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(dos_to_unix(name,False),&st) == 0) { + if (conn->vfs_ops.stat(conn,dos_to_unix(name,False),&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -277,7 +277,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(dos_to_unix(name,False), &st) == 0) { + if (conn->vfs_ops.stat(conn,dos_to_unix(name,False), &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -429,7 +429,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); -- cgit From abf055046fe70842badc2a1904f2cd6966bafbf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Oct 2000 02:58:24 +0000 Subject: Ok - this is a big patch - and it may break smbd a bit (although I hope not). If you encounter strange file-serving behavior after this patch then back it out. I analysed our stat() usage and realised we were doing approx. 3 stat calls per open, and 2 per getattr/setattr. This patch should fix all that. It causes the stat struct returned from unix_convert() (which now *must* be passed a valid SMB_STRUCT_STAT pointer) to be passed through into the open code. This should prevent the multiple stats that were being done so as not to violate layer encapsulation in the API's. Herb - if you could run a NetBench test with this code and do a padc/par syscall test and also run with the current 2.2.0 code and test the padc/par syscalls I'd appreciate it - you should find the number of stat calls reduced - not sure by how much. The patch depends on unix_convert() actually finding the file and returning a stat struct, or returning a zero'd out stat struct if the file didn't exist. I believe we can guarentee this to be the case - I just wasn't confident enough to make this an assertion before. Ok ok - I did write this whilst at the Miami conference..... sometimes you get a little free time at these things :-). Jeremy. (This used to be commit 66a5c05ec46b641224fbe01b30bd7e83571a2a1b) --- source3/smbd/filename.c | 83 +++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 40 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9ac82386f9..5fe4a4c903 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -111,6 +111,11 @@ The bad_path arg is set to True if the filename walk failed. This is used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. + +On exit from unix_convert, if *pst was not null, then the file stat +struct will be returned if the file exists and was found, if not this +stat struct will be filled with zeros (and this can be detected by checking +for nlinks = 0, which can never be true for any file). ****************************************************************************/ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, @@ -127,6 +132,13 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + ZERO_STRUCTP(pst); + + *dirpath = 0; + *bad_path = False; + if(saved_last_component) + *saved_last_component = 0; + if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ @@ -135,15 +147,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); - *dirpath = 0; - *bad_path = False; - if(pst) { - ZERO_STRUCTP(pst); - } - - if(saved_last_component) - *saved_last_component = 0; - /* * Convert to basic unix format - removing \ chars and cleaning it up. */ @@ -165,7 +168,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * printing share. */ - if (!*name && (!conn -> printer)) { + if (!*name) { name[0] = '.'; name[1] = '\0'; } @@ -202,8 +205,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { - if(pst) - *pst = st; + *pst = st; return True; } @@ -211,11 +213,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False),&st) == 0) { + if (vfs_stat(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - if(pst) - *pst = st; + *pst = st; return(True); } @@ -277,7 +278,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False), &st) == 0) { + ZERO_STRUCT(st); + if (vfs_stat(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -308,8 +310,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || - !scan_directory(dirpath, start, conn, end?True:False)) { + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* * An intermediate part of the name can't be found. @@ -392,6 +393,14 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(!component_was_mangled && !name_has_wildcard) stat_cache_add(orig_path, name); + /* + * If we ended up resolving the entire path then return a valid + * stat struct if we got one. + */ + + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + *pst = st; + /* * The name has been resolved. */ @@ -426,15 +435,13 @@ BOOL check_name(char *name,connection_struct *conn) University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) - { + if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) - { + (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; - } + } } #endif @@ -479,33 +486,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d mangled = !check_mangled_cache( name ); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) - { + if (!(cur_dir = OpenDir(conn, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); - } + } /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) - { - if (*dname == '.' && - (strequal(dname,".") || strequal(dname,".."))) - continue; + while ((dname = ReadDirName(cur_dir))) { + if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + continue; pstrcpy(name2,dname); if (!name_map_mangle(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) - { - /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } + if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { + /* we've found the file, change it's name and return */ + if (docache) + DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); } + } CloseDir(cur_dir); return(False); -- cgit From 269acfe1d2e1776ca5afdc4d4ead20db0b88cacd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Dec 2000 00:39:32 +0000 Subject: Fixed *very* subtle statcache bug where invalid stat state could be being used if last component lookup failed, but was found in the directory scan. Jeremy. (This used to be commit 7055fa0bc43f6e2b3f04b8901fccea80d59bf490) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5fe4a4c903..aedd2e820f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -278,7 +278,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - ZERO_STRUCT(st); if (vfs_stat(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be @@ -296,6 +295,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } else { pstring rest; + /* Stat failed - ensure we don't use it. */ + ZERO_STRUCT(st); *rest = 0; /* -- cgit From 93e98d02818e079c9d714e3b5a7894238ead312a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 11 Dec 2000 22:51:57 +0000 Subject: subtle bug where files which missed the stat_cache but were added to the cache during the look returned a blank stat struct. Made weird occurrences such as... $ smbclient //pogo/print$ smb:\ > cd w32x86 ERROR: Invalid path smb:\ > cd w32x86 smb:\w32x86\ > (This used to be commit 8938dc183112b039c21a5a0beadb60068a8c5b00) --- source3/smbd/filename.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index aedd2e820f..4962297428 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,20 +387,17 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ - - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); - - /* + * If we get to here, the filename should have ben added + * to the stat_cache. Therefore a stat_cache_lookup() is needed here + * to fill in the SMB_STRUCT_STAT. + * * If we ended up resolving the entire path then return a valid * stat struct if we got one. */ - - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + if (stat_cache_lookup(conn, name, dirpath, &start, &st) + && (strlen(orig_path) == strlen(name))) { *pst = st; + } /* * The name has been resolved. -- cgit From 4c639caa1f16dae804c4736eb59ffb65ccd15278 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 00:11:34 +0000 Subject: Sorry Gerald, I think the original code was better (plus safer as I'm sure it's working :-). Jeremy. (This used to be commit e18c104ee35d00dcbe2e73e6c9699300a3947364) --- source3/smbd/filename.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 4962297428..aedd2e820f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,17 +387,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * If we get to here, the filename should have ben added - * to the stat_cache. Therefore a stat_cache_lookup() is needed here - * to fill in the SMB_STRUCT_STAT. - * + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); + + /* * If we ended up resolving the entire path then return a valid * stat struct if we got one. */ - if (stat_cache_lookup(conn, name, dirpath, &start, &st) - && (strlen(orig_path) == strlen(name))) { + + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) *pst = st; - } /* * The name has been resolved. -- cgit From da3053048c3d224a20d6383ac6682d31059cd46c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:32:10 +0000 Subject: Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR RPC code to merge with new passdb code. Currently rpcclient doesn't compile. I'm working on it... Jeremy. (This used to be commit 0be41d5158ea4e645e93e8cd30617c038416e549) --- source3/smbd/filename.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index aedd2e820f..bdbcd81b64 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -514,6 +512,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d CloseDir(cur_dir); return(False); } - - -#undef OLD_NTDOMAIN -- cgit From 87fbb7092b8f8b2f0db0f361c3d625e19de57cd9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:15:53 +0000 Subject: The big character set handling changeover! This commit gets rid of all our old codepage handling and replaces it with iconv. All internal strings in Samba are now in "unix" charset, which may be multi-byte. See internals.doc and my posting to samba-technical for a more complete explanation. (This used to be commit debb471267960e56005a741817ebd227ecfc512a) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index bdbcd81b64..9b76d63dc6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -436,7 +436,7 @@ BOOL check_name(char *name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; -- cgit From 527e824293ee934ca5da0ef5424efe5ab7757248 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:36:09 +0000 Subject: strchr and strrchr are macros when compiling with optimisation in gcc, so we can't redefine them. damn. (This used to be commit c41fc06376d1a2b83690612304e85010b5e5f3cf) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9b76d63dc6..70f34c52ad 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -176,7 +176,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, */ if(saved_last_component) { - end = strrchr(name, '/'); + end = strrchr_m(name, '/'); if(end) pstrcpy(saved_last_component, end + 1); else @@ -243,7 +243,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, #if 0 /* Keep Andrew's conservative code around, just in case. JRA. */ /* this is an extremely conservative test for mangled names. */ - if (strchr(start,magic_char)) + if (strchr_m(start,magic_char)) component_was_mangled = True; #endif @@ -261,7 +261,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Pinpoint the end of this section of the filename. */ - end = strchr(start, '/'); + end = strchr_m(start, '/'); /* * Chop the name at this point. -- cgit From 9de7c5e52155ee869605884526b9895ad58c0312 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Jul 2001 06:29:26 +0000 Subject: - don't try to print pointers - removed some unused mangling code (This used to be commit 36af1c0dc41f72ec6a5c671fd6b4f6eb2590b8b4) --- source3/smbd/filename.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 70f34c52ad..17fa35c0d7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -125,10 +125,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstring orig_path; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; -#if 0 - /* Andrew's conservative code... JRA. */ - extern char magic_char; -#endif ZERO_STRUCTP(pst); @@ -240,13 +236,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(is_mangled(start)) component_was_mangled = True; -#if 0 - /* Keep Andrew's conservative code around, just in case. JRA. */ - /* this is an extremely conservative test for mangled names. */ - if (strchr_m(start,magic_char)) - component_was_mangled = True; -#endif - /* * Now we need to recursively match the name against the real * directory structure. -- cgit From dc1fc3ee8ec2199bc73bb5d7ec711c6800f61d65 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 2 Oct 2001 04:29:50 +0000 Subject: Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header. (This used to be commit 2d0922b0eabfdc0aaf1d0797482fef47ed7fde8e) --- source3/smbd/filename.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 17fa35c0d7..5fdbef44fe 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -27,7 +27,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -- cgit From 95aa4c6bbe99f7883bbe3a08e0072685dc04c091 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 Oct 2001 13:19:22 +0000 Subject: change some more functions to the new mangle interface. (This used to be commit 06a7c28ea1be81c4a53f9a5b885c37fdde31f75c) --- source3/smbd/filename.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5fdbef44fe..d1c512c251 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -76,15 +76,17 @@ static BOOL fname_equal(char *name1, char *name2) ****************************************************************************/ static BOOL mangled_equal(char *name1, char *name2) { - pstring tmpname; - - if (is_8_3(name2, True)) - return(False); - - pstrcpy(tmpname,name2); - mangle_name_83(tmpname); - - return(strequal(name1,tmpname)); + char *tmpname; + BOOL ret = False; + + if (is_8_3(name2, True)) + { + tmpname = dos_mangle(name2); + if(tmpname) + ret = strequal(name1,tmpname); + SAFE_FREE(tmpname); + } + return ret; } -- cgit From 0558e2c4024d419dfb7b77a2eec100f7916831d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Dec 2001 01:26:54 +0000 Subject: Fixed the bug with descending into mangled directories. The problem is that name_map_mangle can *change* the length of a patchname. Ensure that all the character pointer messing about can cope with changing sizes of components. This code is too ugly to live..... This also needs *lots* of testing. Jeremy. (This used to be commit 9f2b6a07429da5dec59e562fa5489b8079978677) --- source3/smbd/filename.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d1c512c251..f098950c44 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -283,7 +283,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } else { pstring rest; - /* Stat failed - ensure we don't use it. */ + /* Stat failed - ensure we don't use it. */ ZERO_STRUCT(st); *rest = 0; @@ -320,7 +320,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case + * We may need to strupper() or strlower() it in case * this conversion is being used for file creation * purposes. If the filename is of mixed case then * don't normalise it. @@ -343,11 +343,14 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * Restore the rest of the string. + * Restore the rest of the string. If the string was mangled the size + * may have changed. */ if (end) { - pstrcpy(start+strlen(start)+1,rest); end = start + strlen(start); + pstrcat(start,"/"); + pstrcat(start,rest); + *end = '\0'; } } /* end else */ @@ -489,7 +492,7 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d if (!name_map_mangle(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { + if ((mangled && mangled_equal(name,name2)) || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/smbd/filename.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f098950c44..3053e8a1d8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-200 -- cgit From c21ff8f76209a1e7138ba06ce262a3e2c2880646 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 Apr 2002 01:58:44 +0000 Subject: 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) --- source3/smbd/filename.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3053e8a1d8..8bd09691e4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -75,6 +75,17 @@ static BOOL fname_equal(char *name1, char *name2) ****************************************************************************/ static BOOL mangled_equal(char *name1, char *name2) { +#if 1 + pstring tmpname; + if (is_8_3(name2, True)) { + return False; + } + + pstrcpy(tmpname, name2); + mangle_name_83(tmpname); + + return strequal(name1, tmpname); +#else char *tmpname; BOOL ret = False; @@ -86,6 +97,8 @@ static BOOL mangled_equal(char *name1, char *name2) SAFE_FREE(tmpname); } return ret; +#endif + } @@ -116,7 +129,7 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, +BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; -- cgit From 9cd0306baa1b3a78b40ab97b5d199b90a4c34aa6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 02:20:56 +0000 Subject: This split the mangling code up to allow for the possibility of multiple mangling implementation, selectable using "mangling method = " in smb.conf It also tidies the interface a little, although it is still nasty. (This used to be commit be23d87a178e7d0691e7d942adf89bb3d2d533c2) --- source3/smbd/filename.c | 46 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8bd09691e4..cb6a6d31a4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -73,32 +73,16 @@ static BOOL fname_equal(char *name1, char *name2) /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2) +static BOOL mangled_equal(char *name1, char *name2, int snum) { -#if 1 pstring tmpname; - if (is_8_3(name2, True)) { + if (mangle_is_8_3(name2, True)) { return False; } pstrcpy(tmpname, name2); - mangle_name_83(tmpname); - - return strequal(name1, tmpname); -#else - char *tmpname; - BOOL ret = False; - - if (is_8_3(name2, True)) - { - tmpname = dos_mangle(name2); - if(tmpname) - ret = strequal(name1,tmpname); - SAFE_FREE(tmpname); - } - return ret; -#endif - + return mangle_map(tmpname, True, False, snum) && + strequal(name1, tmpname); } @@ -193,7 +177,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen } if (!case_sensitive && - (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) + (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) strnorm(name); /* @@ -220,7 +204,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (vfs_stat(conn,name,&st) == 0) { +/* ZZZ: stat1 */ if (vfs_stat(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -235,7 +219,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (case_sensitive && !is_mangled(name) && + if (case_sensitive && !mangle_is_mangled(name) && !lp_strip_dot() && !use_mangled_map) return(False); @@ -246,7 +230,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if(is_mangled(start)) + if (mangle_is_mangled(start)) component_was_mangled = True; /* @@ -346,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (is_mangled(start)) { - check_mangled_cache( start ); + if (mangle_is_mangled(start)) { + mangle_check_cache( start ); } DEBUG(5,("New file %s\n",start)); @@ -468,7 +452,7 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d BOOL mangled; pstring name2; - mangled = is_mangled(name); + mangled = mangle_is_mangled(name); /* handle null paths */ if (*path == 0) @@ -482,12 +466,12 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the name_map_mangle() + * read from the directory and then mangled by the mangle_map() * call. We need to mangle both names or neither. * (JRA). */ if (mangled) - mangled = !check_mangled_cache( name ); + mangled = !mangle_check_cache( name ); /* open the directory */ if (!(cur_dir = OpenDir(conn, path, True))) { @@ -501,10 +485,10 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d continue; pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,True,SNUM(conn))) + if (!mangle_map(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) || fname_equal(name, dname)) { + if ((mangled && mangled_equal(name,name2,SNUM(conn))) || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/smbd/filename.c | 760 +++++++++++++++++++++++------------------------- 1 file changed, 369 insertions(+), 391 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cb6a6d31a4..e5f9b7a0ae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -38,54 +38,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d Check if two filenames are equal. This needs to be careful about whether we are case sensitive. ****************************************************************************/ + static BOOL fname_equal(char *name1, char *name2) { - int l1 = strlen(name1); - int l2 = strlen(name2); - - /* handle filenames ending in a single dot */ - if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name1[l1-1] = 0; - ret = fname_equal(name1,name2); - name1[l1-1] = '.'; - return(ret); - } - - if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name2[l2-1] = 0; - ret = fname_equal(name1,name2); - name2[l2-1] = '.'; - return(ret); - } - - /* now normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} + /* Normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + return(strequal(name1,name2)); +} /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2, int snum) + +static BOOL mangled_equal(char *name1, const char *name2, int snum) { pstring tmpname; - if (mangle_is_8_3(name2, True)) { - return False; - } pstrcpy(tmpname, name2); - return mangle_map(tmpname, True, False, snum) && - strequal(name1, tmpname); + mangle_map(tmpname, True, False, snum); + return strequal(name1, tmpname); } - /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -116,388 +91,391 @@ for nlinks = 0, which can never be true for any file). BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { - SMB_STRUCT_STAT st; - char *start, *end; - pstring dirpath; - pstring orig_path; - BOOL component_was_mangled = False; - BOOL name_has_wildcard = False; - - ZERO_STRUCTP(pst); - - *dirpath = 0; - *bad_path = False; - if(saved_last_component) - *saved_last_component = 0; - - if (conn->printer) { - /* we don't ever use the filenames on a printer share as a - filename - so don't convert them */ - return True; - } - - DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); - - /* - * Convert to basic unix format - removing \ chars and cleaning it up. - */ - - unix_format(name); - unix_clean_name(name); - - /* - * Names must be relative to the root of the service - trim any leading /. - * also trim trailing /'s. - */ - - trim_string(name,"/","/"); - - /* - * If we trimmed down to a single '\0' character - * then we should use the "." directory to avoid - * searching the cache, but not if we are in a - * printing share. - */ - - if (!*name) { - name[0] = '.'; - name[1] = '\0'; - } - - /* - * Ensure saved_last_component is valid even if file exists. - */ - - if(saved_last_component) { - end = strrchr_m(name, '/'); - if(end) - pstrcpy(saved_last_component, end + 1); - else - pstrcpy(saved_last_component, name); - } - - if (!case_sensitive && - (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) - strnorm(name); - - /* - * If we trimmed down to a single '\0' character - * then we will be using the "." directory. - * As we know this is valid we can return true here. - */ - - if(!*name) - return(True); - - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - - pstrcpy(orig_path, name); - - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { - *pst = st; - return True; - } - - /* - * stat the name - if it exists then we are all done! - */ - -/* ZZZ: stat1 */ if (vfs_stat(conn,name,&st) == 0) { - stat_cache_add(orig_path, name); - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - *pst = st; - return(True); - } - - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", - name, dirpath, start)); - - /* - * A special case - if we don't have any mangling chars and are case - * sensitive then searching won't help. - */ - - if (case_sensitive && !mangle_is_mangled(name) && - !lp_strip_dot() && !use_mangled_map) - return(False); - - name_has_wildcard = ms_has_wild(start); - - /* - * is_mangled() was changed to look at an entire pathname, not - * just a component. JRA. - */ - - if (mangle_is_mangled(start)) - component_was_mangled = True; - - /* - * Now we need to recursively match the name against the real - * directory structure. - */ - - /* - * Match each part of the path name separately, trying the names - * as is first, then trying to scan the directory for matching names. - */ - - for (; start ; start = (end?end+1:(char *)NULL)) { - /* - * Pinpoint the end of this section of the filename. - */ - end = strchr_m(start, '/'); - - /* - * Chop the name at this point. - */ - if (end) - *end = 0; - - if(saved_last_component != 0) - pstrcpy(saved_last_component, end ? end + 1 : start); - - /* - * Check if the name exists up to this point. - */ - - if (vfs_stat(conn,name, &st) == 0) { - /* - * It exists. it must either be a directory or this must be - * the last part of the path for it to be OK. - */ - if (end && !(st.st_mode & S_IFDIR)) { - /* - * An intermediate part of the name isn't a directory. - */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - - } else { - pstring rest; - - /* Stat failed - ensure we don't use it. */ - ZERO_STRUCT(st); - *rest = 0; - - /* - * Remember the rest of the pathname so it can be restored - * later. - */ - - if (end) - pstrcpy(rest,end+1); - - /* - * Try to find this part of the path in the directory. - */ - - if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { - if (end) { - /* - * An intermediate part of the name can't be found. - */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - - /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between - * these two errors. - */ - *bad_path = True; - return(False); - } + SMB_STRUCT_STAT st; + char *start, *end; + pstring dirpath; + pstring orig_path; + BOOL component_was_mangled = False; + BOOL name_has_wildcard = False; + + ZERO_STRUCTP(pst); + + *dirpath = 0; + *bad_path = False; + if(saved_last_component) + *saved_last_component = 0; + + if (conn->printer) { + /* we don't ever use the filenames on a printer share as a + filename - so don't convert them */ + return True; + } + + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + + /* + * Convert to basic unix format - removing \ chars and cleaning it up. + */ + + unix_format(name); + unix_clean_name(name); + + /* + * Names must be relative to the root of the service - trim any leading /. + * also trim trailing /'s. + */ + + trim_string(name,"/","/"); + + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache, but not if we are in a + * printing share. + */ + + if (!*name) { + name[0] = '.'; + name[1] = '\0'; + } + + /* + * Ensure saved_last_component is valid even if file exists. + */ + + if(saved_last_component) { + end = strrchr_m(name, '/'); + if(end) + pstrcpy(saved_last_component, end + 1); + else + pstrcpy(saved_last_component, name); + } + + if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) + strnorm(name); + + /* + * If we trimmed down to a single '\0' character + * then we will be using the "." directory. + * As we know this is valid we can return true here. + */ + + if(!*name) + return(True); + + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + pstrcpy(orig_path, name); + + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + *pst = st; + return True; + } + + /* + * stat the name - if it exists then we are all done! + */ + + if (vfs_stat(conn,name,&st) == 0) { + stat_cache_add(orig_path, name); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + *pst = st; + return(True); + } + + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); + + /* + * A special case - if we don't have any mangling chars and are case + * sensitive then searching won't help. + */ + + if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map) + return(False); + + name_has_wildcard = ms_has_wild(start); + + /* + * is_mangled() was changed to look at an entire pathname, not + * just a component. JRA. + */ + + if (mangle_is_mangled(start)) + component_was_mangled = True; + + /* + * Now we need to recursively match the name against the real + * directory structure. + */ + + /* + * Match each part of the path name separately, trying the names + * as is first, then trying to scan the directory for matching names. + */ + + for (; start ; start = (end?end+1:(char *)NULL)) { + /* + * Pinpoint the end of this section of the filename. + */ + end = strchr_m(start, '/'); + + /* + * Chop the name at this point. + */ + if (end) + *end = 0; + + if(saved_last_component != 0) + pstrcpy(saved_last_component, end ? end + 1 : start); + + /* + * Check if the name exists up to this point. + */ + + if (vfs_stat(conn,name, &st) == 0) { + /* + * It exists. it must either be a directory or this must be + * the last part of the path for it to be OK. + */ + if (end && !(st.st_mode & S_IFDIR)) { + /* + * An intermediate part of the name isn't a directory. + */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + + } else { + pstring rest; + + /* Stat failed - ensure we don't use it. */ + ZERO_STRUCT(st); + *rest = 0; + + /* + * Remember the rest of the pathname so it can be restored + * later. + */ + + if (end) + pstrcpy(rest,end+1); + + /* + * Try to find this part of the path in the directory. + */ + + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { + if (end) { + /* + * An intermediate part of the name can't be found. + */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + *bad_path = True; + return(False); + } - /* - * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case - * this conversion is being used for file creation - * purposes. If the filename is of mixed case then - * don't normalise it. - */ - - if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* - * check on the mangled stack to see if we can recover the - * base of the filename. - */ - - if (mangle_is_mangled(start)) { - mangle_check_cache( start ); - } - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* - * Restore the rest of the string. If the string was mangled the size - * may have changed. - */ - if (end) { - end = start + strlen(start); - pstrcat(start,"/"); - pstrcat(start,rest); - *end = '\0'; - } - } /* end else */ - - /* - * Add to the dirpath that we have resolved so far. - */ - if (*dirpath) - pstrcat(dirpath,"/"); - - pstrcat(dirpath,start); - - /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ - - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, dirpath); - - /* - * Restore the / that we wiped out earlier. - */ - if (end) - *end = '/'; - } + /* + * Just the last part of the name doesn't exist. + * We may need to strupper() or strlower() it in case + * this conversion is being used for file creation + * purposes. If the filename is of mixed case then + * don't normalise it. + */ + + if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* + * check on the mangled stack to see if we can recover the + * base of the filename. + */ + + if (mangle_is_mangled(start)) { + mangle_check_cache( start ); + } + + DEBUG(5,("New file %s\n",start)); + return(True); + } + + /* + * Restore the rest of the string. If the string was mangled the size + * may have changed. + */ + if (end) { + end = start + strlen(start); + pstrcat(start,"/"); + pstrcat(start,rest); + *end = '\0'; + } + } /* end else */ + + /* + * Add to the dirpath that we have resolved so far. + */ + if (*dirpath) + pstrcat(dirpath,"/"); + + pstrcat(dirpath,start); + + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, dirpath); + + /* + * Restore the / that we wiped out earlier. + */ + if (end) + *end = '/'; + } - /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); - /* - * If we ended up resolving the entire path then return a valid - * stat struct if we got one. - */ + /* + * If we ended up resolving the entire path then return a valid + * stat struct if we got one. + */ - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) - *pst = st; + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + *pst = st; - /* - * The name has been resolved. - */ + /* + * The name has been resolved. + */ - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return(True); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + return(True); } - /**************************************************************************** -check a filename - possibly caling reducename - -This is called by every routine before it allows an operation on a filename. -It does any final confirmation necessary to ensure that the filename is -a valid one for the user to access. + Check a filename - possibly caling reducename. + This is called by every routine before it allows an operation on a filename. + It does any final confirmation necessary to ensure that the filename is + a valid one for the user to access. ****************************************************************************/ + BOOL check_name(char *name,connection_struct *conn) { - BOOL ret; + BOOL ret; - errno = 0; + errno = 0; - if (IS_VETO_PATH(conn, name)) { - DEBUG(5,("file path name %s vetoed\n",name)); - return(0); - } + if (IS_VETO_PATH(conn, name)) { + if(strcmp(name, ".") && strcmp(name, "..")) { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } + } - ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); + ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc - University of Geneva */ + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) { - SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; - } - } + if (!lp_symlinks(SNUM(conn))) { + SMB_STRUCT_STAT statbuf; + if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) { + DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + ret=0; + } + } #endif - if (!ret) - DEBUG(5,("check_name on %s failed\n",name)); + if (!ret) + DEBUG(5,("check_name on %s failed\n",name)); - return(ret); + return(ret); } - /**************************************************************************** -scan a directory to find a filename, matching without case sensitivity - -If the name looks like a mangled name then try via the mangling functions + Scan a directory to find a filename, matching without case sensitivity. + If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ + static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) { - void *cur_dir; - char *dname; - BOOL mangled; - pstring name2; - - mangled = mangle_is_mangled(name); - - /* handle null paths */ - if (*path == 0) - path = "."; - - if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - pstrcpy(name, dname); - return(True); - } - - /* - * The incoming name can be mangled, and if we de-mangle it - * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the mangle_map() - * call. We need to mangle both names or neither. - * (JRA). - */ - if (mangled) - mangled = !mangle_check_cache( name ); - - /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) { - DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - return(False); - } - - /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) { - if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) - continue; - - pstrcpy(name2,dname); - if (!mangle_map(name2,False,True,SNUM(conn))) - continue; - - if ((mangled && mangled_equal(name,name2,SNUM(conn))) || fname_equal(name, dname)) { - /* we've found the file, change it's name and return */ - if (docache) - DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } - } - - CloseDir(cur_dir); - return(False); + void *cur_dir; + char *dname; + BOOL mangled; + + mangled = mangle_is_mangled(name); + + /* handle null paths */ + if (*path == 0) + path = "."; + + if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { + pstrcpy(name, dname); + return(True); + } + + /* + * The incoming name can be mangled, and if we de-mangle it + * here it will not compare correctly against the filename (name2) + * read from the directory and then mangled by the mangle_map() + * call. We need to mangle both names or neither. + * (JRA). + */ + if (mangled) + mangled = !mangle_check_cache( name ); + + /* open the directory */ + if (!(cur_dir = OpenDir(conn, path, True))) { + DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + return(False); + } + + /* now scan for matching names */ + while ((dname = ReadDirName(cur_dir))) { + if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + continue; + + /* + * At this point dname is the unmangled name. + * name is either mangled or not, depending on the state of the "mangled" + * variable. JRA. + */ + + /* + * Check mangled name against mangled name, or unmangled name + * against unmangled name. + */ + + if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname)) { + /* we've found the file, change it's name and return */ + if (docache) + DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); + } + } + + CloseDir(cur_dir); + return(False); } -- cgit From 127e77e6e334fdc33086bffcbe00d340c0ba0097 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 15:27:10 +0000 Subject: Sync 3.0 branch with head (This used to be commit 42615b945e2e48e53a21ea47f2e45407913a6a1e) --- source3/smbd/filename.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index e5f9b7a0ae..ce98af4ace 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -29,7 +29,6 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern fstring remote_machine; extern BOOL use_mangled_map; static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ce98af4ace..d343db26f6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -168,7 +168,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(orig_path, name); - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; return True; } -- cgit From d0a99a261d31f39c2d30a067d3d7efb80282a15a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Oct 2002 01:19:00 +0000 Subject: Turns out with Win9x, we could occasionally return from unix_convert() given a mangled name without a valid stat struct if the file existed. This would then cause open_file_shared1() to erroneously think the file open was new, thus not check for oplock break, thus causing a spurious EAGAIN reply to the open on a file we already had kernel oplocked.... (phew - that was fun to track down :-). Jeremy. (This used to be commit af80b033a5374da9163e3484f7d8707813490597) --- source3/smbd/filename.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d343db26f6..202bd75d4c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -318,6 +318,18 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcat(start,"/"); pstrcat(start,rest); *end = '\0'; + } else { + /* + * We just scanned for, and found the end of the path. + * We must return a valid stat struct if it exists. + * JRA. + */ + + if (vfs_stat(conn,name, &st) == 0) { + *pst = st; + } else { + ZERO_STRUCT(st); + } } } /* end else */ -- cgit From 634c54310c92c48dd4eceec602e230a021bdcfc5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Jan 2003 08:28:12 +0000 Subject: Merge from HEAD - make Samba compile with -Wwrite-strings without additional warnings. (Adds a lot of const). Andrew Bartlett (This used to be commit 3a7458f9472432ef12c43008414925fd1ce8ea0c) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 202bd75d4c..bcfd366741 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -31,7 +31,7 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern BOOL use_mangled_map; -static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); +static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache); /**************************************************************************** Check if two filenames are equal. @@ -387,7 +387,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen a valid one for the user to access. ****************************************************************************/ -BOOL check_name(char *name,connection_struct *conn) +BOOL check_name(pstring name,connection_struct *conn) { BOOL ret; @@ -428,7 +428,7 @@ BOOL check_name(char *name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; -- cgit From 50edc1a8310c18ffc09cbd5dcc285122a638a4d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Feb 2003 04:11:36 +0000 Subject: merge from head (This used to be commit fd3216dbcbaec7d64dd24fe2af6c4156935c47e9) --- source3/smbd/filename.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index bcfd366741..7d3527402e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -31,7 +31,8 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern BOOL use_mangled_map; -static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache); +static BOOL scan_directory(const char *path, char *name,size_t maxlength, + connection_struct *conn,BOOL docache); /**************************************************************************** Check if two filenames are equal. @@ -266,7 +267,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { + if (ms_has_wild(start) || + !scan_directory(dirpath, start, + sizeof(pstring) - 1 - (start - name), + conn, + end?True:False)) { if (end) { /* * An intermediate part of the name can't be found. @@ -315,8 +320,10 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (end) { end = start + strlen(start); - pstrcat(start,"/"); - pstrcat(start,rest); + if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || + !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { + return False; + } *end = '\0'; } else { /* @@ -428,7 +435,8 @@ BOOL check_name(pstring name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(const char *path, char *name, size_t maxlength, + connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; @@ -441,7 +449,7 @@ static BOOL scan_directory(const char *path, pstring name,connection_struct *con path = "."; if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - pstrcpy(name, dname); + safe_strcpy(name, dname, maxlength); return(True); } @@ -481,7 +489,7 @@ static BOOL scan_directory(const char *path, pstring name,connection_struct *con /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); + safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); return(True); } -- cgit From ad0d6509a761154c113e040a82ad78e72a3ccf30 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:56:13 +0000 Subject: Merge from HEAD: - Make ReadDirName return a const char*. - Consequential changes from that - mark our fstring/pstring assumptions in function prototypes Andrew Bartlett (This used to be commit 10b53d7c6fd77f23433dd2ef12bb14b227147a48) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7d3527402e..ad707a2b9d 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -39,7 +39,7 @@ static BOOL scan_directory(const char *path, char *name,size_t maxlength, This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(char *name1, char *name2) +static BOOL fname_equal(const char *name1, const char *name2) { /* Normal filename handling */ if (case_sensitive) @@ -52,7 +52,7 @@ static BOOL fname_equal(char *name1, char *name2) Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, const char *name2, int snum) +static BOOL mangled_equal(const char *name1, const char *name2, int snum) { pstring tmpname; @@ -439,7 +439,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, connection_struct *conn,BOOL docache) { void *cur_dir; - char *dname; + const char *dname; BOOL mangled; mangled = mangle_is_mangled(name); -- cgit From f359b4bdf6134dbd6542a66cecd311cf91d9a074 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 May 2003 01:06:27 +0000 Subject: Fix nasty bug pointed out by samba-technical poster. If name is mangled then we weren't always correctly detecting that it had a valid stat struct and so might now return a 'file existed'. Finally realized this when installing the W2K resource kit as a test case. Jeremy. (This used to be commit d48069ccd8351e4bff097a7f7500c738870a413d) --- source3/smbd/filename.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ad707a2b9d..9dd1523c73 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -248,6 +248,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } + if (!end) { + /* + * We just scanned for, and found the end of the path. + * We must return the valid stat struct. + * JRA. + */ + + *pst = st; + } + } else { pstring rest; @@ -373,7 +383,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * If we ended up resolving the entire path then return a valid - * stat struct if we got one. + * stat struct if we got one. Note this doesn't catch mangled paths, + * but the check in the for loop above will do that. JRA. */ if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) -- cgit From 2d7a8480cf3e58d10c9a11e161a8fe6c91a59039 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 May 2003 00:35:38 +0000 Subject: Optimisation. We don't need to do 2 strlen's when we're setting the stat struct in the correct place. Jeremy. (This used to be commit 4cd8b276715f7e019fcee8fc3ebb2855610c4751) --- source3/smbd/filename.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9dd1523c73..b9e33e8f93 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -381,15 +381,6 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(!component_was_mangled && !name_has_wildcard) stat_cache_add(orig_path, name); - /* - * If we ended up resolving the entire path then return a valid - * stat struct if we got one. Note this doesn't catch mangled paths, - * but the check in the for loop above will do that. JRA. - */ - - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) - *pst = st; - /* * The name has been resolved. */ -- cgit From e7c8c15888454043c73967635deb4d3419a489e9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 11 May 2003 23:34:18 +0000 Subject: Fix VFS layer: 1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978) --- source3/smbd/filename.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b9e33e8f93..6622a6ba63 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -178,7 +178,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (vfs_stat(conn,name,&st) == 0) { + if (VFS_STAT(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -234,7 +234,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Check if the name exists up to this point. */ - if (vfs_stat(conn,name, &st) == 0) { + if (VFS_STAT(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -342,7 +342,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * JRA. */ - if (vfs_stat(conn,name, &st) == 0) { + if (VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { ZERO_STRUCT(st); @@ -418,7 +418,7 @@ BOOL check_name(pstring name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && + if ( (VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; -- cgit From bc2a3748e9caa8f60f7c2387e7eecd7fb3fae899 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 10:59:01 +0000 Subject: Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macros at system side. We currently have one clash with AIX and its VFS_LOCK. Compiled and tested -- no new functionality or code, just plain rename of macros for yet-unreleased VFS API version. Needs to be done before a24 is out (This used to be commit c2689ed118b490e49497a76ed6a2251262018769) --- source3/smbd/filename.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6622a6ba63..ad107f9c3e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -178,7 +178,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (VFS_STAT(conn,name,&st) == 0) { + if (SMB_VFS_STAT(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -234,7 +234,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Check if the name exists up to this point. */ - if (VFS_STAT(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -342,7 +342,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * JRA. */ - if (VFS_STAT(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { ZERO_STRUCT(st); @@ -418,7 +418,7 @@ BOOL check_name(pstring name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (VFS_LSTAT(conn,name,&statbuf) != -1) && + if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; -- cgit From 94f59f54921174fc156fade575ca114d331b1bd8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2003 19:59:55 +0000 Subject: More tuning from cachegrind. Change most trim_string() calls to trim_char(0, as that's what they do. Fix string_replace() to fast-path ascii. Jeremy. (This used to be commit f35e9a8b909d3c74be47083ccc4a4e91a14938db) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ad107f9c3e..643e315c06 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -125,7 +125,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * also trim trailing /'s. */ - trim_string(name,"/","/"); + trim_char(name,'/','/'); /* * If we trimmed down to a single '\0' character @@ -164,7 +164,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(True); start = name; - while (strncmp(start,"./",2) == 0) + while (start[0] == '.' && start[1] == '/') start += 2; pstrcpy(orig_path, name); -- cgit From fba5a722497c1e4577aa463921a0fec5f6d5fe55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Mar 2004 20:55:59 +0000 Subject: Use a common function to parse all pathnames from the wire. This allows much closer emulation of Win2k3 error return codes. Jeremy. (This used to be commit c9f31fafeda6ad79e590276f36e03ecd2e93f818) --- source3/smbd/filename.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 643e315c06..a71e8a806c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -114,29 +114,30 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); /* - * Convert to basic unix format - removing \ chars and cleaning it up. + * Conversion to basic unix format is already done in check_path_syntax(). */ - unix_format(name); - unix_clean_name(name); - /* - * Names must be relative to the root of the service - trim any leading /. - * also trim trailing /'s. + * Names must be relative to the root of the service - any leading /. + * and trailing /'s should have been trimmed by check_path_syntax(). */ - trim_char(name,'/','/'); +#ifdef DEVELOPER + SMB_ASSERT(*name != '/'); +#endif /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid * searching the cache, but not if we are in a * printing share. + * As we know this is valid we can return true here. */ if (!*name) { name[0] = '.'; name[1] = '\0'; + return(True); } /* @@ -154,19 +155,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* - * If we trimmed down to a single '\0' character - * then we will be using the "." directory. - * As we know this is valid we can return true here. - */ - - if(!*name) - return(True); - start = name; - while (start[0] == '.' && start[1] == '/') - start += 2; - pstrcpy(orig_path, name); if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { -- cgit From 893d5eba5d17a1efe600d67c0e82b401ead248ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Mar 2004 01:37:12 +0000 Subject: all_string_sub() is broken as it doesn't handle mb chars correctly (and so breaks when substitution '/' and '\'). It's used by unix_clean_name(), which is used by reduce_name, which is used by check_name() (phew!). Now that we know all filenames passed to check_name() are in a "good" format (no double slashes, all '\\' chars translated to '/' etc.) due to the new check_path_syntax() we can avoid calling reduce_name unless widelinks are denied. After this check-in I can fix all_string_sub() to handle mb chars correctly as it won't be in the direct path in the main path handling code. Jeremy. (This used to be commit 6080186fc4c2e7c59dd12a177539bfb77eb525cb) --- source3/smbd/filename.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a71e8a806c..8300674d61 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,7 +387,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL check_name(pstring name,connection_struct *conn) { - BOOL ret; + BOOL ret = True; errno = 0; @@ -398,7 +398,9 @@ BOOL check_name(pstring name,connection_struct *conn) } } - ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); + if (!lp_widelinks(SNUM(conn))) { + ret = reduce_name(conn,name,conn->connectpath); + } /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc -- cgit From 48eb635f31a09fa0822d95d3e895255ef8a6d5e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Mar 2004 22:32:45 +0000 Subject: Several mb tidyups - getting ready to address the XXX_sub function. Jeremy. (This used to be commit 92c3ae3458177ec7f721598311a8ad04b2db5138) --- source3/smbd/filename.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8300674d61..805af9c494 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 This program is free software; you can redistribute it and/or modify @@ -392,9 +392,10 @@ BOOL check_name(pstring name,connection_struct *conn) errno = 0; if (IS_VETO_PATH(conn, name)) { - if(strcmp(name, ".") && strcmp(name, "..")) { + /* Is it not dot or dot dot. */ + if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { DEBUG(5,("file path name %s vetoed\n",name)); - return(0); + return False; } } @@ -412,7 +413,7 @@ BOOL check_name(pstring name,connection_struct *conn) if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; + ret = False; } } #endif @@ -464,8 +465,11 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, /* now scan for matching names */ while ((dname = ReadDirName(cur_dir))) { - if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + + /* Is it dot or dot dot. */ + if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { continue; + } /* * At this point dname is the unmangled name. -- cgit From e0da56a84808c522bc7324b5d636f1cbd317a2c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 May 2004 18:37:47 +0000 Subject: r570: Remove lots of globals to handle case issues - move them to connection struct entries (as they should have been from the start). Jerry, once you've cut over to 3.0.4 release branch I'll add this to 3.0 also. - Jerry cut over :-). Jeremy. (This used to be commit 578a508509d21226ad3332fc54c3ab54cd8ae452) --- source3/smbd/filename.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 805af9c494..692c7f7610 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,11 +26,6 @@ #include "includes.h" -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL short_case_preserve; -extern BOOL use_mangled_map; - static BOOL scan_directory(const char *path, char *name,size_t maxlength, connection_struct *conn,BOOL docache); @@ -39,7 +34,7 @@ static BOOL scan_directory(const char *path, char *name,size_t maxlength, This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2) +static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) { /* Normal filename handling */ if (case_sensitive) @@ -152,13 +147,17 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) - strnorm(name); +#if 1 + if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) +#else + if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))) +#endif + strnorm(name, lp_defaultcase(SNUM(conn))); start = name; pstrcpy(orig_path, name); - if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; return True; } @@ -168,7 +167,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (SMB_VFS_STAT(conn,name,&st) == 0) { - stat_cache_add(orig_path, name); + stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; return(True); @@ -181,7 +180,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map) + if (conn->case_sensitive && !mangle_is_mangled(name) && !*lp_mangled_map(SNUM(conn))) return(False); name_has_wildcard = ms_has_wild(start); @@ -297,8 +296,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * don't normalise it. */ - if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) - strnorm(start); + if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start, lp_defaultcase(SNUM(conn))); /* * check on the mangled stack to see if we can recover the @@ -353,7 +352,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, dirpath); + stat_cache_add(orig_path, dirpath, conn->case_sensitive); /* * Restore the / that we wiped out earlier. @@ -368,7 +367,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); + stat_cache_add(orig_path, name, conn->case_sensitive); /* * The name has been resolved. @@ -482,7 +481,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname)) { + if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); -- cgit From 89db7e100193c3b895180730f49061424a806c8e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 00:20:50 +0000 Subject: r656: Make widelinks use realpath(). Tidy up cases where we need to become a service. Jeremy. (This used to be commit a03b6a05e02ec8415efc0e8ceade102e06f8fffe) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 692c7f7610..a7223e7527 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -399,7 +399,7 @@ BOOL check_name(pstring name,connection_struct *conn) } if (!lp_widelinks(SNUM(conn))) { - ret = reduce_name(conn,name,conn->connectpath); + ret = reduce_name(conn,name); } /* Check if we are allowing users to follow symlinks */ -- cgit From 400bed7a68ccdeeb8c50326e817788e01b155907 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 May 2004 01:22:17 +0000 Subject: r716: Fix for bugid #1345 (Macromedia Homesite cannot connect anymore after upgrade to 3.0.4). Cause was premature optimization in unix_convert(). My fault, sorry. Jeremy. (This used to be commit e5438f0a841e8ea57b515544cbf638c38405ed55) --- source3/smbd/filename.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a7223e7527..5e5f572691 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -132,6 +132,10 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (!*name) { name[0] = '.'; name[1] = '\0'; + if (SMB_VFS_STAT(conn,name,&st) == 0) { + *pst = st; + } + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); return(True); } -- cgit From cb03592c067a8e475a5f96f72aa0e84ba176a747 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 May 2004 01:54:01 +0000 Subject: r933: When using widelinks = no, use realpath to canonicalize the connection path on connection create for the user. We'll be checking all symlinked paths are below this directory. Jeremy. (This used to be commit b562fe9fbca4971059b913959bbaca02af42c1a4) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5e5f572691..67329b51e6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -135,7 +135,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; } - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + DEBUG(5,("conversion finished \"\" -> %s\n",name)); return(True); } -- cgit From fddef6fc201ed127eaac737e725d1c2dd8c6926e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jun 2004 17:54:23 +0000 Subject: r1115: Fix for #1427. Catch bad path errors at the right point. Ensure all our pathname parsing is consistent. Jeremy. (This used to be commit 5e8237e306f0bb0e492f10fb6487938132899384) --- source3/smbd/filename.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 67329b51e6..ab75d9c06a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -237,6 +237,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + errno = ENOTDIR; + *bad_path = True; return(False); } @@ -265,6 +274,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (end) pstrcpy(rest,end+1); + /* Reset errno so we can detect directory open errors. */ + errno = 0; + /* * Try to find this part of the path in the directory. */ @@ -292,6 +304,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } + if (errno == ENOTDIR) { + *bad_path = True; + return(False); + } + /* * Just the last part of the name doesn't exist. * We may need to strupper() or strlower() it in case @@ -392,12 +409,11 @@ BOOL check_name(pstring name,connection_struct *conn) { BOOL ret = True; - errno = 0; - if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { DEBUG(5,("file path name %s vetoed\n",name)); + errno = ENOENT; return False; } } @@ -416,13 +432,15 @@ BOOL check_name(pstring name,connection_struct *conn) if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + errno = EACCES; ret = False; } } #endif - if (!ret) + if (!ret) { DEBUG(5,("check_name on %s failed\n",name)); + } return(ret); } @@ -496,5 +514,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, } CloseDir(cur_dir); + errno = ENOENT; return(False); } -- cgit From 0c6d7f28d6c1066cc6b3055ebf6a8fcf685ca1f6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 22 Jul 2004 13:39:43 +0000 Subject: r1570: merging changes from 3.0.5 (This used to be commit 430cf63b9148441bce42bfb15a8045de5da108f4) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ab75d9c06a..cc1c0a40b6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -326,7 +326,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (mangle_is_mangled(start)) { - mangle_check_cache( start ); + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); } DEBUG(5,("New file %s\n",start)); @@ -476,7 +476,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, * (JRA). */ if (mangled) - mangled = !mangle_check_cache( name ); + mangled = !mangle_check_cache( name, maxlength ); /* open the directory */ if (!(cur_dir = OpenDir(conn, path, True))) { -- cgit From db2ffe10f9283c86f95ae76d38c21916065a4b87 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Aug 2004 23:20:47 +0000 Subject: r2076: Removed old dir caching code - not being used now we have the statcache anyway. New dir caching will be done on nanosecond timestamps. Jeremy. (This used to be commit ba473a580245430009245a4c8b8dcaf9fc4b6406) --- source3/smbd/filename.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cc1c0a40b6..e12cfb1388 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,8 +26,7 @@ #include "includes.h" -static BOOL scan_directory(const char *path, char *name,size_t maxlength, - connection_struct *conn,BOOL docache); +static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength); /**************************************************************************** Check if two filenames are equal. @@ -282,10 +281,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (ms_has_wild(start) || - !scan_directory(dirpath, start, - sizeof(pstring) - 1 - (start - name), - conn, - end?True:False)) { + !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { if (end) { /* * An intermediate part of the name can't be found. @@ -450,8 +446,7 @@ BOOL check_name(pstring name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(const char *path, char *name, size_t maxlength, - connection_struct *conn,BOOL docache) +static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) { void *cur_dir; const char *dname; @@ -463,11 +458,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, if (*path == 0) path = "."; - if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - safe_strcpy(name, dname, maxlength); - return(True); - } - /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) @@ -505,8 +495,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - if (docache) - DirCacheAdd(path,name,dname,SNUM(conn)); safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); return(True); -- cgit From 3f9bc7fe07364af205741efcbfd3295fc4b81b46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 31 Aug 2004 22:52:05 +0000 Subject: r2152: Fix for bug #1674, move the symlinks checks into reduce_name(). Jeremy. (This used to be commit 341771857fecf9ef72a436c42e0571d486fa0dde) --- source3/smbd/filename.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index e12cfb1388..279c9dd3c4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -414,26 +414,10 @@ BOOL check_name(pstring name,connection_struct *conn) } } - if (!lp_widelinks(SNUM(conn))) { + if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { ret = reduce_name(conn,name); } - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc - University of Geneva */ - -#ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) { - SMB_STRUCT_STAT statbuf; - if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - errno = EACCES; - ret = False; - } - } -#endif - if (!ret) { DEBUG(5,("check_name on %s failed\n",name)); } -- cgit From de728fa81ae549b496f2ff26ebb082092aae2204 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jan 2005 21:01:58 +0000 Subject: r5063: Shamelessly steal the Samba4 logic (and some code :-) for directory evaluation. This stops us from reading the entire directory into memory at one go, and allows partial reads. It also keeps almost the same interface to the OpenDir/ReadDir etc. code (sorry James :-). Next I will optimise the findfirst with exact match code. This speeds up our interactive response for large directories, but not when a missing (ie. negative) findfirst is done. Jeremy (This used to be commit 0af1d2f6f24f238cb05e10d7d53dcd5b5e0f5f5d) --- source3/smbd/filename.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 279c9dd3c4..fa8ddfd6ca 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -435,6 +435,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name void *cur_dir; const char *dname; BOOL mangled; + long curpos; mangled = mangle_is_mangled(name); @@ -459,7 +460,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name } /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) { + curpos = 0; + while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { -- cgit From 784adfbcbb7f3e85b81b3df5a5c8823663bac8d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Feb 2005 00:28:20 +0000 Subject: r5152: Restructure the directory handling code, stop using void * pointers that just allow the wrong pointer to be assigned :-) and make the interface more consistent. Fix the FreeBSD directory problem. Last thing to do is to add the "singleton" directory concept from James Peach's code. Jeremy. (This used to be commit cfa8150fd9932470cb8f3b5e14c0156dda67125d) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fa8ddfd6ca..9af73776eb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -432,7 +432,7 @@ BOOL check_name(pstring name,connection_struct *conn) static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) { - void *cur_dir; + struct smb_Dir *cur_dir; const char *dname; BOOL mangled; long curpos; -- cgit From 021011f90030f6f4c39c9ef27db17eec5d4536ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Feb 2005 18:33:50 +0000 Subject: r5160: First cut at refactoring of directory code to handle non-wildcard directory match more efficiently. Passes RAW-SEARCH under valgrind but needs more testing (which I'll do later today :-). Jeremy. (This used to be commit 0b04dd9d0c6d1fe02d1b5e43f203577bf5466f33) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9af73776eb..c04b43b873 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -454,7 +454,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name mangled = !mangle_check_cache( name, maxlength ); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) { + if (!(cur_dir = OpenDir(conn, path))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } -- cgit From 91ef89daa03551fa17ff78adb9f36420057948da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Feb 2005 02:02:54 +0000 Subject: r5183: Ensure we correctly set the per-connection "case_sensitive" setting. Rename dptrs_open to the more correct dirhandles_open. Remove old #if 1. Jeremy. (This used to be commit c43bae306a18f5716acbe8571f4f414873400cb1) --- source3/smbd/filename.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index c04b43b873..8c484dd232 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,11 +150,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } -#if 1 if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) -#else - if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))) -#endif strnorm(name, lp_defaultcase(SNUM(conn))); start = name; -- cgit From cc5ba986bf4c7b704ae5c3787f2f3881145e719c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 01:19:58 +0000 Subject: r5792: Added new parameter "inherit owner". If set on a share, the created file/directory will be owned by the same uid as the containing directory. Doing this for directories in a race-free mannor has only been tested on Linux (it depends on being able to open a directory and then do a fchown on that file descriptor). If this functionality is not available then the code silently downgrades to not changing the ownership of a new directory. This new parameter (docs to follow) finally makes it possible to create "drop boxes" on Samba, which requires all files within a directory to be commonly owned. A HOWTO on how to use this will follow. Jeremy. (This used to be commit 2e1f727184b9d025d2e3413bdd3d01d5ca803a41) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8c484dd232..9ca2c0efae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -397,7 +397,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen a valid one for the user to access. ****************************************************************************/ -BOOL check_name(pstring name,connection_struct *conn) +BOOL check_name(const pstring name,connection_struct *conn) { BOOL ret = True; -- cgit From 02e3717ee9e045d197d845489e84ac40083ca868 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 08:07:39 +0000 Subject: r6625: Remove another global variable left over from a long time ago (magic char). Jeremy. (This used to be commit b1bfa9cb37deb22d1d08bc60ba44d61334f6446e) --- source3/smbd/filename.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9ca2c0efae..5f3cdfb77e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) + if (!conn->case_preserve || (mangle_is_8_3(name, False, SNUM(conn)) && !conn->short_case_preserve)) strnorm(name, lp_defaultcase(SNUM(conn))); start = name; @@ -179,7 +179,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name) && !*lp_mangled_map(SNUM(conn))) + if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn))) return(False); name_has_wildcard = ms_has_wild(start); @@ -189,7 +189,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if (mangle_is_mangled(start)) + if (mangle_is_mangled(start, SNUM(conn))) component_was_mangled = True; /* @@ -317,7 +317,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (mangle_is_mangled(start)) { + if (mangle_is_mangled(start, SNUM(conn))) { mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); } @@ -433,7 +433,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name BOOL mangled; long curpos; - mangled = mangle_is_mangled(name); + mangled = mangle_is_mangled(name, SNUM(conn)); /* handle null paths */ if (*path == 0) -- cgit From 5622d96cd674bd63ec86db971531f2088e32842f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 10:55:56 +0000 Subject: r6631: More typo's. Sorry. Jeremy. (This used to be commit 2673ccd19f194d1f7756a154afe4200e386ca1b3) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5f3cdfb77e..7191e75715 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -318,7 +318,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (mangle_is_mangled(start, SNUM(conn))) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn)); } DEBUG(5,("New file %s\n",start)); @@ -447,7 +447,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * (JRA). */ if (mangled) - mangled = !mangle_check_cache( name, maxlength ); + mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); /* open the directory */ if (!(cur_dir = OpenDir(conn, path))) { -- cgit From ed5e7ff9f184fd36b4344c958f145cc4a4987c71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jun 2005 23:18:52 +0000 Subject: r7200: Don't use memset, use SET_STAT_INVALID (has the same effect). Jeremy. (This used to be commit 0b6f87d5e14da461bd2b1c3a4e6f47a69d2cd1c4) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7191e75715..733001bc91 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -92,7 +92,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL component_was_mangled = False; BOOL name_has_wildcard = False; - ZERO_STRUCTP(pst); + SET_STAT_INVALID(pst); *dirpath = 0; *bad_path = False; @@ -258,7 +258,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstring rest; /* Stat failed - ensure we don't use it. */ - ZERO_STRUCT(st); + SET_STAT_INVALID(st); *rest = 0; /* @@ -346,7 +346,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (SMB_VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { - ZERO_STRUCT(st); + SET_STAT_INVALID(st); } } } /* end else */ -- cgit From 0deab47cc6f17e597430130df66f7acf8842ff30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Jun 2005 05:35:04 +0000 Subject: r7210: Fix my own mistakes up, sorry. Jeremy. (This used to be commit 53c3a954ee0e1c9dc61950f1a9d0a654de9382c6) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 733001bc91..3fb88974fe 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -92,7 +92,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL component_was_mangled = False; BOOL name_has_wildcard = False; - SET_STAT_INVALID(pst); + SET_STAT_INVALID(*pst); *dirpath = 0; *bad_path = False; -- cgit From ff7e5c26733c933d0ed71616c39e2d931ad1e597 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Jun 2005 03:03:44 +0000 Subject: r7893: Add in the extra parameters to opendir() to fix the large directory/insane app problem. Rev vfs version. Doesn't change the normal codepath. Jeremy. (This used to be commit 0f03a6bdcdbdf60da81e0aeffa84ac6e48fc6a04) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3fb88974fe..f0a33e568e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -450,7 +450,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path))) { + if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } -- cgit From f9b750542933cb60eca7da335193c36361496622 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Oct 2005 01:42:03 +0000 Subject: r11346: Fix for bug found by Dina Fine. If in case sensitive mode then the mangle cache is no good (3 letter extension could be wrong case - so don't demangle in this case - leave as mangled and allow the mangling of the directory entry read (which is done case insensitively) to match instead. This will lead to more false positive matches but we fail completely without it. Jeremy. (This used to be commit 238b35d2e6e21d0e07d500d446f08ec128ea7720) --- source3/smbd/filename.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f0a33e568e..b389b9c1ae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -445,9 +445,18 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * read from the directory and then mangled by the mangle_map() * call. We need to mangle both names or neither. * (JRA). + * + * Fix for bug found by Dina Fine. If in case sensitive mode then + * the mangle cache is no good (3 letter extension could be wrong + * case - so don't demangle in this case - leave as mangled and + * allow the mangling of the directory entry read (which is done + * case insensitively) to match instead. This will lead to more + * false positive matches but we fail completely without it. JRA. */ - if (mangled) + + if (mangled && !conn->case_sensitive) { mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); + } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { -- cgit From 056f06915e9c667393046a674581754d8a581d29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Nov 2005 16:21:52 +0000 Subject: r11861: Fix inspired by Thomas Neumann to ensure that default case applies only to new files and correctly examines 8.3 and long names. Jeremy. (This used to be commit ba931a015132f7e8fffa52c617cd8345a1da35d2) --- source3/smbd/filename.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b389b9c1ae..2ee8ba1e4f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,9 +150,6 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!conn->case_preserve || (mangle_is_8_3(name, False, SNUM(conn)) && !conn->short_case_preserve)) - strnorm(name, lp_defaultcase(SNUM(conn))); - start = name; pstrcpy(orig_path, name); @@ -301,16 +298,17 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } - /* + /* * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case - * this conversion is being used for file creation - * purposes. If the filename is of mixed case then - * don't normalise it. + * We need to strupper() or strlower() it as + * this conversion may be used for file creation + * purposes. Fix inspired by Thomas Neumann . */ - - if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start))) + if (!conn->case_preserve || + (mangle_is_8_3(start, False, SNUM(conn)) && + !conn->short_case_preserve)) { strnorm(start, lp_defaultcase(SNUM(conn))); + } /* * check on the mangled stack to see if we can recover the -- cgit From defe1f3aa8ada898b158836993d8dc98c7cc3b76 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Nov 2005 20:14:07 +0000 Subject: r11945: Make us follow the newly documented pathname processing rules: "As a special case for directories with large numbers of files, if the case options are set as follows, "case sensitive = yes", "case preserve = no", "short preserve case = no" then the "default case" option will be applied and will modify all filenames sent from the client when accessing this share." This is needed as fixing the case preserve rules to only apply to new filenames broke the large directory fix. Glad we caught this before release. Thanks to jht for this one. Jeremy. (This used to be commit abc21cc7322d695cf77b6fb18f4ecdb16288c19b) --- source3/smbd/filename.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2ee8ba1e4f..6c0f8b7758 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,6 +150,19 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } + /* + * Large directory fix normalization. If we're case sensitive, and + * the case preserving parameters are set to "no", normalize the case of + * the incoming filename from the client WHETHER IT EXISTS OR NOT ! + * This is in conflict with the current (3.0.20) man page, but is + * what people expect from the "large directory howto". I'll update + * the man page. Thanks to jht@samba.org for finding this. JRA. + */ + + if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { + strnorm(name, lp_defaultcase(SNUM(conn))); + } + start = name; pstrcpy(orig_path, name); -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/filename.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6c0f8b7758..1ea5228e91 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -46,12 +46,13 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitiv Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, const char *name2, int snum) +static BOOL mangled_equal(const char *name1, const char *name2, + const struct share_params *p) { pstring tmpname; pstrcpy(tmpname, name2); - mangle_map(tmpname, True, False, snum); + mangle_map(tmpname, True, False, p); return strequal(name1, tmpname); } @@ -189,7 +190,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn))) + if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && + !*lp_mangled_map(conn->params)) return(False); name_has_wildcard = ms_has_wild(start); @@ -199,7 +201,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if (mangle_is_mangled(start, SNUM(conn))) + if (mangle_is_mangled(start, conn->params)) component_was_mangled = True; /* @@ -318,7 +320,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * purposes. Fix inspired by Thomas Neumann . */ if (!conn->case_preserve || - (mangle_is_8_3(start, False, SNUM(conn)) && + (mangle_is_8_3(start, False, conn->params) && !conn->short_case_preserve)) { strnorm(start, lp_defaultcase(SNUM(conn))); } @@ -328,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (mangle_is_mangled(start, SNUM(conn))) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn)); + if (mangle_is_mangled(start, conn->params)) { + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); } DEBUG(5,("New file %s\n",start)); @@ -444,7 +446,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name BOOL mangled; long curpos; - mangled = mangle_is_mangled(name, SNUM(conn)); + mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ if (*path == 0) @@ -466,7 +468,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); + mangled = !mangle_check_cache( name, maxlength, conn->params); } /* open the directory */ @@ -495,7 +497,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { + if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); -- cgit From db0ad252a0622dfac17d44ca646168df4c1c22e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Jan 2007 23:47:16 +0000 Subject: r20718: Sync up the filename path parsing changes from SAMBA_3_0_24. The only difference between the two trees now w.r.t file serving are the changes to smbd/open.c in this branch I need to review. Jeremy. (This used to be commit f4474edf6a0c71001dbd01429ef70bafad6abd74) --- source3/smbd/filename.c | 160 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 41 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1ea5228e91..3f02f6090f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -64,18 +64,20 @@ changes etc. We assume that we have already done a chdir() to the right "root" directory for this service. -The function will return False if some part of the name except for the last -part cannot be resolved +The function will return an NTSTATUS error if some part of the name except for the last +part cannot be resolved, else NT_STATUS_OK. + +Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't +get any fatal errors that should immediately terminate the calling +SMB processing whilst resolving. If the saved_last_component != 0, then the unmodified last component of the pathname is returned there. This is used in an exceptional case in reply_mv (so far). If saved_last_component == 0 then nothing is returned there. -The bad_path arg is set to True if the filename walk failed. This is -used to pick the correct error code to return between ENOENT and ENOTDIR -as Windows applications depend on ERRbadpath being returned if a component -of a pathname does not exist. +If last_component_wcard is true then a MS wildcard was detected and +should be allowed in the last component of the path only. On exit from unix_convert, if *pst was not null, then the file stat struct will be returned if the file exists and was found, if not this @@ -83,8 +85,11 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) +NTSTATUS unix_convert(connection_struct *conn, + pstring name, + BOOL allow_wcard_last_component, + char *saved_last_component, + SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; @@ -96,14 +101,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen SET_STAT_INVALID(*pst); *dirpath = 0; - *bad_path = False; - if(saved_last_component) + + if(saved_last_component) { *saved_last_component = 0; + } if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ - return True; + return NT_STATUS_OK; } DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); @@ -136,7 +142,12 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen *pst = st; } DEBUG(5,("conversion finished \"\" -> %s\n",name)); - return(True); + return NT_STATUS_OK; + } + + if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { + /* Start of pathname can't be "." only. */ + return NT_STATUS_OBJECT_NAME_INVALID; } /* @@ -145,10 +156,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(saved_last_component) { end = strrchr_m(name, '/'); - if(end) + if (end) { pstrcpy(saved_last_component, end + 1); - else + } else { pstrcpy(saved_last_component, name); + } } /* @@ -169,7 +181,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; - return True; + return NT_STATUS_OK; } /* @@ -177,10 +189,22 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (SMB_VFS_STAT(conn,name,&st) == 0) { + /* Ensure we catch all names with in "/." + this is disallowed under Windows. */ + const char *p = strstr(name, "/."); /* mb safe. */ + if (p) { + if (p[2] == '/') { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else if (p[2] == '\0') { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } + } stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; - return(True); + return NT_STATUS_OK; } DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); @@ -190,19 +214,20 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && - !*lp_mangled_map(conn->params)) - return(False); - - name_has_wildcard = ms_has_wild(start); + if (conn->case_sensitive && + !mangle_is_mangled(name, conn->params) && + !*lp_mangled_map(conn->params)) { + return NT_STATUS_OK; + } /* * is_mangled() was changed to look at an entire pathname, not * just a component. JRA. */ - if (mangle_is_mangled(start, conn->params)) + if (mangle_is_mangled(start, conn->params)) { component_was_mangled = True; + } /* * Now we need to recursively match the name against the real @@ -218,16 +243,64 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * Pinpoint the end of this section of the filename. */ - end = strchr_m(start, '/'); + end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ /* * Chop the name at this point. */ - if (end) + if (end) { *end = 0; + } - if(saved_last_component != 0) + if (saved_last_component != 0) { pstrcpy(saved_last_component, end ? end + 1 : start); + } + + /* The name cannot have a component of "." */ + + if (ISDOT(start)) { + if (end) { + if (allow_wcard_last_component) { + /* We're terminating here so we + * can be a little slower and get + * the error code right. Windows + * treats the last part of the pathname + * separately I think, so if the last + * component is a wildcard then we treat + * this ./ as "end of component" */ + + const char *p = strchr(end+1, '/'); + + if (!p && ms_has_wild(end+1)) { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* The name cannot have a wildcard if it's not + the last component. */ + + name_has_wildcard = ms_has_wild(start); + + /* Wildcard not valid anywhere. */ + if (name_has_wildcard && !allow_wcard_last_component) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + + /* Wildcards never valid within a pathname. */ + if (name_has_wildcard && end) { + return NT_STATUS_OBJECT_NAME_INVALID; + } /* * Check if the name exists up to this point. @@ -251,9 +324,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Windows applications depend on the difference between * these two errors. */ - errno = ENOTDIR; - *bad_path = True; - return(False); + return NT_STATUS_OBJECT_PATH_NOT_FOUND; } if (!end) { @@ -278,8 +349,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * later. */ - if (end) + if (end) { pstrcpy(rest,end+1); + } /* Reset errno so we can detect directory open errors. */ errno = 0; @@ -288,7 +360,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || + if (name_has_wildcard || !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { if (end) { /* @@ -304,13 +376,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Windows applications depend on the difference between * these two errors. */ - *bad_path = True; - return(False); + if (errno == ENOENT) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + return map_nt_error_from_unix(errno); } if (errno == ENOTDIR) { - *bad_path = True; - return(False); + /* Name exists but is not a directory. */ + return map_nt_error_from_unix(ENOTDIR); } /* @@ -335,7 +409,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen } DEBUG(5,("New file %s\n",start)); - return(True); + return NT_STATUS_OK; } /* @@ -346,7 +420,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen end = start + strlen(start); if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { - return False; + return map_nt_error_from_unix(ENAMETOOLONG); } *end = '\0'; } else { @@ -367,8 +441,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) + if (*dirpath) { pstrcat(dirpath,"/"); + } pstrcat(dirpath,start); @@ -377,14 +452,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * as this can change the size. */ - if(!component_was_mangled && !name_has_wildcard) + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, dirpath, conn->case_sensitive); + } /* * Restore the / that we wiped out earlier. */ - if (end) + if (end) { *end = '/'; + } } /* @@ -392,15 +469,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * as this can change the size. */ - if(!component_was_mangled && !name_has_wildcard) + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, name, conn->case_sensitive); + } /* * The name has been resolved. */ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return(True); + return NT_STATUS_OK; } /**************************************************************************** -- cgit From 1a40a6e08a58d02e912aaa9f81dcff48477f3b81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 01:07:39 +0000 Subject: r20720: Fix the chkpath problem, still looking at findfirst. Jeremy. (This used to be commit c5be0082ef60cd041121a9c36f4af934cd60562d) --- source3/smbd/filename.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3f02f6090f..44916200da 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -147,7 +147,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { /* Start of pathname can't be "." only. */ - return NT_STATUS_OBJECT_NAME_INVALID; + if (name[1] == '\0' || name[2] == '\0') { + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Longer pathname starts with ./ */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } } /* -- cgit From dd5e9e2ae7ba3c4f3d4d8e02c7a993dd8e164c5b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 01:29:10 +0000 Subject: r20721: Fix the search unix_convert error returns. Only open to go... Jeremy. (This used to be commit 89f03a8db40365f99c6755ff19a4bfbf8d1bd316) --- source3/smbd/filename.c | 60 ++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 44916200da..dd1e0de20f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -56,6 +56,38 @@ static BOOL mangled_equal(const char *name1, const char *name2, return strequal(name1, tmpname); } +/**************************************************************************** + Cope with the differing wildcard and non-wildcard error cases. +****************************************************************************/ + +static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component) +{ + const char *p; + + if (!allow_wcard_last_component) { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* We're terminating here so we + * can be a little slower and get + * the error code right. Windows + * treats the last part of the pathname + * separately I think, so if the last + * component is a wildcard then we treat + * this ./ as "end of component" */ + + p = strchr(name, '/'); + + if (!p && (ms_has_wild(name) || ISDOT(name))) { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -150,8 +182,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (name[1] == '\0' || name[2] == '\0') { return NT_STATUS_OBJECT_NAME_INVALID; } else { - /* Longer pathname starts with ./ */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + return determine_path_error(&name[2], allow_wcard_last_component); } } @@ -264,32 +295,11 @@ NTSTATUS unix_convert(connection_struct *conn, /* The name cannot have a component of "." */ if (ISDOT(start)) { - if (end) { - if (allow_wcard_last_component) { - /* We're terminating here so we - * can be a little slower and get - * the error code right. Windows - * treats the last part of the pathname - * separately I think, so if the last - * component is a wildcard then we treat - * this ./ as "end of component" */ - - const char *p = strchr(end+1, '/'); - - if (!p && ms_has_wild(end+1)) { - /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; - } else { - /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } - /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { + if (!end) { /* Error code at the end of a pathname. */ return NT_STATUS_OBJECT_NAME_INVALID; } + return determine_path_error(end+1, allow_wcard_last_component); } /* The name cannot have a wildcard if it's not -- cgit From 50b3dacb525d026dd7d280948d8a63075756d029 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 02:13:45 +0000 Subject: r20722: RAW-CHKPATH should now pass, build farm should go back to normal. Sorry about that. Jeremy. (This used to be commit d4127034fb89185fe7464d57c9f56f7914da6141) --- source3/smbd/filename.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index dd1e0de20f..a36b7ff282 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -391,15 +391,24 @@ NTSTATUS unix_convert(connection_struct *conn, * Windows applications depend on the difference between * these two errors. */ - if (errno == ENOENT) { + + /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND + in the filename walk. */ + + if (errno == ENOENT || errno == ENOTDIR) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } return map_nt_error_from_unix(errno); } - if (errno == ENOTDIR) { - /* Name exists but is not a directory. */ - return map_nt_error_from_unix(ENOTDIR); + /* ENOENT is the only valid error here. */ + if (errno != ENOENT) { + /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND + in the filename walk. */ + if (errno == ENOTDIR) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + return map_nt_error_from_unix(errno); } /* -- cgit From 83eb0d1d6d90d182e8eee8496695113c89f8dba1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Jan 2007 02:09:37 +0000 Subject: r20844: Somewhat radical change - this may break the build (I will watch carefully - so I'm doing it in one transaction so I can roll back). Change check_name(), reduce_name() and dptr_create() to return NTSTATUS. This helps a lot in error path processing and especially in reduce_name() allows us to ditch the flaky and error-prone saving of errno and return errors directly. Jeremy. (This used to be commit 6133a694aa429d638320e39ffe1c49d172583ccf) --- source3/smbd/filename.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a36b7ff282..b69d2f3e5e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -512,28 +512,25 @@ NTSTATUS unix_convert(connection_struct *conn, a valid one for the user to access. ****************************************************************************/ -BOOL check_name(const pstring name,connection_struct *conn) +NTSTATUS check_name(connection_struct *conn, const pstring name) { - BOOL ret = True; - if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { - DEBUG(5,("file path name %s vetoed\n",name)); - errno = ENOENT; - return False; + DEBUG(5,("check_name: file path name %s vetoed\n",name)); + return map_nt_error_from_unix(ENOENT); } } if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { - ret = reduce_name(conn,name); - } - - if (!ret) { - DEBUG(5,("check_name on %s failed\n",name)); + NTSTATUS status = reduce_name(conn,name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); + return status; + } } - return(ret); + return NT_STATUS_OK; } /**************************************************************************** -- cgit From aacd16e7c4bea5018560eea09d55f2a6473be84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Jan 2007 21:46:12 +0000 Subject: r20916: Add in the delete on close final fix - but only enabled with -DDEVELOPER. Jeremy. (This used to be commit 7f817067a70930ee3502ea3373173e0c23733253) --- source3/smbd/filename.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b69d2f3e5e..eb86a0efd1 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -462,6 +462,12 @@ NTSTATUS unix_convert(connection_struct *conn, } } /* end else */ +#ifdef DEVELOPER + if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { + return NT_STATUS_DELETE_PENDING; + } +#endif + /* * Add to the dirpath that we have resolved so far. */ -- cgit From e8156439f24137b5418baad20a7f00f6949cfe29 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 09:30:34 +0000 Subject: r23183: Check in a change made by Tridge: This replaces the internal explicit dev/ino file id representation by a "struct file_id". This is necessary as cluster file systems and NFS don't necessarily assign the same device number to the shared file system. With this structure in place we can now easily add different schemes to map a file to a unique 64-bit device node. Jeremy, you might note that I did not change the external interface of smb_share_modes.c. Volker (This used to be commit 9b10dbbd5de8813fc15ebbb6be9b18010ffe8139) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index eb86a0efd1..c26eba2ded 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -463,7 +463,7 @@ NTSTATUS unix_convert(connection_struct *conn, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { + if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { return NT_STATUS_DELETE_PENDING; } #endif -- cgit From ead70dc92e16a79cd7767dbc9f727bc530925abd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 09:43:41 +0000 Subject: r23761: Rename reduce_name to check_reduced_name The function name reduce_name is misleading, making the user believe it changes an argument. (This used to be commit 68234f0bc6fb4d6d99ae94ff067db118c60804aa) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index c26eba2ded..de15d923b8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -512,7 +512,7 @@ NTSTATUS unix_convert(connection_struct *conn, } /**************************************************************************** - Check a filename - possibly caling reducename. + Check a filename - possibly calling check_reduced_name. This is called by every routine before it allows an operation on a filename. It does any final confirmation necessary to ensure that the filename is a valid one for the user to access. @@ -529,7 +529,7 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) } if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { - NTSTATUS status = reduce_name(conn,name); + NTSTATUS status = check_reduced_name(conn,name); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); return status; -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index de15d923b8..b7470aa902 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -7,7 +7,7 @@ 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, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/filename.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b7470aa902..737ed5a89c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -16,8 +16,7 @@ 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 . */ /* -- cgit From f01698027d15ca546d9a92c799d0cad18a625789 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 22:39:11 +0000 Subject: r23844: Add patch series from Volker (after review and consultation). 0001-Save-a-strdup-in-stat_cache_add.patch 0002-Use-ISDOT-and-ISDOTDOT.patch 0003-Move-fname_equal-around.patch 0004-unix_convert-pstring-dirpath-char.patch 0005-Ignore-.o-files.patch 0006-Get-rid-of-pstrings-inside-unix_convert.patch 0007-revert-pstring-unix_convert.patch 0008-Make-name-an-allocated-pstring-inside-unix_convert.patch 0009-Pass-explicit-pstring-to-mangle_check_cache.patch 0010-Don-t-overwrite-orig_path-unnecessarily.patch 0011-Defer-allocating-name.patch 0012-Make-sure-dirpath-is-always-correctly-allocated.patch 0013-Remove-one-pstring-dependency-in-unix_convert.patch 0014-Remove-more-name-pstring-dependencies.patch 0015-Hide-the-nasty-API-of-mangle_check_cache-in-mangle_c.patch 0016-name-does-not-need-to-be-pstring-size-anymore.patch 0017-Make-use-of-ISDOT-and-ISDOTDOT.patch 0018-Remove-pstring-from-stat_cache_lookup.patch 0019-Add-my-copyright.patch To remove pstrings from statcache and unix_convert. Jeremy. (This used to be commit ea6ef368891af24164d2e76700c405a82b3dfc19) --- source3/smbd/filename.c | 306 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 207 insertions(+), 99 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 737ed5a89c..fd7727c594 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 + Copyright (C) Volker Lendecke 2007 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 @@ -25,21 +26,8 @@ #include "includes.h" -static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength); - -/**************************************************************************** - Check if two filenames are equal. - This needs to be careful about whether we are case sensitive. -****************************************************************************/ - -static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) -{ - /* Normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} +static BOOL scan_directory(connection_struct *conn, const char *path, + char *name, char **found_name); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. @@ -117,22 +105,21 @@ for nlinks = 0, which can never be true for any file). ****************************************************************************/ NTSTATUS unix_convert(connection_struct *conn, - pstring name, + pstring orig_path, BOOL allow_wcard_last_component, - char *saved_last_component, + char *saved_last_component, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; - pstring dirpath; - pstring orig_path; + char *dirpath = NULL; + char *name = NULL; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; + NTSTATUS result; SET_STAT_INVALID(*pst); - *dirpath = 0; - if(saved_last_component) { *saved_last_component = 0; } @@ -143,19 +130,19 @@ NTSTATUS unix_convert(connection_struct *conn, return NT_STATUS_OK; } - DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path)); - /* + /* * Conversion to basic unix format is already done in check_path_syntax(). */ - /* + /* * Names must be relative to the root of the service - any leading /. * and trailing /'s should have been trimmed by check_path_syntax(). */ #ifdef DEVELOPER - SMB_ASSERT(*name != '/'); + SMB_ASSERT(*orig_path != '/'); #endif /* @@ -166,23 +153,27 @@ NTSTATUS unix_convert(connection_struct *conn, * As we know this is valid we can return true here. */ - if (!*name) { - name[0] = '.'; - name[1] = '\0'; + if (!*orig_path) { + if (!(name = SMB_STRDUP("."))) { + result = NT_STATUS_NO_MEMORY; + goto fail; + } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; } DEBUG(5,("conversion finished \"\" -> %s\n",name)); - return NT_STATUS_OK; + goto done; } - if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { + if (orig_path[0] == '.' && (orig_path[1] == '/' || orig_path[1] == '\0')) { /* Start of pathname can't be "." only. */ - if (name[1] == '\0' || name[2] == '\0') { - return NT_STATUS_OBJECT_NAME_INVALID; + if (orig_path[1] == '\0' || orig_path[2] == '\0') { + result = NT_STATUS_OBJECT_NAME_INVALID; } else { - return determine_path_error(&name[2], allow_wcard_last_component); + result =determine_path_error( + &orig_path[2], allow_wcard_last_component); } + goto fail; } /* @@ -190,14 +181,19 @@ NTSTATUS unix_convert(connection_struct *conn, */ if(saved_last_component) { - end = strrchr_m(name, '/'); + end = strrchr_m(orig_path, '/'); if (end) { pstrcpy(saved_last_component, end + 1); } else { - pstrcpy(saved_last_component, name); + pstrcpy(saved_last_component, orig_path); } } + if (!(name = SMB_STRDUP(orig_path))) { + DEBUG(0, ("strdup failed\n")); + return NT_STATUS_NO_MEMORY; + } + /* * Large directory fix normalization. If we're case sensitive, and * the case preserving parameters are set to "no", normalize the case of @@ -210,16 +206,27 @@ NTSTATUS unix_convert(connection_struct *conn, if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { strnorm(name, lp_defaultcase(SNUM(conn))); } - + start = name; - pstrcpy(orig_path, name); - if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!conn->case_sensitive + && stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { *pst = st; - return NT_STATUS_OK; + goto done; + } + + /* + * Make sure "dirpath" is an allocated string, we use this for + * building the directories with asprintf and free it. + */ + + if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { + DEBUG(0, ("strdup failed\n")); + result = NT_STATUS_NO_MEMORY; + goto fail; } - /* + /* * stat the name - if it exists then we are all done! */ @@ -239,24 +246,24 @@ NTSTATUS unix_convert(connection_struct *conn, stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; - return NT_STATUS_OK; + goto done; } DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); - /* + /* * A special case - if we don't have any mangling chars and are case * sensitive then searching won't help. */ - if (conn->case_sensitive && + if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && !*lp_mangled_map(conn->params)) { - return NT_STATUS_OK; + goto done; } - /* - * is_mangled() was changed to look at an entire pathname, not + /* + * is_mangled() was changed to look at an entire pathname, not * just a component. JRA. */ @@ -264,23 +271,23 @@ NTSTATUS unix_convert(connection_struct *conn, component_was_mangled = True; } - /* - * Now we need to recursively match the name against the real + /* + * Now we need to recursively match the name against the real * directory structure. */ - /* + /* * Match each part of the path name separately, trying the names * as is first, then trying to scan the directory for matching names. */ for (; start ; start = (end?end+1:(char *)NULL)) { - /* + /* * Pinpoint the end of this section of the filename. */ end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ - /* + /* * Chop the name at this point. */ if (end) { @@ -296,9 +303,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (ISDOT(start)) { if (!end) { /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + } else { + result = determine_path_error(end+1, + allow_wcard_last_component); } - return determine_path_error(end+1, allow_wcard_last_component); + goto fail; } /* The name cannot have a wildcard if it's not @@ -308,15 +318,17 @@ NTSTATUS unix_convert(connection_struct *conn, /* Wildcard not valid anywhere. */ if (name_has_wildcard && !allow_wcard_last_component) { - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } /* Wildcards never valid within a pathname. */ if (name_has_wildcard && end) { - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } - /* + /* * Check if the name exists up to this point. */ @@ -331,14 +343,15 @@ NTSTATUS unix_convert(connection_struct *conn, */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; - /* + /* * We need to return the fact that the intermediate * name resolution failed. This is used to return an * error of ERRbadpath rather than ERRbadfile. Some * Windows applications depend on the difference between * these two errors. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; } if (!end) { @@ -352,20 +365,10 @@ NTSTATUS unix_convert(connection_struct *conn, } } else { - pstring rest; + char *found_name = NULL; /* Stat failed - ensure we don't use it. */ SET_STAT_INVALID(st); - *rest = 0; - - /* - * Remember the rest of the pathname so it can be restored - * later. - */ - - if (end) { - pstrcpy(rest,end+1); - } /* Reset errno so we can detect directory open errors. */ errno = 0; @@ -375,7 +378,9 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (name_has_wildcard || - !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { + !scan_directory(conn, dirpath, start, &found_name)) { + char *unmangled; + if (end) { /* * An intermediate part of the name can't be found. @@ -383,7 +388,7 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("Intermediate not found %s\n",start)); *end = '/'; - /* + /* * We need to return the fact that the intermediate * name resolution failed. This is used to return an * error of ERRbadpath rather than ERRbadfile. Some @@ -395,19 +400,25 @@ NTSTATUS unix_convert(connection_struct *conn, in the filename walk. */ if (errno == ENOENT || errno == ENOTDIR) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + else { + result = map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + goto fail; } - + /* ENOENT is the only valid error here. */ if (errno != ENOENT) { /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND in the filename walk. */ if (errno == ENOTDIR) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + else { + result = map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + goto fail; } /* @@ -427,26 +438,79 @@ NTSTATUS unix_convert(connection_struct *conn, * base of the filename. */ - if (mangle_is_mangled(start, conn->params)) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); + if (mangle_is_mangled(start, conn->params) + && mangle_check_cache_alloc(start, &unmangled, + conn->params)) { + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s", dirpath, + unmangled); + SAFE_FREE(unmangled); + } + else { + tmp = unmangled; + } + if (tmp == NULL) { + DEBUG(0, ("malloc failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + end = start + strlen(start); } DEBUG(5,("New file %s\n",start)); - return NT_STATUS_OK; + goto done; } - /* + + /* * Restore the rest of the string. If the string was mangled the size * may have changed. */ if (end) { - end = start + strlen(start); - if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || - !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { - return map_nt_error_from_unix(ENAMETOOLONG); + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s/%s", dirpath, + found_name, end+1); } + else { + asprintf(&tmp, "%s/%s", found_name, + end+1); + } + if (tmp == NULL) { + DEBUG(0, ("asprintf failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + end = start + strlen(found_name); *end = '\0'; } else { + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s", dirpath, + found_name); + } + else { + tmp = SMB_STRDUP(found_name); + } + if (tmp == NULL) { + DEBUG(0, ("malloc failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + /* * We just scanned for, and found the end of the path. * We must return a valid stat struct if it exists. @@ -459,40 +523,56 @@ NTSTATUS unix_convert(connection_struct *conn, SET_STAT_INVALID(st); } } + + SAFE_FREE(found_name); } /* end else */ #ifdef DEVELOPER if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { - return NT_STATUS_DELETE_PENDING; + result = NT_STATUS_DELETE_PENDING; + goto fail; } #endif /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) { - pstrcat(dirpath,"/"); - } - pstrcat(dirpath,start); + if (*dirpath != '\0') { + char *tmp; + + if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) { + DEBUG(0, ("asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + SAFE_FREE(dirpath); + dirpath = tmp; + } + else { + SAFE_FREE(dirpath); + if (!(dirpath = SMB_STRDUP(start))) { + DEBUG(0, ("strdup failed\n")); + return NT_STATUS_NO_MEMORY; + } + } /* * Don't cache a name with mangled or wildcard components * as this can change the size. */ - + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, dirpath, conn->case_sensitive); } - - /* + + /* * Restore the / that we wiped out earlier. */ if (end) { *end = '/'; } } - + /* * Don't cache a name with mangled or wildcard components * as this can change the size. @@ -502,12 +582,19 @@ NTSTATUS unix_convert(connection_struct *conn, stat_cache_add(orig_path, name, conn->case_sensitive); } - /* + /* * The name has been resolved. */ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return NT_STATUS_OK; + + done: + result = NT_STATUS_OK; + pstrcpy(orig_path, name); + fail: + SAFE_FREE(name); + SAFE_FREE(dirpath); + return result; } /**************************************************************************** @@ -538,22 +625,38 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) return NT_STATUS_OK; } +/**************************************************************************** + Check if two filenames are equal. + This needs to be careful about whether we are case sensitive. +****************************************************************************/ + +static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) +{ + /* Normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + + return(strequal(name1,name2)); +} + /**************************************************************************** Scan a directory to find a filename, matching without case sensitivity. If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) +static BOOL scan_directory(connection_struct *conn, const char *path, + char *name, char **found_name) { struct smb_Dir *cur_dir; const char *dname; BOOL mangled; + char *unmangled_name = NULL; long curpos; mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ - if (*path == 0) + if ((path == NULL) || (*path == 0)) path = "."; /* @@ -572,12 +675,15 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache( name, maxlength, conn->params); + mangled = !mangle_check_cache_alloc(name, &unmangled_name, + conn->params); + name = unmangled_name; } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + SAFE_FREE(unmangled_name); return(False); } @@ -603,12 +709,14 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - safe_strcpy(name, dname, maxlength); + *found_name = SMB_STRDUP(dname); + SAFE_FREE(unmangled_name); CloseDir(cur_dir); return(True); } } + SAFE_FREE(unmangled_name); CloseDir(cur_dir); errno = ENOENT; return(False); -- cgit From b114d3dc70a631f41c9d6e0e05b0ed98baa9d815 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 23:54:01 +0000 Subject: r23846: Belt-and-braces on the msdfs bug. Ensure ELOOP maps correctly. Jeremy. (This used to be commit f2cf4b6b9d1ce561fdf9f6815564d5b4f033dd10) --- source3/smbd/filename.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fd7727c594..cf6613aa71 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -396,10 +396,15 @@ NTSTATUS unix_convert(connection_struct *conn, * these two errors. */ - /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND - in the filename walk. */ + /* + * ENOENT, ENOTDIR and ELOOP all map + * to NT_STATUS_OBJECT_PATH_NOT_FOUND + * in the filename walk. + */ - if (errno == ENOENT || errno == ENOTDIR) { + if (errno == ENOENT || + errno == ENOTDIR || + errno == ELOOP) { result = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { @@ -410,9 +415,13 @@ NTSTATUS unix_convert(connection_struct *conn, /* ENOENT is the only valid error here. */ if (errno != ENOENT) { - /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND - in the filename walk. */ - if (errno == ENOTDIR) { + /* + * ENOTDIR and ELOOP both map to + * NT_STATUS_OBJECT_PATH_NOT_FOUND + * in the filename walk. + */ + if (errno == ENOTDIR || + errno == ELOOP) { result = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { -- cgit From e84f8662e6af515aba5db7ffd874ad5da97188bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jul 2007 09:40:00 +0000 Subject: r23878: Fix an error return, found by the IBM checker (This used to be commit a369c67f6678bdcc0689929238bc96f45cdeeb25) --- source3/smbd/filename.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cf6613aa71..824c32867a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -515,6 +515,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (tmp == NULL) { DEBUG(0, ("malloc failed\n")); result = NT_STATUS_NO_MEMORY; + goto fail; } SAFE_FREE(name); name = tmp; -- cgit From d537225c4c467e8bda6e8f45b69a64c16c5ecb58 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jul 2007 09:42:43 +0000 Subject: r23879: Fix two memleaks, found by the IBM checker (This used to be commit 4d1b33f51308c95293fa2494b47ba1255af8d216) --- source3/smbd/filename.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 824c32867a..a1b56736a0 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -237,10 +237,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (p) { if (p[2] == '/') { /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; } else if (p[2] == '\0') { /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } } stat_cache_add(orig_path, name, conn->case_sensitive); -- cgit From 4b15f31f106f1dd69fdda721b5c3b787f5245a80 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Aug 2007 08:53:24 +0000 Subject: r24120: add a file_id_create() hook into the VFS layer it's needed for some cluster filesystems to overload this function. metze (This used to be commit cdaa24e8047399002e4b287a31a8340a665e580f) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a1b56736a0..d5c22e81c3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -540,7 +540,8 @@ NTSTATUS unix_convert(connection_struct *conn, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { + if (VALID_STAT(st) && + get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, &st))) { result = NT_STATUS_DELETE_PENDING; goto fail; } -- cgit From 93fc3a024820bd4a01565b301d37b0e4106500ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 16 Aug 2007 12:15:52 +0000 Subject: r24485: Even in the failure case unix_convert must pass the already converted part of the string to the caller. (This used to be commit 301ae3d68bc64c9526eb7d4458584a5ebb151137) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d5c22e81c3..6ab179a316 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -603,8 +603,8 @@ NTSTATUS unix_convert(connection_struct *conn, done: result = NT_STATUS_OK; - pstrcpy(orig_path, name); fail: + pstrcpy(orig_path, name); SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From bcc7bdcfe38673ab9a409b94d525ca5c09e0e591 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 16 Aug 2007 15:44:13 +0000 Subject: r24497: Revert r24485 -- this needs more thought (This used to be commit 01f701ba1ea9859b090aaf8f4ae9722c5502316c) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6ab179a316..d5c22e81c3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -603,8 +603,8 @@ NTSTATUS unix_convert(connection_struct *conn, done: result = NT_STATUS_OK; - fail: pstrcpy(orig_path, name); + fail: SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From f5ab9ddd760321ed983f0ef3354410e0a05decfc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 19 Aug 2007 20:00:43 +0000 Subject: r24549: Fix unix_convert to return the already converted part This API will change anyway when moving away from pstrings. It took so long to fix, because that rename bug I just fixed gave make test failures that had nothing to do with this one. I have samba4 tests for both bugs, will check them in when the build farm has caught up (This used to be commit d4f442ed9b145990af4db26859663954ddd70926) --- source3/smbd/filename.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d5c22e81c3..73e3869f50 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -173,7 +173,7 @@ NTSTATUS unix_convert(connection_struct *conn, result =determine_path_error( &orig_path[2], allow_wcard_last_component); } - goto fail; + return result; } /* @@ -222,8 +222,8 @@ NTSTATUS unix_convert(connection_struct *conn, if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { DEBUG(0, ("strdup failed\n")); - result = NT_STATUS_NO_MEMORY; - goto fail; + SAFE_FREE(name); + return NT_STATUS_NO_MEMORY; } /* @@ -602,9 +602,15 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: - result = NT_STATUS_OK; pstrcpy(orig_path, name); + SAFE_FREE(name); + SAFE_FREE(dirpath); + return NT_STATUS_OK; fail: + DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); + pstrcpy(orig_path, dirpath); + pstrcat(orig_path, "/"); + pstrcat(orig_path, start); SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From a9184f49d3226358042bd88e65e29adacc2ecf41 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 21 Aug 2007 12:58:10 +0000 Subject: r24595: Fix Coverity ID 393 In this error case we would have used "start" not having it initialized (This used to be commit 751834fff92e85a424152c1642b238daa3060dbd) --- source3/smbd/filename.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 73e3869f50..25ade52947 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -155,8 +155,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (!*orig_path) { if (!(name = SMB_STRDUP("."))) { - result = NT_STATUS_NO_MEMORY; - goto fail; + return NT_STATUS_NO_MEMORY; } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; -- cgit From 3b0422ee01ec69c2cf8a538a3547bf5c3e111992 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Aug 2007 21:46:42 +0000 Subject: r24811: Simple reformatting to fit the 80 columns rule. Jeremy. (This used to be commit 0cdf046dae8ba0741bb7786aa4e85c34fc35dade) --- source3/smbd/filename.c | 159 +++++++++++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 63 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 25ade52947..5f9563b83c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 Copyright (C) Volker Lendecke 2007 - + 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 3 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, see . */ @@ -33,11 +33,12 @@ static BOOL scan_directory(connection_struct *conn, const char *path, Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, const char *name2, - const struct share_params *p) +static BOOL mangled_equal(const char *name1, + const char *name2, + const struct share_params *p) { pstring tmpname; - + pstrcpy(tmpname, name2); mangle_map(tmpname, True, False, p); return strequal(name1, tmpname); @@ -47,7 +48,8 @@ static BOOL mangled_equal(const char *name1, const char *name2, Cope with the differing wildcard and non-wildcard error cases. ****************************************************************************/ -static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component) +static NTSTATUS determine_path_error(const char *name, + BOOL allow_wcard_last_component) { const char *p; @@ -74,7 +76,7 @@ static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_com return NT_STATUS_OBJECT_PATH_NOT_FOUND; } } - + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -83,8 +85,8 @@ changes etc. We assume that we have already done a chdir() to the right "root" directory for this service. -The function will return an NTSTATUS error if some part of the name except for the last -part cannot be resolved, else NT_STATUS_OK. +The function will return an NTSTATUS error if some part of the name except for +the last part cannot be resolved, else NT_STATUS_OK. Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't get any fatal errors that should immediately terminate the calling @@ -133,7 +135,8 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path)); /* - * Conversion to basic unix format is already done in check_path_syntax(). + * Conversion to basic unix format is already done in + * check_path_syntax(). */ /* @@ -164,7 +167,8 @@ NTSTATUS unix_convert(connection_struct *conn, goto done; } - if (orig_path[0] == '.' && (orig_path[1] == '/' || orig_path[1] == '\0')) { + if (orig_path[0] == '.' && (orig_path[1] == '/' || + orig_path[1] == '\0')) { /* Start of pathname can't be "." only. */ if (orig_path[1] == '\0' || orig_path[2] == '\0') { result = NT_STATUS_OBJECT_NAME_INVALID; @@ -202,7 +206,8 @@ NTSTATUS unix_convert(connection_struct *conn, * the man page. Thanks to jht@samba.org for finding this. JRA. */ - if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { + if (conn->case_sensitive && !conn->case_preserve && + !conn->short_case_preserve) { strnorm(name, lp_defaultcase(SNUM(conn))); } @@ -250,7 +255,8 @@ NTSTATUS unix_convert(connection_struct *conn, goto done; } - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", + name, dirpath, start)); /* * A special case - if we don't have any mangling chars and are case @@ -286,7 +292,8 @@ NTSTATUS unix_convert(connection_struct *conn, /* * Pinpoint the end of this section of the filename. */ - end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ + /* mb safe. '/' can't be in any encoded char. */ + end = strchr(start, '/'); /* * Chop the name at this point. @@ -335,20 +342,22 @@ NTSTATUS unix_convert(connection_struct *conn, if (SMB_VFS_STAT(conn,name, &st) == 0) { /* - * It exists. it must either be a directory or this must be - * the last part of the path for it to be OK. + * It exists. it must either be a directory or this must + * be the last part of the path for it to be OK. */ if (end && !(st.st_mode & S_IFDIR)) { /* - * An intermediate part of the name isn't a directory. + * An intermediate part of the name isn't + * a directory. */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between + * We need to return the fact that the + * intermediate name resolution failed. This + * is used to return an error of ERRbadpath + * rather than ERRbadfile. Some Windows + * applications depend on the difference between * these two errors. */ result = NT_STATUS_OBJECT_PATH_NOT_FOUND; @@ -357,9 +366,9 @@ NTSTATUS unix_convert(connection_struct *conn, if (!end) { /* - * We just scanned for, and found the end of the path. - * We must return the valid stat struct. - * JRA. + * We just scanned for, and found the end of + * the path. We must return the valid stat + * struct. JRA. */ *pst = st; @@ -371,30 +380,38 @@ NTSTATUS unix_convert(connection_struct *conn, /* Stat failed - ensure we don't use it. */ SET_STAT_INVALID(st); - /* Reset errno so we can detect directory open errors. */ + /* + * Reset errno so we can detect + * directory open errors. + */ errno = 0; /* * Try to find this part of the path in the directory. */ - if (name_has_wildcard || - !scan_directory(conn, dirpath, start, &found_name)) { + if (name_has_wildcard || + !scan_directory(conn, dirpath, + start, &found_name)) { char *unmangled; if (end) { /* - * An intermediate part of the name can't be found. + * An intermediate part of the name + * can't be found. */ - DEBUG(5,("Intermediate not found %s\n",start)); + DEBUG(5,("Intermediate not found %s\n", + start)); *end = '/'; /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between - * these two errors. + * We need to return the fact that the + * intermediate name resolution failed. + * This is used to return an error of + * ERRbadpath rather than ERRbadfile. + * Some Windows applications depend on + * the difference between these two + * errors. */ /* @@ -406,10 +423,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (errno == ENOENT || errno == ENOTDIR || errno == ELOOP) { - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = + NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = map_nt_error_from_unix(errno); + result = + map_nt_error_from_unix(errno); } goto fail; } @@ -423,10 +442,12 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (errno == ENOTDIR || errno == ELOOP) { - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = + NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = map_nt_error_from_unix(errno); + result = + map_nt_error_from_unix(errno); } goto fail; } @@ -434,22 +455,26 @@ NTSTATUS unix_convert(connection_struct *conn, /* * Just the last part of the name doesn't exist. * We need to strupper() or strlower() it as - * this conversion may be used for file creation - * purposes. Fix inspired by Thomas Neumann . + * this conversion may be used for file creation + * purposes. Fix inspired by + * Thomas Neumann . */ if (!conn->case_preserve || - (mangle_is_8_3(start, False, conn->params) && + (mangle_is_8_3(start, False, + conn->params) && !conn->short_case_preserve)) { - strnorm(start, lp_defaultcase(SNUM(conn))); + strnorm(start, + lp_defaultcase(SNUM(conn))); } /* - * check on the mangled stack to see if we can recover the - * base of the filename. + * check on the mangled stack to see if we can + * recover the base of the filename. */ if (mangle_is_mangled(start, conn->params) - && mangle_check_cache_alloc(start, &unmangled, + && mangle_check_cache_alloc(start, + &unmangled, conn->params)) { char *tmp; size_t start_ofs = start - name; @@ -478,8 +503,8 @@ NTSTATUS unix_convert(connection_struct *conn, /* - * Restore the rest of the string. If the string was mangled the size - * may have changed. + * Restore the rest of the string. If the string was + * mangled the size may have changed. */ if (end) { char *tmp; @@ -523,9 +548,9 @@ NTSTATUS unix_convert(connection_struct *conn, start = name + start_ofs; /* - * We just scanned for, and found the end of the path. - * We must return a valid stat struct if it exists. - * JRA. + * We just scanned for, and found the end of + * the path. We must return a valid stat struct + * if it exists. JRA. */ if (SMB_VFS_STAT(conn,name, &st) == 0) { @@ -540,13 +565,14 @@ NTSTATUS unix_convert(connection_struct *conn, #ifdef DEVELOPER if (VALID_STAT(st) && - get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, &st))) { + get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, + &st))) { result = NT_STATUS_DELETE_PENDING; goto fail; } #endif - /* + /* * Add to the dirpath that we have resolved so far. */ @@ -574,7 +600,8 @@ NTSTATUS unix_convert(connection_struct *conn, */ if(!component_was_mangled && !name_has_wildcard) { - stat_cache_add(orig_path, dirpath, conn->case_sensitive); + stat_cache_add(orig_path, dirpath, + conn->case_sensitive); } /* @@ -626,8 +653,10 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) { if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ - if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { - DEBUG(5,("check_name: file path name %s vetoed\n",name)); + if (!((name[0] == '.') && (!name[1] || + (name[1] == '.' && !name[2])))) { + DEBUG(5,("check_name: file path name %s vetoed\n", + name)); return map_nt_error_from_unix(ENOENT); } } @@ -635,7 +664,8 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { NTSTATUS status = check_reduced_name(conn,name); if (!NT_STATUS_IS_OK(status)) { - DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); + DEBUG(5,("check_name: name %s failed with %s\n",name, + nt_errstr(status))); return status; } } @@ -648,7 +678,8 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) +static BOOL fname_equal(const char *name1, const char *name2, + BOOL case_sensitive) { /* Normal filename handling */ if (case_sensitive) @@ -710,14 +741,15 @@ static BOOL scan_directory(connection_struct *conn, const char *path, while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ - if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { + if ((dname[0] == '.') && (!dname[1] || + (dname[1] == '.' && !dname[2]))) { continue; } /* * At this point dname is the unmangled name. - * name is either mangled or not, depending on the state of the "mangled" - * variable. JRA. + * name is either mangled or not, depending on the state + * of the "mangled" variable. JRA. */ /* @@ -725,7 +757,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { + if ((mangled && mangled_equal(name,dname,conn->params)) || + fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ *found_name = SMB_STRDUP(dname); SAFE_FREE(unmangled_name); -- cgit From 132ee3990af5d31573978f5a3abf43db2303880b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 20:57:01 +0000 Subject: r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736) --- source3/smbd/filename.c | 189 ++++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 77 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5f9563b83c..5871fd143f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1999-2004 + Copyright (C) Jeremy Allison 1999-2007 Copyright (C) Ying Chen 2000 Copyright (C) Volker Lendecke 2007 @@ -37,11 +37,12 @@ static BOOL mangled_equal(const char *name1, const char *name2, const struct share_params *p) { - pstring tmpname; + char mname[13]; - pstrcpy(tmpname, name2); - mangle_map(tmpname, True, False, p); - return strequal(name1, tmpname); + if (!name_to_8_3(name2, mname, False, p)) { + return False; + } + return strequal(name1, mname); } /**************************************************************************** @@ -107,9 +108,10 @@ for nlinks = 0, which can never be true for any file). ****************************************************************************/ NTSTATUS unix_convert(connection_struct *conn, - pstring orig_path, + const char *orig_path, BOOL allow_wcard_last_component, - char *saved_last_component, + char **pp_conv_path, + char **pp_saved_last_component, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; @@ -119,16 +121,20 @@ NTSTATUS unix_convert(connection_struct *conn, BOOL component_was_mangled = False; BOOL name_has_wildcard = False; NTSTATUS result; + TALLOC_CTX *ctx = talloc_tos(); SET_STAT_INVALID(*pst); - - if(saved_last_component) { - *saved_last_component = 0; + *pp_conv_path = NULL; + if(pp_saved_last_component) { + *pp_saved_last_component = NULL; } if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ + if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) { + return NT_STATUS_NO_MEMORY; + } return NT_STATUS_OK; } @@ -157,11 +163,13 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (!*orig_path) { - if (!(name = SMB_STRDUP("."))) { + if (!(name = talloc_strdup(ctx,"."))) { return NT_STATUS_NO_MEMORY; } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; + } else { + return map_nt_error_from_unix(errno); } DEBUG(5,("conversion finished \"\" -> %s\n",name)); goto done; @@ -183,17 +191,18 @@ NTSTATUS unix_convert(connection_struct *conn, * Ensure saved_last_component is valid even if file exists. */ - if(saved_last_component) { + if(pp_saved_last_component) { end = strrchr_m(orig_path, '/'); if (end) { - pstrcpy(saved_last_component, end + 1); + *pp_saved_last_component = talloc_strdup(ctx, end + 1); } else { - pstrcpy(saved_last_component, orig_path); + *pp_saved_last_component = talloc_strdup(ctx, + orig_path); } } - if (!(name = SMB_STRDUP(orig_path))) { - DEBUG(0, ("strdup failed\n")); + if (!(name = talloc_strdup(ctx, orig_path))) { + DEBUG(0, ("talloc_strdup failed\n")); return NT_STATUS_NO_MEMORY; } @@ -224,9 +233,9 @@ NTSTATUS unix_convert(connection_struct *conn, * building the directories with asprintf and free it. */ - if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { - DEBUG(0, ("strdup failed\n")); - SAFE_FREE(name); + if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) { + DEBUG(0, ("talloc_strdup failed\n")); + TALLOC_FREE(name); return NT_STATUS_NO_MEMORY; } @@ -264,8 +273,7 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (conn->case_sensitive && - !mangle_is_mangled(name, conn->params) && - !*lp_mangled_map(conn->params)) { + !mangle_is_mangled(name, conn->params)) { goto done; } @@ -302,8 +310,14 @@ NTSTATUS unix_convert(connection_struct *conn, *end = 0; } - if (saved_last_component != 0) { - pstrcpy(saved_last_component, end ? end + 1 : start); + if (pp_saved_last_component) { + TALLOC_FREE(*pp_saved_last_component); + *pp_saved_last_component = talloc_strdup(ctx, + end ? end + 1 : start); + if (!*pp_saved_last_component) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } } /* The name cannot have a component of "." */ @@ -473,25 +487,27 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (mangle_is_mangled(start, conn->params) - && mangle_check_cache_alloc(start, - &unmangled, - conn->params)) { + && mangle_lookup_name_from_8_3(ctx, + start, + &unmangled, + conn->params)) { char *tmp; size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s", dirpath, - unmangled); - SAFE_FREE(unmangled); + tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, + unmangled); + TALLOC_FREE(unmangled); } else { tmp = unmangled; } if (tmp == NULL) { - DEBUG(0, ("malloc failed\n")); - result = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; end = start + strlen(start); @@ -511,18 +527,20 @@ NTSTATUS unix_convert(connection_struct *conn, size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s/%s", dirpath, - found_name, end+1); + tmp = talloc_asprintf(ctx, + "%s/%s/%s", dirpath, + found_name, end+1); } else { - asprintf(&tmp, "%s/%s", found_name, - end+1); + tmp = talloc_asprintf(ctx, + "%s/%s", found_name, + end+1); } if (tmp == NULL) { - DEBUG(0, ("asprintf failed\n")); - result = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc_asprintf failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; end = start + strlen(found_name); @@ -532,18 +550,19 @@ NTSTATUS unix_convert(connection_struct *conn, size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s", dirpath, - found_name); + tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, + found_name); } else { - tmp = SMB_STRDUP(found_name); + tmp = talloc_strdup(ctx, + found_name); } if (tmp == NULL) { - DEBUG(0, ("malloc failed\n")); - result = NT_STATUS_NO_MEMORY; - goto fail; + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; @@ -560,7 +579,7 @@ NTSTATUS unix_convert(connection_struct *conn, } } - SAFE_FREE(found_name); + TALLOC_FREE(found_name); } /* end else */ #ifdef DEVELOPER @@ -577,19 +596,19 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (*dirpath != '\0') { - char *tmp; - - if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) { - DEBUG(0, ("asprintf failed\n")); + char *tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, start); + if (!tmp) { + DEBUG(0, ("talloc_asprintf failed\n")); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(dirpath); + TALLOC_FREE(dirpath); dirpath = tmp; } else { - SAFE_FREE(dirpath); - if (!(dirpath = SMB_STRDUP(start))) { - DEBUG(0, ("strdup failed\n")); + TALLOC_FREE(dirpath); + if (!(dirpath = talloc_strdup(ctx,start))) { + DEBUG(0, ("talloc_strdup failed\n")); return NT_STATUS_NO_MEMORY; } } @@ -628,17 +647,23 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: - pstrcpy(orig_path, name); - SAFE_FREE(name); - SAFE_FREE(dirpath); + *pp_conv_path = name; + TALLOC_FREE(dirpath); return NT_STATUS_OK; fail: DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); - pstrcpy(orig_path, dirpath); - pstrcat(orig_path, "/"); - pstrcat(orig_path, start); - SAFE_FREE(name); - SAFE_FREE(dirpath); + if (*dirpath != '\0') { + *pp_conv_path = talloc_asprintf(ctx, + "%s/%s", dirpath, start); + } else { + *pp_conv_path = talloc_strdup(ctx, start); + } + if (!*pp_conv_path) { + DEBUG(0, ("talloc_asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(name); + TALLOC_FREE(dirpath); return result; } @@ -649,7 +674,7 @@ NTSTATUS unix_convert(connection_struct *conn, a valid one for the user to access. ****************************************************************************/ -NTSTATUS check_name(connection_struct *conn, const pstring name) +NTSTATUS check_name(connection_struct *conn, const char *name) { if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ @@ -682,8 +707,9 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) { /* Normal filename handling */ - if (case_sensitive) + if (case_sensitive) { return(strcmp(name1,name2) == 0); + } return(strequal(name1,name2)); } @@ -701,17 +727,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, BOOL mangled; char *unmangled_name = NULL; long curpos; + TALLOC_CTX *ctx = talloc_tos(); mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ - if ((path == NULL) || (*path == 0)) + if ((path == NULL) || (*path == 0)) { path = "."; + } /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the mangle_map() + * read from the directory and then mangled by the name_to_8_3() * call. We need to mangle both names or neither. * (JRA). * @@ -724,15 +752,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache_alloc(name, &unmangled_name, - conn->params); - name = unmangled_name; + mangled = !mangle_lookup_name_from_8_3(ctx, + name, + &unmangled_name, + conn->params); + if (mangled) { + name = unmangled_name; + } } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - SAFE_FREE(unmangled_name); + TALLOC_FREE(unmangled_name); return(False); } @@ -741,8 +773,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ - if ((dname[0] == '.') && (!dname[1] || - (dname[1] == '.' && !dname[2]))) { + if (ISDOT(dname) || ISDOTDOT(dname)) { continue; } @@ -760,15 +791,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - *found_name = SMB_STRDUP(dname); - SAFE_FREE(unmangled_name); + *found_name = talloc_strdup(ctx,dname); + TALLOC_FREE(unmangled_name); CloseDir(cur_dir); + if (!*found_name) { + errno = ENOMEM; + return False; + } return(True); } } - SAFE_FREE(unmangled_name); + TALLOC_FREE(unmangled_name); CloseDir(cur_dir); errno = ENOENT; - return(False); + return False; } -- cgit From 3a9d3821649c9ea88a6cd424f0838a453165a00a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 23:57:59 +0000 Subject: r25111: Move to talloced pathnames on most code paths. There are now ony 17 pstrings left in reply.c, and these will be easy to remove (and I'll be doing that shortly). Had to fix an interesting bug in pull_ucs2_base_talloc() when a source string is not null terminated :-). Jeremy. (This used to be commit 0c9a8c4dff10974dbffd2a302ae982896122fcc0) --- source3/smbd/filename.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5871fd143f..27f17f9628 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -553,8 +553,7 @@ NTSTATUS unix_convert(connection_struct *conn, tmp = talloc_asprintf(ctx, "%s/%s", dirpath, found_name); - } - else { + } else { tmp = talloc_strdup(ctx, found_name); } -- cgit From eacd3140573d1122a3785823e4003bfc6352c431 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Sep 2007 22:08:59 +0000 Subject: r25138: More pstring elimination. Add a TALLOC_CTX parameter to unix_convert(). Jeremy. (This used to be commit 39c211a702e91c34c1a5a689e1b0c4530ea8a1ac) --- source3/smbd/filename.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 27f17f9628..f15c107711 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -107,7 +107,8 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -NTSTATUS unix_convert(connection_struct *conn, +NTSTATUS unix_convert(TALLOC_CTX *ctx, + connection_struct *conn, const char *orig_path, BOOL allow_wcard_last_component, char **pp_conv_path, @@ -121,7 +122,6 @@ NTSTATUS unix_convert(connection_struct *conn, BOOL component_was_mangled = False; BOOL name_has_wildcard = False; NTSTATUS result; - TALLOC_CTX *ctx = talloc_tos(); SET_STAT_INVALID(*pst); *pp_conv_path = NULL; -- cgit From b91b78530697556aec7764de9ef16735cdd22902 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 18:24:31 +0000 Subject: r25167: Fix breakage from mangling rewrite. Use the new name if unmangling succeeded, not if it failed. Jerry - please re-test, this should fix your bug. Jeremy. (This used to be commit c215d6e84929b70e4472e19f32ec4f1db7449d90) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f15c107711..fb8ed07ee8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -755,7 +755,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, name, &unmangled_name, conn->params); - if (mangled) { + if (!mangled) { + /* Name is now unmangled. */ name = unmangled_name; } } -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/filename.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fb8ed07ee8..dc733d4568 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,14 +26,14 @@ #include "includes.h" -static BOOL scan_directory(connection_struct *conn, const char *path, +static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, +static bool mangled_equal(const char *name1, const char *name2, const struct share_params *p) { @@ -50,7 +50,7 @@ static BOOL mangled_equal(const char *name1, ****************************************************************************/ static NTSTATUS determine_path_error(const char *name, - BOOL allow_wcard_last_component) + bool allow_wcard_last_component) { const char *p; @@ -110,7 +110,7 @@ for nlinks = 0, which can never be true for any file). NTSTATUS unix_convert(TALLOC_CTX *ctx, connection_struct *conn, const char *orig_path, - BOOL allow_wcard_last_component, + bool allow_wcard_last_component, char **pp_conv_path, char **pp_saved_last_component, SMB_STRUCT_STAT *pst) @@ -119,8 +119,8 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *start, *end; char *dirpath = NULL; char *name = NULL; - BOOL component_was_mangled = False; - BOOL name_has_wildcard = False; + bool component_was_mangled = False; + bool name_has_wildcard = False; NTSTATUS result; SET_STAT_INVALID(*pst); @@ -702,8 +702,8 @@ NTSTATUS check_name(connection_struct *conn, const char *name) This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2, - BOOL case_sensitive) +static bool fname_equal(const char *name1, const char *name2, + bool case_sensitive) { /* Normal filename handling */ if (case_sensitive) { @@ -718,12 +718,12 @@ static BOOL fname_equal(const char *name1, const char *name2, If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(connection_struct *conn, const char *path, +static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name) { struct smb_Dir *cur_dir; const char *dname; - BOOL mangled; + bool mangled; char *unmangled_name = NULL; long curpos; TALLOC_CTX *ctx = talloc_tos(); -- cgit From 596018455af0d80add90215689a80d336157429c Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 22 Dec 2007 14:55:37 -0800 Subject: Use filesystem capabilities to support case-insensitive filesystems. If we know the underlying filesystem is case-insensitive, then we know that it won't help to search for case variations of the requested name. Jeremy, please review (and revert if you disagree). (This used to be commit 9e8b8f8c16612d8a08b55802f4fd9afca5498a7c) --- source3/smbd/filename.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index dc733d4568..f0d036b82b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -735,6 +735,15 @@ static bool scan_directory(connection_struct *conn, const char *path, path = "."; } + /* If we have a case-sensitive filesystem, it doesn't do us any + * good to search for a name. If a case variation of the name was + * there, then the original stat(2) would have found it. + */ + if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) { + errno = ENOENT; + return False; + } + /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) -- cgit From f980d3ea14c020869102d8cd90fb69ecc2f78416 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Dec 2007 17:38:18 -0800 Subject: If we detect a case insensitive filesystem make sure we don't search directories on name misses for non-mangled names. Jeremy (This used to be commit 120048d2f40cf1a0ace2ecde205cbc694d263d69) --- source3/smbd/filename.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f0d036b82b..5ae193fb46 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -222,8 +222,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, start = name; - if(!conn->case_sensitive - && stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { + /* If we're providing case insentive semantics or + * the underlying filesystem is case insensitive, + * then a case-normalized hit in the stat-cache is + * authoratitive. JRA. + */ + + if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && + stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { *pst = st; goto done; } @@ -269,10 +275,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, /* * A special case - if we don't have any mangling chars and are case - * sensitive then searching won't help. + * sensitive or the underlying filesystem is case insentive then searching + * won't help. */ - if (conn->case_sensitive && + if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && !mangle_is_mangled(name, conn->params)) { goto done; } -- cgit From ec412b60ea6d6a4e0fd2e03ca9299b4264483c0c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 17:08:04 +0100 Subject: Convert OpenDir to talloc, use talloc_tos() This cuts some mallocs on NtCreate&X (This used to be commit 8e64107b7846d8f9cce71aabc95b28b7488d01ce) --- source3/smbd/filename.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5ae193fb46..be4960cab8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -778,7 +778,7 @@ static bool scan_directory(connection_struct *conn, const char *path, } /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { + if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); return(False); @@ -809,7 +809,7 @@ static bool scan_directory(connection_struct *conn, const char *path, /* we've found the file, change it's name and return */ *found_name = talloc_strdup(ctx,dname); TALLOC_FREE(unmangled_name); - CloseDir(cur_dir); + TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; return False; @@ -819,7 +819,7 @@ static bool scan_directory(connection_struct *conn, const char *path, } TALLOC_FREE(unmangled_name); - CloseDir(cur_dir); + TALLOC_FREE(cur_dir); errno = ENOENT; return False; } -- cgit From 1069cfe4ade88a032164c1242c9480a544584655 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:25:36 +0100 Subject: Add streams support This is the core of the streams support. The main change is that in files_struct there is now a base_fsp pointer that holds the main file open while a stream is open. This is necessary to get the rather strange delete semantics right: You can't delete the main file while a stream is open without FILE_SHARE_DELETE, and while a stream is open a successful unlink of the main file leads to DELETE_PENDING for all further access on the main file or any stream. (This used to be commit 6022873cc155bdbbd3fb620689715f07a24d6ed1) --- source3/smbd/filename.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index be4960cab8..1d44c7498e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -28,6 +28,13 @@ static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name); +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. @@ -119,6 +126,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *start, *end; char *dirpath = NULL; char *name = NULL; + char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; NTSTATUS result; @@ -206,6 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } + stream = strchr_m(name, ':'); + + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; + } + /* * Large directory fix normalization. If we're case sensitive, and * the case preserving parameters are set to "no", normalize the case of @@ -653,6 +673,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: + if (stream != NULL) { + char *tmp = NULL; + + result = build_stream_path(ctx, conn, orig_path, name, stream, + pst, &tmp); + if (!NT_STATUS_IS_OK(result)) { + goto fail; + } + + DEBUG(10, ("build_stream_path returned %s\n", tmp)); + + TALLOC_FREE(name); + name = tmp; + } *pp_conv_path = name; TALLOC_FREE(dirpath); return NT_STATUS_OK; @@ -823,3 +857,90 @@ static bool scan_directory(connection_struct *conn, const char *path, errno = ENOENT; return False; } + +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path) +{ + SMB_STRUCT_STAT st; + char *result = NULL; + NTSTATUS status; + unsigned int i, num_streams; + struct stream_struct *streams = NULL; + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (SMB_VFS_STAT(conn, result, &st) == 0) { + *pst = st; + *path = result; + return NT_STATUS_OK; + } + + if (errno != ENOENT) { + status = map_nt_error_from_unix(errno); + DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status))); + goto fail; + } + + status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx, + &num_streams, &streams); + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + SET_STAT_INVALID(*pst); + *path = result; + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); + goto fail; + } + + for (i=0; icase_sensitive)) { + DEBUGADD(10, ("equal\n")); + break; + } + DEBUGADD(10, ("not equal\n")); + } + + if (i == num_streams) { + SET_STAT_INVALID(*pst); + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + } + + TALLOC_FREE(result); + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name); + if (result == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + SET_STAT_INVALID(*pst); + + if (SMB_VFS_STAT(conn, result, pst) == 0) { + stat_cache_add(orig_path, result, conn->case_sensitive); + } + + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + + fail: + TALLOC_FREE(result); + TALLOC_FREE(streams); + return status; +} -- cgit From 0bb6fb7b6f8ea1c039e710f55bba779363716f2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Jan 2008 21:53:49 -0800 Subject: Couple of minor fixes for POSIX pathname processing in the new stream code. (1) In smbd/filename, don't split the name at ':' if we know it's a posix path (this should be parameterized....). (2). When calling posix_mkdir, we get the flag FILE_FLAG_POSIX_SEMANTICS passed to open_directory(). I know for a posix client lp_posix_pathnames should be true (which is checked for in is_ntfs_stream_name() but we have an explicit flag here, so let's use it. Jeremy. (This used to be commit 7bb7a0def6518784befa75e5303289d2b4d36dd4) --- source3/smbd/filename.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1d44c7498e..10e9583049 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -214,16 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - stream = strchr_m(name, ':'); + if (!lp_posix_pathnames()) { + stream = strchr_m(name, ':'); - if (stream != NULL) { - char *tmp = talloc_strdup(ctx, stream); - if (tmp == NULL) { - TALLOC_FREE(name); - return NT_STATUS_NO_MEMORY; + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; } - *stream = '\0'; - stream = tmp; } /* -- cgit From 851cadba51b00b326c5f040f23f95932aec53105 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 11:40:23 +0200 Subject: locking: combine get_delete_on_close_flag() and get_write_time() into get_file_infos() This means we need to fetch the record only once. metze (This used to be commit 4130b873291d39e363184fe4e38dc1f24ebe5056) --- source3/smbd/filename.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 10e9583049..4323e843d2 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -611,11 +611,19 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && - get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, - &st))) { - result = NT_STATUS_DELETE_PENDING; - goto fail; + /* + * This sucks! + * We should never provide different behaviors + * depending on DEVELOPER!!! + */ + if (VALID_STAT(st)) { + bool delete_pending; + get_file_infos(vfs_file_id_from_sbuf(conn, &st), + &delete_pending, NULL); + if (delete_pending) { + result = NT_STATUS_DELETE_PENDING; + goto fail; + } } #endif -- cgit From ac9f55b9102574085ae6c7364c794a386d4981a1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 12 Aug 2008 14:59:59 +0200 Subject: Fix unix_convert() for "*" after changing map_nt_error_from_unix(). map_nt_error_from_unix() now assumes that it is called in an error path and returns an error even for a given errno == 0. The original behaviour of unix_convert() used the mapping of errno == 0 ==> NT_STATUS_OK to return success through an error path. I think this must have been an oversight, and unix_convert() worked only by coincidence (or because explicitly using the knowledge of the conceptually wrong working of map_nt_error_from_unix(). This patch puts this straight by not interpreting errno == 0 as an error condition and proceeding in that case. Jeremy - please check! Michael (This used to be commit ec5956ab0df1b3f567470b2481b73da9c3c67371) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/filename.c') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 4323e843d2..41a0b9296a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -477,7 +477,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } /* ENOENT is the only valid error here. */ - if (errno != ENOENT) { + if ((errno != 0) && (errno != ENOENT)) { /* * ENOTDIR and ELOOP both map to * NT_STATUS_OBJECT_PATH_NOT_FOUND -- cgit