将超级块读入C结构

时间:2009-12-08 01:49:34

标签: c++ c fuse

我有一个磁盘映像,其中包含使用fuse的标准映像。 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);

3 个答案:

答案 0 :(得分:4)

是的,我认为你最好把它读成一个结构。包含有用数据的字段都是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;

您可以在调用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);
...

答案 1 :(得分:1)

这里要添加两件事:

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

答案 2 :(得分:0)

成功将数据复制到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);