将超级块读入 C 结构

发布于 2024-08-14 02:22:53 字数 591 浏览 5 评论 0原文

我有一个磁盘映像,其中包含使用保险丝的标准映像。 Superblock 包含以下内容,我有一个函数 read_superblock(*buf) 返回以下原始数据:

Bytes 0-3: Magic Number (0xC0000112)
      4-7: Block Size (1024)
     8-11: Total file system size (in blocks)
    12-15: FAT length (in blocks)
    16-19: Root Directory (block number)
  20-1023: NOT USED

我对 C 非常陌生,为了让我开始这个项目,我很好奇将其读入一个简单的方法是什么结构体或一些变量,只需使用 printf 将它们打印到屏幕上即可进行调试。

我最初想做类似以下的事情,认为我可以看到原始数据,但我认为事实并非如此。也没有结构,我试图将其作为字符串读取,这似乎也非常错误。让我从中获取数据。有没有办法让我指定结构并定义每个变量中的字节数?

char *buf;
read_superblock(*buf);
printf("%s", buf);

I have a disk image which contains a standard image using fuse. The Superblock contains the following, and I have a function read_superblock(*buf) that returns the following raw data:

Bytes 0-3: Magic Number (0xC0000112)
      4-7: Block Size (1024)
     8-11: Total file system size (in blocks)
    12-15: FAT length (in blocks)
    16-19: Root Directory (block number)
  20-1023: NOT USED

I am very new to C and to get me started on this project I am curious what is a simple way to read this into a structure or some variables and simply print them out to the screen using printf for debugging.

I was initially thinking of doing something like the following thinking I could see the raw data, but I think this is not the case. There is also no structure and I am trying to read it in as a string which also seems terribly wrong. for me to grab data out of. Is there a way for me to specify the structure and define the number of bytes in each variable?

char *buf;
read_superblock(*buf);
printf("%s", buf);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

转身泪倾城 2024-08-21 02:22:53

是的,我认为你最好将其读入一个结构中。包含有用数据的字段都是 32 位整数,因此您可以定义如下所示的结构(使用标准头文件 stdint.h 中定义的类型):

typedef struct SuperBlock_Struct {
  uint32_t magic_number;
  uint32_t block_size;
  uint32_t fs_size;
  uint32_t fat_length;
  uint32_t root_dir;
} SuperBlock_t;

您可以将该结构强制转换为a char* 调用 read_superblock 时,如下所示:

SuperBlock_t sb;
read_superblock((char*) &sb);

现在要打印数据,您可以进行如下调用:

printf("%d %d %d %d\n",
  sb.magic_number,
  sb.block_size,
  sb.fs_size,
  sb.fat_length,
  sb.root_dir);

请注意,您需要了解您的平台的使用此类技术时的字节顺序,因为您正在读取整数数据(即,在读取数据时可能需要交换字节)。您应该能够使用第一个字段中的幻数快速确定这一点。

请注意,通常最好传递这样的结构而不进行强制转换;这使您可以利用编译器的类型检查并消除转换可能隐藏的潜在问题。但是,这需要更改 read_superblock 的实现以将数据直接读取到结构中。这并不困难,可以使用标准 C 运行时函数 fread 来完成(假设您的数据位于文件中,正如您的问题所暗示的那样),如下所示:

fread(&sb.magic_number, sizeof(sb.magic_number), 1, fp);
fread(&sb.block_size, sizeof(sb.block_size), 1, fp);
...

Yes, I think you'd be better off reading this into a structure. The fields containing useful data are all 32-bit integers, so you could define a structure that looks like this (using the types defined in the standard header file stdint.h):

typedef struct SuperBlock_Struct {
  uint32_t magic_number;
  uint32_t block_size;
  uint32_t fs_size;
  uint32_t fat_length;
  uint32_t root_dir;
} SuperBlock_t;

You can cast the structure to a char* when calling read_superblock, like this:

SuperBlock_t sb;
read_superblock((char*) &sb);

Now to print out your data, you can make a call like the following:

printf("%d %d %d %d\n",
  sb.magic_number,
  sb.block_size,
  sb.fs_size,
  sb.fat_length,
  sb.root_dir);

Note that you need to be aware of your platform's endianness when using a technique like this, since you're reading integer data (i.e., you may need to swap bytes when reading your data). You should be able to determine that quickly using the magic number in the first field.

Note that it's usually preferable to pass a structure like this without casting it; this allows you to take advantage of the compiler's type-checking and eliminates potential problems that casting may hide. However, that would entail changing your implementation of read_superblock to read data directly into a structure. This is not difficult and can be done using the standard C runtime function fread (assuming your data is in a file, as hinted at in your question), like so:

fread(&sb.magic_number, sizeof(sb.magic_number), 1, fp);
fread(&sb.block_size, sizeof(sb.block_size), 1, fp);
...
捂风挽笑 2024-08-21 02:22:53

这里要添加两件事:

  1. 将原始数据拉入结构体时,最好将结构体设置为零填充,即使它完全由 32 位无符号整数组成。在 gcc 中,您可以在结构定义之前使用 #pragma pack(0) 并在结构定义之后使用 #pragma pack() 来执行此操作。
  2. 为了处理潜在的字节顺序问题,需要查看两个调用:ntohs()ntohl(),分别针对 16 位和 32 位值。请注意,它们从网络字节顺序交换为主机字节顺序;如果它们相同(它们不在基于 x86 的平台上),则它们不执行任何操作。您可以使用 htons()htonl() 从主机字节顺序转到网络字节顺序。但是,由于这些数据来自您的文件系统而不是网络,因此我不知道字节顺序是否是一个问题。通过将您期望的值(例如块大小)与您获得的十六进制值进行比较,应该很容易弄清楚。

Two things to add here:

  1. It's a good idea, when pulling raw data into a struct, to set the struct to have zero padding, even if it's entirely composed of 32-bit unsigned integers. In gcc you do this with #pragma pack(0) before the struct definition and #pragma pack() after it.
  2. For dealing with potential endianness issues, two calls to look at are ntohs() and ntohl(), for 16- and 32-bit values respectively. Note that these swap from network byte order to host byte order; if these are the same (which they aren't on x86-based platforms), they do nothing. You go from host to network byte order with htons() and htonl(). However, since this data is coming from your filesystem and not the network, I don't know if endianness is an issue. It should be easy enough to figure out by comparing the values you expect (e.g. the block size) with the values you get, in hex.
离笑几人歌 2024-08-21 02:22:53

将数据成功复制到 Emerick 提出的结构后,打印数据并不困难。假设用于保存数据的结构实例名为 SuperBlock_t_Instance。

然后你可以像这样打印它的字段:

printf("Magic Number:\t%u\nBlock Size:\t%u\n etc", 
SuperBlock_t_Instance.magic_number, 
SuperBlock_t_Instance.block_size);

It's not difficult to print the data after you successfully copied data into a structure Emerick proposed. Suppose the instance of the structure you use to hold data is named SuperBlock_t_Instance.

Then you can print its fields like this:

printf("Magic Number:\t%u\nBlock Size:\t%u\n etc", 
SuperBlock_t_Instance.magic_number, 
SuperBlock_t_Instance.block_size);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文