- struct tdb_context *i;
-
- for (i = tdbs; i; i = i->next) {
- if (i->device == device && i->inode == ino) {
- return true;
- }
- }
-
- return false;
-}
-
-static uint64_t random_number(struct tdb_context *tdb)
-{
- int fd;
- uint64_t ret = 0;
- struct timeval now;
-
- fd = open("/dev/urandom", O_RDONLY);
- if (fd >= 0) {
- if (tdb_read_all(fd, &ret, sizeof(ret))) {
- tdb->log(tdb, TDB_DEBUG_TRACE, tdb->log_priv,
- "tdb_open: random from /dev/urandom\n");
- close(fd);
- return ret;
- }
- close(fd);
- }
- /* FIXME: Untested! Based on Wikipedia protocol description! */
- fd = open("/dev/egd-pool", O_RDWR);
- if (fd >= 0) {
- /* Command is 1, next byte is size we want to read. */
- char cmd[2] = { 1, sizeof(uint64_t) };
- if (write(fd, cmd, sizeof(cmd)) == sizeof(cmd)) {
- char reply[1 + sizeof(uint64_t)];
- int r = read(fd, reply, sizeof(reply));
- if (r > 1) {
- tdb->log(tdb, TDB_DEBUG_TRACE, tdb->log_priv,
- "tdb_open: %u random bytes from"
- " /dev/egd-pool\n", r-1);
- /* Copy at least some bytes. */
- memcpy(&ret, reply+1, r - 1);
- if (reply[0] == sizeof(uint64_t)
- && r == sizeof(reply)) {
- close(fd);
- return ret;
- }
- }
- }
- close(fd);
- }
-
- /* Fallback: pid and time. */
- gettimeofday(&now, NULL);
- ret = getpid() * 100132289ULL + now.tv_sec * 1000000ULL + now.tv_usec;
- tdb->log(tdb, TDB_DEBUG_TRACE, tdb->log_priv,
- "tdb_open: random from getpid and time\n");
- return ret;
-}
-
-struct new_database {
- struct tdb_header hdr;
- /* Initial free zone. */
- struct free_zone_header zhdr;
- tdb_off_t free[BUCKETS_FOR_ZONE(INITIAL_ZONE_BITS) + 1];
- struct tdb_free_record frec;
- /* Rest up to 1 << INITIAL_ZONE_BITS is empty. */
- char space[(1 << INITIAL_ZONE_BITS)
- - sizeof(struct free_zone_header)
- - sizeof(tdb_off_t) * (BUCKETS_FOR_ZONE(INITIAL_ZONE_BITS)+1)
- - sizeof(struct tdb_free_record)];
- uint8_t tailer;
- /* Don't count final padding! */
-};
-
-/* initialise a new database */
-static int tdb_new_database(struct tdb_context *tdb,
- struct tdb_attribute_seed *seed,
- struct tdb_header *hdr)
-{
- /* We make it up in memory, then write it out if not internal */
- struct new_database newdb;
- unsigned int bucket, magic_len, dbsize;
-
- /* Don't want any extra padding! */
- dbsize = offsetof(struct new_database, tailer) + sizeof(newdb.tailer);
-
- /* Fill in the header */
- newdb.hdr.version = TDB_VERSION;
- if (seed)
- newdb.hdr.hash_seed = seed->seed;
- else
- newdb.hdr.hash_seed = random_number(tdb);
- newdb.hdr.hash_test = TDB_HASH_MAGIC;
- newdb.hdr.hash_test = tdb->khash(&newdb.hdr.hash_test,
- sizeof(newdb.hdr.hash_test),
- newdb.hdr.hash_seed,
- tdb->hash_priv);
- memset(newdb.hdr.reserved, 0, sizeof(newdb.hdr.reserved));
- /* Initial hashes are empty. */
- memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable));
-
- /* Free is mostly empty... */
- newdb.zhdr.zone_bits = INITIAL_ZONE_BITS;
- memset(newdb.free, 0, sizeof(newdb.free));
-
- /* Create the single free entry. */
- newdb.frec.magic_and_meta = TDB_FREE_MAGIC | INITIAL_ZONE_BITS;
- newdb.frec.data_len = (sizeof(newdb.frec)
- - sizeof(struct tdb_used_record)
- + sizeof(newdb.space));
-
- /* Add it to the correct bucket. */
- bucket = size_to_bucket(INITIAL_ZONE_BITS, newdb.frec.data_len);
- newdb.free[bucket] = offsetof(struct new_database, frec);
- newdb.frec.next = newdb.frec.prev = 0;
-
- /* Clear free space to keep valgrind happy, and avoid leaking stack. */
- memset(newdb.space, 0, sizeof(newdb.space));
-
- /* Tailer contains maximum number of free_zone bits. */
- newdb.tailer = INITIAL_ZONE_BITS;
-
- /* Magic food */
- memset(newdb.hdr.magic_food, 0, sizeof(newdb.hdr.magic_food));
- strcpy(newdb.hdr.magic_food, TDB_MAGIC_FOOD);
-
- /* This creates an endian-converted database, as if read from disk */
- magic_len = sizeof(newdb.hdr.magic_food);
- tdb_convert(tdb,
- (char *)&newdb.hdr + magic_len,
- offsetof(struct new_database, space) - magic_len);
-
- *hdr = newdb.hdr;
-
- if (tdb->flags & TDB_INTERNAL) {
- tdb->map_size = dbsize;
- tdb->map_ptr = malloc(tdb->map_size);
- if (!tdb->map_ptr) {
- tdb->ecode = TDB_ERR_OOM;
- return -1;
- }
- memcpy(tdb->map_ptr, &newdb, tdb->map_size);
- return 0;
- }
- if (lseek(tdb->fd, 0, SEEK_SET) == -1)
- return -1;
-
- if (ftruncate(tdb->fd, 0) == -1)
- return -1;