文件系统所在的块设备的大小与该文件系统本身的大小之间存在差异。鉴于您的任务是对文件系统本身内的超级块进行操作,我假设您对后者更感兴趣。如果您对实际设备尺寸更感兴趣,那么@that-other-guy 的回答是正确的。
假设您正在使用ext4
文件系统,并且根据此处的信息,文件系统的完整大小将是总块数乘以块大小。在超级块的结构中,相关字段有:
s_blocks_count_lo
很简单,但s_log_block_size
需要一些处理,因为存储的值意味着:
块大小为 2 ^ (10 + s_log_block_size)。
将所有这些放在一起,您可以执行以下操作:
uintmax_t get_filesystem_size(const char *device) {
int fd;
if((fd = open(device, O_RDONLY)) < 0) {
perror(device);
exit(1);
}
if (lseek(fd, 1024, SEEK_SET) < 0) {
perror("lseek");
exit(1);
}
uint8_t block0[1024];
if (read(fd, &block0, 1024) < 0) {
perror("read");
exit(1);
}
if (s_magic(block0) != 0xef53) {
fprintf(stderr, "bad magic\n");
exit(1);
}
close(fd);
return s_blocks_count_lo(block0) * s_block_size(block0);
}
使用以下 ext4 超级块特定的辅助函数:
uint16_t s_magic(const uint8_t *buffer) {
return le16(buffer + 0x38);
}
uint32_t s_blocks_count_lo(const uint8_t *buffer) {
return le32(buffer + 0x4);
}
uintmax_t s_block_size(const uint8_t *buffer) {
return 1 << (10 + le32(buffer + 0x18));
}
和以下通用字节序辅助函数:
uint16_t le16(const uint8_t *buffer) {
int result = 0;
for (int i = 1; i >= 0; i--) {
result *= 256;
result += buffer[i];
}
return result;
}
uint32_t le32(const uint8_t *buffer) {
int result = 0;
for (int i = 3; i >= 0; i--) {
result *= 256;
result += buffer[i];
}
return result;
}