0

my recover.c runs and finds all 50 images, but the images are incomplete

enter image description here

It seems like something is going wrong with how I'm reading the fat blocks or writing each image file, but I can't seem to spot it.

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

int main(int argc, char *argv[])
{
    // fat blocks are 512 bytes
    typedef uint8_t  BYTE;

    // verify the correct number of arguments have been passing
    if (argc != 2)
    {
        fprintf(stderr, "usage: ./recover infile\n");
        return 1;
    }

    // store the recovery file
    char *image = argv[1];

    FILE *rcvr = fopen(image, "r");
    if (rcvr == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", image);
        return 2;
    }

    // Track the current image
    int curImg = 0;

    // array to store read data in
    BYTE buffer[512];


    // starting data for the while loop to work on.
    fread(&buffer, 1, 512, rcvr);

    // File read loop
    while (!feof(rcvr))
    {

        // I don't think I really understand bitwise operators well.
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // create the filename
            char filename[8];
            sprintf(filename, "%03i.jpg", curImg);

            printf("found jpeg! Current Image: %i\n", curImg);

            // create and open the newly found jpg for writing
            FILE *fndjpg = fopen(filename, "w");

            do
            {
                printf(".");

                // write the bytes
                fwrite(&buffer, 1, 512, fndjpg);

                // read the next set
                fread(&buffer, 1, 512, rcvr);
            }
            while(buffer[0] != 0xff && buffer[1] != 0xd8 && buffer[2] != 0xff && (buffer[3] & 0xf0) != 0xe0);

            printf("\n");

            fclose(fndjpg);
            curImg ++;
        }
        else
        {
            // read fat blocks
            fread(&buffer, 1, 512, rcvr);
        }
    }

    // Close the recovery file
    fclose(rcvr);
}

My only guess is that is has something to do with the inner do while loop not working like I think it's supposed to work. Hoping it might provide some useful errors, I ran check50 and it finds the first image, but not the remaining images.

Update I found a thread in the subreddit where another student was failing the same checks and there was a suggestion to check the file size deltas between the recovered jpg files and the raw file.

du -c --bytes *.jpg && du --bytes card.raw
...
427520  total
11830784        card.raw

Mine is off significantly, so there must be something wrong with my do while writing loop.

1 Answer 1

1

The problem was with the exit condition of the do while loop:

while(buffer[0] != 0xff && buffer[1] != 0xd8 && buffer[2] != 0xff && (buffer[3] & 0xf0) != 0xe0);

Changing it to negate the entire condition instead of each condition individually worked.

while(!(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0));

But that created an infinite loop because it didn't know to bail out at the end of the file so I added a check at the beginning of the do while:

if (feof(rcvr)) { break;}

Now it works perfectly and passes check50. I'm not sure why the original do while check didn't work and why the program didn't have an infinite loop before, but it's working now.

1
  • My code is almost identical to yours and I've been encountering the same problems. However the if condition you added above the do while doesn't seem to be working for me Commented May 2, 2020 at 13:21

You must log in to answer this question.

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