Samba 3.0.20 - findfirst optimization

Jeremy Allison jra at samba.org
Mon Oct 31 19:56:50 GMT 2005


On Mon, Oct 31, 2005 at 07:09:36AM +0200, Dina Fine wrote:
> Yes, this is the reason.
> <>*?\" are valid windows wildcards characters, but they are also valid
> linux characters.
> It means that every mangled name with one of this characters will be
> treated as a pattern with wildcards and all matching files will be
> returned on Find First request.

Ok - the only way to fix this is to detect an incoming wcard on
string parse from the packet and pass it into the dptr_create
function. That way it doesn't matter if a name unmangles into
a wildcard name. Luckily we already distinguish between name
parsing where a wildcard name is acceptable and parsing where
it isn't, as we need this for error code returns.

Here is the fix I'm checking into HEAD and 3.0. It changes
a lot of code but actually simplifies quite a few things.

Thanks a *lot* for persuing this - it's a fascinating discussion !

Jeremy.
-------------- next part --------------
Index: smbd/msdfs.c
===================================================================
--- smbd/msdfs.c	(revision 11419)
+++ smbd/msdfs.c	(working copy)
@@ -114,7 +114,8 @@
 
 	/* rest is reqpath */
 	if (allow_wcards) {
-		check_path_syntax_wcard(pdp->reqpath, p+1);
+		BOOL path_contains_wcard;
+		check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard);
 	} else {
 		check_path_syntax(pdp->reqpath, p+1);
 	}
Index: smbd/nttrans.c
===================================================================
--- smbd/nttrans.c	(revision 11419)
+++ smbd/nttrans.c	(working copy)
@@ -541,7 +541,7 @@
 
 		if(!dir_fsp->is_directory) {
 
-			srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
+			srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				END_PROFILE(SMBntcreateX);
 				return ERROR_NT(status);
@@ -583,14 +583,14 @@
 			dir_name_len++;
 		}
 
-		srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False);
+		srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			END_PROFILE(SMBntcreateX);
 			return ERROR_NT(status);
 		}
 		pstrcat(fname, rel_fname);
 	} else {
-		srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
+		srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			END_PROFILE(SMBntcreateX);
 			return ERROR_NT(status);
@@ -939,7 +939,7 @@
 		return ERROR_DOS(ERRDOS,ERRnoaccess);
 	}
 
-	srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		return ERROR_NT(status);
 	}
@@ -1195,7 +1195,7 @@
 		}
 
 		if(!dir_fsp->is_directory) {
-			srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+			srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				return ERROR_NT(status);
 			}
@@ -1229,14 +1229,14 @@
 
 		{
 			pstring tmpname;
-			srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False);
+			srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				return ERROR_NT(status);
 			}
 			pstrcat(fname, tmpname);
 		}
 	} else {
-		srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+		srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			return ERROR_NT(status);
 		}
@@ -1738,13 +1738,14 @@
 	pstring newname;
 	char *p;
 	NTSTATUS status;
+	BOOL path_contains_wcard = False;
 	uint32 attrs = SVAL(inbuf,smb_vwv0);
 	uint16 rename_type = SVAL(inbuf,smb_vwv1);
 
 	START_PROFILE(SMBntrename);
 
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True);
+	p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBntrename);
 		return ERROR_NT(status);
@@ -1762,7 +1763,7 @@
 	}
 
 	p++;
-	p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False);
+	p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBntrename);
 		return ERROR_NT(status);
@@ -1775,13 +1776,18 @@
 	
 	switch(rename_type) {
 		case RENAME_FLAG_RENAME:
-			status = rename_internals(conn, oldname, newname, attrs, False);
+			status = rename_internals(conn, oldname, newname, attrs, False, path_contains_wcard);
 			break;
 		case RENAME_FLAG_HARD_LINK:
 			status = hardlink_internals(conn, oldname, newname);
 			break;
 		case RENAME_FLAG_COPY:
-			status = copy_internals(conn, oldname, newname, attrs);
+			if (path_contains_wcard) {
+				/* No wildcards. */
+				status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+			} else {
+				status = copy_internals(conn, oldname, newname, attrs);
+			}
 			break;
 		case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
 			status = NT_STATUS_INVALID_PARAMETER;
@@ -1878,6 +1884,7 @@
 	pstring new_name;
 	files_struct *fsp = NULL;
 	BOOL replace_if_exists = False;
+	BOOL path_contains_wcard = False;
 	NTSTATUS status;
 
         if(parameter_count < 4) {
@@ -1887,13 +1894,13 @@
 	fsp = file_fsp(params, 0);
 	replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
 	CHECK_FSP(fsp, conn);
-	srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True);
+	srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, &path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		return ERROR_NT(status);
 	}
 
 	status = rename_internals(conn, fsp->fsp_name,
-				  new_name, 0, replace_if_exists);
+				  new_name, 0, replace_if_exists, path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status))
 		return ERROR_NT(status);
 
Index: smbd/reply.c
===================================================================
--- smbd/reply.c	(revision 11419)
+++ smbd/reply.c	(working copy)
@@ -172,7 +172,7 @@
  set.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
 {
 	char *d = destname;
 	const char *s = srcname;
@@ -180,6 +180,8 @@
 	BOOL start_of_name_component = True;
 	unsigned int num_bad_components = 0;
 
+	*p_contains_wcard = False;
+
 	while (*s) {
 		if (IS_DIRECTORY_SEP(*s)) {
 			/*
@@ -249,6 +251,19 @@
 			if (*s <= 0x1f) {
 				return NT_STATUS_OBJECT_NAME_INVALID;
 			}
+			if (!*p_contains_wcard) {
+				switch (*s) {
+					case '*':
+					case '?':
+					case '<':
+					case '>':
+					case '"':
+						*p_contains_wcard = True;
+						break;
+					default:
+						break;
+				}
+			}
 			*d++ = *s++;
 		} else {
 			switch(next_mb_char_size(s)) {
@@ -380,10 +395,40 @@
 }
 
 /****************************************************************************
+ Pull a string and check the path allowing a wilcard - provide for error return.
+****************************************************************************/
+
+size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
+				NTSTATUS *err, BOOL *contains_wcard)
+{
+	pstring tmppath;
+	char *tmppath_ptr = tmppath;
+	size_t ret;
+#ifdef DEVELOPER
+	SMB_ASSERT(dest_len == sizeof(pstring));
+#endif
+
+	if (src_len == 0) {
+		ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
+	} else {
+		ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+	}
+
+	*contains_wcard = False;
+
+	if (lp_posix_pathnames()) {
+		*err = check_path_syntax_posix(dest, tmppath);
+	} else {
+		*err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
+	}
+	return ret;
+}
+
+/****************************************************************************
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
+size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
 {
 	pstring tmppath;
 	char *tmppath_ptr = tmppath;
@@ -399,8 +444,6 @@
 	}
 	if (lp_posix_pathnames()) {
 		*err = check_path_syntax_posix(dest, tmppath);
-	} else if (allow_wcard_names) {
-		*err = check_path_syntax_wcard(dest, tmppath);
 	} else {
 		*err = check_path_syntax(dest, tmppath);
 	}
@@ -754,7 +797,7 @@
 
 	START_PROFILE(SMBchkpth);
 
-	srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBchkpth);
 		return ERROR_NT(status);
@@ -826,7 +869,7 @@
 	START_PROFILE(SMBgetatr);
 
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
+	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBgetatr);
 		return ERROR_NT(status);
@@ -905,7 +948,7 @@
 	START_PROFILE(SMBsetatr);
 
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
+	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBsetatr);
 		return ERROR_NT(status);
@@ -1031,6 +1074,7 @@
 	BOOL can_open = True;
 	BOOL bad_path = False;
 	NTSTATUS nt_status;
+	BOOL mask_contains_wcard = False;
 	BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
 
 	if (lp_posix_pathnames()) {
@@ -1049,7 +1093,7 @@
 	maxentries = SVAL(inbuf,smb_vwv0); 
 	dirtype = SVAL(inbuf,smb_vwv1);
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
+	p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		END_PROFILE(SMBsearch);
 		return ERROR_NT(nt_status);
@@ -1114,7 +1158,7 @@
 		ok = True;
      
 		if (status_len == 0) {
-			dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype);
+			dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
 			if (dptr_num < 0) {
 				if(dptr_num == -2) {
 					END_PROFILE(SMBsearch);
@@ -1185,7 +1229,7 @@
 		dptr_close(&dptr_num);
 	}
 
-	if ((numentries == 0) && !ms_has_wild(mask)) {
+	if ((numentries == 0) && !mask_contains_wcard) {
 		return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
 	}
 
@@ -1230,6 +1274,7 @@
 	int dptr_num= -2;
 	char *p;
 	NTSTATUS err;
+	BOOL path_contains_wcard = False;
 
 	if (lp_posix_pathnames()) {
 		return reply_unknown(inbuf, outbuf);
@@ -1239,7 +1284,7 @@
 
 	outsize = set_message(outbuf,1,0,True);
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
+	p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
 	if (!NT_STATUS_IS_OK(err)) {
 		END_PROFILE(SMBfclose);
 		return ERROR_NT(err);
@@ -1295,7 +1340,7 @@
  
 	deny_mode = SVAL(inbuf,smb_vwv0);
 
-	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBopen);
 		return ERROR_NT(status);
@@ -1415,7 +1460,7 @@
 	}
 
 	/* XXXX we need to handle passed times, sattr and flags */
-	srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBopenX);
 		return ERROR_NT(status);
@@ -1586,7 +1631,7 @@
  
 	com = SVAL(inbuf,smb_com);
 
-	srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBcreate);
 		return ERROR_NT(status);
@@ -1669,7 +1714,7 @@
 
 	START_PROFILE(SMBctemp);
 
-	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBctemp);
 		return ERROR_NT(status);
@@ -1889,30 +1934,19 @@
  code.
 ****************************************************************************/
 
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
 {
 	pstring directory;
 	pstring mask;
 	char *p;
 	int count=0;
 	NTSTATUS error = NT_STATUS_OK;
-	BOOL has_wild;
 	BOOL bad_path = False;
 	BOOL rc = True;
 	SMB_STRUCT_STAT sbuf;
 	
 	*directory = *mask = 0;
 	
-	/* We must check for wildcards in the name given
-	 * directly by the client - before any unmangling.
-	 * This prevents an unmangling of a UNIX name containing
-	 * a DOS wildcard like '*' or '?' from unmangling into
-	 * a wildcard delete which was not intended.
-	 * FIX for #226. JRA.
-	 */
-
-	has_wild = ms_has_wild(name);
-
 	rc = unix_convert(name,conn,0,&bad_path,&sbuf);
 	
 	p = strrchr_m(name,'/');
@@ -2029,10 +2063,11 @@
 	uint32 dirtype;
 	NTSTATUS status;
 	START_PROFILE(SMBunlink);
-	
+	BOOL path_contains_wcard = False;
+
 	dirtype = SVAL(inbuf,smb_vwv0);
 	
-	srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
+	srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBunlink);
 		return ERROR_NT(status);
@@ -2042,7 +2077,7 @@
 	
 	DEBUG(3,("reply_unlink : %s\n",name));
 	
-	status = unlink_internals(conn, dirtype, name);
+	status = unlink_internals(conn, dirtype, name, path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
 			/* We have re-scheduled this call. */
@@ -3721,7 +3756,7 @@
 
 	START_PROFILE(SMBmkdir);
  
-	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBmkdir);
 		return ERROR_NT(status);
@@ -3925,7 +3960,7 @@
 	NTSTATUS status;
 	START_PROFILE(SMBrmdir);
 
-	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBrmdir);
 		return ERROR_NT(status);
@@ -4216,14 +4251,13 @@
  code. 
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
 {
 	pstring directory;
 	pstring mask;
 	pstring last_component_src;
 	pstring last_component_dest;
 	char *p;
-	BOOL has_wild;
 	BOOL bad_path_src = False;
 	BOOL bad_path_dest = False;
 	int count=0;
@@ -4292,8 +4326,6 @@
 	if (!rc && mangle_is_mangled(mask,SNUM(conn)))
 		mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
 
-	has_wild = ms_has_wild(mask);
-
 	if (!has_wild) {
 		/*
 		 * No wildcards - just process the one file.
@@ -4559,17 +4591,18 @@
 	char *p;
 	uint32 attrs = SVAL(inbuf,smb_vwv0);
 	NTSTATUS status;
+	BOOL path_contains_wcard = False;
 
 	START_PROFILE(SMBmv);
 
 	p = smb_buf(inbuf) + 1;
-	p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
+	p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBmv);
 		return ERROR_NT(status);
 	}
 	p++;
-	p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
+	p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBmv);
 		return ERROR_NT(status);
@@ -4580,7 +4613,7 @@
 	
 	DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
 	
-	status = rename_internals(conn, name, newname, attrs, False);
+	status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBmv);
 		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4727,21 +4760,22 @@
 	BOOL target_is_directory=False;
 	BOOL bad_path1 = False;
 	BOOL bad_path2 = False;
+	BOOL path_contains_wcard1 = False;
+	BOOL path_contains_wcard2 = False;
 	BOOL rc = True;
 	SMB_STRUCT_STAT sbuf1, sbuf2;
 	NTSTATUS status;
-
 	START_PROFILE(SMBcopy);
 
 	*directory = *mask = 0;
 
 	p = smb_buf(inbuf);
-	p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
+	p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBcopy);
 		return ERROR_NT(status);
 	}
-	p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
+	p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBcopy);
 		return ERROR_NT(status);
@@ -4803,7 +4837,7 @@
 	if (!rc && mangle_is_mangled(mask, SNUM(conn)))
 		mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
 
-	has_wild = ms_has_wild(mask);
+	has_wild = path_contains_wcard1;
 
 	if (!has_wild) {
 		pstrcat(directory,"/");
@@ -4904,7 +4938,7 @@
 		return ERROR_DOS(ERRDOS,ERRnoaccess);
 	}
 
-	srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(pathworks_setdir);
 		return ERROR_NT(status);
Index: smbd/trans2.c
===================================================================
--- smbd/trans2.c	(revision 11419)
+++ smbd/trans2.c	(working copy)
@@ -775,7 +775,7 @@
 		return(ERROR_DOS(ERRSRV,ERRaccess));
 	}
 
-	srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		return ERROR_NT(status);
 	}
@@ -1614,6 +1614,7 @@
 	BOOL out_of_space = False;
 	int space_remaining;
 	BOOL bad_path = False;
+	BOOL mask_contains_wcard = False;
 	SMB_STRUCT_STAT sbuf;
 	TALLOC_CTX *ea_ctx = NULL;
 	struct ea_list *ea_list = NULL;
@@ -1654,7 +1655,7 @@
 			return(ERROR_DOS(ERRDOS,ERRunknownlevel));
 	}
 
-	srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
+	srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
 	if (!NT_STATUS_IS_OK(ntstatus)) {
 		return ERROR_NT(ntstatus);
 	}
@@ -1672,10 +1673,12 @@
 	p = strrchr_m(directory,'/');
 	if(p == NULL) {
 		/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
-		if((directory[0] == '.') && (directory[1] == '\0'))
+		if((directory[0] == '.') && (directory[1] == '\0')) {
 			pstrcpy(mask,"*");
-		else
+			mask_contains_wcard = True;
+		} else {
 			pstrcpy(mask,directory);
+		}
 		pstrcpy(directory,"./");
 	} else {
 		pstrcpy(mask,p+1);
@@ -1733,7 +1736,7 @@
 	/* Save the wildcard match and attribs we are using on this directory - 
 		needed as lanman2 assumes these are being saved between calls */
 
-	dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype);
+	dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
 	if (dptr_num < 0) {
 		talloc_destroy(ea_ctx);
 		return(UNIXERROR(ERRDOS,ERRbadfile));
@@ -1868,6 +1871,7 @@
 	BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
 	BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
 	BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
+	BOOL mask_contains_wcard = False;
 	pstring resume_name;
 	pstring mask;
 	pstring directory;
@@ -1889,7 +1893,7 @@
 
 	*mask = *directory = *resume_name = 0;
 
-	srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
+	srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
 	if (!NT_STATUS_IS_OK(ntstatus)) {
 		/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
 		   complain (it thinks we're asking for the directory above the shared
@@ -2854,7 +2858,7 @@
 
 		DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
-		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
+		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			return ERROR_NT(status);
 		}
@@ -3659,7 +3663,7 @@
 		}
 
 		info_level = SVAL(params,0);    
-		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
+		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			return ERROR_NT(status);
 		}
@@ -4217,7 +4221,7 @@
 			char *newname = fname;
 
 			/* Set a hard link. */
-			srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
+			srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				return ERROR_NT(status);
 			}
@@ -4251,7 +4255,7 @@
 			overwrite = (CVAL(pdata,0) ? True : False);
 			root_fid = IVAL(pdata,4);
 			len = IVAL(pdata,8);
-			srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
+			srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				return ERROR_NT(status);
 			}
@@ -4278,7 +4282,7 @@
 			} else {
 				DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
 					fname, newname ));
-				status = rename_internals(conn, fname, base_name, 0, overwrite);
+				status = rename_internals(conn, fname, base_name, 0, overwrite, False);
 			}
 			if (!NT_STATUS_IS_OK(status)) {
 				return ERROR_NT(status);
@@ -4489,7 +4493,7 @@
 		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 	}
 
-	srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
+	srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		return ERROR_NT(status);
 	}
Index: smbd/dir.c
===================================================================
--- smbd/dir.c	(revision 11419)
+++ smbd/dir.c	(working copy)
@@ -382,7 +382,7 @@
 ****************************************************************************/
 
 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
-		const char *wcard, uint32 attr)
+		const char *wcard, BOOL wcard_has_wild, uint32 attr)
 {
 	struct dptr_struct *dptr = NULL;
 	struct smb_Dir *dir_hnd;
@@ -500,7 +500,7 @@
 	if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
 		dptr->has_wild = True;
 	} else {
-		dptr->has_wild = ms_has_wild(wcard);
+		dptr->has_wild = wcard_has_wild;
 	}
 
 	dptr->attr = attr;
Index: printing/nt_printing.c
===================================================================
--- printing/nt_printing.c	(revision 11419)
+++ printing/nt_printing.c	(working copy)
@@ -4792,7 +4792,7 @@
 			pstrcpy( file, s );
 			driver_unix_convert(file, conn, NULL, &bad_path, &st);
 			DEBUG(10,("deleting driverfile [%s]\n", s));
-			unlink_internals(conn, 0, file);
+			unlink_internals(conn, 0, file, False);
 		}
 	}
 		
@@ -4801,7 +4801,7 @@
 			pstrcpy( file, s );
 			driver_unix_convert(file, conn, NULL, &bad_path, &st);
 			DEBUG(10,("deleting configfile [%s]\n", s));
-			unlink_internals(conn, 0, file);
+			unlink_internals(conn, 0, file, False);
 		}
 	}
 	
@@ -4810,7 +4810,7 @@
 			pstrcpy( file, s );
 			driver_unix_convert(file, conn, NULL, &bad_path, &st);
 			DEBUG(10,("deleting datafile [%s]\n", s));
-			unlink_internals(conn, 0, file);
+			unlink_internals(conn, 0, file, False);
 		}
 	}
 	
@@ -4819,7 +4819,7 @@
 			pstrcpy( file, s );
 			driver_unix_convert(file, conn, NULL, &bad_path, &st);
 			DEBUG(10,("deleting helpfile [%s]\n", s));
-			unlink_internals(conn, 0, file);
+			unlink_internals(conn, 0, file, False);
 		}
 	}
 	
@@ -4835,7 +4835,7 @@
 				pstrcpy( file, p );
 				driver_unix_convert(file, conn, NULL, &bad_path, &st);
 				DEBUG(10,("deleting dependent file [%s]\n", file));
-				unlink_internals(conn, 0, file );
+				unlink_internals(conn, 0, file, False);
 			}
 			
 			i++;


More information about the samba-technical mailing list