Lettura superblocco in una struttura C
Domanda
Ho un immagine disco che contiene un'immagine standard con fusibile. Il superblocco contiene la seguente, e ho una funzione di read_superblock (* buf) che restituisce i seguenti dati grezzi:
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
Sono molto nuovo per C e per ottenere mi ha iniziato a questo progetto sono curioso quello che è un modo semplice per leggere questo in una struttura o di alcune variabili e semplicemente stamparli sullo schermo utilizzando printf per il debug.
Mi è stato inizialmente pensando di fare qualcosa di simile alla seguente pensiero ho potuto vedere i dati grezzi, ma penso che questo non è il caso. Non v'è inoltre alcuna struttura e sto cercando di leggerla come una stringa che sembra anche terribilmente sbagliato. per me, per afferrare i dati fuori. C'è un modo per me di specificare la struttura e definire il numero di byte in ogni variabile?
char *buf;
read_superblock(*buf);
printf("%s", buf);
Soluzione
Sì, penso che sarebbe meglio la lettura di questo in una struttura. I campi contenenti dati utili sono tutti interi a 32 bit, così si potrebbe definire una struttura che assomiglia a questo (utilizzando i tipi definiti nel stdint.h
file di intestazione standard):
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;
Si può lanciare la struttura ad un char*
quando si chiama read_superblock
, in questo modo:
SuperBlock_t sb;
read_superblock((char*) &sb);
Ora di stampare i dati, è possibile effettuare una chiamata come il seguente:
printf("%d %d %d %d\n",
sb.magic_number,
sb.block_size,
sb.fs_size,
sb.fat_length,
sb.root_dir);
Si noti che è necessario essere a conoscenza di endianness della vostra piattaforma quando si utilizza una tecnica di questo tipo, dal momento che stai leggendo i dati interi (vale a dire, potrebbe essere necessario scambiare i byte durante la lettura dei dati). Si dovrebbe essere in grado di determinare che rapidamente utilizzando il numero magico nel primo campo.
Si noti che di solito è preferibile passare una struttura come questa, senza il cast; questo permette di sfruttare i vantaggi di tipo controllo del compilatore ed elimina i potenziali problemi che getto può nascondere. Tuttavia, ciò comporterebbe cambiare la realizzazione di read_superblock
per leggere i dati direttamente in una struttura. Questo non è difficile e può essere fatto utilizzando la funzione di runtime C fread
standard (supponendo i dati sono in un file, come accennato in questione), in questo modo:
fread(&sb.magic_number, sizeof(sb.magic_number), 1, fp);
fread(&sb.block_size, sizeof(sb.block_size), 1, fp);
...
Altri suggerimenti
Due cose da aggiungere qui:
- E 'una buona idea, quando si tira dati grezzi in una struttura, per impostare la struttura per avere zero padding, anche se è interamente composto di 32 bit interi senza segno. In gcc si esegue questa operazione con
#pragma pack(0)
prima della definizione struct e#pragma pack()
dopo di esso. - Per trattare con potenziali problemi di endianness, due chiamate da guardare sono
ntohs()
entohl()
, per i valori di 16 e 32 bit, rispettivamente. Si noti che questi swap dal byte order di rete per ospitare l'ordine dei byte; se questi sono gli stessi (che non sono su piattaforme x86), non fanno nulla. Si va da host di rete byte order conhtons()
ehtonl()
. Tuttavia, dal momento che questi dati proviene dal vostro file system e non la rete, non so se endianness è un problema. Dovrebbe essere abbastanza facile da capire, confrontando i valori che ci si aspetta (ad esempio la dimensione del blocco) con i valori si ottiene, in esadecimale.
Non è difficile per stampare i dati dopo aver copiato i dati in una struttura Emerick proposto. Supponiamo che l'istanza della struttura che si utilizza per contenere i dati è denominato SuperBlock_t_Instance.
Quindi è possibile stampare i suoi campi in questo modo:
printf("Magic Number:\t%u\nBlock Size:\t%u\n etc",
SuperBlock_t_Instance.magic_number,
SuperBlock_t_Instance.block_size);