I've now sunk ~20 hours into recover, and still can't get my code to work on the check50 data.

The issue I've seen on here that other people have been having was with checking the jpeg headers, but I think I'm doing this part correctly, as I check the fourth byte of the buffer with:

 (buffer[3] & 0xf0) == 0xe0

From my understanding, the bitwise and operator should ensure that the first 4 bits of the byte are equal to 0xe, and ignore the final four bits.

I know the test data is different than card.raw, and my code must somehow be tailored to only solve card.raw, but I'm not sure what my issue is, or even how to go about fixing it.

My code:

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

#define BLOCK 512
typedef uint8_t (BYTE);

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

    //read in the file in a read state
    FILE *infile = fopen(argv[1],"r");

    if(infile == NULL)
        fprintf(stderr, "Could not read in card\n");
        return 2;

    //create the buffer variable
    BYTE buffer[BLOCK];

    //creates name variable for image naming
    char imagename[8];

    //initialize counter variable for image naming
    int counter = 0;

    //creates null file pointer for image
    FILE *img = NULL;

    while(fread(&buffer, 1, BLOCK, infile)==BLOCK)
        if(buffer[0] == 0xff && buffer[1] == 0xd8 &&
           buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {   //condition to close open images before opening new ones
            if(counter != 0)
            //writes name of image
            sprintf(imagename, "%03d.jpg",counter++);
            //opens a new image
            img = fopen(imagename, "w");

        //We skip using fseek until we find the jpeg header
        {fseek(infile, BLOCK, SEEK_CUR);}
        //if counter>0, we write the buffer to the image file
        else{fwrite(&buffer, 1, BLOCK, img);}
    //Closing out of our files
    if(counter > 0)
        //fprintf(stdout,"Congrats you finished!\n");
        return 0;

Any help would be great.

1 Answer 1


What is the meaning of fseek(infile, BLOCK, SEEK_CUR);? fread already consumes 512 bytes, so it would mean you skip every second block before the first file, possibly missing the first file's start if it is on an odd block number (counting zero-based, or even when counting one-based). Should work without this statement.

The fclose(infile); return 0; should not be part of the if block, but always be executed. That code should produce warnings on compilation (as you might reach the end of the function without having returned), and with -Werror used in the application, warnings would be errors and abort the compilation. You did not use the standard makefile for compilation?


Did not realize there is no explicit Makefile for this. Uses default rules instead, which incorporate CFLAGS environment variable. Seems like the must-return-something rule is a bit more relaxed for main, probably with an implicit return 0; at the end.

C standard as written on http://c0x.coding-guidelines.com/6.9.1.html says:

1844 If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

That's why compilers tend to warn in this case. I'd consider the return value of main being used (for the exit code of the application), but compiler seems to have a different opinion.


  • Thank you for your help. I didn't realize that fread moves the stream of the pointer 512 bytes, and therefore makes the fseek redundant (and in fact unhelpful because it skips the buffer again.) What is the standard makefile for compilation? I don't quite understand that part of your comment.
    – PWalton
    Oct 18, 2017 at 14:59
  • When you do a make recover, I'd expect the compiler to use -Werror, and to refuse compilation as long as it's possible to end the function without an explicit return value (by reaching its end without a return). My IDE has environment variable CFLAGS=-fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wshadow. There is no Makefile in my directory (not required in such a simple project), but even the standard rule set seems to use this variable.
    – Blauelf
    Oct 18, 2017 at 15:51
  • comeaucomputing.com/techtalk/#return0 also states that there's an implicit return 0; just for main. Something I learnt today.
    – Blauelf
    Oct 18, 2017 at 16:22

You must log in to answer this question.

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