/** * @brief Restore the peers on disk to #valid_peers. */ static void restore_valid_peers () { off_t file_size; uint32_t num_peers; struct GNUNET_DISK_FileHandle *fh; char *buf; ssize_t size_read; char *iter_buf; char *str_repr; const struct GNUNET_PeerIdentity *peer; if (0 == strncmp ("DISABLE", filename_valid_peers, 7)) { return; } if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers)) { return; } fh = GNUNET_DISK_file_open (filename_valid_peers, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); GNUNET_assert (NULL != fh); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size)); num_peers = file_size / 53; buf = GNUNET_malloc (file_size); size_read = GNUNET_DISK_file_read (fh, buf, file_size); GNUNET_assert (size_read == file_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restoring %" PRIu32 " peers from file `%s'\n", num_peers, filename_valid_peers); for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53) { str_repr = GNUNET_strndup (iter_buf, 53); peer = s2i_full (str_repr); GNUNET_free (str_repr); add_valid_peer (peer); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restored valid peer %s from disk\n", GNUNET_i2s_full (peer)); } iter_buf = NULL; GNUNET_free (buf); LOG (GNUNET_ERROR_TYPE_DEBUG, "num_peers: %" PRIu32 ", _size (valid_peers): %u\n", num_peers, GNUNET_CONTAINER_multipeermap_size (valid_peers)); if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Number of restored peers does not match file size. Have probably duplicates.\n"); } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restored %u valid peers from disk\n", GNUNET_CONTAINER_multipeermap_size (valid_peers)); }
/** * Load a bloom-filter from a file. * * @param filename the name of the file (or the prefix) * @param size the size of the bloom-filter (number of * bytes of storage space to use); will be rounded up * to next power of 2 * @param k the number of GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; char *rbuff; OFF_T pos; int i; size_t ui; OFF_T fsize; int must_read; GNUNET_assert (NULL != filename); if ((k == 0) || (size == 0)) return NULL; if (size < BUFFSIZE) size = BUFFSIZE; ui = 1; while ( (ui < size) && (ui * 2 > ui) ) ui *= 2; size = ui; /* make sure it's a power of 2 */ bf = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_BloomFilter)); /* Try to open a bloomfilter file */ if (GNUNET_YES == GNUNET_DISK_file_test (filename)) bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL != bf->fh) { /* file existed, try to read it! */ must_read = GNUNET_YES; if (GNUNET_OK != GNUNET_DISK_file_handle_size (bf->fh, &fsize)) { GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } if (fsize == 0) { /* found existing empty file, just overwrite */ if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } else if (fsize != size * 4LL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu)\n"), (unsigned long long) (size * 4LL), (unsigned long long) fsize); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } else { /* file did not exist, don't read, just create */ must_read = GNUNET_NO; bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == bf->fh) { GNUNET_free (bf); return NULL; } if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } bf->filename = GNUNET_strdup (filename); /* Alloc block */ bf->bitArray = GNUNET_malloc_large (size); if (bf->bitArray == NULL) { if (bf->fh != NULL) GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf->filename); GNUNET_free (bf); return NULL; } bf->bitArraySize = size; bf->addressesPerElement = k; if (GNUNET_YES != must_read) return bf; /* already done! */ /* Read from the file what bits we can */ rbuff = GNUNET_malloc (BUFFSIZE); pos = 0; while (pos < size * 8LL) { int res; res = GNUNET_DISK_file_read (bf->fh, rbuff, BUFFSIZE); if (res == -1) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", bf->filename); GNUNET_free (rbuff); GNUNET_free (bf->filename); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } if (res == 0) break; /* is ok! we just did not use that many bits yet */ for (i = 0; i < res; i++) { if ((rbuff[i] & 0x0F) != 0) setBit (bf->bitArray, pos + i * 2); if ((rbuff[i] & 0xF0) != 0) setBit (bf->bitArray, pos + i * 2 + 1); } if (res < BUFFSIZE) break; pos += BUFFSIZE * 2; /* 2 bits per byte in the buffer */ } GNUNET_free (rbuff); return bf; }