Esempio n. 1
0
/* 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;
}
Esempio n. 2
0
File: open.c Progetto: 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;
}