⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 open.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	return True;}/* Map generic permissions to file object specific permissions */                                                                                                               struct generic_mapping file_generic_mapping = {	FILE_GENERIC_READ,	FILE_GENERIC_WRITE,	FILE_GENERIC_EXECUTE,	FILE_GENERIC_ALL};/**************************************************************************** Open a file with a share mode.****************************************************************************/files_struct *open_file_ntcreate(connection_struct *conn,				 const char *fname,				 SMB_STRUCT_STAT *psbuf,				 uint32 access_mask,		/* access bits (FILE_READ_DATA etc.) */				 uint32 share_access,		/* share constants (FILE_SHARE_READ etc). */				 uint32 create_disposition,	/* FILE_OPEN_IF etc. */				 uint32 create_options,		/* options such as delete on close. */				 uint32 new_dos_attributes,	/* attributes used for new file. */				 int oplock_request, 		/* internal Samba oplock codes. */				 				/* Information (FILE_EXISTS etc.) */				 int *pinfo){	int flags=0;	int flags2=0;	BOOL file_existed = VALID_STAT(*psbuf);	BOOL def_acl = False;	BOOL internal_only_open = False;	SMB_DEV_T dev = 0;	SMB_INO_T inode = 0;	BOOL fsp_open = False;	files_struct *fsp = NULL;	mode_t new_unx_mode = (mode_t)0;	mode_t unx_mode = (mode_t)0;	int info;	uint32 existing_dos_attributes = 0;	struct pending_message_list *pml = NULL;	uint16 mid = get_current_mid();	BOOL delayed_for_oplocks = False;	struct timeval request_time = timeval_zero();	struct share_mode_lock *lck = NULL;	NTSTATUS status;	if (conn->printer) {		/* 		 * Printers are handled completely differently.		 * Most of the passed parameters are ignored.		 */		if (pinfo) {			*pinfo = FILE_WAS_CREATED;		}		DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));		return print_fsp_open(conn, fname);	}	/* We add aARCH to this as this mode is only used if the file is	 * created new. */	unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True);	DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "		   "access_mask=0x%x share_access=0x%x "		   "create_disposition = 0x%x create_options=0x%x "		   "unix mode=0%o oplock_request=%d\n",		   fname, new_dos_attributes, access_mask, share_access,		   create_disposition, create_options, unx_mode,		   oplock_request));	if (oplock_request == INTERNAL_OPEN_ONLY) {		internal_only_open = True;		oplock_request = 0;	}	if ((pml = get_open_deferred_message(mid)) != NULL) {		struct deferred_open_record *state =			(struct deferred_open_record *)pml->private_data.data;		request_time = pml->request_time;		delayed_for_oplocks = state->delayed_for_oplocks;		/* There could be a race condition where the dev/inode pair		   has changed since we deferred the message. If so, just		   remove the deferred open entry and return sharing		   violation. */		/* If the timeout value is non-zero, we need to just return		   sharing violation. Don't retry the open as we were not		   notified of a close and we don't want to trigger another		   spurious oplock break. */		/* Now remove the deferred open entry under lock. */		lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL);		if (lck == NULL) {			DEBUG(0, ("could not get share mode lock\n"));		} else {			del_deferred_open_entry(lck, mid);			talloc_destroy(lck);		}		/* Ensure we don't reprocess this message. */		remove_deferred_open_smb_message(mid);	}	if (!check_name(fname,conn)) {		return NULL;	} 	new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;	if (file_existed) {		existing_dos_attributes = dos_mode(conn, fname, psbuf);	}	/* ignore any oplock requests if oplocks are disabled */	if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break ||	    IS_VETO_OPLOCK_PATH(conn, fname)) {		oplock_request = 0;	}	/* this is for OS/2 long file names - say we don't support them */	if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {		/* OS/2 Workplace shell fix may be main code stream in a later		 * release. */ 		set_saved_error_triple(ERRDOS, ERRcannotopen,				       NT_STATUS_OBJECT_NAME_NOT_FOUND);		DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "			 "supported.\n"));		return NULL;	}	switch( create_disposition ) {		/*		 * Currently we're using FILE_SUPERSEDE as the same as		 * FILE_OVERWRITE_IF but they really are		 * different. FILE_SUPERSEDE deletes an existing file		 * (requiring delete access) then recreates it.		 */		case FILE_SUPERSEDE:			/* If file exists replace/overwrite. If file doesn't			 * exist create. */			flags2 |= (O_CREAT | O_TRUNC);			break;		case FILE_OVERWRITE_IF:			/* If file exists replace/overwrite. If file doesn't			 * exist create. */			flags2 |= (O_CREAT | O_TRUNC);			break;		case FILE_OPEN:			/* If file exists open. If file doesn't exist error. */			if (!file_existed) {				DEBUG(5,("open_file_ntcreate: FILE_OPEN "					 "requested for file %s and file "					 "doesn't exist.\n", fname ));				set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);				errno = ENOENT;				return NULL;			}			break;		case FILE_OVERWRITE:			/* If file exists overwrite. If file doesn't exist			 * error. */			if (!file_existed) {				DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "					 "requested for file %s and file "					 "doesn't exist.\n", fname ));				set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);				errno = ENOENT;				return NULL;			}			flags2 |= O_TRUNC;			break;		case FILE_CREATE:			/* If file exists error. If file doesn't exist			 * create. */			if (file_existed) {				DEBUG(5,("open_file_ntcreate: FILE_CREATE "					 "requested for file %s and file "					 "already exists.\n", fname ));				if (S_ISDIR(psbuf->st_mode)) {					errno = EISDIR;				} else {					errno = EEXIST;				}				return NULL;			}			flags2 |= (O_CREAT|O_EXCL);			break;		case FILE_OPEN_IF:			/* If file exists open. If file doesn't exist			 * create. */			flags2 |= O_CREAT;			break;		default:			set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);			return NULL;	}	/* We only care about matching attributes on file exists and	 * overwrite. */	if (file_existed && ((create_disposition == FILE_OVERWRITE) ||			     (create_disposition == FILE_OVERWRITE_IF))) {		if (!open_match_attributes(conn, fname,					   existing_dos_attributes,					   new_dos_attributes, psbuf->st_mode,					   unx_mode, &new_unx_mode)) {			DEBUG(5,("open_file_ntcreate: attributes missmatch "				 "for file %s (%x %x) (0%o, 0%o)\n",				 fname, existing_dos_attributes,				 new_dos_attributes,				 (unsigned int)psbuf->st_mode,				 (unsigned int)unx_mode ));			errno = EACCES;			return NULL;		}	}	/* This is a nasty hack - must fix... JRA. */	if (access_mask == MAXIMUM_ALLOWED_ACCESS) {		access_mask = FILE_GENERIC_ALL;	}	/*	 * Convert GENERIC bits to specific bits.	 */	se_map_generic(&access_mask, &file_generic_mapping);	DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping "		   "access_mask=0x%x\n", fname, access_mask ));	/*	 * Note that we ignore the append flag as append does not	 * mean the same thing under DOS and Unix.	 */	if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) {		flags = O_RDWR;	} else {		flags = O_RDONLY;	}	/*	 * Currently we only look at FILE_WRITE_THROUGH for create options.	 */#if defined(O_SYNC)	if (create_options & FILE_WRITE_THROUGH) {		flags2 |= O_SYNC;	}#endif /* O_SYNC */  	if (!CAN_WRITE(conn)) {		/*		 * We should really return a permission denied error if either		 * O_CREAT or O_TRUNC are set, but for compatibility with		 * older versions of Samba we just AND them out.		 */		flags2 &= ~(O_CREAT|O_TRUNC);	}	/*	 * Ensure we can't write on a read-only share or file.	 */	if (flags != O_RDONLY && file_existed &&	    (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) {		DEBUG(5,("open_file_ntcreate: write access requested for "			 "file %s on read only %s\n",			 fname, !CAN_WRITE(conn) ? "share" : "file" ));		set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);		errno = EACCES;		return NULL;	}	fsp = file_new(conn);	if(!fsp) {		return NULL;	}	fsp->dev = psbuf->st_dev;	fsp->inode = psbuf->st_ino;	fsp->share_access = share_access;	fsp->fh->private_options = create_options;	fsp->access_mask = access_mask;	fsp->oplock_type = oplock_request;	if (timeval_is_zero(&request_time)) {		request_time = fsp->open_time;	}	if (file_existed) {		dev = psbuf->st_dev;		inode = psbuf->st_ino;		lck = get_share_mode_lock(NULL, dev, inode,					conn->connectpath,					fname);		if (lck == NULL) {			DEBUG(0, ("Could not get share mode lock\n"));			set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);			return NULL;		}		if (delay_for_oplocks(lck, fsp)) {			struct deferred_open_record state;			struct timeval timeout;			if (delayed_for_oplocks) {				DEBUG(0, ("Trying to delay for oplocks "					  "twice\n"));				exit_server("exiting");			}			timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);			/* Normally the smbd we asked should respond within			 * OPLOCK_BREAK_TIMEOUT seconds regardless of whether			 * the client did, give twice the timeout as a safety			 * measure here in case the other smbd is stuck			 * somewhere else. */			state.delayed_for_oplocks = True;			state.dev = dev;			state.inode = inode;			if (!request_timed_out(request_time, timeout)) {				defer_open(lck, request_time, timeout,					   &state);			}			talloc_free(lck);			return NULL;		}		status = open_mode_check(conn, fname, lck,					 access_mask, share_access,					 create_options, &file_existed);		if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {			/* DELETE_PENDING is not deferred for a second */			set_saved_ntstatus(status);			talloc_free(lck);			file_free(fsp);			return NULL;		}		if (!NT_STATUS_IS_OK(status)) {			SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));			/* Check if this can be done with the deny_dos and fcb			 * calls. */			if (create_options &			    (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|			     NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {				files_struct *fsp_dup;				fsp_dup = fcb_or_dos_open(conn, fname, dev,							  inode, access_mask,							  share_access,							  create_options);				if (fsp_dup) {					talloc_free(lck);					file_free(fsp);					if (pinfo) {						*pinfo = FILE_WAS_OPENED;					}					conn->num_files_open++;					return fsp_dup;				}			}			/*			 * This next line is a subtlety we need for			 * MS-Access. If a file open will fail due to share			 * permissions and also for security (access) reasons,			 * we need to return the access failed error, not the			 * share error. This means we must attempt to open the			 * file anyway in order to get the UNIX access error -			 * even if we're going to fail the open for share			 * reasons. This is bad, as we're burning another fd			 * if there are existing locks but there's nothing			 * else we can do. We also ensure we're not going to			 * create or tuncate the file as we only want an			 * access decision at this stage. JRA.			 */			errno = 0;			fsp_open = open_file(fsp,conn,fname,psbuf,					     flags|(flags2&~(O_TRUNC|O_CREAT)),					     unx_mode,access_mask);			DEBUG(4,("open_file_ntcreate : share_mode deny - "				 "calling open_file with flags=0x%X "				 "flags2=0x%X mode=0%o returned %d\n",				 flags, (flags2&~(O_TRUNC|O_CREAT)),				 (unsigned int)unx_mode, (int)fsp_open ));			if (!fsp_open && errno) {				/* Default error. */				set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);			}			/* 			 * If we're returning a share violation, ensure we			 * cope with the braindead 1 second delay.			 */			if (!internal_only_open &&			    lp_defer_sharing_violations()) {				struct timeval timeout;				struct deferred_open_record state;				timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT);				state.delayed_for_oplocks = False;				state.dev = dev;				state.inode = inode;				if (!request_timed_out(request_time,						       timeout)) {					defer_open(lck, request_time, timeout,						   &state);				}			}			talloc_free(lck);			if (fsp_open) {				fd_close(conn, fsp);				/*				 * We have detected a sharing violation here				 * so return the correct error code				 */				set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);			}			file_free(fsp);			return NULL;		}		/*		 * We exit this block with the share entry *locked*.....		 */	}	SMB_ASSERT(!file_existed || (lck != NULL));	/*	 * Ensure we pay attention to default ACLs on directories if required.	 */        if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&	    (def_acl = directory_has_default_acl(conn,						 parent_dirname(fname)))) {		unx_mode = 0777;	}	DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",		 (unsigned int)flags, (unsigned int)flags2,		 (unsigned int)unx_mode));	/*	 * open_file strips any O_TRUNC flags itself.	 */	fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,			     access_mask);	if (!fsp_open) {		if (lck != NULL) {			talloc_free(lck);		}		file_free(fsp);		return NULL;	}	if (!file_existed) { 		/*		 * Deal with the race condition where two smbd's detect the		 * file doesn't exist and do the create at the same time. One		 * of them will win and set a share mode, the other (ie. this		 * one) should check if the requested share mode for this		 * create is allowed.		 */		/*		 * Now the file exists and fsp is successfully opened,		 * fsp->dev and fsp->inode are valid and should replace the		 * dev=0,inode=0 from a non existent file. Spotted by		 * Nadav Danieli <nadavd@exanet.com>. JRA.		 */		dev = fsp->dev;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -