svn commit: samba r20338 - in branches/SAMBA_3_0/source/smbd: .

vlendec at samba.org vlendec at samba.org
Sun Dec 24 11:13:33 GMT 2006


Author: vlendec
Date: 2006-12-24 11:13:32 +0000 (Sun, 24 Dec 2006)
New Revision: 20338

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=20338

Log:
Restructure open_directory a bit. This gets rid of a race condition regarding
error messages: We relied upon a stat that a directory did not exist to later
on then do the mkdir or not. This does the mkdir directly and copes with a
potential error.

The second one is more important: It's possible with Samba 3 to do a
ntcreate&x with NTCREATEX_OPTIONS_DIRECTORY and we happily do a NT_STATUS_OK.

Also move up the use_nt_status() logic a bit. I think this does not belong
into the core routines, the smb server as such should take care of it.

Jeremy, do you think this should go to 3.0.24?

I'll update samba4torture when the build farm has picked up this checkin.

Volker

Modified:
   branches/SAMBA_3_0/source/smbd/nttrans.c
   branches/SAMBA_3_0/source/smbd/open.c
   branches/SAMBA_3_0/source/smbd/reply.c


Changeset:
Modified: branches/SAMBA_3_0/source/smbd/nttrans.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/nttrans.c	2006-12-23 19:44:43 UTC (rev 20337)
+++ branches/SAMBA_3_0/source/smbd/nttrans.c	2006-12-24 11:13:32 UTC (rev 20338)
@@ -688,6 +688,10 @@
 		restore_case_semantics(conn, file_attributes);
 
 		if(!NT_STATUS_IS_OK(status)) {
+			if (!use_nt_status() && NT_STATUS_EQUAL(
+				    status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+				status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+			}
 			END_PROFILE(SMBntcreateX);
 			return ERROR_NT(status);
 		}
@@ -760,6 +764,10 @@
 
 				if(!NT_STATUS_IS_OK(status)) {
 					restore_case_semantics(conn, file_attributes);
+					if (!use_nt_status() && NT_STATUS_EQUAL(
+						    status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+						status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+					}
 					END_PROFILE(SMBntcreateX);
 					return ERROR_NT(status);
 				}

Modified: branches/SAMBA_3_0/source/smbd/open.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/open.c	2006-12-23 19:44:43 UTC (rev 20337)
+++ branches/SAMBA_3_0/source/smbd/open.c	2006-12-24 11:13:32 UTC (rev 20338)
@@ -1867,7 +1867,6 @@
 {
 	files_struct *fsp = NULL;
 	BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
-	BOOL create_dir = False;
 	struct share_mode_lock *lck = NULL;
 	NTSTATUS status;
 	int info = 0;
@@ -1888,44 +1887,47 @@
 
 	switch( create_disposition ) {
 		case FILE_OPEN:
-			/* If directory exists open. If directory doesn't
-			 * exist error. */
-			if (!dir_existed) {
-				DEBUG(5,("open_directory: FILE_OPEN requested "
-					 "for directory %s and it doesn't "
-					 "exist.\n", fname ));
-				return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-			}
+			/*
+			 * Don't do anything. The check for existence is done
+			 * futher down.
+			 */
 			info = FILE_WAS_OPENED;
 			break;
 
 		case FILE_CREATE:
+
 			/* If directory exists error. If directory doesn't
 			 * exist create. */
-			if (dir_existed) {
-				DEBUG(5,("open_directory: FILE_CREATE "
-					 "requested for directory %s and it "
-					 "already exists.\n", fname ));
-				if (use_nt_status()) {
-					return NT_STATUS_OBJECT_NAME_COLLISION;
-				} else {
-					return NT_STATUS_DOS(ERRDOS,
-							     ERRfilexists);
-				}
+
+			status = mkdir_internal(conn, fname, False);
+			if (!NT_STATUS_IS_OK(status)) {
+				DEBUG(2, ("open_directory: unable to create "
+					  "%s. Error was %s\n", fname,
+					  nt_errstr(status)));
+				return status;
 			}
-			create_dir = True;
+
 			info = FILE_WAS_CREATED;
 			break;
 
 		case FILE_OPEN_IF:
-			/* If directory exists open. If directory doesn't
-			 * exist create. */
-			if (!dir_existed) {
-				create_dir = True;
+			/*
+			 * If directory exists open. If directory doesn't
+			 * exist create.
+			 */
+
+			status = mkdir_internal(conn, fname, False);
+
+			if (NT_STATUS_IS_OK(status)) {
 				info = FILE_WAS_CREATED;
-			} else {
+			}
+
+			if (NT_STATUS_EQUAL(status,
+					    NT_STATUS_OBJECT_NAME_COLLISION)) {
 				info = FILE_WAS_OPENED;
+				status = NT_STATUS_OK;
 			}
+				
 			break;
 
 		case FILE_SUPERSEDE:
@@ -1938,35 +1940,17 @@
 			return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	if (create_dir) {
-		/*
-		 * Try and create the directory.
-		 */
+	/* Ensure we're checking for a symlink here.... */
+	/* We don't want to get caught by a symlink racer. */
 
-		/* We know bad_path is false as it's caught earlier. */
+	if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
+		return map_nt_error_from_unix(errno);
+	}
 
-		status = mkdir_internal(conn, fname, False);
-
-		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(2,("open_directory: unable to create %s. "
-				 "Error was %s\n", fname, strerror(errno) ));
-			/* Ensure we return the correct NT status to the
-			 * client. */
-			return status;
-		}
-
-		/* Ensure we're checking for a symlink here.... */
-		/* We don't want to get caught by a symlink racer. */
-
-		if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
-			return map_nt_error_from_unix(errno);
-		}
-
-		if(!S_ISDIR(psbuf->st_mode)) {
-			DEBUG(0,("open_directory: %s is not a directory !\n",
-				 fname ));
-			return NT_STATUS_NOT_A_DIRECTORY;
-		}
+	if(!S_ISDIR(psbuf->st_mode)) {
+		DEBUG(0,("open_directory: %s is not a directory !\n",
+			 fname ));
+		return NT_STATUS_NOT_A_DIRECTORY;
 	}
 
 	status = file_new(conn, &fsp);

Modified: branches/SAMBA_3_0/source/smbd/reply.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/reply.c	2006-12-23 19:44:43 UTC (rev 20337)
+++ branches/SAMBA_3_0/source/smbd/reply.c	2006-12-24 11:13:32 UTC (rev 20338)
@@ -3818,8 +3818,9 @@
 
 	if (!NT_STATUS_IS_OK(status)) {
 
-		if (NT_STATUS_EQUAL(
-			    status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
+		if (!use_nt_status()
+		    && NT_STATUS_EQUAL(status,
+				       NT_STATUS_OBJECT_NAME_COLLISION)) {
 			/*
 			 * Yes, in the DOS error code case we get a
 			 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR



More information about the samba-cvs mailing list