Search code examples
c++cfuse

Reading Superblock into a C Structure


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);

Solution

  • 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);
    ...