Esempio n. 1
0
/**
 * Verify for all algorithms, that rhash_final() returns the same result as
 * rhash_print().
 */
static void test_results_consistency(void)
{
	const char * msg = "a";
	size_t msg_size = strlen(msg);

	size_t digest_size;
	struct rhash_context *ctx;
	unsigned char res1[70];
	char res2[70];
	unsigned i, hash_id;

	for(i = 0, hash_id = 1; (hash_id & RHASH_ALL_HASHES); hash_id <<= 1, i++) {
		digest_size = rhash_get_digest_size(hash_id);
		assert(digest_size < 70);

		ctx = rhash_init(hash_id);

#ifdef USE_BTIH_WITH_TEST_FILENAME
		if((hash_id & RHASH_BTIH) != 0) {
			unsigned long long total_size = msg_size;
			rhash_transmit(RMSG_BT_ADD_FILE, ctx, RHASH_STR2UPTR("test.txt"), (rhash_uptr_t)&total_size);
		}
#endif

		rhash_update(ctx, msg, msg_size);
		rhash_final(ctx, res1);
		rhash_print(res2, ctx, hash_id, RHPR_RAW);
		rhash_free(ctx);

		if(memcmp(res1, res2, digest_size) != 0) {
			log_message("failed: inconsistent %s(\"%s\") hash results\n", rhash_get_name(hash_id), msg);
		}
	}
}
Esempio n. 2
0
/**
 * Calculate hash sums simultaneously, according to the info->sums_flags.
 * Calculated hashes are stored in info->rctx.
 *
 * @param info file data. The info->full_path can be "-" to denote stdin
 * @return 0 on success, -1 on fail with error code stored in errno
 */
static int calc_sums(struct file_info *info)
{
	FILE* fd = stdin; /* stdin */
	int res;
	uint64_t initial_size;

	if(IS_DASH_STR(info->full_path)) {
		info->print_path = "(stdin)";

#ifdef _WIN32
		/* using 0 instead of _fileno(stdin). _fileno() is undefined under 'gcc -ansi' */
		if(setmode(0, _O_BINARY) < 0) {
			return -1;
		}
#endif
	} else {
		struct rsh_stat_struct stat_buf;
		/* skip non-existing files */
		if(rsh_stat(info->full_path, &stat_buf) < 0) {
			return -1;
		}

		if((opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED)) && S_ISDIR(stat_buf.st_mode)) {
			errno = EISDIR;
			return -1;
		}

		info->size = stat_buf.st_size; /* total size, in bytes */
		IF_WINDOWS(win32_set_filesize64(info->full_path, &info->size)); /* set correct filesize for large files under win32 */

		if(!info->sums_flags) return 0;

		/* skip files opened with exclusive rights without reporting an error */
		fd = rsh_fopen_bin(info->full_path, "rb");
		if(!fd) {
			return -1;
		}
	}

	re_init_rhash_context(info);
	initial_size = info->rctx->msg_size;

	if(percents_output->update != 0) {
		rhash_set_callback(info->rctx, (rhash_callback_t)percents_output->update, info);
	}

	/* read and hash file content */
	if((res = rhash_file_update(info->rctx, fd)) != -1) {
		if(!opt.bt_batch_file) {
			rhash_final(info->rctx, 0); /* finalize hashing */
		}
	}
	info->size = info->rctx->msg_size - initial_size;
	rhash_data.total_size += info->size;

	if(fd != stdin) fclose(fd);
	return res;
}
Esempio n. 3
0
/**
 * Calculate hash sums simultaneously, according to the info->sums_flags.
 * Calculated hashes are stored in info->rctx.
 *
 * @param info file data. The info->full_path can be "-" to denote stdin
 * @return 0 on success, -1 on fail with error code stored in errno
 */
static int calc_sums(struct file_info *info)
{
	FILE* fd = stdin; /* stdin */
	int res;

	assert(info->file);
	if(info->file->mode & FILE_IFSTDIN) {
		info->print_path = "(stdin)";

#ifdef _WIN32
		/* using 0 instead of _fileno(stdin). _fileno() is undefined under 'gcc -ansi' */
		if(setmode(0, _O_BINARY) < 0) {
			return -1;
		}
#endif
	} else {
		if((opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED)) && FILE_ISDIR(info->file)) {
			errno = EISDIR;
			return -1;
		}

		info->size = info->file->size; /* total size, in bytes */

		if(!info->sums_flags) return 0;

		/* skip without reporting an error the files
		 * opened exclusively by another process */
		fd = rsh_fopen_bin(info->full_path, "rb");
		if(!fd) {
			return -1;
		}
	}

	re_init_rhash_context(info);
	/* save initial msg_size, for correct calculation of percents */
	info->msg_offset = info->rctx->msg_size;

	if(percents_output->update != 0) {
		rhash_set_callback(info->rctx, (rhash_callback_t)percents_output->update, info);
	}

	/* read and hash file content */
	if((res = rhash_file_update(info->rctx, fd)) != -1) {
		if(!opt.bt_batch_file) {
			rhash_final(info->rctx, 0); /* finalize hashing */
		}
	}
	/* calculate real file size */
	info->size = info->rctx->msg_size - info->msg_offset;
	rhash_data.total_size += info->size;

	if(fd != stdin) fclose(fd);
	return res;
}
Esempio n. 4
0
/**
 * Hash a repeated message chunk by specified hash function.
 *
 * @deprecated This function shall be removed soon.
 *
 * @param hash_id hash function identifier
 * @param message a message chunk to hash
 * @param msg_size message chunk size
 * @param count number of chunks
 * @param out computed hash
 * @return 1 on success, 0 on error
 */
static int hash_in_loop(unsigned hash_id, const unsigned char* message, size_t msg_size, int count, unsigned char* out)
{
	int i;
	struct rhash_context *context = rhash_init(hash_id);
	if (!context) return 0;

	/* process the repeated message buffer */
	for (i = 0; i < count; i++) rhash_update(context, message, msg_size);
	rhash_final(context, out);
	rhash_free(context);
	return 1;
}
Esempio n. 5
0
/**
 * Calculate hash of the message specified by chunk string, repeated until
 * the given length is reached.
 *
 * @param chunk a null-terminated string representing the chunk
 * @param msg_size the total message length
 * @param length the total length of the message
 * @param hash_id id of the hash algorithm to use
 */
static char* calc_sums_c(const char* chunk, size_t msg_size, size_t length, unsigned hash_id)
{
    struct rhash_context *ctx;
    static char out[130];
    size_t i;

    ctx = rhash_init(hash_id);
    for(i = 0; i < length; i += msg_size) {
        rhash_update(ctx, (const unsigned char*)chunk,
                     ((i + msg_size) <= length ? msg_size : length % msg_size));
    }
    rhash_final(ctx, hash_id, 0);
    rhash_print(out, ctx, hash_id, RHPR_UPPERCASE);
    rhash_free(ctx);
    return out;
}
Esempio n. 6
0
/**
 * Test printing of magnet links.
 */
static void test_magnet(void)
{
	unsigned bit;

	rhash ctx = rhash_init(RHASH_ALL_HASHES);
	rhash_update(ctx, "a", 1);
	rhash_final(ctx, 0);

	assert_magnet("magnet:?xl=1&dn=test.txt&xt=urn:tree:tiger:czquwh3iyxbf5l3bgyugzhassmxu647ip2ike4y", ctx, RHASH_TTH, RHPR_FILESIZE | TEST_PATH);
	assert_magnet("magnet:?xl=1&xt=urn:md5:0CC175B9C0F1B6A831C399E269772661", ctx, RHASH_MD5, RHPR_FILESIZE | RHPR_UPPERCASE);
	assert_magnet("xt=urn:ed2k:bde52cb31de33e46245e05fbdbd6fb24&xt=urn:aich:q336in72uwt7zyk5dxolt2xk5i3xmz5y&xt=urn:sha1:q336in72uwt7zyk5dxolt2xk5i3xmz5y&xt=urn:btih:qj6nrgcg7qjs4lth4kocpbggkrb3wtob",
		ctx, RHASH_ED2K | RHASH_AICH | RHASH_SHA1 | RHASH_BTIH, RHPR_NO_MAGNET);

	/* verify length calculation for all hashes */
	for(bit = 1; bit < RHASH_ALL_HASHES; bit <<= 1) {
		assert_magnet(NULL, ctx, bit, RHPR_FILESIZE | RHPR_NO_MAGNET);
	}

	rhash_free(ctx);
}
Esempio n. 7
0
/**
 * Calculate hash of the message specified by chunk string, repeated until
 * the given length is reached.
 *
 * @param hash_id id of the hash algorithm to use
 * @param msg_chunk the message chunk as a null-terminated string
 * @param chunk_size the size of the chunk in bytes
 * @param count the number of chunks in the message
 * @param set_filename need to set a filename for BTIH hash
 */
static char* repeat_hash(unsigned hash_id, const char* chunk, size_t chunk_size, size_t msg_size, int set_filename)
{
	struct rhash_context *ctx;
	size_t left, size;
	static char out[130];
	assert(rhash_get_hash_length(hash_id) < 130);

	ctx = rhash_init(hash_id);

	if((hash_id & RHASH_BTIH) && set_filename) {
		unsigned long long total_size = msg_size;
		rhash_transmit(RMSG_BT_ADD_FILE, ctx, RHASH_STR2UPTR("test.txt"), (rhash_uptr_t)&total_size);
	}

	for(left = msg_size; left > 0; left -= size) {
		size = (left > chunk_size ? chunk_size : left);
		rhash_update(ctx, (const unsigned char*)chunk, size);
	}
	rhash_final(ctx, 0);
	rhash_print(out, ctx, hash_id, RHPR_UPPERCASE);
	rhash_free(ctx);
	return out;
}
Esempio n. 8
0
/**
 * RHash program entry point.
 *
 * @param argc number of program arguments including the program path
 * @param argv program arguments
 * @return the program exit code, zero on success and 1 on error
 */
int main(int argc, char *argv[])
{
	find_file_options search_opt;
	timedelta_t timer;
	int sfv;

	i18n_initialize(); /* initialize locale and translation */

	memset(&rhash_data, 0, sizeof(rhash_data));
	rhash_data.out = stdout; /* set initial output streams */
	rhash_data.log = stderr; /* can be altered by options later */
	rhash_data.search_opt = &search_opt;

	init_hash_info_table();

	read_options(argc, argv); /* load config and parse command line options */
	prev_sigint_handler = signal(SIGINT, ctrl_c_handler); /* install SIGINT handler */
	rhash_library_init();

	/* in benchmark mode just run benchmark and exit */
	if(opt.mode & MODE_BENCHMARK) {
		unsigned flags = (opt.flags & OPT_BENCH_RAW ? RHASH_BENCHMARK_CPB | RHASH_BENCHMARK_RAW : RHASH_BENCHMARK_CPB);
		if((opt.flags & OPT_BENCH_RAW) == 0) {
			fprintf(rhash_data.out, _("%s v%s benchmarking...\n"), PROGRAM_NAME, VERSION);
		}
		rhash_run_benchmark(opt.sum_flags, flags, rhash_data.out);
		rsh_exit(0);
	}

	if(opt.n_files == 0) {
		if(argc > 1) {
			log_warning(_("no files/directories were specified at command line\n"));
		}

		/* print short usage help */
		log_msg(_("Usage: %s [OPTION...] <FILE>...\n\n"
			"Run `%s --help' for more help.\n"), CMD_FILENAME, CMD_FILENAME);
		rsh_exit(0);
	}

	/* setup printf formating string */
	rhash_data.printf_str = opt.printf_str;

	if(opt.template_file) {
		if(!load_printf_template()) rsh_exit(2);
	} else if(!rhash_data.printf_str && !(opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED))) {
		/* initialize printf output format according to '--<hashname>' options */
		init_printf_format( (rhash_data.template_text = rsh_str_new()) );
		rhash_data.printf_str = rhash_data.template_text->str;

		if(opt.flags & OPT_VERBOSE) {
			char* str = rsh_strdup(rhash_data.printf_str);
			log_msg(_("Format string is: %s\n"), str_trim(str));
			free(str);
		}
	}

	if(rhash_data.printf_str) {
		rhash_data.print_list = parse_print_string(rhash_data.printf_str, &opt.sum_flags);
	}

	memset(&search_opt, 0, sizeof(search_opt));
	search_opt.max_depth = (opt.flags & OPT_RECURSIVE ? opt.find_max_depth : 0);
	search_opt.options = FIND_SKIP_DIRS;
	search_opt.call_back = find_file_callback;

	if((sfv = (opt.fmt == FMT_SFV && !opt.mode))) {
		print_sfv_banner(rhash_data.out);
	}

	/* pre-process files */
	if(sfv || opt.bt_batch_file) {
		/* note: errors are not reported on pre-processing */
		search_opt.call_back_data = (void*)1;
		process_files((const char**)opt.files, opt.n_files, &search_opt);

		fflush(rhash_data.out);
	}

	/* measure total processing time */
	rhash_timer_start(&timer);
	rhash_data.processed = 0;

	/* process files */
	search_opt.options |= FIND_LOG_ERRORS;
	search_opt.call_back_data = (void*)0;
	process_files((const char**)opt.files, opt.n_files, &search_opt);

	if((opt.mode & MODE_CHECK_EMBEDDED) && rhash_data.processed > 1) {
		print_check_stats();
	}

	if(!rhash_data.interrupted)
	{
		if(opt.bt_batch_file && rhash_data.rctx) {
			rhash_final(rhash_data.rctx, 0);
			save_torrent_to(opt.bt_batch_file, rhash_data.rctx);
		}

		if((opt.flags & OPT_SPEED) &&
			!(opt.mode & (MODE_CHECK | MODE_UPDATE)) &&
			rhash_data.processed > 1) {
			double time = rhash_timer_stop(&timer);
			print_time_stats(time, rhash_data.total_size, 1);
		}
	} else {
		/* check if interruption was not reported yet */
		if(rhash_data.interrupted == 1) report_interrupted();
	}

	options_destroy(&opt);
	rhash_destroy(&rhash_data);

	/* return non-zero error code if error occurred */
	return (rhash_data.error_flag ? 1 :
		search_opt.errors_count ? 2 :
		rhash_data.interrupted ? 3 : 0);
}
Esempio n. 9
0
/*
 * Class:     org_sf_rhash_Bindings
 * Method:    rhash_final
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1final
(JNIEnv *env, jclass clz, jlong context) {
	rhash_final(TO_RHASH(context), NULL);
}