Beispiel #1
0
static void gtkhash_hash_file_read_finish(
	G_GNUC_UNUSED GObject *source, GAsyncResult *res, struct hash_file_s *data)
{
	data->just_read = g_input_stream_read_finish(
		G_INPUT_STREAM(data->stream), res, NULL);

	if (G_UNLIKELY(data->just_read == -1) &&
		!g_cancellable_is_cancelled(data->cancellable))
	{
		g_warning("failed to read file (%s)", data->uri);
		g_cancellable_cancel(data->cancellable);
	} else if (G_UNLIKELY(data->just_read == 0)) {
		g_warning("unexpected EOF (%s)", data->uri);
		g_cancellable_cancel(data->cancellable);
	} else {
		g_mutex_lock(data->priv.mutex);
		data->priv.total_read += data->just_read;
		const goffset total_read = data->priv.total_read;
		g_mutex_unlock(data->priv.mutex);
		if (G_UNLIKELY(total_read > data->file_size)) {
			g_warning("read %" G_GOFFSET_FORMAT
				" more bytes than expected (%s)", total_read - data->file_size,
				data->uri);
			g_cancellable_cancel(data->cancellable);
		} else
			gtkhash_hash_file_set_state(data, HASH_FILE_STATE_HASH);
	}

	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable)))
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);

	gtkhash_hash_file_add_source(data);
}
Beispiel #2
0
static void gtkhash_hash_file_hash_finish(struct hash_file_s *data)
{
	g_assert(g_atomic_int_get(&data->pool_threads_n) == 0);

	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
		return;
	}

	if (data->priv.total_read >= data->file_size)
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
	else
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_READ);
}
Beispiel #3
0
static void gtkhash_hash_file_callback(struct hash_file_s *data)
{
	gtkhash_hash_file_remove_source(data);
	gtkhash_hash_file_set_state(data, HASH_FILE_STATE_IDLE);

	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable)))
		gtkhash_hash_file_stop_cb(data->cb_data);
	else
		gtkhash_hash_file_finish_cb(data->cb_data);
}
Beispiel #4
0
static void gtkhash_hash_file_get_size_finish(
	G_GNUC_UNUSED GObject *source, GAsyncResult *res, struct hash_file_s *data)
{
	GFileInfo *info = g_file_input_stream_query_info_finish(
		data->stream, res, NULL);
	data->file_size = g_file_info_get_size(info);
	g_object_unref(info);

	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable)))
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
	else if (data->file_size == 0)
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_HASH);
	else {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_READ);
		gtkhash_hash_file_add_report_source(data);
	}

	gtkhash_hash_file_add_source(data);
}
Beispiel #5
0
static void gtkhash_hash_file_open(struct hash_file_s *data)
{
	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_FINISH);
		return;
	}

	gtkhash_hash_file_remove_source(data);
	g_file_read_async(data->file, G_PRIORITY_DEFAULT, data->cancellable,
		(GAsyncReadyCallback)gtkhash_hash_file_open_finish, data);
}
Beispiel #6
0
static void gtkhash_hash_file_hash(struct hash_file_s *data)
{
	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
		return;
	}

	gtkhash_hash_file_remove_source(data);
	gtkhash_hash_file_set_state(data, HASH_FILE_STATE_HASH_FINISH);

	g_atomic_int_inc(&data->pool_threads_n);
	for (unsigned int i = 0; i < HASH_FUNCS_N; i++) {
		if (data->funcs[i].enabled) {
			g_atomic_int_inc(&data->pool_threads_n);
			g_thread_pool_push(data->thread_pool, GUINT_TO_POINTER(i + 1), NULL);
		}
	}

	if (g_atomic_int_dec_and_test(&data->pool_threads_n))
		gtkhash_hash_file_add_source(data);
}
Beispiel #7
0
static void gtkhash_hash_file_get_size(struct hash_file_s *data)
{
	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
		return;
	}

	gtkhash_hash_file_remove_source(data);
	g_file_input_stream_query_info_async(data->stream,
		G_FILE_ATTRIBUTE_STANDARD_SIZE, G_PRIORITY_DEFAULT, data->cancellable,
		(GAsyncReadyCallback)gtkhash_hash_file_get_size_finish, data);
}
Beispiel #8
0
static void gtkhash_hash_file_open_finish(
	G_GNUC_UNUSED GObject *source, GAsyncResult *res, struct hash_file_s *data)
{
	data->stream = g_file_read_finish(data->file, res, NULL);
	if (G_UNLIKELY(!data->stream &&
		!g_cancellable_is_cancelled(data->cancellable)))
	{
		g_warning("failed to open file (%s)", data->uri);
		g_cancellable_cancel(data->cancellable);
	}

	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		if (data->stream)
			gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
		else
			gtkhash_hash_file_set_state(data, HASH_FILE_STATE_FINISH);
	} else
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_GET_SIZE);

	gtkhash_hash_file_add_source(data);
}
Beispiel #9
0
static void gtkhash_hash_file_read(struct hash_file_s *data)
{
	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CLOSE);
		return;
	}

	gtkhash_hash_file_remove_source(data);
	g_input_stream_read_async(G_INPUT_STREAM(data->stream),
		data->buffer, HASH_FILE_BUFFER_SIZE, G_PRIORITY_DEFAULT,
		data->cancellable, (GAsyncReadyCallback)gtkhash_hash_file_read_finish,
		data);
}
Beispiel #10
0
static void gtkhash_hash_file_close_finish(
	G_GNUC_UNUSED GObject *source, GAsyncResult *res, struct hash_file_s *data)
{
	if (G_UNLIKELY(!g_input_stream_close_finish(G_INPUT_STREAM(data->stream), res, NULL) &&
		!g_cancellable_is_cancelled(data->cancellable)))
	{
		g_warning("failed to close file (%s)", data->uri);
	}

	g_object_unref(data->stream);

	gtkhash_hash_file_remove_report_source(data);
	gtkhash_hash_file_set_state(data, HASH_FILE_STATE_FINISH);
	gtkhash_hash_file_add_source(data);
}
Beispiel #11
0
void hash_file_start(const char *uri)
{
	if (gui_get_view() != GUI_VIEW_FILE_LIST)
		gtkhash_hash_file_clear_digests(&hash_priv.file_data);

	GFile *file = g_file_new_for_uri(uri);
	char *pname = g_file_get_parse_name(file);
	gtk_progress_bar_set_text(gui.progressbar, pname);
	g_free(pname);
	g_object_unref(file);

	gtkhash_hash_file_set_uri(&hash_priv.file_data, uri);
	gtkhash_hash_file_set_stop(&hash_priv.file_data, false);
	gtkhash_hash_file_set_state(&hash_priv.file_data, HASH_FILE_STATE_START);
	gtkhash_hash_file_add_source(&hash_priv.file_data);
}
Beispiel #12
0
static void gtkhash_hash_file_finish(struct hash_file_s *data)
{
	if (G_UNLIKELY(g_cancellable_is_cancelled(data->cancellable))) {
		for (int i = 0; i < HASH_FUNCS_N; i++)
			if (data->funcs[i].enabled)
				gtkhash_hash_lib_stop(&data->funcs[i]);
	} else {
		for (int i = 0; i < HASH_FUNCS_N; i++)
			if (data->funcs[i].enabled)
				gtkhash_hash_lib_finish(&data->funcs[i]);
	}

	g_object_unref(data->file);
	g_free(data->buffer);
	g_timer_destroy(data->timer);
	g_thread_pool_free(data->thread_pool, true, false);

	gtkhash_hash_file_set_state(data, HASH_FILE_STATE_CALLBACK);
}
Beispiel #13
0
static void gtkhash_hash_file_start(struct hash_file_s *data)
{
	g_assert(data->uri);

	int funcs_enabled = 0;

	for (int i = 0; i < HASH_FUNCS_N; i++) {
		if (data->funcs[i].enabled) {
			gtkhash_hash_lib_start(&data->funcs[i], data->hmac_key,
				data->key_size);
			funcs_enabled++;
		}
	}

	g_assert(funcs_enabled > 0);

#ifdef _SC_NPROCESSORS_ONLN
	const long int cpus = sysconf(_SC_NPROCESSORS_ONLN);
	if (cpus < 1)
		g_warning("sysconf(_SC_NPROCESSORS_ONLN) returned %ld", cpus);
#else
	#warning "insert code to find number of CPUs here"
	const int cpus = 1;
#endif

	const int threads = CLAMP(MIN(funcs_enabled, cpus), 1, HASH_FUNCS_N);

	g_atomic_int_set(&data->pool_threads_n, 0);
	data->thread_pool = g_thread_pool_new((GFunc)gtkhash_hash_file_hash_thread,
		data, threads, true, NULL);

	data->file = g_file_new_for_uri(data->uri);
	data->just_read = 0;
	data->buffer = g_malloc(HASH_FILE_BUFFER_SIZE);
	data->timer = g_timer_new();
	data->priv.total_read = 0;

	gtkhash_hash_file_set_state(data, HASH_FILE_STATE_OPEN);
}