0

I've been having problems with recognizing the jpg signature (0xffd8ff) in my code. In my current version, the first if statement never recognizes the first few bytes of a block; therefore, it won't open an outfile but will seg fault when it tries to close a file that was never opened.

Any tips on how to fix this?

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

#define BLOCK 512

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

    // Opens card.raw
    FILE* raw = fopen("card.raw", "r");
    if (raw == NULL)
    {
        printf("Could not open file.");
        return 2;
    }

    // Initialize jpg counter
    int count = 0;

    // Create a buffer and outfile
    uint8_t buffer[512];
    FILE* jpg;
    char outfile[8];

    while (fread(&buffer, BLOCK, 1, raw))
    {
        // Checks the first 3 bytes of block for jpg signature
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)
        {
            // Names and opens new jpg
            sprintf(outfile, "%03d.jpg", count);
            jpg = fopen(outfile, "a");

            // Write the buffer to the outfile
            fwrite(&buffer, BLOCK, 1, jpg);

            // Close jpg
            fclose(jpg);
        }
        else
        {
            // Write the buffer to the outfile
            fwrite(&buffer, BLOCK, 1, jpg);

            // Close jpg
            fclose(jpg);
        }

        // Update counter
        count++;
    }

    // Close any remaining files
    fclose(raw);

    // Fin
    return 0;
}
1

There are a number of issues going on. First is the seg fault. Yes, it's failing because the code is trying to close a file that was never opened. That's because the code EITHER recognize a signature block and process it OR writes the current block (without a signature) to the output file. Unfortunately, the first several thousand blocks are trash and need to be discarded, not written to an output file. Once the first file is opened, then you can write out the blocks without signatures.

On a related note, you should initialize the file pointer jpg = NULL at creation so that you can test whether the first file has been opened.

Next, you have a severe problem with your file numbering, but I'll let you discover that one on your own. It'll be easy enough. ;-)

You still have an issue with the signature. You're testing the first 3 bytes, but you're not doing any testing on the 4th byte. You should reread the pset spec on that to understand what's missing.

Finally, why are you closing the output file after writing every block? It should be left open until the next signature block is detected.

There may be other issues, but this will get you going.

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

1
  • Thanks so much for your help!
    – Jake
    Jan 27 '16 at 23:51
0

the specs don't tell you that the signature of the first JPG is going to be at the beginning of card.raw. instead, they tell you that digital cameras tend to store photographs contiguously on CF cards, whereby each photo is stored immediately after the previously taken photo. Accordingly, the start of a JPEG usually demarks the end of another.

so you shouldn't rely on the fact that the very first 4 bytes you read represent a JPG signature.

You must log in to answer this question.

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