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

📄 blocking.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   Blocking Locking functions   Copyright (C) Jeremy Allison 1998-2003      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"/**************************************************************************** This is the structure to queue to implement blocking locks. notify. It consists of the requesting SMB and the expiry time.*****************************************************************************/typedef struct _blocking_lock_record {	struct _blocking_lock_record *next;	struct _blocking_lock_record *prev;	int com_type;	files_struct *fsp;	time_t expire_time;	int lock_num;	SMB_BIG_UINT offset;	SMB_BIG_UINT count;	uint16 lock_pid;	char *inbuf;	int length;} blocking_lock_record;static blocking_lock_record *blocking_lock_queue;/**************************************************************************** Destructor for the above structure.****************************************************************************/static void free_blocking_lock_record(blocking_lock_record *blr){	DLIST_REMOVE(blocking_lock_queue, blr);	SAFE_FREE(blr->inbuf);	SAFE_FREE(blr);}/**************************************************************************** Get the files_struct given a particular queued SMB.*****************************************************************************/static files_struct *get_fsp_from_pkt(char *inbuf){	switch(CVAL(inbuf,smb_com)) {		case SMBlock:		case SMBlockread:			return file_fsp(inbuf,smb_vwv0);		case SMBlockingX:			return file_fsp(inbuf,smb_vwv2);		default:			DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n"));			exit_server("PANIC - unknown type on blocking lock queue");	}	return NULL; /* Keep compiler happy. */}/**************************************************************************** Determine if this is a secondary element of a chained SMB.  **************************************************************************/static BOOL in_chained_smb(void){	return (chain_size != 0);}static void received_unlock_msg(int msg_type, struct process_id src,				void *buf, size_t len);/**************************************************************************** Function to push a blocking lock request onto the lock queue.****************************************************************************/BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,		int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count){	static BOOL set_lock_msg;	blocking_lock_record *blr, *tmp;	BOOL my_lock_ctx = False;	NTSTATUS status;	if(in_chained_smb() ) {		DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));		return False;	}	/*	 * Now queue an entry on the blocking lock queue. We setup	 * the expiration time here.	 */	if((blr = SMB_MALLOC_P(blocking_lock_record)) == NULL) {		DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));		return False;	}	if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) {		DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));		SAFE_FREE(blr);		return False;	}	blr->com_type = CVAL(inbuf,smb_com);	blr->fsp = get_fsp_from_pkt(inbuf);	blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;	blr->lock_num = lock_num;	blr->lock_pid = lock_pid;	blr->offset = offset;	blr->count = count;	memcpy(blr->inbuf, inbuf, length);	blr->length = length;	/* Add a pending lock record for this. */	status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,			lock_pid, procid_self(), blr->fsp->conn->cnum,			offset, count, PENDING_LOCK, &my_lock_ctx);	if (!NT_STATUS_IS_OK(status)) {		DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));		free_blocking_lock_record(blr);		return False;	}	DLIST_ADD_END(blocking_lock_queue, blr, tmp);	/* Ensure we'll receive messages when this is unlocked. */	if (!set_lock_msg) {		message_register(MSG_SMB_UNLOCK, received_unlock_msg);		set_lock_msg = True;	}	DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout,		blr->fsp->fnum, blr->fsp->fsp_name ));	/* Push the MID of this packet on the signing queue. */	srv_defer_sign_response(SVAL(inbuf,smb_mid));	return True;}/**************************************************************************** Return a smd with a given size.*****************************************************************************/static void send_blocking_reply(char *outbuf, int outsize){	if(outsize > 4)		smb_setlen(outbuf,outsize - 4);	if (!send_smb(smbd_server_fd(),outbuf))		exit_server("send_blocking_reply: send_smb failed.");}/**************************************************************************** Return a lockingX success SMB.*****************************************************************************/static void reply_lockingX_success(blocking_lock_record *blr){	char *outbuf = get_OutBuffer();	int bufsize = BUFFER_SIZE;	char *inbuf = blr->inbuf;	int outsize = 0;	construct_reply_common(inbuf, outbuf);	set_message(outbuf,2,0,True);	/*	 * As this message is a lockingX call we must handle	 * any following chained message correctly.	 * This is normally handled in construct_reply(),	 * but as that calls switch_message, we can't use	 * that here and must set up the chain info manually.	 */	outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);	outsize += chain_size;	send_blocking_reply(outbuf,outsize);}/**************************************************************************** Return a generic lock fail error blocking call.*****************************************************************************/static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status){	char *outbuf = get_OutBuffer();	char *inbuf = blr->inbuf;	construct_reply_common(inbuf, outbuf);	/* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to	   FILE_LOCK_CONFLICT! (tridge) */	if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {		status = NT_STATUS_FILE_LOCK_CONFLICT;	}	ERROR_NT(status);	if (!send_smb(smbd_server_fd(),outbuf))		exit_server("generic_blocking_lock_error: send_smb failed.");}/**************************************************************************** Return a lock fail error for a lockingX call. Undo all the locks we have  obtained first.*****************************************************************************/static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status){	char *inbuf = blr->inbuf;	files_struct *fsp = blr->fsp;	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));	uint16 num_ulocks = SVAL(inbuf,smb_vwv6);	SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0;	uint16 lock_pid;	unsigned char locktype = CVAL(inbuf,smb_vwv3);	BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);	char *data;	int i;	data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks);		/* 	 * Data now points at the beginning of the list	 * of smb_lkrng structs.	 */	/*	 * Ensure we don't do a remove on the lock that just failed,	 * as under POSIX rules, if we have a lock already there, we	 * will delete it (and we shouldn't) .....	 */		for(i = blr->lock_num - 1; i >= 0; i--) {		BOOL err;				lock_pid = get_lock_pid( data, i, large_file_format);		count = get_lock_count( data, i, large_file_format);		offset = get_lock_offset( data, i, large_file_format, &err);				/*		 * We know err cannot be set as if it was the lock		 * request would never have been queued. JRA.		 */				do_unlock(fsp,conn,lock_pid,count,offset);	}		generic_blocking_lock_error(blr, status);}/**************************************************************************** Return a lock fail error.*****************************************************************************/static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status){	switch(blr->com_type) {	case SMBlock:	case SMBlockread:		generic_blocking_lock_error(blr, status);		break;	case SMBlockingX:		reply_lockingX_error(blr, status);		break;	default:		DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));		exit_server("PANIC - unknown type on blocking lock queue");	}}/**************************************************************************** Attempt to finish off getting all pending blocking locks for a lockread call. Returns True if we want to be removed from the list.*****************************************************************************/static BOOL process_lockread(blocking_lock_record *blr){	char *outbuf = get_OutBuffer();	char *inbuf = blr->inbuf;	ssize_t nread = -1;	char *data, *p;	int outsize = 0;	SMB_BIG_UINT startpos;	size_t numtoread;	NTSTATUS status;	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));	files_struct *fsp = blr->fsp;	BOOL my_lock_ctx = False;	numtoread = SVAL(inbuf,smb_vwv1);	startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2);		numtoread = MIN(BUFFER_SIZE-outsize,numtoread);	data = smb_buf(outbuf) + 3; 	status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx);	if (NT_STATUS_V(status)) {		if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&			!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {			/*			 * We have other than a "can't get lock"			 * error. Send an error.			 * Return True so we get dequeued.			 */			generic_blocking_lock_error(blr, status);			return True;		}		/*		 * Still waiting for lock....		 */				DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n",			  fsp->fsp_name));		return False;	}	nread = read_file(fsp,data,startpos,numtoread);	if (nread < 0) {		generic_blocking_lock_error(blr,NT_STATUS_ACCESS_DENIED);		return True;	}		construct_reply_common(inbuf, outbuf);	outsize = set_message(outbuf,5,0,True);		outsize += nread;	SSVAL(outbuf,smb_vwv0,nread);	SSVAL(outbuf,smb_vwv5,nread+3);	p = smb_buf(outbuf);	*p++ = 1;	SSVAL(p,0,nread); p += 2;

⌨️ 快捷键说明

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