Search code examples
cstructiobinaryfiles

How to make a void pointer to read a given part of a binary file


I have a binary file which contains 3 differents structs and a christmas text. On the first line of the binaryfile have they provided me with a int which represents the size of a package inside the file. A package contains 3 structs ,the chistmastext and the size. The structs lies in a file called framehdr.h and the binary file I'm reading is called TCPdump.

Now am I trying to create a program att will read each package at a time and then withdraw the text. I have started with something like this:

#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>

int main()
{
  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  FILE *fileOpen;
  char *buffer;
  size_t dataInFile;
  long filesize;

  // The three structs
  struct ethernet_hdr ethHdr;
  struct ip_hdr ipHdr;
  struct tcp_hdr tcpHDr;

  fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");
  if (fileOpen == NULL)
  {
    printf("Error\n");
  }
  else
  {
    printf("Success\n");
  }

  char lenOf[10];
  size_t nr;
  // Reads until \n comes 
  fgets(lenOf, sizeof(lenOf), fileOpen);
  sscanf(lenOf, "%d", &nr);
  // Withdraw the size of a package and check if it's correct
  printf("Value: %d\n", nr);
  printf("Adress: %d\n", &nr);

  void *ptr;
  fread(&ptr, nr, 1, fileOpen);
  int resEth = 14;
  printf("resEth: %d\n", resEth);
  int resIP = IP_HL((struct ip_hdr*)ptr);
  printf("ResIP: %d\n", resIP);
  int resTcp = TH_OFF((struct tcp_hdr*)ptr);
  printf("tcpIP: %d\n", resTcp);
  int res = resEth + resIP + resTcp;
  printf("Total: %d", res);

  fclose(fileOpen);
  //free(buffer);

  system("pause");

  return 0;
}

I know that the first struct ethernet will always have the size of 14 but I need to get the size of the other 2 and I'm suppose to use IP_HL and TH_OFF for that.

But my problems lies in that I can't seem to read the entire package to one void * with the fread. I get noting in my *ptr. Which in turn makes the code break when I try to convert the void * to one of the structs ones.

What I'm doing wrong with the void *?


Solution

  • Two problems:

    First you should not really use text functions when reading binary files. Binary files doesn't really have "lines" in the sense that text file have it.

    Secondly, with

    void *ptr;
    fread(&ptr, nr, 1, fileOpen);
    

    you are passing a pointer to the pointer variable, you don't actually read anything into memory and then make ptr point to that memory. What happens now is that the fread function will read nr bytes from the file, and then write it to the memory pointed to by &ptr, which will lead to undefined behavior if nr > sizeof ptr (as then the data will be written out of bounds).

    You have to allocate nr bytes of memory, and then pass a pointer to the first element of that:

    char data[nr];
    fread(data, nr, 1, fileOpen);
    

    You should also get into the habit of checking for errors. What if the fread function fails? Or the file is truncated and there isn't nr bytes left to read?

    You can check for these conditions by checking what fread returns.

    And not only check for fread, there are more functions than fopen that can fail.