Skip to content

Commit

Permalink
Correct size detection for special block devices
Browse files Browse the repository at this point in the history
When writing directly to a special block device instead of a regular
file image, the size reported by fstat(2) returns 0, which is incorrect.
This commit introduces a check to identify if the target file is a
special block device. If it is, the commit uses the ioctl(2) to
accurately determine the size of the block device.
  • Loading branch information
jserv committed May 15, 2024
1 parent 5e11fa7 commit bf61cd4
Showing 1 changed file with 14 additions and 11 deletions.
25 changes: 14 additions & 11 deletions mkfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ _Static_assert(sizeof(struct superblock) == SIMPLEFS_BLOCK_SIZE);
*/
#define DIV_ROUND_UP(n, d) (((n) + (d) -1) / (d))

static struct superblock *write_superblock(int fd, struct stat *fstats)
static struct superblock *write_superblock(int fd, int64_t partition_size)
{
struct superblock *sb = malloc(sizeof(struct superblock));
if (!sb)
return NULL;

uint32_t nr_blocks = fstats->st_size / SIMPLEFS_BLOCK_SIZE;
uint32_t nr_blocks = partition_size / SIMPLEFS_BLOCK_SIZE;
uint32_t nr_inodes = nr_blocks;
uint32_t mod = nr_inodes % SIMPLEFS_INODES_PER_BLOCK;
if (mod)
Expand Down Expand Up @@ -246,14 +246,14 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}

/* Open disk image */
/* Open disk partition */
int fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror("open():");
return EXIT_FAILURE;
}

/* Get image size */
/* Get partition size */
struct stat stat_buf;
int ret = fstat(fd, &stat_buf);
if (ret) {
Expand All @@ -263,28 +263,31 @@ int main(int argc, char **argv)
}

/* Get block device size */
if ((stat_buf.st_mode & S_IFMT) == S_IFBLK) {
long int blk_size = 0;
ret = ioctl(fd, BLKGETSIZE64, &blk_size);
uint64_t partition_size = 0;
if (S_ISBLK(stat_buf.st_mode)) {
/* a block device */
ret = ioctl(fd, BLKGETSIZE64, partition_size);
if (ret != 0) {
perror("BLKGETSIZE64:");
ret = EXIT_FAILURE;
goto fclose;
}
stat_buf.st_size = blk_size;
} else {
/* a regular file */
partition_size = stat_buf.st_size;
}

/* Verify if the file system image has sufficient size. */
/* Verify if the partition has sufficient size. */
long int min_size = 100 * SIMPLEFS_BLOCK_SIZE;
if (stat_buf.st_size < min_size) {
if (partition_size <= min_size) {
fprintf(stderr, "File is not large enough (size=%ld, min size=%ld)\n",
stat_buf.st_size, min_size);
ret = EXIT_FAILURE;
goto fclose;
}

/* Write superblock (block 0) */
struct superblock *sb = write_superblock(fd, &stat_buf);
struct superblock *sb = write_superblock(fd, partition_size);
if (!sb) {
perror("write_superblock():");
ret = EXIT_FAILURE;
Expand Down

0 comments on commit bf61cd4

Please sign in to comment.