Example #1
0
static inline void
buffer_check_limits(struct real_buffer *buf, size_t pos, size_t data_size)
{
	unsigned int extra;
	size_t new_size;

	if (unlikely((size_t)-1 - pos < data_size)) {
		i_panic("Buffer write out of range (%"PRIuSIZE_T
			" + %"PRIuSIZE_T")", pos, data_size);
	}
	new_size = pos + data_size;

	if (new_size > buf->used && buf->used < buf->dirty) {
		/* clear used..dirty area */
		size_t max = I_MIN(I_MIN(buf->alloc, buf->dirty), new_size);

		memset(buf->w_buffer + buf->used, 0, max - buf->used);
	}

	/* always keep +1 byte allocated available in case str_c() is called
	   for this buffer. this is mainly for cases where the buffer is
	   allocated from data stack, and str_c() is called in a separate stack
	   frame. */
	extra = buf->dynamic ? 1 : 0;
	if (new_size + extra > buf->alloc) {
		if (unlikely(!buf->dynamic)) {
			i_panic("Buffer full (%"PRIuSIZE_T" > %"PRIuSIZE_T", "
				"pool %s)", pos + data_size, buf->alloc,
				buf->pool == NULL ? "<none>" :
				pool_get_name(buf->pool));
		}

		buffer_alloc(buf, pool_get_exp_grown_size(buf->pool, buf->alloc,
							  new_size + extra));
	}
#if 0
	else if (new_size > buf->used && buf->alloced &&
		 !buf->pool->alloconly_pool && !buf->pool->datastack_pool) {
		void *new_buf;

		/* buffer's size increased: move the buffer's memory elsewhere.
		   this should help catch bugs where old pointers are tried to
		   be used to access the buffer's memory */
		new_buf = p_malloc(buf->pool, buf->alloc);
		memcpy(new_buf, buf->w_buffer, buf->alloc);
		p_free(buf->pool, buf->w_buffer);

		buf->w_buffer = new_buf;
		buf->r_buffer = new_buf;
	}
#endif

	if (new_size > buf->used)
		buf->used = new_size;
	i_assert(buf->used <= buf->alloc);
}
Example #2
0
static size_t
o_stream_ssl_buffer(struct ssl_ostream *sstream, const struct const_iovec *iov,
		    unsigned int iov_count, size_t bytes_sent)
{
	size_t avail, skip_left, size;
	unsigned int i;

	if (sstream->buffer == NULL)
		sstream->buffer = buffer_create_dynamic(default_pool, 4096);

	skip_left = bytes_sent;
	for (i = 0; i < iov_count; i++) {
		if (skip_left < iov[i].iov_len)
			break;
		skip_left -= iov[i].iov_len;
	}

	if (sstream->ostream.max_buffer_size == 0) {
		/* we're requeted to use whatever space is available in
		   the buffer */
		avail = buffer_get_size(sstream->buffer) - sstream->buffer->used;
	} else {
		avail = sstream->ostream.max_buffer_size > sstream->buffer->used ?
			sstream->ostream.max_buffer_size - sstream->buffer->used : 0;
	}
	if (i < iov_count && skip_left > 0) {
		size = I_MIN(iov[i].iov_len - skip_left, avail);
		buffer_append(sstream->buffer,
			      CONST_PTR_OFFSET(iov[i].iov_base, skip_left),
			      size);
		bytes_sent += size;
		avail -= size;
		if (size != iov[i].iov_len)
			i = iov_count;
	}
	if (avail > 0)
		o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);

	for (; i < iov_count; i++) {
		size = I_MIN(iov[i].iov_len, avail);
		buffer_append(sstream->buffer, iov[i].iov_base, size);
		bytes_sent += size;
		avail -= size;

		if (size != iov[i].iov_len)
			break;
	}

	sstream->ostream.ostream.offset += bytes_sent;
	return bytes_sent;
}
Example #3
0
static ssize_t
o_stream_escaped_send_chunk(struct escaped_ostream *estream,
			    const unsigned char *data, size_t len)
{
	size_t i, max_buffer_size;
	ssize_t ret;

	max_buffer_size = I_MIN(o_stream_get_max_buffer_size(estream->ostream.parent),
				estream->ostream.max_buffer_size);
	if (max_buffer_size > IO_BLOCK_SIZE) {
		/* avoid using up too much memory in case of large buffers */
		max_buffer_size = IO_BLOCK_SIZE;
	}

	for (i = 0; i < len; i++) {
		if (str_len(estream->buf) + 2 > max_buffer_size) { /* escaping takes at least two bytes */
			ret = o_stream_escaped_send_outbuf(estream);
			if (ret < 0) {
				estream->ostream.ostream.offset += i;
				return ret;
			}
			if (ret == 0)
				break;
		}
		estream->format(estream->buf, data[i]);
		estream->flushed = FALSE;
	}
	estream->ostream.ostream.offset += i;
	return i;
}
Example #4
0
static bool pop3_uidl_assign_by_size(struct mailbox *box)
{
	struct pop3_migration_mailbox *mbox = POP3_MIGRATION_CONTEXT(box);
	struct pop3_migration_mail_storage *mstorage =
		POP3_MIGRATION_CONTEXT(box->storage);
	struct pop3_uidl_map *pop3_map;
	struct imap_msg_map *imap_map;
	unsigned int i, pop3_count, imap_count, count;

	pop3_map = array_get_modifiable(&mstorage->pop3_uidl_map, &pop3_count);
	imap_map = array_get_modifiable(&mbox->imap_msg_map, &imap_count);
	count = I_MIN(pop3_count, imap_count);

	/* see if we can match the messages using sizes */
	for (i = 0; i < count; i++) {
		if (pop3_map[i].size != imap_map[i].psize)
			break;
		if (i+1 < count && pop3_map[i].size == pop3_map[i+1].size) {
			/* two messages with same size, don't trust them */
			break;
		}

		pop3_map[i].imap_uid = imap_map[i].uid;
		imap_map[i].pop3_uidl = pop3_map[i].pop3_uidl;
		imap_map[i].pop3_seq = pop3_map[i].pop3_seq;
	}
	mbox->first_unfound_idx = i;
	return i == count;
}
void mailbox_name_get_sha128(const char *name, guid_128_t guid_128_r)
{
	unsigned char sha[SHA1_RESULTLEN];

	sha1_get_digest(name, strlen(name), sha);
	memcpy(guid_128_r, sha, I_MIN(GUID_128_SIZE, sizeof(sha)));
}
static void tok_append_truncated(struct generic_fts_tokenizer *tok,
				 const unsigned char *data, size_t size)
{
	buffer_append(tok->token, data,
		      I_MIN(size, tok->max_length - tok->token->used));
	tok->untruncated_length += size;
}
Example #7
0
static void aqueue_grow(struct aqueue *aqueue)
{
	unsigned int orig_area_size, count;

	i_assert(aqueue->full && aqueue->head == aqueue->tail);

	orig_area_size = aqueue->area_size;
	(void)array_append_space_i(aqueue->arr);
	aqueue->area_size = buffer_get_size(aqueue->arr->buffer) /
		aqueue->arr->element_size;
	i_assert(orig_area_size < aqueue->area_size);

	count = I_MIN(aqueue->area_size - orig_area_size, aqueue->head);
	array_copy(aqueue->arr, orig_area_size, aqueue->arr, 0, count);
	if (count < aqueue->area_size - orig_area_size)
		aqueue->head = orig_area_size + count;
	else {
		array_copy(aqueue->arr, 0, aqueue->arr, count,
			   aqueue->head - count);
		aqueue->head -= count;
	}

	i_assert(aqueue->head != aqueue->tail);
	aqueue->full = FALSE;
}
Example #8
0
static void test_ostream_multiplex_simple(void)
{
	test_begin("ostream multiplex (simple)");

	const unsigned char expected[] = {
		'\x00','\x00','\x00','\x00','\x05','\x68','\x65',
		'\x6c','\x6c','\x6f','\x01','\x00','\x00','\x00',
		'\x05','\x77','\x6f','\x72','\x6c','\x64'
	};

	buffer_t *result = t_str_new(64);
	struct ostream *os = test_ostream_create(result);
	struct ostream *os2 = o_stream_create_multiplex(os, (size_t)-1);
	struct ostream *os3 = o_stream_multiplex_add_channel(os2, 1);

	test_assert(o_stream_send_str(os2, "hello") == 5);
	test_assert(o_stream_send_str(os3, "world") == 5);

	o_stream_unref(&os3);
	o_stream_unref(&os2);
	o_stream_unref(&os);

	test_assert(sizeof(expected) == result->used);
	test_assert(memcmp(result->data, expected, I_MIN(sizeof(expected),
		    result->used)) == 0);

	test_end();
}
Example #9
0
struct mail_index *mail_index_alloc(const char *dir, const char *prefix)
{
	struct mail_index *index;

	index = i_new(struct mail_index, 1);
	index->dir = i_strdup(dir);
	index->prefix = i_strdup(prefix);
	index->fd = -1;

	index->extension_pool =
		pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
	p_array_init(&index->extensions, index->extension_pool, 5);
	i_array_init(&index->sync_lost_handlers, 4);
	i_array_init(&index->module_contexts,
		     I_MIN(5, mail_index_module_register.id));

	index->mode = 0600;
	index->gid = (gid_t)-1;
	index->lock_method = FILE_LOCK_METHOD_FCNTL;
	index->max_lock_timeout_secs = UINT_MAX;

	index->keywords_ext_id =
		mail_index_ext_register(index, MAIL_INDEX_EXT_KEYWORDS,
					128, 2, 1);
	index->keywords_pool = pool_alloconly_create("keywords", 512);
	i_array_init(&index->keywords, 16);
	hash_table_create(&index->keywords_hash, index->keywords_pool, 0,
			  strcase_hash, strcasecmp);
	index->log = mail_transaction_log_alloc(index);
	mail_index_modseq_init(index);
	return index;
}
Example #10
0
void mail_index_view_clone(struct mail_index_view *dest,
			   const struct mail_index_view *src)
{
	memset(dest, 0, sizeof(*dest));
	dest->refcount = 1;
	dest->v = src->v;
	dest->index = src->index;
	if (src->log_view != NULL) {
		dest->log_view =
			mail_transaction_log_view_open(src->index->log);
	}

	dest->indexid = src->indexid;
	dest->inconsistency_id = src->inconsistency_id;
	dest->map = src->map;
	if (dest->map != NULL)
		dest->map->refcount++;

	dest->log_file_expunge_seq = src->log_file_expunge_seq;
	dest->log_file_expunge_offset = src->log_file_expunge_offset;
	dest->log_file_head_seq = src->log_file_head_seq;
	dest->log_file_head_offset = src->log_file_head_offset;

	i_array_init(&dest->module_contexts,
		     I_MIN(5, mail_index_module_register.id));

	DLLIST_PREPEND(&dest->index->views, dest);
}
Example #11
0
static int mail_index_recreate(struct mail_index *index)
{
	struct mail_index_map *map = index->map;
	struct ostream *output;
	unsigned int base_size;
	const char *path;
	int ret = 0, fd;

	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
	i_assert(map->hdr.indexid == index->indexid);
	i_assert((map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) == 0);
	i_assert(index->indexid != 0);

	fd = mail_index_create_tmp_file(index, index->filepath, &path);
	if (fd == -1)
		return -1;

	output = o_stream_create_fd_file(fd, 0, FALSE);
	o_stream_cork(output);

	base_size = I_MIN(map->hdr.base_header_size, sizeof(map->hdr));
	o_stream_nsend(output, &map->hdr, base_size);
	o_stream_nsend(output, CONST_PTR_OFFSET(map->hdr_base, base_size),
		       map->hdr.header_size - base_size);
	o_stream_nsend(output, map->rec_map->records,
		       map->rec_map->records_count * map->hdr.record_size);
	o_stream_nflush(output);
	if (o_stream_nfinish(output) < 0) {
		mail_index_file_set_syscall_error(index, path, "write()");
		ret = -1;
	}
	o_stream_destroy(&output);

	if (ret == 0 && index->fsync_mode != FSYNC_MODE_NEVER) {
		if (fdatasync(fd) < 0) {
			mail_index_file_set_syscall_error(index, path,
							  "fdatasync()");
			ret = -1;
		}
	}

	if (close(fd) < 0) {
		mail_index_file_set_syscall_error(index, path, "close()");
		ret = -1;
	}

	if ((index->flags & MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS) != 0)
		(void)mail_index_create_backup(index);

	if (ret == 0 && rename(path, index->filepath) < 0) {
		mail_index_set_error(index, "rename(%s, %s) failed: %m",
				     path, index->filepath);
		ret = -1;
	}

	if (ret < 0)
		i_unlink(path);
	return ret;
}
Example #12
0
static
void dcrypt_gnutls_ctx_sym_set_iv(struct dcrypt_context_symmetric *ctx, const unsigned char *iv, size_t iv_len)
{
	if(ctx->iv.data != NULL) p_free(ctx->pool, ctx->iv.data);
	ctx->iv.size = I_MIN(iv_len,(size_t)gnutls_cipher_get_iv_size(ctx->cipher));
	ctx->iv.data = p_malloc(ctx->pool, ctx->iv.size);
	memcpy(ctx->iv.data, iv, ctx->iv.size);
}
Example #13
0
static
void dcrypt_gnutls_ctx_hmac_set_key(struct dcrypt_context_hmac *ctx, const unsigned char *key, size_t key_len)
{
        if(ctx->key.data != NULL) p_free(ctx->pool, ctx->key.data);
        ctx->key.size = I_MIN(key_len,(size_t)gnutls_hmac_get_len(ctx->md));
        ctx->key.data = p_malloc(ctx->pool, ctx->key.size);
        memcpy(ctx->key.data, key, ctx->key.size);
}
Example #14
0
static
void dcrypt_gnutls_ctx_sym_set_key(struct dcrypt_context_symmetric *ctx, const unsigned char *key, size_t key_len)
{
	if(ctx->key.data != NULL) p_free(ctx->pool, ctx->key.data);
	ctx->key.size = I_MIN(key_len,(size_t)gnutls_cipher_get_key_size(ctx->cipher));
	ctx->key.data = p_malloc(ctx->pool, ctx->key.size);
	memcpy(ctx->key.data, key, ctx->key.size);
}
Example #15
0
static void iostream_pump_copy(struct iostream_pump *pump)
{
	enum ostream_send_istream_result res;
	size_t old_size;

	o_stream_cork(pump->output);
	old_size = o_stream_get_max_buffer_size(pump->output);
	o_stream_set_max_buffer_size(pump->output,
		I_MIN(IO_BLOCK_SIZE,
		      o_stream_get_max_buffer_size(pump->output)));
	res = o_stream_send_istream(pump->output, pump->input);
	o_stream_set_max_buffer_size(pump->output, old_size);
	o_stream_uncork(pump->output);

	switch(res) {
	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
		io_remove(&pump->io);
		pump->callback(IOSTREAM_PUMP_STATUS_INPUT_ERROR,
			       pump->context);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
		io_remove(&pump->io);
		pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR,
			       pump->context);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
		i_assert(!pump->output->blocking);
		pump->waiting_output = TRUE;
		io_remove(&pump->io);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
		pump->waiting_output = FALSE;
		io_remove(&pump->io);
		/* flush it */
		switch (o_stream_flush(pump->output)) {
		case -1:
			pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR,
				       pump->context);
			break;
		case 0:
			pump->waiting_output = TRUE;
			pump->completed = TRUE;
			break;
		default:
			pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF,
				       pump->context);
			break;
		}
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
		i_assert(!pump->input->blocking);
		pump->waiting_output = FALSE;
		return;
	}
	i_unreached();
}
Example #16
0
static void
mdbox_map_get_ext_hdr(struct mdbox_map *map, struct mail_index_view *view,
		      struct mdbox_map_mail_index_header *hdr_r)
{
	const void *data;
	size_t data_size;

	mail_index_get_header_ext(view, map->map_ext_id, &data, &data_size);
	memset(hdr_r, 0, sizeof(*hdr_r));
	memcpy(hdr_r, data, I_MIN(data_size, sizeof(*hdr_r)));
}
Example #17
0
static int squat_uidlist_map_blocks(struct squat_uidlist *uidlist)
{
	const struct squat_uidlist_file_header *hdr = &uidlist->hdr;
	const void *base;
	uint32_t block_count, blocks_offset, blocks_size, i, verify_count;

	if (hdr->block_list_offset == 0) {
		/* empty file */
		uidlist->cur_block_count = 0;
		return 1;
	}

	/* get number of blocks */
	if (uidlist_file_cache_read(uidlist, hdr->block_list_offset,
				    sizeof(block_count)) < 0)
		return -1;
	blocks_offset = hdr->block_list_offset + sizeof(block_count);
	if (blocks_offset > uidlist->data_size) {
		squat_uidlist_set_corrupted(uidlist, "block list outside file");
		return 0;
	}

	i_assert(uidlist->data != NULL);
	base = CONST_PTR_OFFSET(uidlist->data, hdr->block_list_offset);
	memcpy(&block_count, base, sizeof(block_count));

	/* map the blocks */
	blocks_size = block_count * sizeof(uint32_t)*2;
	if (uidlist_file_cache_read(uidlist, blocks_offset, blocks_size) < 0)
		return -1;
	if (blocks_offset + blocks_size > uidlist->data_size) {
		squat_uidlist_set_corrupted(uidlist, "block list outside file");
		return 0;
	}

	uidlist->cur_block_count = block_count;
	squat_uidlist_map_blocks_set_pointers(uidlist);

	i_assert(uidlist->cur_block_end_indexes != NULL);

	/* verify just a couple of the end indexes to make sure they
	   look correct */
	verify_count = I_MIN(block_count, 8);
	for (i = 1; i < verify_count; i++) {
		if (unlikely(uidlist->cur_block_end_indexes[i-1] >=
			     uidlist->cur_block_end_indexes[i])) {
			squat_uidlist_set_corrupted(uidlist,
				"block list corrupted");
			return 0;
		}
	}
	return 1;
}
Example #18
0
void mail_transaction_log_get_dotlock_set(struct mail_transaction_log *log,
					  struct dotlock_settings *set_r)
{
	struct mail_index *index = log->index;

	memset(set_r, 0, sizeof(*set_r));
	set_r->timeout = I_MIN(MAIL_TRANSACTION_LOG_LOCK_TIMEOUT,
			       index->max_lock_timeout_secs);
	set_r->stale_timeout = MAIL_TRANSACTION_LOG_LOCK_CHANGE_TIMEOUT;
	set_r->nfs_flush = (index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
	set_r->use_excl_lock =
		(index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
}
static void test_penalty_checksum(void)
{
	struct penalty *penalty;
	struct ioloop *ioloop;
	time_t t;
	unsigned int i, j;

	test_begin("penalty");

	ioloop = io_loop_create();
	penalty = penalty_init();

	test_assert(penalty_get(penalty, "foo", &t) == 0);
	for (i = 1; i <= 10; i++) {
		ioloop_time = 12345678 + i;
		penalty_inc(penalty, "foo", i, 5+i);

		for (j = I_MIN(1, i-1); j <= i; j++) {
			test_assert(penalty_get(penalty, "foo", &t) == 5+i);
			test_assert(t == (time_t)(12345678 + i));
			test_assert(penalty_has_checksum(penalty, "foo", i));
		}
		test_assert(penalty_get(penalty, "foo", &t) == 5+i);
		test_assert(t == (time_t)(12345678 + i));
		test_assert(!penalty_has_checksum(penalty, "foo", j));
	}
	test_assert(penalty_get(penalty, "foo2", &t) == 0);

	/* overflows checksum array */
	ioloop_time = 12345678 + i;
	penalty_inc(penalty, "foo", i, 5 + i);
	penalty_inc(penalty, "foo", i, 5 + i);
	penalty_inc(penalty, "foo", 0, 5 + i);

	test_assert(penalty_get(penalty, "foo", &t) == 5+i);
	test_assert(t == (time_t)(12345678 + i));
	test_assert(!penalty_has_checksum(penalty, "foo", 1));

	for (j = 2; j <= i; j++) {
		test_assert(penalty_get(penalty, "foo", &t) == 5+i);
		test_assert(t == (time_t)(12345678 + i));
		test_assert(penalty_has_checksum(penalty, "foo", i));
	}

	penalty_deinit(&penalty);
	io_loop_destroy(&ioloop);
	test_end();
}
Example #20
0
const char *str_sanitize(const char *src, size_t max_bytes)
{
	string_t *str;
	size_t i;

	if (src == NULL)
		return NULL;

	i = str_sanitize_skip_start(src, max_bytes);
	if (src[i] == '\0')
		return src;

	str = t_str_new(I_MIN(max_bytes, 256));
	str_sanitize_append(str, src, max_bytes);
	return str_c(str);
}
int mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
{
	unsigned int lock_timeout_secs;
	int ret;

	if (file->locked)
		return 0;

	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
		file->locked = TRUE;
		return 0;
	}

	if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK)
		return mail_transaction_log_file_dotlock(file);

	if (file->log->index->readonly) {
		mail_index_set_error(file->log->index,
			"Index is read-only, can't write-lock %s",
			file->filepath);
		return -1;
	}

	i_assert(file->file_lock == NULL);
	lock_timeout_secs = I_MIN(MAIL_TRANSACTION_LOG_LOCK_TIMEOUT,
				  file->log->index->max_lock_timeout_secs);
	ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
				 F_WRLCK, lock_timeout_secs,
				 &file->file_lock);
	if (ret > 0) {
		file->locked = TRUE;
		file->lock_created = time(NULL);
		return 0;
	}
	if (ret < 0) {
		log_file_set_syscall_error(file, "mail_index_wait_lock_fd()");
		return -1;
	}

	mail_index_set_error(file->log->index,
		"Timeout (%us) while waiting for lock for "
		"transaction log file %s%s",
		lock_timeout_secs, file->filepath,
		file_lock_find(file->fd, file->log->index->lock_method, F_WRLCK));
	file->log->index->index_lock_timeout = TRUE;
	return -1;
}
Example #22
0
bool stream_cmp_block(struct istream *input,
		      const unsigned char *data, size_t size)
{
	const unsigned char *indata;
	size_t insize, max;

	while (size > 0) {
		(void)i_stream_read_data(input, &indata, &insize, size-1);
		max = I_MIN(insize, size);
		if (insize == 0 || memcmp(data, indata, max) != 0)
			return FALSE;
		data += max;
		size -= max;
		i_stream_skip(input, max);
	}
	return TRUE;
}
Example #23
0
static bool proxy_try_reconnect(struct login_proxy *proxy)
{
	int since_started_msecs, left_msecs;

	since_started_msecs =
		timeval_diff_msecs(&ioloop_timeval, &proxy->created);
	if (since_started_msecs < 0)
		return FALSE; /* time moved backwards */
	left_msecs = proxy->connect_timeout_msecs - since_started_msecs;
	if (left_msecs <= 0)
		return FALSE;

	login_proxy_disconnect(proxy);
	proxy->to = timeout_add(I_MIN(PROXY_CONNECT_RETRY_MSECS, left_msecs),
				proxy_reconnect_timeout, proxy);
	proxy->reconnect_count++;
	return TRUE;
}
static ssize_t
mail_transaction_log_file_read_header(struct mail_transaction_log_file *file)
{
	void *dest;
	size_t pos, dest_size;
	ssize_t ret;

	i_assert(file->buffer == NULL && file->mmap_base == NULL);

	memset(&file->hdr, 0, sizeof(file->hdr));
	if (file->last_size < mmap_get_page_size() && file->last_size > 0) {
		/* just read the entire transaction log to memory.
		   note that if some of the data hasn't been fully committed
		   yet (hdr.size=0), the buffer must be truncated later */
		file->buffer = buffer_create_dynamic(default_pool, 4096);
		file->buffer_offset = 0;
		dest_size = file->last_size;
		dest = buffer_append_space_unsafe(file->buffer, dest_size);
	} else {
		/* read only the header */
		dest = &file->hdr;
		dest_size = sizeof(file->hdr);
	}

	/* it's not necessarily an error to read less than wanted header size,
	   since older versions of the log format used smaller headers. */
        pos = 0;
	do {
		ret = pread(file->fd, PTR_OFFSET(dest, pos),
			    dest_size - pos, pos);
		if (ret > 0)
			pos += ret;
	} while (ret > 0 && pos < dest_size);

	if (file->buffer != NULL) {
		buffer_set_used_size(file->buffer, pos);
		memcpy(&file->hdr, file->buffer->data,
		       I_MIN(pos, sizeof(file->hdr)));
	}

	return ret < 0 ? -1 : (ssize_t)pos;
}
Example #25
0
int sdbox_read_header(struct sdbox_mailbox *mbox,
		      struct sdbox_index_header *hdr, bool log_error,
		      bool *need_resize_r)
{
	struct mail_index_view *view;
	const void *data;
	size_t data_size;
	int ret = 0;

	i_assert(mbox->box.opened);

	view = mail_index_view_open(mbox->box.index);
	mail_index_get_header_ext(view, mbox->hdr_ext_id,
				  &data, &data_size);
	if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE &&
	    (!mbox->box.creating || data_size != 0)) {
		if (log_error) {
			mail_storage_set_critical(
				&mbox->storage->storage.storage,
				"sdbox %s: Invalid dbox header size",
				mailbox_get_path(&mbox->box));
		}
		ret = -1;
	} else {
		memset(hdr, 0, sizeof(*hdr));
		memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
		if (guid_128_is_empty(hdr->mailbox_guid))
			ret = -1;
		else {
			/* data is valid. remember it in case mailbox
			   is being reset */
			mail_index_set_ext_init_data(mbox->box.index,
						     mbox->hdr_ext_id,
						     hdr, sizeof(*hdr));
		}
	}
	mail_index_view_close(&view);
	*need_resize_r = data_size < sizeof(*hdr);
	return ret;
}
Example #26
0
static ssize_t
o_stream_buffer_sendv(struct ostream_private *stream,
		      const struct const_iovec *iov, unsigned int iov_count)
{
	struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
	size_t left, n;
	ssize_t ret = 0;
	unsigned int i;

	for (i = 0; i < iov_count; i++) {
		left = bstream->ostream.max_buffer_size -
			stream->ostream.offset;
		n = I_MIN(left, iov[i].iov_len);
		buffer_write(bstream->buf, stream->ostream.offset,
			     iov[i].iov_base, n);
		ret += n;
		if (n != iov[i].iov_len)
			break;
	}
	stream->ostream.offset += ret;
	return ret;
}
Example #27
0
int mdbox_read_header(struct mdbox_mailbox *mbox,
                      struct mdbox_index_header *hdr, bool *need_resize_r)
{
    const void *data;
    size_t data_size;

    i_assert(mbox->box.opened);

    mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
                              &data, &data_size);
    if (data_size < MDBOX_INDEX_HEADER_MIN_SIZE &&
            (!mbox->creating || data_size != 0)) {
        mail_storage_set_critical(&mbox->storage->storage.storage,
                                  "mdbox %s: Invalid dbox header size: %"PRIuSIZE_T,
                                  mailbox_get_path(&mbox->box), data_size);
        mdbox_storage_set_corrupted(mbox->storage);
        return -1;
    }
    memset(hdr, 0, sizeof(*hdr));
    memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
    *need_resize_r = data_size < sizeof(*hdr);
    return 0;
}
Example #28
0
static int
i_stream_base64_try_decode_block(struct base64_decoder_istream *bstream)
{
	struct istream_private *stream = &bstream->istream;
	const unsigned char *data;
	size_t size, avail, buffer_avail, pos;
	buffer_t buf;

	data = i_stream_get_data(stream->parent, &size);
	if (size == 0)
		return 0;

	i_stream_try_alloc(stream, (size+3)/4*3, &avail);
	buffer_avail = stream->buffer_size - stream->pos;

	if ((size + 3) / 4 * 3 > buffer_avail) {
		/* can't fit everything to destination buffer.
		   write as much as we can. */
		size = (buffer_avail / 3) * 4;
		if (size == 0)
			return -2;
	}

	buffer_create_from_data(&buf, stream->w_buffer + stream->pos,
				buffer_avail);
	if (base64_decode(data, size, &pos, &buf) < 0) {
		io_stream_set_error(&stream->iostream,
			"Invalid base64 data: 0x%s",
			binary_to_hex(data+pos, I_MIN(size-pos, 8)));
		stream->istream.stream_errno = EINVAL;
		return -1;
	}

	stream->pos += buf.used;
	i_stream_skip(stream->parent, pos);
	return pos > 0 ? 1 : 0;
}
Example #29
0
static int solr_xml_parse(struct solr_connection *conn,
			  const void *data, size_t size, bool done)
{
	enum XML_Error err;
	int line, col;

	if (conn->xml_failed)
		return -1;

	if (XML_Parse(conn->xml_parser, data, size, done))
		return 0;

	err = XML_GetErrorCode(conn->xml_parser);
	if (err != XML_ERROR_FINISHED) {
		line = XML_GetCurrentLineNumber(conn->xml_parser);
		col = XML_GetCurrentColumnNumber(conn->xml_parser);
		i_error("fts_solr: Invalid XML input at %d:%d: %s "
			"(near: %.*s)", line, col, XML_ErrorString(err),
			(int)I_MIN(size, 128), (const char *)data);
		conn->xml_failed = TRUE;
		return -1;
	}
	return 0;
}
Example #30
0
static ssize_t i_stream_mmap_read(struct istream_private *stream)
{
	struct mmap_istream *mstream = (struct mmap_istream *) stream;
	size_t aligned_skip;
	uoff_t top;

	if (stream->pos < stream->buffer_size) {
		/* more bytes available without needing to mmap() */
		stream->pos = stream->buffer_size;
		return stream->pos - stream->skip;
	}

	if (stream->istream.v_offset >= mstream->v_size) {
		stream->istream.eof = TRUE;
		return -1;
	}

	aligned_skip = stream->skip & ~mmap_pagemask;
	if (aligned_skip == 0 && mstream->mmap_base != NULL) {
		/* didn't skip enough bytes */
		return -2;
	}

	stream->skip -= aligned_skip;
	mstream->mmap_offset += aligned_skip;

	if (mstream->mmap_base != NULL) {
		if (munmap(mstream->mmap_base, stream->buffer_size) < 0) {
			i_error("mmap_istream.munmap(%s) failed: %m",
				i_stream_get_name(&stream->istream));
		}
	}

	top = mstream->v_size - mstream->mmap_offset;
	stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));

	i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
		 mstream->v_size);

	if (stream->buffer_size == 0) {
		/* don't bother even trying mmap */
		mstream->mmap_base = NULL;
		stream->buffer = NULL;
	} else {
		mstream->mmap_base =
			mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
			     stream->fd, mstream->mmap_offset);
		if (mstream->mmap_base == MAP_FAILED) {
			i_assert(errno != 0);
			stream->istream.stream_errno = errno;
			mstream->mmap_base = NULL;
			stream->buffer = NULL;
			stream->buffer_size = 0;
			stream->skip = stream->pos = 0;
			i_error("mmap_istream.mmap(%s) failed: %m",
				i_stream_get_name(&stream->istream));
			return -1;
		}
		stream->buffer = mstream->mmap_base;
	}

	if (stream->buffer_size > mmap_get_page_size()) {
		if (madvise(mstream->mmap_base, stream->buffer_size,
			    MADV_SEQUENTIAL) < 0) {
			i_error("mmap_istream.madvise(%s): %m",
				i_stream_get_name(&stream->istream));
		}
	}

	stream->pos = stream->buffer_size;
	i_assert(stream->pos - stream->skip > 0);
	return stream->pos - stream->skip;
}