:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:) recovers middle images correctly
:( recovers 049.jpg correctly
    recovered image does not match

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

#define bs 512

typedef unsigned char byte;

byte buffer[bs];
// char outfile[17]; //  = "recovered-000.jpg";
char outfile[50];

int main(int argc, char *argv[])
    if(argc < 2)
        printf("Usage: ./recover image");
        return 1;
    char *infile = argv[1];
  //  char *fn = argv[1];
    FILE *inptr = fopen(infile, "r");
    //FILE *outfile;

    if(inptr == NULL)
        printf("Could not open Given file");
        return 2;

    printf("Opened %s to read\n", infile);

    int nof = 0;

    FILE *outptr;
    sprintf(outfile, "recovered-%03d.jpg", nof);
    outptr = fopen(outfile, "w");

    printf("Opened %s to write\n", outfile);
    int block_count = 0;
    while (true)
        if (feof(inptr)) {
            printf("Reached end of input file\n");
        int read_chunks = fread(buffer, 512, 1, inptr);
        printf("Read %d chunks from inputfile\n", read_chunks);
//        if (fread(buffer, 512, 1, inptr) < 1) break;

       // bool containsjpegHeader;
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)

            printf("Found jpegHeader count: %d\n", nof);
                fclose (outptr);
                printf("Closed %s\n", outfile);
                printf("outfile about to change from %s\n", outfile);
            sprintf(outfile, "%03d.jpg", nof);
            printf("outfile changed to %s\n", outfile);
             outptr = fopen(outfile, "w");

             printf("Opened %s to write\n", outfile);
            fwrite (buffer, 512, 1, outptr);

           /* while (true) {
                if (feof(inptr)) {
                    printf("Reached end of input file in inner loop\n");
                fread(buffer, 512, 1, inptr);
                fwrite (buffer, 512, 1, outptr);
                printf("%07x block read from %s and wrote to %s\n", block_count++*512, infile, outfile);

                if (buffer[0] == (0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)) break;
            } */



//       if (some codnditions meet) break;


This is a common problem. First understand that EOF isn't set until after an attempt is made to read past the end of a file. It's analogus to a blind person on a diving board. They don't know where the end of the board is until they step off!

When the last 512 bytes of the input file are read, there's no more data to read, but the EOF flag has not yet been set. Remember that.

Your code works like this:

  1. Check for EOF. If not set, continue.
  2. Read the next 512 byte block.
  3. Process the block.
  4. return to step 1.

The problem with this is that it's going to set EOF on step 2 when it tries to read past the end of the file. Since nothing is read, the buffer will remain unchanged from the last read. That last block will be written to the output file a second time. On the next pass, the program will terminate the loop and execute the program ending code, but the damage has been done.

The result is that the last image file is 512 bytes too large. That's why it fails.

Instead of while (true) have you considered incorporating the read and some kind of test for reading into the end of the file into the read statement?

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

  • Hi Cliff, I'm a 12 year old newbie and loving this world of C coding. I couldn't have solved it without your beautiful explanation. Learning for life. Keep up the good work and thank you so much. Regards, Aahaan – Aahaan Sachin May 10 '20 at 7:59

You must log in to answer this question.

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