Esempio n. 1
0
BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
{
	TDB_DATA dbuf;
	struct locking_data *data;
	int i;
	share_mode_entry *shares;

	/* read in the existing share modes */
	dbuf = tdb_fetch(tdb, locking_key(dev, inode));
	if (!dbuf.dptr)
		return False;

	data = (struct locking_data *)dbuf.dptr;
	shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));

	/* Set/Unset the delete on close element. */
	for (i=0;i<data->u.num_share_mode_entries;i++,shares++) {
		shares->share_mode = (delete_on_close ?
			    (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
			    (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
	}

	/* store it back */
	if (data->u.num_share_mode_entries) {
		if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) {
			SAFE_FREE(dbuf.dptr);
			return False;
		}
	}

	SAFE_FREE(dbuf.dptr);
	return True;
}
Esempio n. 2
0
/*******************************************************************
 Get all share mode entries for a dev/inode pair.
********************************************************************/
int get_share_modes(struct vfs_connection_struct *conn,
		    SMB_DEV_T dev, SMB_INO_T inode,
		    share_mode_entry ** shares)
{
	TDB_DATA dbuf;
	struct locking_data *data;
	int ret;

	*shares = NULL;

	dbuf = tdb_fetch(tdb, locking_key(dev, inode));
	if (!dbuf.dptr)
		return 0;

	data = (struct locking_data *)dbuf.dptr;
	ret = data->num_share_mode_entries;
	if (ret)
		*shares =
			(share_mode_entry *) memdup(dbuf.dptr + sizeof(*data),
						    ret * sizeof(**shares));
	free(dbuf.dptr);

	if (!*shares)
		return 0;

	return ret;
}
Esempio n. 3
0
static int share_mode_lock_destructor(void *p)
{
	struct share_mode_lock *lck =
		talloc_get_type_abort(p, struct share_mode_lock);
	TDB_DATA key = locking_key(lck->dev, lck->ino);
	TDB_DATA data;

	if (!lck->modified) {
		goto done;
	}

	data = unparse_share_modes(lck);

	if (data.dptr == NULL) {
		if (!lck->fresh) {
			/* There has been an entry before, delete it */
			if (tdb_delete(tdb, key) == -1) {
				smb_panic("Could not delete share entry\n");
			}
		}
		goto done;
	}

	if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
		smb_panic("Could not store share mode entry\n");
	}

 done:
	tdb_chainunlock(tdb, key);

	return 0;
}
Esempio n. 4
0
struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
						  struct file_id id)
{
	struct share_mode_lock *lck;
	TDB_DATA key = locking_key(&id);
	TDB_DATA data;
	NTSTATUS status;

	status = dbwrap_fetch(lock_db, talloc_tos(), key, &data);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(3, ("Could not fetch share entry\n"));
		return NULL;
	}
	if (data.dptr == NULL) {
		return NULL;
	}
	lck = talloc(mem_ctx, struct share_mode_lock);
	if (lck == NULL) {
		TALLOC_FREE(data.dptr);
		return NULL;
	}
	lck->data = parse_share_modes(lck, data);
	TALLOC_FREE(data.dptr);
	if (lck->data == NULL) {
		TALLOC_FREE(lck);
		return NULL;
	}
	return lck;
}
Esempio n. 5
0
BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
{
	TDB_DATA key = locking_key(dev, inode);
	BOOL result = False;

	tdb_parse_record(tdb, key, pull_delete_on_close_flag,
			 (void *)&result);
	return result;
}
Esempio n. 6
0
BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		  uint16 smbpid, pid_t pid, uint16 tid,
		  br_off start, br_off size, 
		  enum brl_type lock_type, int check_self)
{
	TDB_DATA kbuf, dbuf;
	int count, i;
	struct lock_struct lock, *locks;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	lock.context.smbpid = smbpid;
	lock.context.pid = pid;
	lock.context.tid = tid;
	lock.start = start;
	lock.size = size;
	lock.fnum = fnum;
	lock.lock_type = lock_type;

	if (dbuf.dptr) {
		/* there are existing locks - make sure they don't conflict */
		locks = (struct lock_struct *)dbuf.dptr;
		count = dbuf.dsize / sizeof(*locks);
		for (i=0; i<count; i++) {
			if (check_self) {
				if (brl_conflict(&locks[i], &lock))
					goto fail;
			} else {
				/*
				 * Our own locks don't conflict.
				 */
				if (brl_conflict_other(&locks[i], &lock))
					goto fail;
			}
		}
	}

	/* no conflicts - we could have added it */
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return True;

 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Esempio n. 7
0
static struct share_mode_lock *get_share_mode_lock_internal(
	TALLOC_CTX *mem_ctx, struct file_id id,
	const char *servicepath, const struct smb_filename *smb_fname,
	const struct timespec *old_write_time)
{
	struct share_mode_lock *lck;
	struct share_mode_data *d;
	struct db_record *rec;
	TDB_DATA key = locking_key(&id);
	TDB_DATA value;

	rec = dbwrap_fetch_locked(lock_db, mem_ctx, key);
	if (rec == NULL) {
		DEBUG(3, ("Could not lock share entry\n"));
		return NULL;
	}

	value = dbwrap_record_get_value(rec);

	if (value.dptr == NULL) {
		d = fresh_share_mode_lock(mem_ctx, servicepath, smb_fname,
					  old_write_time);
	} else {
		d = parse_share_modes(mem_ctx, value);
	}

	if (d == NULL) {
		DEBUG(5, ("get_share_mode_lock_internal: "
			"Could not get share mode lock\n"));
		TALLOC_FREE(rec);
		return NULL;
	}
	d->id = id;
	d->record = talloc_move(d, &rec);
	talloc_set_destructor(d, share_mode_data_destructor);

	lck = talloc(mem_ctx, struct share_mode_lock);
	if (lck == NULL) {
		DEBUG(1, ("talloc failed\n"));
		TALLOC_FREE(d);
		return NULL;
	}
	lck->data = talloc_move(lck, &d);
	return lck;
}
struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
						  struct file_id id)
{
	struct share_mode_lock *lck;
	TDB_DATA key = locking_key(&id);
	NTSTATUS status;

	lck = talloc(mem_ctx, struct share_mode_lock);
	if (lck == NULL) {
		DEBUG(0, ("talloc failed\n"));
		return NULL;
	}
	status = dbwrap_parse_record(
		lock_db, key, fetch_share_mode_unlocked_parser, lck);
	if (!NT_STATUS_IS_OK(status) ||
	    (lck->data == NULL)) {
		TALLOC_FREE(lck);
		return NULL;
	}
	return lck;
}
Esempio n. 9
0
struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
						SMB_DEV_T dev, SMB_INO_T ino,
						const char *servicepath,
						const char *fname)
{
	struct share_mode_lock *lck;
	TDB_DATA key = locking_key(dev, ino);
	TDB_DATA data;

	lck = TALLOC_P(mem_ctx, struct share_mode_lock);
	if (lck == NULL) {
		DEBUG(0, ("talloc failed\n"));
		return NULL;
	}

	/* Ensure we set every field here as the destructor must be
	   valid even if parse_share_modes fails. */

	lck->servicepath = NULL;
	lck->filename = NULL;
	lck->dev = dev;
	lck->ino = ino;
	lck->num_share_modes = 0;
	lck->share_modes = NULL;
	lck->delete_token = NULL;
	lck->delete_on_close = False;
	lck->initial_delete_on_close = False;
	lck->fresh = False;
	lck->modified = False;

	if (tdb_chainlock(tdb, key) != 0) {
		DEBUG(3, ("Could not lock share entry\n"));
		TALLOC_FREE(lck);
		return NULL;
	}

	/* We must set the destructor immediately after the chainlock
	   ensure the lock is cleaned up on any of the error return
	   paths below. */

	talloc_set_destructor(lck, share_mode_lock_destructor);

	data = tdb_fetch(tdb, key);
	lck->fresh = (data.dptr == NULL);

	if (lck->fresh) {

		if (fname == NULL || servicepath == NULL) {
			TALLOC_FREE(lck);
			return NULL;
		}
		lck->filename = talloc_strdup(lck, fname);
		lck->servicepath = talloc_strdup(lck, servicepath);
		if (lck->filename == NULL || lck->servicepath == NULL) {
			DEBUG(0, ("talloc failed\n"));
			TALLOC_FREE(lck);
			return NULL;
		}
	} else {
		if (!parse_share_modes(data, lck)) {
			DEBUG(0, ("Could not parse share modes\n"));
			TALLOC_FREE(lck);
			SAFE_FREE(data.dptr);
			return NULL;
		}
	}

	SAFE_FREE(data.dptr);

	return lck;
}
Esempio n. 10
0
BOOL lock_share_entry(connection_struct *conn,
		      SMB_DEV_T dev, SMB_INO_T inode)
{
	return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
}
Esempio n. 11
0
void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j, dcount=0;
	struct lock_struct *locks;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) goto fail;

	/* there are existing locks - remove any for this fnum */
	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);

	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (lock->context.tid == tid &&
		    lock->context.pid == pid &&
		    lock->fnum == fnum) {

			/* Send unlock messages to any pending waiters that overlap. */
			for (j=0; j<count; j++) {
				struct lock_struct *pend_lock = &locks[j];

				/* Ignore our own or non-pending locks. */
				if (pend_lock->lock_type != PENDING_LOCK)
					continue;

				if (pend_lock->context.tid == tid &&
				    pend_lock->context.pid == pid &&
				    pend_lock->fnum == fnum)
					continue;

				/* We could send specific lock info here... */
				if (brl_pending_overlap(lock, pend_lock))
					message_send_pid(pend_lock->context.pid,
							MSG_SMB_UNLOCK,
							NULL, 0, True);
			}

			/* found it - delete it */
			if (count > 1 && i < count-1) {
				memmove(&locks[i], &locks[i+1], 
					sizeof(*locks)*((count-1) - i));
			}
			count--;
			i--;
			dcount++;
		}
	}

	if (count == 0) {
		tdb_delete(tdb, kbuf);
	} else if (count < (dbuf.dsize / sizeof(*locks))) {
		dbuf.dsize -= dcount * sizeof(*locks);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
	}

	/* we didn't find it */
 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
}
Esempio n. 12
0
BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		uint16 smbpid, pid_t pid, uint16 tid,
		br_off start, br_off size,
		BOOL remove_pending_locks_only)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j;
	struct lock_struct *locks;
	struct lock_context context;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) {
		DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
		goto fail;
	}

	context.smbpid = smbpid;
	context.pid = pid;
	context.tid = tid;

	/* there are existing locks - find a match */
	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);

#if ZERO_ZERO
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (lock->lock_type == WRITE_LOCK &&
		    brl_same_context(&lock->context, &context) &&
		    lock->fnum == fnum &&
		    lock->start == start &&
		    lock->size == size) {
			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}
#endif

	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (brl_same_context(&lock->context, &context) &&
				lock->fnum == fnum &&
				lock->start == start &&
				lock->size == size) {

			if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK)
				continue;

			if (lock->lock_type != PENDING_LOCK) {
				/* Send unlock messages to any pending waiters that overlap. */
				for (j=0; j<count; j++) {
					struct lock_struct *pend_lock = &locks[j];

					/* Ignore non-pending locks. */
					if (pend_lock->lock_type != PENDING_LOCK)
						continue;

					/* We could send specific lock info here... */
					if (brl_pending_overlap(lock, pend_lock)) {
						DEBUG(10,("brl_unlock: sending unlock message to pid %u\n",
									(unsigned int)pend_lock->context.pid ));

						message_send_pid(pend_lock->context.pid,
								MSG_SMB_UNLOCK,
								NULL, 0, True);
					}
				}
			}

			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}

	/* we didn't find it */

 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Esempio n. 13
0
NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		  uint16 smbpid, pid_t pid, uint16 tid,
		  br_off start, br_off size, 
		  enum brl_type lock_type)
{
	TDB_DATA kbuf, dbuf;
	int count, i;
	struct lock_struct lock, *locks;
	char *tp;
	NTSTATUS status = NT_STATUS_OK;
	static int last_failed = -1;
	static br_off last_failed_start;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

#if !ZERO_ZERO
	if (start == 0 && size == 0) {
		DEBUG(0,("client sent 0/0 lock - please report this\n"));
	}
#endif

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	lock.context.smbpid = smbpid;
	lock.context.pid = pid;
	lock.context.tid = tid;
	lock.start = start;
	lock.size = size;
	lock.fnum = fnum;
	lock.lock_type = lock_type;

	if (dbuf.dptr) {
		/* there are existing locks - make sure they don't conflict */
		locks = (struct lock_struct *)dbuf.dptr;
		count = dbuf.dsize / sizeof(*locks);
		for (i=0; i<count; i++) {
			if (brl_conflict(&locks[i], &lock)) {
				status = NT_STATUS_LOCK_NOT_GRANTED;
				goto fail;
			}
#if ZERO_ZERO
			if (lock.start == 0 && lock.size == 0 && 
			    locks[i].size == 0) {
				break;
			}
#endif
		}
	}

	/* no conflicts - add it to the list of locks */
	tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks));
	if (!tp) {
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	} else {
		dbuf.dptr = tp;
	}
	memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
	dbuf.dsize += sizeof(lock);

#if ZERO_ZERO
	/* sort the lock list */
	qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
#endif

	tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return NT_STATUS_OK;

 fail:
	/* this is a nasty hack to try to simulate the lock result cache code in w2k.
	   It isn't completely accurate as I haven't yet worked out the correct
	   semantics (tridge)
	*/
	if (last_failed == fnum &&
	    last_failed_start == start &&
	    NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
		status = NT_STATUS_FILE_LOCK_CONFLICT;
	}
	last_failed = fnum;
	last_failed_start = start;

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return status;
}
Esempio n. 14
0
int get_share_modes(connection_struct *conn,
		    SMB_DEV_T dev, SMB_INO_T inode,
		    share_mode_entry **pp_shares)
{
	TDB_DATA dbuf;
	struct locking_data *data;
	int num_share_modes;
	share_mode_entry *shares = NULL;

	*pp_shares = NULL;

	dbuf = tdb_fetch(tdb, locking_key(dev, inode));
	if (!dbuf.dptr)
		return 0;

	data = (struct locking_data *)dbuf.dptr;
	num_share_modes = data->u.num_share_mode_entries;
	if(num_share_modes) {
		int i;
		int del_count = 0;

		shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data),
						num_share_modes * sizeof(share_mode_entry));

		if (!shares) {
			SAFE_FREE(dbuf.dptr);
			return 0;
		}

		/*
		 * Ensure that each entry has a real process attached.
		 */

		for (i = 0; i < num_share_modes; ) {
			share_mode_entry *entry_p = &shares[i];
			if (process_exists(entry_p->pid)) {
				DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) ));
				i++;
			} else {
				DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
				memcpy( &shares[i], &shares[i+1],
					sizeof(share_mode_entry) * (num_share_modes - i - 1));
				num_share_modes--;
				del_count++;
			}
		}

		/* Did we delete any ? If so, re-store in tdb. */
		if (del_count) {
			data->u.num_share_mode_entries = num_share_modes;

			if (num_share_modes)
				memcpy(dbuf.dptr + sizeof(*data), shares,
						num_share_modes * sizeof(share_mode_entry));

			/* The record has shrunk a bit */
			dbuf.dsize -= del_count * sizeof(share_mode_entry);

			if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) {
				SAFE_FREE(shares);
				SAFE_FREE(dbuf.dptr);
				return 0;
			}
		}
	}

	SAFE_FREE(dbuf.dptr);
	*pp_shares = shares;
	return num_share_modes;
}
Esempio n. 15
0
/*******************************************************************
 Unlock a hash bucket entry.
******************************************************************/
BOOL unlock_share_entry_fsp(files_struct * fsp)
{
	return tdb_unlockchain(tdb,
			       locking_key(fsp->sbuf.st_dev,
					   fsp->sbuf.st_ino)) == 0;
}
Esempio n. 16
0
static TDB_DATA locking_key_fsp(files_struct *fsp)
{
	return locking_key(fsp->dev, fsp->inode);
}
Esempio n. 17
0
static TDB_DATA locking_key_fsp(files_struct * fsp)
{
	return locking_key(fsp->sbuf.st_dev, fsp->sbuf.st_ino);
}
Esempio n. 18
0
BOOL lock_share_entry_fsp(files_struct *fsp)
{
	return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
}
Esempio n. 19
0
ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
			share_mode_entry *entry, share_mode_entry **ppse)
{
	TDB_DATA dbuf;
	struct locking_data *data;
	int i, del_count=0;
	share_mode_entry *shares;
	ssize_t count = 0;

	if (ppse)
		*ppse = NULL;

	/* read in the existing share modes */
	dbuf = tdb_fetch(tdb, locking_key(dev, inode));
	if (!dbuf.dptr)
		return -1;

	data = (struct locking_data *)dbuf.dptr;
	shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));

	/*
	 * Find any with this pid and delete it
	 * by overwriting with the rest of the data
	 * from the record.
	 */

	DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries ));

	for (i=0;i<data->u.num_share_mode_entries;) {
		if (share_modes_identical(&shares[i], entry)) {
			DEBUG(10,("del_share_entry: deleted %s\n",
				share_mode_str(i, &shares[i]) ));
			if (ppse)
				*ppse = memdup(&shares[i], sizeof(*shares));
			data->u.num_share_mode_entries--;
			memmove(&shares[i], &shares[i+1],
				dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
			del_count++;

			DEBUG(10,("del_share_entry: deleting entry %d\n", i ));

		} else {
			i++;
		}
	}

	if (del_count) {
		/* the record may have shrunk a bit */
		dbuf.dsize -= del_count * sizeof(*shares);

		count = (ssize_t)data->u.num_share_mode_entries;

		/* store it back in the database */
		if (data->u.num_share_mode_entries == 0) {
			if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
				count = -1;
		} else {
			if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
				count = -1;
		}
	}
	DEBUG(10,("del_share_entry: Remaining table.\n"));
	print_share_mode_table((struct locking_data *)dbuf.dptr);
	SAFE_FREE(dbuf.dptr);
	return count;
}
Esempio n. 20
0
void unlock_share_entry(connection_struct *conn,
			SMB_DEV_T dev, SMB_INO_T inode)
{
	tdb_chainunlock(tdb, locking_key(dev, inode));
}
Esempio n. 21
0
/*******************************************************************
 Unlock a hash bucket entry.
******************************************************************/
BOOL unlock_share_entry(struct vfs_connection_struct *conn,
			SMB_DEV_T dev, SMB_INO_T inode)
{
	return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0;
}
Esempio n. 22
0
void unlock_share_entry_fsp(files_struct *fsp)
{
	tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
}