svn commit: samba r13825 - in trunk/source: include libsmb smbd

jra at samba.org jra at samba.org
Fri Mar 3 21:43:22 GMT 2006


Author: jra
Date: 2006-03-03 21:43:21 +0000 (Fri, 03 Mar 2006)
New Revision: 13825

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

Log:
First prototype of F_GETLK.
Jeremy.

Modified:
   trunk/source/include/trans2.h
   trunk/source/libsmb/errormap.c
   trunk/source/smbd/trans2.c


Changeset:
Modified: trunk/source/include/trans2.h
===================================================================
--- trunk/source/include/trans2.h	2006-03-03 20:49:31 UTC (rev 13824)
+++ trunk/source/include/trans2.h	2006-03-03 21:43:21 UTC (rev 13825)
@@ -441,7 +441,9 @@
 #define SMB_QUERY_ATTR_FLAGS           0x206 /* chflags, chattr */
 #define SMB_SET_ATTR_FLAGS             0x206 
 #define SMB_QUERY_POSIX_PERMISSION     0x207
+/* Only valid for qfileinfo */
 #define SMB_QUERY_POSIX_LOCK	       0x208
+/* Only valid for setfileinfo */
 #define SMB_SET_POSIX_LOCK	       0x208
 
 /* Transact 2 Find First levels */

Modified: trunk/source/libsmb/errormap.c
===================================================================
--- trunk/source/libsmb/errormap.c	2006-03-03 20:49:31 UTC (rev 13824)
+++ trunk/source/libsmb/errormap.c	2006-03-03 21:43:21 UTC (rev 13825)
@@ -407,7 +407,7 @@
 	{ERRHRD,	ERRgeneral,	NT_STATUS_APP_INIT_FAILURE},
 	{ERRHRD,	ERRgeneral,	NT_STATUS_PAGEFILE_CREATE_FAILED},
 	{ERRHRD,	ERRgeneral,	NT_STATUS_NO_PAGEFILE},
-	{ERRDOS,	124,	NT_STATUS_INVALID_LEVEL},
+	{ERRDOS,	ERRunknownlevel,	NT_STATUS_INVALID_LEVEL},
 	{ERRDOS,	86,	NT_STATUS_WRONG_PASSWORD_CORE},
 	{ERRHRD,	ERRgeneral,	NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
 	{ERRDOS,	109,	NT_STATUS_PIPE_BROKEN},
@@ -680,7 +680,7 @@
 	{ERRDOS,	121,	NT_STATUS_IO_TIMEOUT},
 	{ERRDOS,	122,	NT_STATUS_BUFFER_TOO_SMALL},
 	{ERRDOS,	ERRinvalidname,	NT_STATUS_OBJECT_NAME_INVALID},
-	{ERRDOS,	124,	NT_STATUS_INVALID_LEVEL},
+	{ERRDOS,	ERRunknownlevel,	NT_STATUS_INVALID_LEVEL},
 	{ERRDOS,	126,	NT_STATUS_DLL_NOT_FOUND},
 	{ERRDOS,	127,	NT_STATUS_PROCEDURE_NOT_FOUND},
 	{ERRDOS,	145,	NT_STATUS_DIRECTORY_NOT_EMPTY},

Modified: trunk/source/smbd/trans2.c
===================================================================
--- trunk/source/smbd/trans2.c	2006-03-03 20:49:31 UTC (rev 13824)
+++ trunk/source/smbd/trans2.c	2006-03-03 21:43:21 UTC (rev 13825)
@@ -1642,11 +1642,12 @@
 		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
 			break;
 		case SMB_FIND_FILE_UNIX:
-			if (!lp_unix_extensions())
-				return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+			if (!lp_unix_extensions()) {
+				return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+			}
 			break;
 		default:
-			return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 	srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
@@ -1925,11 +1926,12 @@
 		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
 			break;
 		case SMB_FIND_FILE_UNIX:
-			if (!lp_unix_extensions())
-				return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+			if (!lp_unix_extensions()) {
+				return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+			}
 			break;
 		default:
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 	if (info_level == SMB_FIND_EA_LIST) {
@@ -2397,8 +2399,9 @@
 		 */
 
 		case SMB_QUERY_CIFS_UNIX_INFO:
-			if (!lp_unix_extensions())
-				return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			if (!lp_unix_extensions()) {
+				return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+			}
 			data_len = 12;
 			SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
 			SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
@@ -2414,9 +2417,10 @@
 			int rc;
 			vfs_statvfs_struct svfs;
 
-			if (!lp_unix_extensions())
-				return ERROR_DOS(ERRDOS,ERRunknownlevel);
-			
+			if (!lp_unix_extensions()) {
+				return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+			}
+
 			rc = SMB_VFS_STATVFS(conn, ".", &svfs);
 
 			if (!rc) {
@@ -2432,7 +2436,7 @@
 				DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
 #ifdef EOPNOTSUPP
 			} else if (rc == EOPNOTSUPP) {
-				return ERROR_DOS(ERRDOS, ERRunknownlevel);
+				return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 #endif /* EOPNOTSUPP */
 			} else {
 				DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
@@ -2453,7 +2457,7 @@
 			}
 			/* drop through */
 		default:
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 
@@ -2497,7 +2501,7 @@
 				uint32 client_unix_cap_high;
 
 				if (!lp_unix_extensions()) {
-					return ERROR_DOS(ERRDOS,ERRunknownlevel);
+					return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 				}
 
 				/* There should be 12 bytes of capabilities set. */
@@ -2600,7 +2604,7 @@
 		default:
 			DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
 				info_level));
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 			break;
 	}
 
@@ -2775,13 +2779,14 @@
 	char *fullpathname;
 	char *base_name;
 	char *p;
+	char *lock_data;
 	SMB_OFF_T pos = 0;
 	BOOL bad_path = False;
 	BOOL delete_pending = False;
 	int len;
 	time_t c_time;
 	files_struct *fsp = NULL;
-	TALLOC_CTX *ea_ctx = NULL;
+	TALLOC_CTX *data_ctx = NULL;
 	struct ea_list *ea_list = NULL;
 	uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
 
@@ -2900,8 +2905,9 @@
 		nlink -= 1;
 	}
 
-	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
-		return ERROR_DOS(ERRDOS,ERRunknownlevel);
+	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+		return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+	}
 
 	DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
 		fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
@@ -2920,40 +2926,68 @@
 	if (!(mode & aDIR))
 		file_size = get_file_size(sbuf);
 
-	/* Pull any EA list from the data portion. */
-	if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
-		uint32 ea_size;
+	/* Pull out any data sent here before we realloc. */
+	switch (info_level) {
+		case SMB_INFO_QUERY_EAS_FROM_LIST:
+		{
+			/* Pull any EA list from the data portion. */
+			uint32 ea_size;
 
-		if (total_data < 4) {
-			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-		}
-		ea_size = IVAL(pdata,0);
+			if (total_data < 4) {
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
+			ea_size = IVAL(pdata,0);
 
-		if (total_data > 0 && ea_size != total_data) {
-			DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
+			if (total_data > 0 && ea_size != total_data) {
+				DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-		}
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
 
-		if (!lp_ea_support(SNUM(conn))) {
-			return ERROR_DOS(ERRDOS,ERReasnotsupported);
-		}
+			if (!lp_ea_support(SNUM(conn))) {
+				return ERROR_DOS(ERRDOS,ERReasnotsupported);
+			}
 
-		if ((ea_ctx = talloc_init("ea_list")) == NULL) {
-			return ERROR_NT(NT_STATUS_NO_MEMORY);
+			if ((data_ctx = talloc_init("ea_list")) == NULL) {
+				return ERROR_NT(NT_STATUS_NO_MEMORY);
+			}
+
+			/* Pull out the list of names. */
+			ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
+			if (!ea_list) {
+				talloc_destroy(data_ctx);
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
+			break;
 		}
+		case SMB_QUERY_POSIX_LOCK:
+		{
+			if (fsp == NULL || fsp->fh->fd == -1) {
+				return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+			}
 
-		/* Pull out the list of names. */
-		ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
-		if (!ea_list) {
-			talloc_destroy(ea_ctx);
-			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			if (total_data != POSIX_LOCK_DATA_SIZE) {
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
+
+			if ((data_ctx = talloc_init("lock_request")) == NULL) {
+				return ERROR_NT(NT_STATUS_NO_MEMORY);
+			}
+
+			/* Copy the lock range data. */
+			lock_data = talloc_memdup(data_ctx, pdata, total_data);
+			if (!lock_data) {
+				talloc_destroy(data_ctx);
+				return ERROR_NT(NT_STATUS_NO_MEMORY);
+			}
 		}
+		default:
+			break;
 	}
 
 	params = SMB_REALLOC(*pparams,2);
 	if (params == NULL) {
-		talloc_destroy(ea_ctx);
+		talloc_destroy(data_ctx);
 		return ERROR_NT(NT_STATUS_NO_MEMORY);
 	}
 	*pparams = params;
@@ -2961,7 +2995,7 @@
 	data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
 	pdata = SMB_REALLOC(*ppdata, data_size); 
 	if ( pdata == NULL ) {
-		talloc_destroy(ea_ctx);
+		talloc_destroy(data_ctx);
 		return ERROR_NT(NT_STATUS_NO_MEMORY);
 	}
 	*ppdata = pdata;
@@ -3047,18 +3081,18 @@
 
 			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
 
-			ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
+			ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
 			ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
 
 			if (!ea_list || (total_ea_len > data_size)) {
-				talloc_destroy(ea_ctx);
+				talloc_destroy(data_ctx);
 				data_size = 4;
 				SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
 				break;
 			}
 
-			data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
-			talloc_destroy(ea_ctx);
+			data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
+			talloc_destroy(data_ctx);
 			break;
 		}
 
@@ -3069,21 +3103,21 @@
 
 			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
 
-			ea_ctx = talloc_init("ea_ctx");
-			if (!ea_ctx) {
+			data_ctx = talloc_init("ea_ctx");
+			if (!data_ctx) {
 				return ERROR_NT(NT_STATUS_NO_MEMORY);
 			}
 
-			ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
+			ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
 			if (!ea_list || (total_ea_len > data_size)) {
-				talloc_destroy(ea_ctx);
+				talloc_destroy(data_ctx);
 				data_size = 4;
 				SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
 				break;
 			}
 
-			data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
-			talloc_destroy(ea_ctx);
+			data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
+			talloc_destroy(data_ctx);
 			break;
 		}
 
@@ -3476,8 +3510,66 @@
 			}
 #endif
 
+		case SMB_QUERY_POSIX_LOCK:
+		{
+			NTSTATUS status;
+			SMB_BIG_UINT count;
+			SMB_BIG_UINT offset;
+			uint16 lock_pid;
+			enum brl_type lock_type;
+
+			switch (SVAL(lock_data, POSIX_LOCK_TYPE_OFFSET)) {
+				case POSIX_LOCK_TYPE_READ:
+					lock_type = READ_LOCK;
+					break;
+				case POSIX_LOCK_TYPE_WRITE:
+					lock_type = WRITE_LOCK;
+					break;
+				case POSIX_LOCK_TYPE_UNLOCK:
+				default:
+					/* There's no point in asking for an unlock... */
+					talloc_destroy(data_ctx);
+					return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
+
+			lock_pid = (uint16)IVAL(lock_data, POSIX_LOCK_PID_OFFSET);
+#if defined(HAVE_LONGLONG)
+			offset = (((SMB_BIG_UINT) IVAL(lock_data,(POSIX_LOCK_START_OFFSET+4))) << 32) |
+					((SMB_BIG_UINT) IVAL(lock_data,POSIX_LOCK_START_OFFSET));
+			count = (((SMB_BIG_UINT) IVAL(lock_data,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
+					((SMB_BIG_UINT) IVAL(lock_data,POSIX_LOCK_LEN_OFFSET));
+#else /* HAVE_LONGLONG */
+			offset = (SMB_BIG_UINT)IVAL(lock_data,POSIX_LOCK_START_OFFSET);
+			count = (SMB_BIG_UINT)IVAL(lock_data,POSIX_LOCK_LEN_OFFSET);
+#endif /* HAVE_LONGLONG */
+
+#if 0
+			/* We need a vfs change to get data on already locked regions... */
+			status = do_lock(fsp,
+					lock_pid,
+					count,
+					offset,
+					lock_type,
+					POSIX_LOCK,
+					&my_lock_ctx);
+#endif
+
+			if (!NT_STATUS_IS_OK(status)) {
+				/* Here we need to report who has it locked... */
+				data_size = POSIX_LOCK_DATA_SIZE;
+				memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
+			} else {
+				/* For success we just return a copy of what we sent
+				   with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
+				data_size = POSIX_LOCK_DATA_SIZE;
+				memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
+				SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET,POSIX_LOCK_TYPE_UNLOCK);
+			}
+			break;
+		}
+
 		default:
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 	send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
@@ -3681,8 +3773,9 @@
 	if (!CAN_WRITE(conn))
 		return ERROR_DOS(ERRSRV,ERRaccess);
 
-	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
-		return ERROR_DOS(ERRDOS,ERRunknownlevel);
+	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+		return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+	}
 
 	if (VALID_STAT(sbuf))
 		unixmode = sbuf.st_mode;
@@ -3850,8 +3943,10 @@
 #ifdef LARGE_SMB_OFF_T
 			allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
-			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
-				return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			if (IVAL(pdata,4) != 0) {
+				/* more than 32 bits? */
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
 #endif /* LARGE_SMB_OFF_T */
 			DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
 					fname, (double)allocation_size ));
@@ -3917,8 +4012,10 @@
 #ifdef LARGE_SMB_OFF_T
 			size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
-			if (IVAL(pdata,4) != 0)	/* more than 32 bits? */
-				return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			if (IVAL(pdata,4) != 0)	{
+				/* more than 32 bits? */
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
 #endif /* LARGE_SMB_OFF_T */
 			DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
 			break;
@@ -3971,8 +4068,10 @@
 #ifdef LARGE_SMB_OFF_T
 			position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
-			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
-				return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			if (IVAL(pdata,4) != 0) {
+				/* more than 32 bits? */
+				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+			}
 #endif /* LARGE_SMB_OFF_T */
 			DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
 					fname, (double)position_information ));
@@ -4028,8 +4127,10 @@
 #ifdef LARGE_SMB_OFF_T
 				size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
-				if (IVAL(pdata,4) != 0)	/* more than 32 bits? */
-					return ERROR_DOS(ERRDOS,ERRunknownlevel);
+				if (IVAL(pdata,4) != 0)	{
+					/* more than 32 bits? */
+					return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+				}
 #endif /* LARGE_SMB_OFF_T */
 			}
 			pdata+=24;          /* ctime & st_blocks are not changed */
@@ -4349,7 +4450,7 @@
 				return ERROR_NT(NT_STATUS_INVALID_HANDLE);
 			}
 
-			if (total_data < POSIX_LOCK_DATA_SIZE) {
+			if (total_data != POSIX_LOCK_DATA_SIZE) {
 				return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 			}
 
@@ -4358,6 +4459,10 @@
 					lock_type = READ_LOCK;
 					break;
 				case POSIX_LOCK_TYPE_WRITE:
+					/* Return the right POSIX-mappable error code for files opened read-only. */
+					if (!fsp->can_write) {
+						return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+					}
 					lock_type = WRITE_LOCK;
 					break;
 				case POSIX_LOCK_TYPE_UNLOCK:
@@ -4414,7 +4519,7 @@
 		}
 
 		default:
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 	/* get some defaults (no modifications) if any info is zero or -1. */
@@ -4666,7 +4771,7 @@
 		case 2:
 			break;
 		default:
-			return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			return ERROR_NT(NT_STATUS_INVALID_LEVEL);
 	}
 
 	/* Realloc the parameter and data sizes */



More information about the samba-cvs mailing list