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

📄 posix.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    Unix SMB/CIFS implementation.   Locking functions   Copyright (C) Jeremy Allison 1992-2000      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.   Revision History:   POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.*/#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_LOCKING/* * The POSIX locking database handle. */static TDB_CONTEXT *posix_lock_tdb;/* * The pending close database handle. */static TDB_CONTEXT *posix_pending_close_tdb;/* * The data in POSIX lock records is an unsorted linear array of these * records.  It is unnecessary to store the count as tdb provides the * size of the record. */struct posix_lock {	int fd;	SMB_OFF_T start;	SMB_OFF_T size;	int lock_type;};/* * The data in POSIX pending close records is an unsorted linear array of int * records.  It is unnecessary to store the count as tdb provides the * size of the record. *//* The key used in both the POSIX databases. */struct posix_lock_key {	SMB_DEV_T device;	SMB_INO_T inode;}; /******************************************************************* Form a static locking key for a dev/inode pair.******************************************************************/static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode){	static struct posix_lock_key key;	TDB_DATA kbuf;	memset(&key, '\0', sizeof(key));	key.device = dev;	key.inode = inode;	kbuf.dptr = (char *)&key;	kbuf.dsize = sizeof(key);	return kbuf;}/******************************************************************* Convenience function to get a key from an fsp.******************************************************************/static TDB_DATA locking_key_fsp(files_struct *fsp){	return locking_key(fsp->dev, fsp->inode);}/**************************************************************************** Add an fd to the pending close tdb.****************************************************************************/static BOOL add_fd_to_close_entry(files_struct *fsp){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	char *tp;	dbuf.dptr = NULL;	dbuf.dsize = 0;	dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);	tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));	if (!tp) {		DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));		SAFE_FREE(dbuf.dptr);		return False;	} else		dbuf.dptr = tp;	memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));	dbuf.dsize += sizeof(int);	if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {		DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));	}	SAFE_FREE(dbuf.dptr);	return True;}/**************************************************************************** Remove all fd entries for a specific dev/inode pair from the tdb.****************************************************************************/static void delete_close_entries(files_struct *fsp){	TDB_DATA kbuf = locking_key_fsp(fsp);	if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)		DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));}/**************************************************************************** Get the array of POSIX pending close records for an open fsp. Caller must free. Returns number of entries.****************************************************************************/static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	size_t count = 0;	*entries = NULL;	dbuf.dptr = NULL;	dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);	if (!dbuf.dptr) {		return 0;	}	*entries = (int *)dbuf.dptr;	count = (size_t)(dbuf.dsize / sizeof(int));	return count;}/**************************************************************************** Get the array of POSIX locks for an fsp. Caller must free. Returns number of entries.****************************************************************************/static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	size_t count = 0;	*entries = NULL;	dbuf.dptr = NULL;	dbuf = tdb_fetch(posix_lock_tdb, kbuf);	if (!dbuf.dptr) {		return 0;	}	*entries = (struct posix_lock *)dbuf.dptr;	count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));	return count;}/**************************************************************************** Deal with pending closes needed by POSIX locking support. Note that posix_locking_close_file() is expected to have been called to delete all locks on this fsp before this function is called.****************************************************************************/int fd_close_posix(struct connection_struct *conn, files_struct *fsp){	int saved_errno = 0;	int ret;	size_t count, i;	struct posix_lock *entries = NULL;	int *fd_array = NULL;	BOOL locks_on_other_fds = False;	if (!lp_posix_locking(SNUM(conn))) {		/*		 * No POSIX to worry about, just close.		 */		ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);		fsp->fh->fd = -1;		return ret;	}	/*	 * Get the number of outstanding POSIX locks on this dev/inode pair.	 */	count = get_posix_lock_entries(fsp, &entries);	/*	 * Check if there are any outstanding locks belonging to	 * other fd's. This should never be the case if posix_locking_close_file()	 * has been called first, but it never hurts to be *sure*.	 */	for (i = 0; i < count; i++) {		if (entries[i].fd != fsp->fh->fd) {			locks_on_other_fds = True;			break;		}	}	if (locks_on_other_fds) {		/*		 * There are outstanding locks on this dev/inode pair on other fds.		 * Add our fd to the pending close tdb and set fsp->fh->fd to -1.		 */		if (!add_fd_to_close_entry(fsp)) {			SAFE_FREE(entries);			return -1;		}		SAFE_FREE(entries);		fsp->fh->fd = -1;		return 0;	}	SAFE_FREE(entries);	/*	 * No outstanding POSIX locks. Get the pending close fd's	 * from the tdb and close them all.	 */	count = get_posix_pending_close_entries(fsp, &fd_array);	if (count) {		DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));		for(i = 0; i < count; i++) {			if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {				saved_errno = errno;			}		}		/*		 * Delete all fd's stored in the tdb		 * for this dev/inode pair.		 */		delete_close_entries(fsp);	}	SAFE_FREE(fd_array);	/*	 * Finally close the fd associated with this fsp.	 */	ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);	if (saved_errno != 0) {		errno = saved_errno;		ret = -1;	} 	fsp->fh->fd = -1;	return ret;}/**************************************************************************** Debugging aid :-).****************************************************************************/static const char *posix_lock_type_name(int lock_type){	return (lock_type == F_RDLCK) ? "READ" : "WRITE";}/**************************************************************************** Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but then the POSIX fcntl lock fails.****************************************************************************/static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	struct posix_lock *locks;	size_t count;	dbuf.dptr = NULL;		dbuf = tdb_fetch(posix_lock_tdb, kbuf);	if (!dbuf.dptr) {		DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));		goto fail;	}	count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));	locks = (struct posix_lock *)dbuf.dptr;	if (count == 1) {		tdb_delete(posix_lock_tdb, kbuf);	} else {		if (entry < count-1) {			memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry));		}		dbuf.dsize -= sizeof(struct posix_lock);		tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);	}	SAFE_FREE(dbuf.dptr);	return True; fail:	SAFE_FREE(dbuf.dptr);	return False;}/**************************************************************************** Add an entry into the POSIX locking tdb. We return the index number of the added lock (used in case we need to delete *exactly* this entry). Returns False on fail, True on success.****************************************************************************/static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	struct posix_lock pl;	char *tp;	dbuf.dptr = NULL;	dbuf.dsize = 0;	dbuf = tdb_fetch(posix_lock_tdb, kbuf);	*pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));	/*	 * Add new record.	 */	pl.fd = fsp->fh->fd;	pl.start = start;	pl.size = size;	pl.lock_type = lock_type;	tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));	if (!tp) {		DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));		goto fail;	} else		dbuf.dptr = tp;	memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));	dbuf.dsize += sizeof(struct posix_lock);	if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {		DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name));		goto fail;	}	SAFE_FREE(dbuf.dptr);	DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n",			fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,			(double)fsp->dev, (double)fsp->inode ));	return True; fail:	SAFE_FREE(dbuf.dptr);	return False;}/**************************************************************************** Calculate if locks have any overlap at all.****************************************************************************/static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2){	if (start1 >= start2 && start1 <= start2 + size2)		return True;	if (start1 < start2 && start1 + size1 > start2)		return True;	return False;}/**************************************************************************** Delete an entry from the POSIX locking tdb. Returns a copy of the entry being deleted and the number of records that are overlapped by this one, or -1 on error.****************************************************************************/static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl){	TDB_DATA kbuf = locking_key_fsp(fsp);	TDB_DATA dbuf;	struct posix_lock *locks;	size_t i, count;	BOOL found = False;	int num_overlapping_records = 0;	dbuf.dptr = NULL;		dbuf = tdb_fetch(posix_lock_tdb, kbuf);	if (!dbuf.dptr) {

⌨️ 快捷键说明

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