示例#1
0
文件: badblocks.c 项目: hanji/rufus
static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size, blk_t first_block,
	size_t blocks_at_once, int nb_passes)
{
	unsigned char *buffer = NULL, *read_buffer;
	const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00};
	int i, pat_idx;
	unsigned int bb_count = 0;
	blk_t got, tryout, recover_block = ~0, *blk_id;
	size_t id_offset;

	if ((nb_passes < 1) || (nb_passes > 4)) {
		uprintf("%sInvalid number of passes\n", bb_prefix);
		cancel_ops = -1;
		return 0;
	}

	buffer = allocate_buffer(2 * blocks_at_once * block_size);
	read_buffer = buffer + blocks_at_once * block_size;

	if (!buffer) {
		uprintf("%sError while allocating buffers\n", bb_prefix);
		cancel_ops = -1;
		return 0;
	}

	uprintf("%sChecking from block %lu to %lu\n", bb_prefix,
		(unsigned long) first_block, (unsigned long) last_block - 1);
	nr_pattern = nb_passes;
	cur_pattern = 0;

	for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) {
		if (cancel_ops) goto out;
		srand((unsigned int)GetTickCount());
		id_offset = rand()* (block_size-sizeof(blk_t)) / RAND_MAX;
		pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size);
		uprintf("%sBlock ID at offset: %d\n", bb_prefix, id_offset);
		num_blocks = last_block - 1;
		currently_testing = first_block;
		if (s_flag | v_flag)
			uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pat_idx]);
		cur_op = OP_WRITE;
		tryout = blocks_at_once;
		while (currently_testing < last_block) {
			if (cancel_ops) goto out;
			if (max_bb && bb_count >= max_bb) {
				if (s_flag || v_flag) {
					uprintf(abort_msg);
					fprintf(log_fd, abort_msg);
					fflush(log_fd);
				}
				cancel_ops = -1;
				goto out;
			}
			if (currently_testing + tryout > last_block)
				tryout = last_block - currently_testing;
			if (detect_fakes) {
				/* Add the block number at a fixed (random) offset during each pass to
				   allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */
				for (i=0; i<(int)blocks_at_once; i++) {
					blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size);
					*blk_id = (blk_t)(currently_testing + i);
				}
			}
			got = do_write(hDrive, buffer, tryout, block_size, currently_testing);
			if (v_flag > 1)
				print_status();

			if (got == 0 && tryout == 1)
				bb_count += bb_output(currently_testing++, WRITE_ERROR);
			currently_testing += got;
			if (got != tryout) {
				tryout = 1;
				if (recover_block == ~0)
					recover_block = currently_testing -
						got + blocks_at_once;
				continue;
			} else if (currently_testing == recover_block) {
				tryout = blocks_at_once;
				recover_block = ~0;
			}
		}

		num_blocks = 0;
		if (s_flag | v_flag)
			uprintf("%sReading and comparing\n", bb_prefix);
		cur_op = OP_READ;
		num_blocks = last_block;
		currently_testing = first_block;

		tryout = blocks_at_once;
		while (currently_testing < last_block) {
			if (cancel_ops) goto out;
			if (max_bb && bb_count >= max_bb) {
				if (s_flag || v_flag) {
					uprintf(abort_msg);
					fprintf(log_fd, abort_msg);
					fflush(log_fd);
				}
				cancel_ops = -1;
				goto out;
			}
			if (currently_testing + tryout > last_block)
				tryout = last_block - currently_testing;
			if (detect_fakes) {
				for (i=0; i<(int)blocks_at_once; i++) {
					blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size);
					*blk_id = (blk_t)(currently_testing + i);
				}
			}
			got = do_read(hDrive, read_buffer, tryout, block_size,
				       currently_testing);
			if (got == 0 && tryout == 1)
				bb_count += bb_output(currently_testing++, READ_ERROR);
			currently_testing += got;
			if (got != tryout) {
				tryout = 1;
				if (recover_block == ~0)
					recover_block = currently_testing -
						got + blocks_at_once;
				continue;
			} else if (currently_testing == recover_block) {
				tryout = blocks_at_once;
				recover_block = ~0;
			}
			for (i=0; i < got; i++) {
				if (memcmp(read_buffer + i * block_size,
					   buffer + i * block_size,
					   block_size))
					bb_count += bb_output(currently_testing+i-got, CORRUPTION_ERROR);
			}
			if (v_flag > 1)
				print_status();
		}

		num_blocks = 0;
	}
out:
	free_buffer(buffer);
	return bb_count;
}
示例#2
0
static unsigned int test_rw(HANDLE hDrive, blk64_t last_block, size_t block_size, blk64_t first_block,
							size_t blocks_at_once, int pattern_type, int nb_passes)
{
	const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] =
		{ BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC };
	unsigned char *buffer = NULL, *read_buffer;
	int i, pat_idx;
	unsigned int bb_count = 0;
	blk64_t got, tryout, recover_block = ~0, *blk_id;
	size_t id_offset = 0;

	if ((pattern_type < 0) || (pattern_type >= BADLOCKS_PATTERN_TYPES)) {
		uprintf("%sInvalid pattern type\n", bb_prefix);
		cancel_ops = -1;
		return 0;
	}
	if ((nb_passes < 1) || (nb_passes > BADBLOCK_PATTERN_COUNT)) {
		uprintf("%sInvalid number of passes\n", bb_prefix);
		cancel_ops = -1;
		return 0;
	}

	buffer = allocate_buffer(2 * blocks_at_once * block_size);
	read_buffer = buffer + blocks_at_once * block_size;

	if (!buffer) {
		uprintf("%sError while allocating buffers\n", bb_prefix);
		cancel_ops = -1;
		return 0;
	}

	uprintf("%sChecking from block %lu to %lu (1 block = %s)\n", bb_prefix,
		(unsigned long) first_block, (unsigned long) last_block - 1,
		SizeToHumanReadable(BADBLOCK_BLOCK_SIZE, FALSE, FALSE));
	nr_pattern = nb_passes;
	cur_pattern = 0;

	for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) {
		if (cancel_ops)
			goto out;
		if (detect_fakes && (pat_idx == 0)) {
			srand((unsigned int)GetTickCount64());
			id_offset = rand() * (block_size - sizeof(blk64_t)) / RAND_MAX;
			uprintf("%sUsing offset %d for fake device check\n", bb_prefix, id_offset);
		}
		// coverity[dont_call]
		pattern_fill(buffer, pattern[pattern_type][pat_idx], blocks_at_once * block_size);
		num_blocks = last_block - 1;
		currently_testing = first_block;
		if (s_flag | v_flag)
			uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pattern_type][pat_idx]);
		cur_op = OP_WRITE;
		tryout = blocks_at_once;
		while (currently_testing < last_block) {
			if (cancel_ops)
				goto out;
			if (max_bb && bb_count >= max_bb) {
				if (s_flag || v_flag) {
					uprintf(abort_msg);
					fprintf(log_fd, abort_msg);
					fflush(log_fd);
				}
				cancel_ops = -1;
				goto out;
			}
			if (currently_testing + tryout > last_block)
				tryout = last_block - currently_testing;
			if (detect_fakes && (pat_idx == 0)) {
				/* Add the block number at a fixed (random) offset during each pass to
				   allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */
				for (i=0; i<(int)blocks_at_once; i++) {
					blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size);
					*blk_id = (blk64_t)(currently_testing + i);
				}
			}
			got = do_write(hDrive, buffer, tryout, block_size, currently_testing);
			if (v_flag > 1)
				print_status();

			if (got == 0 && tryout == 1)
				bb_count += bb_output(currently_testing++, WRITE_ERROR);
			currently_testing += got;
			if (got != tryout) {
				tryout = 1;
				if (recover_block == ~0)
					recover_block = currently_testing -
						got + blocks_at_once;
				continue;
			} else if (currently_testing == recover_block) {
				tryout = blocks_at_once;
				recover_block = ~0;
			}
		}

		num_blocks = 0;
		if (s_flag | v_flag)
			uprintf("%sReading and comparing\n", bb_prefix);
		cur_op = OP_READ;
		num_blocks = last_block;
		currently_testing = first_block;

		tryout = blocks_at_once;
		while (currently_testing < last_block) {
			if (cancel_ops) goto out;
			if (max_bb && bb_count >= max_bb) {
				if (s_flag || v_flag) {
					uprintf(abort_msg);
					fprintf(log_fd, abort_msg);
					fflush(log_fd);
				}
				cancel_ops = -1;
				goto out;
			}
			if (currently_testing + tryout > last_block)
				tryout = last_block - currently_testing;
			if (detect_fakes && (pat_idx == 0)) {
				for (i=0; i<(int)blocks_at_once; i++) {
					blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size);
					*blk_id = (blk64_t)(currently_testing + i);
				}
			}
			got = do_read(hDrive, read_buffer, tryout, block_size,
				       currently_testing);
			if (got == 0 && tryout == 1)
				bb_count += bb_output(currently_testing++, READ_ERROR);
			currently_testing += got;
			if (got != tryout) {
				tryout = 1;
				if (recover_block == ~0)
					recover_block = currently_testing -
						got + blocks_at_once;
				continue;
			} else if (currently_testing == recover_block) {
				tryout = blocks_at_once;
				recover_block = ~0;
			}
			for (i=0; i < got; i++) {
				if (memcmp(read_buffer + i * block_size,
					   buffer + i * block_size,
					   block_size))
					bb_count += bb_output(currently_testing+i-got, CORRUPTION_ERROR);
			}
			if (v_flag > 1)
				print_status();
		}

		num_blocks = 0;
	}
out:
	free_buffer(buffer);
	return bb_count;
}