My recover successfully recovers 24 images that are all good; nothing scrambled or anything. But I thought there were supposed to be 50 images. I imagine that I'm skipping over every other image or something. Moreover, check50 says 015.jpg does not exist when there is a 015.jpg.

:) recover.c exists :) recover.c compiles :( recovers 000.jpg correctly :( recovers middle files correctly :( recovers last file correctly \ expected 015.jpg to exist

EDIT: I realized the issue may have to do with limiting the 4th JPEG byte to only two possibilities. Since the 4th byte has to be between 0xe0 and 0xef, I tried to do a greater than/lesser than comparison. But it didn't extract any files at all this way. I'm still not even sure this is the problem.

if ((buffer[0] == 0xff) && (buffer[1] == 0xd8) && (buffer[2]== 0xff) && ((buffer[3] >= 0xe0 && buffer[3] <= 0xef)))

code starts here:

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

//blocks are 512 bytes
int const block = 512;

//define byte
typedef unsigned char BYTE;

int main()

 FILE* inptr = fopen("card.raw", "r");
    if (inptr == NULL) {
    printf("Could not open file.\n");
    return 1;

//calculate size of input file in blocks
fseek (inptr, 0L ,SEEK_END); //Go to end of file
int length = ftell (inptr); //return cursor position, which is size of file in bytes
fseek (inptr, 0L, SEEK_SET); //go back to the beginning of file
int blocknum = (length/block); // how many blocks

int counter = 0;

//do this for each block of the input file
for (int i = 0; i < blocknum; i++)
    //make buffer array that has 512 capacity
    BYTE buffer[512];

    //read input file to buffer 512 bytes at a time
    fread(&buffer, sizeof(buffer), 1, inptr);

    //compare first 4 bytes for jpg sig
    if ((buffer[0] == 0xff) && (buffer[1] == 0xd8) && (buffer[2]== 0xff) && ((buffer[3] & 0xf0) == 0xe0))
        char name[9];
        sprintf(name, "%03i.jpg", counter);
        //make output file
        FILE* outfile;
        outfile = fopen(name, "w");
        fwrite(&buffer , 512, 1, outfile);

        //going on to next block
        fread(&buffer, 512, 1, inptr);

        //keep reading blocks until you find another sig
        while (!(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] == 0xe0 || buffer[3] == 0xe1)))
            fwrite(&buffer, 512, 1, outfile);
            fread(&buffer, 512, 1, inptr);

        //close file you just made

  • Use buffer not &buffer in fread and fwrite, buffer itself is a pointer to the chunk of 512 bytes. Otherwise, you risk segfaults.
    – Blauelf
    Mar 2, 2017 at 20:02
  • @Blauelf buffer is an array, not a pointer, so &buffer is correct. Mar 3, 2017 at 11:29
  • In C, an array is a pointer. Just where the allocated space is differs, for this array, it's on the stack, for malloc, it's on the heap. But C seems to do some magic, buffer and &buffer are both the same. Did not know that.
    – Blauelf
    Mar 3, 2017 at 11:39

1 Answer 1


The main problem is where it skips a jpg signature, so it's only creating about half the jpgs.

Assume that the while has found the next jpg signature. What does it do then? Control returns to the for loop and it reads the next block here fread(&buffer, sizeof(buffer), 1, inptr);. Which is (presumably) not a jpg signature. So it continues through the for loop 'til it finds the next next jpg sig. And the same thing happens for every other jpg.

You're kinda using mixed metaphors here. The for loop will process "blocknum" times, but there are 3 freads in the loop. Something will get out of sync; it is going to read way past the end-of-file.


while (!(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] == 0xe0 || buffer[3] == 0xe1)))
            fwrite(&buffer, 512, 1, outfile);
            fread(&buffer, 512, 1, inptr);


has serious infinite loop potential. I think it's not happening because program is only creating the "odd" jpgs. So it will "miss" the 50th jpg and not go to infinity and beyond.

If you are going to use the "for 0 - blocknum" strategy, there should be exactly one fread because you know exactly how many blocks will be read. Then there are 3 ways a block can be handled:

  1. Rejected/skipped (haven't found a jpg yet)
  2. Create a new outfile (it's a jpg sig)
  3. Write to current outfile.

Re: the signature, it looks like the if in the original post is correct for the 2017 version of the pset. Also, program does not accept command line argument (also per 2017 version of the pset).

You must log in to answer this question.

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