コード例 #1
0
ファイル: open.c プロジェクト: jrasamba/samba
/* initialise a new database with a specified hash size */
static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header,
			    int hash_size)
{
	struct tdb_header *newdb;
	size_t size;
	int ret = -1;

	/* We make it up in memory, then write it out if not internal */
	size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
	if (!(newdb = (struct tdb_header *)calloc(size, 1))) {
		tdb->ecode = TDB_ERR_OOM;
		return -1;
	}

	/* Fill in the header */
	newdb->version = TDB_VERSION;
	newdb->hash_size = hash_size;

	tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);

	/* Make sure older tdbs (which don't check the magic hash fields)
	 * will refuse to open this TDB. */
	if (tdb->flags & TDB_INCOMPATIBLE_HASH)
		newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;

	if (tdb->flags & TDB_INTERNAL) {
		tdb->map_size = size;
		tdb->map_ptr = (char *)newdb;
		memcpy(header, newdb, sizeof(*header));
		/* Convert the `ondisk' version if asked. */
		CONVERT(*newdb);
		return 0;
	}
	if (lseek(tdb->fd, 0, SEEK_SET) == -1)
		goto fail;

	if (ftruncate(tdb->fd, 0) == -1)
		goto fail;

	/* This creates an endian-converted header, as if read from disk */
	CONVERT(*newdb);
	memcpy(header, newdb, sizeof(*header));
	/* Don't endian-convert the magic food! */
	memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);

	if (!tdb_write_all(tdb->fd, newdb, size))
		goto fail;

	ret = 0;
  fail:
	SAFE_FREE(newdb);
	return ret;
}
コード例 #2
0
ファイル: check.c プロジェクト: Alexander--/samba
/* Since we opened it, these shouldn't fail unless it's recent corruption. */
static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery)
{
	struct tdb_header hdr;
	uint32_t h1, h2;

	if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
		return false;
	if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0)
		goto corrupt;

	CONVERT(hdr);
	if (hdr.version != TDB_VERSION)
		goto corrupt;

	if (hdr.rwlocks != 0 &&
	    hdr.rwlocks != TDB_FEATURE_FLAG_MAGIC &&
	    hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC)
		goto corrupt;

	tdb_header_hash(tdb, &h1, &h2);
	if (hdr.magic1_hash && hdr.magic2_hash &&
	    (hdr.magic1_hash != h1 || hdr.magic2_hash != h2))
		goto corrupt;

	if (hdr.hash_size == 0)
		goto corrupt;

	if (hdr.hash_size != tdb->hash_size)
		goto corrupt;

	if (hdr.recovery_start != 0 &&
	    hdr.recovery_start < TDB_DATA_START(tdb->hash_size))
		goto corrupt;

	*recovery = hdr.recovery_start;
	return true;

corrupt:
	tdb->ecode = TDB_ERR_CORRUPT;
	TDB_LOG((tdb, TDB_DEBUG_ERROR, "Header is corrupt\n"));
	return false;
}
コード例 #3
0
ファイル: open.c プロジェクト: ekohl/samba
static bool check_header_hash(struct tdb_context *tdb,
			      bool default_hash, uint32_t *m1, uint32_t *m2)
{
	tdb_header_hash(tdb, m1, m2);
	if (tdb->header.magic1_hash == *m1 &&
	    tdb->header.magic2_hash == *m2) {
		return true;
	}

	/* If they explicitly set a hash, always respect it. */
	if (!default_hash)
		return false;

	/* Otherwise, try the other inbuilt hash. */
	if (tdb->hash_fn == tdb_old_hash)
		tdb->hash_fn = tdb_jenkins_hash;
	else
		tdb->hash_fn = tdb_old_hash;
	return check_header_hash(tdb, false, m1, m2);
}
コード例 #4
0
ファイル: open.c プロジェクト: hef/samba
/* initialise a new database with a specified hash size */
static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header,
			    int hash_size)
{
	struct tdb_header *newdb;
	size_t size;
	int ret = -1;

	/* We make it up in memory, then write it out if not internal */
	size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
	if (!(newdb = (struct tdb_header *)calloc(size, 1))) {
		tdb->ecode = TDB_ERR_OOM;
		return -1;
	}

	/* Fill in the header */
	newdb->version = TDB_VERSION;
	newdb->hash_size = hash_size;

	tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);

	/* Make sure older tdbs (which don't check the magic hash fields)
	 * will refuse to open this TDB. */
	if (tdb->flags & TDB_INCOMPATIBLE_HASH)
		newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;

	/*
	 * We create a tdb with TDB_FEATURE_FLAG_MUTEX support,
	 * the flag combination and runtime feature checks
	 * are done by the caller already.
	 */
	if (tdb->flags & TDB_MUTEX_LOCKING) {
		newdb->feature_flags |= TDB_FEATURE_FLAG_MUTEX;
	}

	/*
	 * If we have any features we add the FEATURE_FLAG_MAGIC, overwriting the
	 * TDB_HASH_RWLOCK_MAGIC above.
	 */
	if (newdb->feature_flags != 0) {
		newdb->rwlocks = TDB_FEATURE_FLAG_MAGIC;
	}

	/*
	 * It's required for some following code pathes
	 * to have the fields on 'tdb' up-to-date.
	 *
	 * E.g. tdb_mutex_size() requires it
	 */
	tdb->feature_flags = newdb->feature_flags;
	tdb->hash_size = newdb->hash_size;

	if (tdb->flags & TDB_INTERNAL) {
		tdb->map_size = size;
		tdb->map_ptr = (char *)newdb;
		memcpy(header, newdb, sizeof(*header));
		/* Convert the `ondisk' version if asked. */
		CONVERT(*newdb);
		return 0;
	}
	if (lseek(tdb->fd, 0, SEEK_SET) == -1)
		goto fail;

	if (ftruncate(tdb->fd, 0) == -1)
		goto fail;

	if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
		newdb->mutex_size = tdb_mutex_size(tdb);
		tdb->hdr_ofs = newdb->mutex_size;
	}

	/* This creates an endian-converted header, as if read from disk */
	CONVERT(*newdb);
	memcpy(header, newdb, sizeof(*header));
	/* Don't endian-convert the magic food! */
	memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);

	if (!tdb_write_all(tdb->fd, newdb, size))
		goto fail;

	if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {

		/*
		 * Now we init the mutex area
		 * followed by a second header.
		 */

		ret = ftruncate(
			tdb->fd,
			newdb->mutex_size + sizeof(struct tdb_header));
		if (ret == -1) {
			goto fail;
		}
		ret = tdb_mutex_init(tdb);
		if (ret == -1) {
			goto fail;
		}

		/*
		 * Write a second header behind the mutexes. That's the area
		 * that will be mmapp'ed.
		 */
		ret = lseek(tdb->fd, newdb->mutex_size, SEEK_SET);
		if (ret == -1) {
			goto fail;
		}
		if (!tdb_write_all(tdb->fd, newdb, size)) {
			goto fail;
		}
	}

	ret = 0;
  fail:
	SAFE_FREE(newdb);
	return ret;
}