Beispiel #1
0
/**
 * Output SFV-formated file header.
 */
static void preprocess_files(void)
{
	int i;

	/* print SFV file header */
	if(opt.fmt == FMT_SFV && opt.mode == 0) {
		print_sfv_banner(rhash_data.out);

		for(i = 0; i < opt.n_files; i++) {
			char *path = opt.files[i];
			if(opt.flags & OPT_RECURSIVE) {
				struct rsh_stat_struct stat_buf;
				if(rsh_stat(path, &stat_buf) < 0) {
					continue; /* don't report error here, it'll be reported later */
				}
				/* if file is a directory, then walk it recursively */
				if(S_ISDIR(stat_buf.st_mode)) {
					find_file(path, find_file_callback, 0, opt.find_max_depth, (void*)1);
					continue;
				}
			}
			print_sfv_header_line(rhash_data.out, path, path);
		}
		fflush(rhash_data.out);
	}
}
Beispiel #2
0
/**
 * Callback function to process a file found while recursively traversing
 * a directory.
 *
 * @param filepath path to the file
 * @param type file attributes
 * @param data the paramater specified, when calling find_file(). It shall be
 *             non-zero for printing SFV header, zero for actual processing.
 */
static int find_file_callback(const char* filepath, int type, void* data)
{
	int res = 0;
	if( !(type & FIND_IFDIR) ) {
		if(data) {
			if(!file_mask_match(opt.files_accept, filepath)) return 0;
			if(filepath[0] == '.' && IS_PATH_SEPARATOR(filepath[1])) filepath += 2;
			/* TODO: get size, fill file struct */
			print_sfv_header_line(rhash_data.out, filepath, filepath);
			/* rhash_data.total_size += file.size */
		} else {
			/* only check an update modes use crc_accept mask */
			file_mask_array* masks = (opt.mode & (MODE_CHECK | MODE_UPDATE) ?
				opt.crc_accept : opt.files_accept);
			if(!file_mask_match(masks, filepath)) return 0;

			if(opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED)) {
				res = check_hash_file(filepath, 1);
			} else {
				if(opt.mode & MODE_UPDATE) {
					res = update_hash_file(filepath);
				} else {
					/* default mode: calculate hash */
					if(filepath[0] == '.' && IS_PATH_SEPARATOR(filepath[1])) filepath += 2;
					res = calculate_and_print_sums(rhash_data.out, filepath, filepath, NULL);
					rhash_data.processed++;
				}
			}
		}
	}
	if(res < 0) rhash_data.error_flag = 1;
	return 1;
}
Beispiel #3
0
/**
 * Callback function to process files while recursively traversing a directory.
 * It hashes, checks or updates a file according to the current work mode.
 *
 * @param file the file to process
 * @param preprocess non-zero when preprocessing files, zero for actual processing.
 */
static int find_file_callback(file_t* file, int preprocess)
{
	int res = 0;
	assert(!FILE_ISDIR(file));
	assert(opt.search_data);

	if (rhash_data.interrupted) {
		opt.search_data->options |= FIND_CANCEL;
		return 0;
	}

	if (preprocess) {
		if (!file_mask_match(opt.files_accept, file->path) || must_skip_file(file)) {
			return 0;
		}

		if (opt.fmt & FMT_SFV) {
			print_sfv_header_line(rhash_data.out, file, 0);
		}

		rhash_data.batch_size += file->size;
	} else {
		int not_root = !(file->mode & FILE_IFROOT);

		if (not_root) {
			/* only check and update modes use the crc_accept mask */
			file_mask_array* masks = (opt.mode & (MODE_CHECK | MODE_UPDATE) ?
				opt.crc_accept : opt.files_accept);
			if (!file_mask_match(masks, file->path)) return 0;
		}
		if (must_skip_file(file)) return 0;

		if (opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED)) {
			res = check_hash_file(file, not_root);
		} else {
			if (opt.mode & MODE_UPDATE) {
				res = update_hash_file(file);
			} else {
				/* default mode: calculate hash */
				const char* print_path = file->path;
				if (print_path[0] == '.' && IS_PATH_SEPARATOR(print_path[1])) print_path += 2;
				res = calculate_and_print_sums(rhash_data.out, file, print_path);
				if (rhash_data.interrupted) return 0;
				rhash_data.processed++;
			}
		}
	}
	if (res < 0) rhash_data.error_flag = 1;
	return 1;
}
Beispiel #4
0
/**
 * Calculate and print file hash sums using printf format.
 *
 * @param out a stream to print to
 * @param file the file to calculate sums for
 * @param print_path the path to print
 * @return 0 on success, -1 on fail
 */
int calculate_and_print_sums(FILE* out, file_t* file, const char *print_path)
{
	struct file_info info;
	timedelta_t timer;
	int res = 0;

	memset(&info, 0, sizeof(info));
	info.file = file;
	info.full_path = rsh_strdup(file->path);
	file_info_set_print_path(&info, print_path);
	info.size = 0;

	info.sums_flags = opt.sum_flags;

	if(file->mode & FILE_IFSTDIN) {
		print_path = "(stdin)";
	} else {
		if(file->mode & FILE_IFDIR) return 0; /* don't handle directories */
		info.size = file->size; /* total size, in bytes */
	}

	/* initialize percents output */
	init_percents(&info);
	rhash_timer_start(&timer);

	if(info.sums_flags) {
		/* calculate sums */
		if(calc_sums(&info) < 0) {
			/* print error unless sharing access error occurred */
			if(errno == EACCES) return 0;
			log_file_error(file->path);
			res = -1;
		}
		if(rhash_data.interrupted) {
			report_interrupted();
			return 0;
		}
	}

	info.time = rhash_timer_stop(&timer);
	finish_percents(&info, res);

	if(opt.flags & OPT_EMBED_CRC) {
		/* rename the file */
		rename_file_by_embeding_crc32(&info);
	}

	if((opt.mode & MODE_TORRENT) && !opt.bt_batch_file) {
		save_torrent(&info);
	}

	if((opt.mode & MODE_UPDATE) && opt.fmt == FMT_SFV) {
		/* updating SFV file: print SFV header line */
		print_sfv_header_line(rhash_data.upd_fd, file, 0);
		if(opt.flags & OPT_VERBOSE) {
			print_sfv_header_line(rhash_data.log, file, 0);
			fflush(rhash_data.log);
		}
		rsh_file_cleanup(file);
	}

	if(rhash_data.print_list && res >= 0) {
		if (!opt.bt_batch_file) {
			print_line(out, rhash_data.print_list, &info);
			fflush(out);

			/* print calculated line to stderr or log-file if verbose */
			if((opt.mode & MODE_UPDATE) && (opt.flags & OPT_VERBOSE)) {
				print_line(rhash_data.log, rhash_data.print_list, &info);
				fflush(rhash_data.log);
			}
		}

		if((opt.flags & OPT_SPEED) && info.sums_flags) {
			print_file_time_stats(&info);
		}
	}
	free(info.full_path);
	file_info_destroy(&info);
	return res;
}