您如何找到 Linux 驱动器上分区结束的位置?
How do you find where the end of a partition ends on a Linux drive?
在我的一个 类 中,我们的任务是在第一个超级块中查找并打印一些值,然后将这些值与所有其他超级块以 3、5 和 7 的幂进行比较,直到结束分区.
例如,您将 superblock0 与 superblock1、0 和 3、0 和 5、0 和 7、0 和 9 等进行比较。
我在超级块中输出值的代码有效,我有一个算法可以得到 3、5 和 7 的所有幂,但我不确定如何检测分区的末尾。
以及如何使用这些权力遍历所有超级块直到结束或中断情况是什么。
下面是我访问第一个超级块的代码。
int fd;
super_block_t s;
if((fd = open(DEVICE, O_RDONLY)) < 0){ //check if disk can be read
perror(DEVICE);
exit(1);
}
//read superblock
lseek(fd, OFFSET, SEEK_SET);
read(fd, &s, sizeof(s));
close(fd);
您可以尝试在那里寻找并查看是否得到 EINVAL
,或者您可以使用 BLKGETSIZE64
ioctl 来获取块设备的大小:
#include <linux/fs.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
void main(int argc, char** argv) {
int fd = open(argv[1], O_RDONLY);
uint64_t size;
ioctl(fd, BLKGETSIZE64, &size);
printf("Size in bytes: %llu\n", size);
}
文件系统所在的块设备的大小与文件系统本身的大小不同。鉴于您的任务是对文件系统本身内的超级块进行操作,我假设您对后者更感兴趣。如果您对实际设备尺寸更感兴趣,那么@that-other-guy 的回答是正确的。
假设您正在为文件系统使用 ext4
,并且根据信息 here,文件系统的完整大小将是总块数乘以块大小。在超级块的结构中,相关的字段是:
s_blocks_count_lo
在偏移量 0x4 处,并且
s_log_block_size
在偏移量 0x18
s_blocks_count_lo
很简单,但是 s_log_block_size
需要一些处理,因为存储的值意味着:
Block size is 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;
}
在我的一个 类 中,我们的任务是在第一个超级块中查找并打印一些值,然后将这些值与所有其他超级块以 3、5 和 7 的幂进行比较,直到结束分区.
例如,您将 superblock0 与 superblock1、0 和 3、0 和 5、0 和 7、0 和 9 等进行比较。
我在超级块中输出值的代码有效,我有一个算法可以得到 3、5 和 7 的所有幂,但我不确定如何检测分区的末尾。
以及如何使用这些权力遍历所有超级块直到结束或中断情况是什么。
下面是我访问第一个超级块的代码。
int fd;
super_block_t s;
if((fd = open(DEVICE, O_RDONLY)) < 0){ //check if disk can be read
perror(DEVICE);
exit(1);
}
//read superblock
lseek(fd, OFFSET, SEEK_SET);
read(fd, &s, sizeof(s));
close(fd);
您可以尝试在那里寻找并查看是否得到 EINVAL
,或者您可以使用 BLKGETSIZE64
ioctl 来获取块设备的大小:
#include <linux/fs.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
void main(int argc, char** argv) {
int fd = open(argv[1], O_RDONLY);
uint64_t size;
ioctl(fd, BLKGETSIZE64, &size);
printf("Size in bytes: %llu\n", size);
}
文件系统所在的块设备的大小与文件系统本身的大小不同。鉴于您的任务是对文件系统本身内的超级块进行操作,我假设您对后者更感兴趣。如果您对实际设备尺寸更感兴趣,那么@that-other-guy 的回答是正确的。
假设您正在为文件系统使用 ext4
,并且根据信息 here,文件系统的完整大小将是总块数乘以块大小。在超级块的结构中,相关的字段是:
s_blocks_count_lo
在偏移量 0x4 处,并且s_log_block_size
在偏移量 0x18
s_blocks_count_lo
很简单,但是 s_log_block_size
需要一些处理,因为存储的值意味着:
Block size is 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;
}