diff --git a/f3brew.c b/f3brew.c index 2e9c4d2..b01953a 100644 --- a/f3brew.c +++ b/f3brew.c @@ -171,7 +171,7 @@ int main(void) 22, /* Wrap. */ 9, /* Block order. */ false) /* Keep file? */ - : create_block_device("/dev/sdc", false); + : create_block_device("/dev/sdc", 0, RT_MANUAL_USB); assert(dev); write_and_read_blocks(dev, first_block, last_block); diff --git a/f3probe.c b/f3probe.c index a59bf51..566a42e 100644 --- a/f3probe.c +++ b/f3probe.c @@ -35,14 +35,14 @@ static struct argp_option options[] = { "Fake size of the emulated drive", 0}, {"debug-wrap", 'w', "N", OPTION_HIDDEN, "Wrap parameter of the emulated drive", 0}, - {"debug-block-order", 'b', "ORDER", OPTION_HIDDEN, - "Block size the emulated drive is 2^ORDER Byte", 0}, {"debug-keep-file", 'k', NULL, OPTION_HIDDEN, "Don't remove file used for emulating the drive", 0}, {"debug-unit-test", 'u', NULL, OPTION_HIDDEN, "Run a unit test; it ignores all other debug options", 0}, + {"block-order", 'b', "ORDER", 0, + "Force block size of the drive to 2^ORDER Bytes", 2}, {"destructive", 'n', NULL, 0, - "Do not restore blocks of the device after probing it", 2}, + "Do not restore blocks of the device after probing it", 0}, {"min-memory", 'l', NULL, 0, "Trade speed for less use of memory", 0}, {"reset-type", 's', "TYPE", 0, @@ -159,9 +159,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) case 'b': ll = arg_to_long_long(state, arg); - if (ll < 9 || ll > 20) + if (ll != 0 && (ll < 9 || ll > 20)) argp_error(state, - "Block order must be in the interval [9, 20]"); + "Block order must be in the interval [9, 20] or be zero"); args->block_order = ll; args->debug = true; break; @@ -367,7 +367,8 @@ static int test_device(struct args *args) ? create_file_device(args->filename, args->real_size_byte, args->fake_size_byte, args->wrap, args->block_order, args->keep_file) - : create_block_device(args->filename, args->reset_type); + : create_block_device(args->filename, args->block_order, + args->reset_type); if (!dev) { fprintf(stderr, "\nApplication cannot continue, finishing...\n"); exit(1); @@ -480,7 +481,7 @@ int main(int argc, char **argv) .real_size_byte = 1ULL << 31, .fake_size_byte = 1ULL << 34, .wrap = 31, - .block_order = 9, + .block_order = 0, }; /* Read parameters. */ diff --git a/libdevs.c b/libdevs.c index 12a4ab5..748d0db 100644 --- a/libdevs.c +++ b/libdevs.c @@ -232,9 +232,6 @@ struct device *create_file_device(const char *filename, { struct file_device *fdev; - if (!dev_param_valid(real_size_byte, fake_size_byte, wrap, block_order)) - goto error; - fdev = malloc(sizeof(*fdev)); if (!fdev) goto error; @@ -251,6 +248,18 @@ struct device *create_file_device(const char *filename, assert(!unlink(filename)); } + if (!block_order) { + struct stat fd_stat; + blksize_t block_size; + assert(!fstat(fdev->fd, &fd_stat)); + block_size = fd_stat.st_blksize; + block_order = ilog2(block_size); + assert(block_size == (1 << block_order)); + } + + if (!dev_param_valid(real_size_byte, fake_size_byte, wrap, block_order)) + goto keep_file; + fdev->real_size_byte = real_size_byte; fdev->address_mask = (((uint64_t)1) << wrap) - 1; @@ -263,6 +272,10 @@ struct device *create_file_device(const char *filename, return &fdev->dev; +keep_file: + if (keep_file) + unlink(filename); + assert(!close(fdev->fd)); fdev: free(fdev); error: @@ -562,13 +575,13 @@ static struct udev_device *map_partition_to_disk(struct udev_device *dev) return udev_device_ref(disk_dev); } -struct device *create_block_device(const char *filename, enum reset_type rt) +struct device *create_block_device(const char *filename, int block_order, + enum reset_type rt) { struct block_device *bdev; struct udev *udev; struct udev_device *fd_dev, *usb_dev; const char *s; - int block_size; bdev = malloc(sizeof(*bdev)); if (!bdev) @@ -648,9 +661,13 @@ struct device *create_block_device(const char *filename, enum reset_type rt) assert(!ioctl(bdev->fd, BLKGETSIZE64, &bdev->dev.size_byte)); - assert(!ioctl(bdev->fd, BLKBSZGET, &block_size)); - bdev->dev.block_order = ilog2(block_size); - assert(block_size == (1 << bdev->dev.block_order)); + if (!block_order) { + int block_size; + assert(!ioctl(bdev->fd, BLKBSZGET, &block_size)); + block_order = ilog2(block_size); + assert(block_size == (1 << block_order)); + } + bdev->dev.block_order = block_order; bdev->dev.read_block = bdev_read_block; bdev->dev.write_block = bdev_write_block; diff --git a/libdevs.h b/libdevs.h index 93fbd90..e29db15 100644 --- a/libdevs.h +++ b/libdevs.h @@ -74,7 +74,8 @@ enum reset_type { }; #define RT_DEFAULT RT_MANUAL_USB -struct device *create_block_device(const char *filename, enum reset_type rt); +struct device *create_block_device(const char *filename, int block_order, + enum reset_type rt); struct device *create_perf_device(struct device *dev); void perf_device_sample(struct device *dev,