0

I'm currently trying out CS50's Recover (PSET4). The program compiles and I manage to get back all the 50 jpgs. But I can't open them because the image isn't correctly returned and I get an "Invalid or Unsupported Image Format". Could someone please help me identify where the error(s) lies?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    if(argv[1] == NULL)
    {
        return 1;
    }

    FILE *file = fopen(argv[1], "r");

    if(file == NULL)
    {
        printf("The forensic image cannot be opened for reading.\n");
        return 1;
    }

    int name_counter = 0;
    BYTE b[512];
    char filename[8];
    sprintf(filename, "%03i.jpg", name_counter);
    FILE *img = fopen(filename, "w");
    
    while (fread(b, sizeof(BYTE), 512, file) == 512)
    {
        if(file == NULL)
        {
            return 1;
        }

        if(b[0] == 0xff && b[1] == 0xd8 && b[2] == 0xff && (b[3] & 0xf0) == 0xe0)
        {
            if(name_counter == 0)
            {
                fwrite(b, 1, 512, img);
            }
            else if (name_counter > 0)
            {
                fclose(img);
                sprintf(filename, "%03i.jpg", name_counter);
                img = fopen(filename, "w");
                fwrite(b, 1, 512, img);
            }
            name_counter++;
        }
        else if (img != NULL)
        {
            fwrite(b, 1, 512, img);
        }
     }
    fclose(file);
    fclose(img);
}
1

First of all, you need to be more thorough in validating your data before making conclusions. Did you try opening just the first file, or more of them? I'm betting that you couldn't open the first file and concluded none of them would open. ;-)

I ran the test code and most of the files open fine. The first file is corrupt. (TBH, I didn't check them all, but then I've completed the exercise.) So, knowing that the first file is likely the only file that is not opening, it's likely something to do with the way the code handles the first file.

Interesting detail. Remember that the input file contains garbage at the beginning that needs to be discarded before the first signature is found?

Let's walk through what happens in the code above. It opens the input file and then it opens the first output file, and then starts the main loop.

Now, the code reads the first 512 bytes of data. It doesn't find a signature, so it drops down to this code:

    else if (img != NULL)
    {
        fwrite(b, 1, 512, img);
    }

Since the first file is already opened, what do you suppose the code is doing with that first block of 512 bytes of garbage data?

Have you considered that just maybe the code shouldn't open the first output file until it actually finds a signature? What would happen if the code didn't find any signatures? It'd open one garbage output file when it shouldn't open any output files, right?

Perhaps a little more rethink of program logic is in order? ;-)

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

1
  • I would just like to express how grateful I am to you for taking the time to help me out with the problem. I brought the 'img = fopen(filename, "w");' inside 'if(name_counter == 0)' and that solved my issue. Now, on to lecture 5. Thank you so very much! Jun 23 at 6:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .