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

📄 posix.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));		goto fail;	}	/* There are existing locks - find a match. */	locks = (struct posix_lock *)dbuf.dptr;	count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));	/*	 * Search for and delete the first record that matches the	 * unlock criteria.	 */	for (i=0; i<count; i++) { 		struct posix_lock *entry = &locks[i];		if (entry->fd == fsp->fh->fd &&			entry->start == start &&			entry->size == size) {			/* Make a copy if requested. */			if (pl)				*pl = *entry;			/* Found it - delete it. */			if (count == 1) {				tdb_delete(posix_lock_tdb, kbuf);			} else {				if (i < count-1) {					memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i));				}				dbuf.dsize -= sizeof(struct posix_lock);				tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);			}			count--;			found = True;			break;		}	}	if (!found)		goto fail;	/*	 * Count the number of entries that are	 * overlapped by this unlock request.	 */	for (i = 0; i < count; i++) {		struct posix_lock *entry = &locks[i];		if (fsp->fh->fd == entry->fd &&			does_lock_overlap( start, size, entry->start, entry->size))				num_overlapping_records++;	}	DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",			posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size,				(unsigned int)num_overlapping_records ));	SAFE_FREE(dbuf.dptr);	return num_overlapping_records; fail:	SAFE_FREE(dbuf.dptr);	return -1;}/**************************************************************************** Utility function to map a lock type correctly depending on the open mode of a file.****************************************************************************/static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type){	if((lock_type == WRITE_LOCK) && !fsp->can_write) {		/*		 * Many UNIX's cannot get a write lock on a file opened read-only.		 * Win32 locking semantics allow this.		 * Do the best we can and attempt a read-only lock.		 */		DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));		return F_RDLCK;	}#if 0	/* We no longer open files write-only. */	 else if((lock_type == READ_LOCK) && !fsp->can_read) {		/*		 * Ditto for read locks on write only files.		 */		DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));		return F_WRLCK;	}#endif	/*	 * This return should be the most normal, as we attempt	 * to always open files read/write.	 */	return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;}/**************************************************************************** Check to see if the given unsigned lock range is within the possible POSIX range. Modifies the given args to be in range if possible, just returns False if not.****************************************************************************/static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,				SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count){	SMB_OFF_T offset = (SMB_OFF_T)u_offset;	SMB_OFF_T count = (SMB_OFF_T)u_count;	/*	 * For the type of system we are, attempt to	 * find the maximum positive lock offset as an SMB_OFF_T.	 */#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */	SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)	/*	 * In this case SMB_OFF_T is 64 bits,	 * and the underlying system can handle 64 bit signed locks.	 */	SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);	SMB_OFF_T mask = (mask2<<1);	SMB_OFF_T max_positive_lock_offset = ~mask;#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */	/*	 * In this case either SMB_OFF_T is 32 bits,	 * or the underlying system cannot handle 64 bit signed locks.	 * All offsets & counts must be 2^31 or less.	 */	SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */	/*	 * POSIX locks of length zero mean lock to end-of-file.	 * Win32 locks of length zero are point probes. Ignore	 * any Win32 locks of length zero. JRA.	 */	if (count == (SMB_OFF_T)0) {		DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));		return False;	}	/*	 * If the given offset was > max_positive_lock_offset then we cannot map this at all	 * ignore this lock.	 */	if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {		DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",				(double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));		return False;	}	/*	 * We must truncate the count to less than max_positive_lock_offset.	 */	if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset))		count = max_positive_lock_offset;	/*	 * Truncate count to end at max lock offset.	 */	if (offset + count < 0 || offset + count > max_positive_lock_offset)		count = max_positive_lock_offset - offset;	/*	 * If we ate all the count, ignore this lock.	 */	if (count == 0) {		DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",				(double)u_offset, (double)u_count ));		return False;	}	/*	 * The mapping was successful.	 */	DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",			(double)offset, (double)count ));	*offset_out = offset;	*count_out = count;		return True;}/**************************************************************************** Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and broken NFS implementations.****************************************************************************/static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type){	int ret;	DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));	ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);	if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {		DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",					(double)offset,(double)count));		DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));		DEBUG(0,("on 32 bit NFS mounted file systems.\n"));		/*		 * If the offset is > 0x7FFFFFFF then this will cause problems on		 * 32 bit NFS mounted filesystems. Just ignore it.		 */		if (offset & ~((SMB_OFF_T)0x7fffffff)) {			DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));			return True;		}		if (count & ~((SMB_OFF_T)0x7fffffff)) {			/* 32 bit NFS file system, retry with smaller offset */			DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));			errno = 0;			count &= 0x7fffffff;			ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);		}	}	DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));	return ret;}/**************************************************************************** POSIX function to see if a file region is locked. Returns True if the region is locked, False otherwise.****************************************************************************/BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type){	SMB_OFF_T offset;	SMB_OFF_T count;	int posix_lock_type = map_posix_lock_type(fsp,lock_type);	DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",			fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));	/*	 * If the requested lock won't fit in the POSIX range, we will	 * never set it, so presume it is not locked.	 */	if(!posix_lock_in_range(&offset, &count, u_offset, u_count))		return False;	/*	 * Note that most UNIX's can *test* for a write lock on	 * a read-only fd, just not *set* a write lock on a read-only	 * fd. So we don't need to use map_lock_type here.	 */ 	return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type);}/* * Structure used when splitting a lock range * into a POSIX lock range. Doubly linked list. */struct lock_list {	struct lock_list *next;	struct lock_list *prev;	SMB_OFF_T start;	SMB_OFF_T size;};/**************************************************************************** Create a list of lock ranges that don't overlap a given range. Used in calculating POSIX locks and unlocks. This is a difficult function that requires ASCII art to understand it :-).****************************************************************************/static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	struct posix_lock *locks;	size_t num_locks, i;	dbuf.dptr = NULL;	dbuf = tdb_fetch(posix_lock_tdb, kbuf);	if (!dbuf.dptr)		return lhead;		locks = (struct posix_lock *)dbuf.dptr;	num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock));	/*	 * Check the current lock list on this dev/inode pair.	 * Quit if the list is deleted.	 */	DEBUG(10,("posix_lock_list: curr: start=%.0f,size=%.0f\n",		(double)lhead->start, (double)lhead->size ));	for (i=0; i<num_locks && lhead; i++) {		struct posix_lock *lock = &locks[i];		struct lock_list *l_curr;		/*		 * Walk the lock list, checking for overlaps. Note that		 * the lock list can expand within this loop if the current		 * range being examined needs to be split.		 */		for (l_curr = lhead; l_curr;) {			DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd,				(double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) ));			if ( (l_curr->start >= (lock->start + lock->size)) ||				 (lock->start >= (l_curr->start + l_curr->size))) {				/* No overlap with this lock - leave this range alone. *//*********************************************                                             +---------+                                             | l_curr  |                                             +---------+                                +-------+                                | lock  |                                +-------+OR....             +---------+             |  l_curr |             +---------+**********************************************/				DEBUG(10,("no overlap case.\n" ));				l_curr = l_curr->next;			} else if ( (l_curr->start >= lock->start) &&						(l_curr->start + l_curr->size <= lock->start + lock->size) ) {				/*				 * This unlock is completely overlapped by this existing lock range				 * and thus should have no effect (not be unlocked). Delete it from the list.				 *//*********************************************                +---------+                |  l_curr |                +---------+        +---------------------------+        |       lock                |        +---------------------------+**********************************************/				/* Save the next pointer */				struct lock_list *ul_next = l_curr->next;				DEBUG(10,("delete case.\n" ));				DLIST_REMOVE(lhead, l_curr);				if(lhead == NULL)					break; /* No more list... */				l_curr = ul_next;							} else if ( (l_curr->start >= lock->start) &&						(l_curr->start < lock->start + lock->size) &&						(l_curr->start + l_curr->size > lock->start + lock->size) ) {				/*				 * This unlock overlaps the existing lock range at the high end.				 * Truncate by moving start to existing range end and reducing size.				 *//*********************************************                +---------------+                |  l_curr       |                +---------------+        +---------------+        |    lock       |        +---------------+BECOMES....                        +-------+                        | l_curr|                        +-------+**********************************************/				l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);				l_curr->start = lock->start + lock->size;				DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n",								(double)l_curr->start, (double)l_curr->size ));				l_curr = l_curr->next;			} else if ( (l_curr->start < lock->start) &&						(l_curr->start + l_curr->size > lock->start) &&						(l_curr->start + l_curr->size <= lock->start + lock->size) ) {				/*				 * This unlock overlaps the existing lock range at the low end.				 * Truncate by reducing size.				 *//*********************************************   +---------------+   |  l_curr       |   +---------------+           +---------------+           |    lock       |           +---------------+BECOMES....   +-------+   | l_curr|   +-------+**********************************************/				l_curr->size = lock->start - l_curr->start;

⌨️ 快捷键说明

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