1

My PSET 4 Recover code is able to recover the 50 jpg's from the raw file. However, when checking the code with the check50 it only partially passes. I checked a lot other related issues on SE CS50 with the same Check50 output, however those solutions seem to be not applicable to my issue.

This is my Check50 output:

:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:( recovers middle images correctly
    recovered image does not match
:( recovers 015.jpg correctly
    015.jpg not found
See https://cs50.me/checks/e31ee9089ccf70fd723aeffc4ee91aacb0929849 for more detail.

My code:

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

#define BUFFER_SIZE 512
#define NUMBER 1

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

    char *infile = argv[1];

    // open input file 
    FILE *inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 2;
    }

    // Initialize jpeg picture counter, buffer and output file
    int jpg_nr = 0;
    unsigned char buffer[512]; 
    FILE *outptr = NULL;
    char outfile[10];



    // Read file as long reading is possible
    while (fread(&buffer, BUFFER_SIZE, NUMBER, inptr))
    {    
        // Start of a new JPEG? 
        if (buffer[0] == 0xff && 
        buffer[1] == 0xd8 &&
        buffer[2] == 0xff &&
        (buffer[3] == 0xf0 || buffer[3] == 0xe0))
        {
            // If new JPEG header
            if (outptr == NULL)
            {
                // make a new JPEG name
                sprintf(outfile, "%03i.jpg", jpg_nr);
                outfile[9] = '\0';

                // open output file
                outptr = fopen(outfile, "w");
                if (outptr == NULL)
                {
                    fclose(inptr);
                    fprintf(stderr, "Could not create %s.\n", outfile);
                    return 3;
                }

                // Write 
                fwrite(&buffer, BUFFER_SIZE, NUMBER, outptr);
            }
            // JPEG ALREADY OPEN
            else
            {
                fclose(outptr);
                // Keep track of JPG order, starting at 000
                jpg_nr += 1;
                sprintf(outfile, "%03i.jpg", jpg_nr);
                // open output file
                outptr = fopen(outfile, "w");
                // Write 
                fwrite(&buffer, BUFFER_SIZE, NUMBER, outptr);
            }
        }
        else
        {
            // JPEG ALREADY OPEN
            if (outptr != NULL)
            { 
                // Skip writing if pointer is at EOF
                if (feof(inptr) == 0)
                {
                    // Write 
                    fwrite(&buffer, BUFFER_SIZE, NUMBER, outptr);
                }
            }    
        }     
    }


    // close infile
    fclose(inptr);
    fclose(outptr);

    return 0;
}

My ls -l output:

~/workspace/pset4/recover/ $ ls -l
total 23856
-rw------- 1 ubuntu ubuntu   224768 Sep 24 18:35 000.jpg
-rw------- 1 ubuntu ubuntu   222208 Sep 24 18:35 001.jpg
-rw------- 1 ubuntu ubuntu   148992 Sep 24 18:35 002.jpg
-rw------- 1 ubuntu ubuntu   253952 Sep 24 18:35 003.jpg
-rw------- 1 ubuntu ubuntu   244224 Sep 24 18:35 004.jpg
-rw------- 1 ubuntu ubuntu   205312 Sep 24 18:35 005.jpg
-rw------- 1 ubuntu ubuntu   125440 Sep 24 18:35 006.jpg
-rw------- 1 ubuntu ubuntu   119296 Sep 24 18:35 007.jpg
-rw------- 1 ubuntu ubuntu   188928 Sep 24 18:35 008.jpg
-rw------- 1 ubuntu ubuntu   130048 Sep 24 18:35 009.jpg
-rw------- 1 ubuntu ubuntu   181248 Sep 24 18:35 010.jpg
-rw------- 1 ubuntu ubuntu   249856 Sep 24 18:35 011.jpg
-rw------- 1 ubuntu ubuntu    68608 Sep 24 18:35 012.jpg
-rw------- 1 ubuntu ubuntu   175104 Sep 24 18:35 013.jpg
-rw------- 1 ubuntu ubuntu    68608 Sep 24 18:35 014.jpg
-rw------- 1 ubuntu ubuntu   244736 Sep 24 18:35 015.jpg
-rw------- 1 ubuntu ubuntu   195072 Sep 24 18:35 016.jpg
-rw------- 1 ubuntu ubuntu   169984 Sep 24 18:35 017.jpg
-rw------- 1 ubuntu ubuntu   243200 Sep 24 18:35 018.jpg
-rw------- 1 ubuntu ubuntu   194048 Sep 24 18:35 019.jpg
-rw------- 1 ubuntu ubuntu   175104 Sep 24 18:35 020.jpg
-rw------- 1 ubuntu ubuntu   222208 Sep 24 18:35 021.jpg
-rw------- 1 ubuntu ubuntu   171520 Sep 24 18:35 022.jpg
-rw------- 1 ubuntu ubuntu   334336 Sep 24 18:35 023.jpg
-rw------- 1 ubuntu ubuntu  1563648 Sep 24 18:35 024.jpg
-rw------- 1 ubuntu ubuntu   520704 Sep 24 18:35 025.jpg
-rw------- 1 ubuntu ubuntu   130048 Sep 24 18:35 026.jpg
-rw------- 1 ubuntu ubuntu   192000 Sep 24 18:35 027.jpg
-rw------- 1 ubuntu ubuntu   222720 Sep 24 18:35 028.jpg
-rw------- 1 ubuntu ubuntu    28160 Sep 24 18:35 029.jpg
-rw------- 1 ubuntu ubuntu   357888 Sep 24 18:35 030.jpg
-rw------- 1 ubuntu ubuntu   105472 Sep 24 18:35 031.jpg
-rw------- 1 ubuntu ubuntu    81920 Sep 24 18:35 032.jpg
-rw------- 1 ubuntu ubuntu   150016 Sep 24 18:35 033.jpg
-rw------- 1 ubuntu ubuntu   155648 Sep 24 18:35 034.jpg
-rw------- 1 ubuntu ubuntu   342016 Sep 24 18:35 035.jpg
-rw------- 1 ubuntu ubuntu   778752 Sep 24 18:35 036.jpg
-rw------- 1 ubuntu ubuntu   231424 Sep 24 18:35 037.jpg
-rw------- 1 ubuntu ubuntu   494080 Sep 24 18:35 038.jpg
-rw------- 1 ubuntu ubuntu   232960 Sep 24 18:35 039.jpg
-rw------- 1 ubuntu ubuntu    80896 Sep 24 18:35 040.jpg
-rw------- 1 ubuntu ubuntu   305664 Sep 24 18:35 041.jpg
-rw------- 1 ubuntu ubuntu   266752 Sep 24 18:35 042.jpg
-rw------- 1 ubuntu ubuntu   145920 Sep 24 18:35 043.jpg
-rw------- 1 ubuntu ubuntu   267776 Sep 24 18:35 044.jpg
-rw------- 1 ubuntu ubuntu    80384 Sep 24 18:35 045.jpg
-rw------- 1 ubuntu ubuntu   251904 Sep 24 18:35 046.jpg
-rw------- 1 ubuntu ubuntu   162304 Sep 24 18:35 047.jpg
-rw------- 1 ubuntu ubuntu    44544 Sep 24 18:35 048.jpg
-rw------- 1 ubuntu ubuntu    79360 Sep 24 18:35 049.jpg
-rw------- 1 ubuntu ubuntu 11830784 Sep 23  2016 card.raw

Hopefully somebody can identify what's wrong

1

This is one of those problems that illustrates why production code has to be tested on as many input sets as you can get your hands on. You have a subtle error, but your program happens to work on the input file card.raw. It will fail on many other files full of .jpg images (like the file that check50 uses).

According to the problem specification:

The fourth byte, meanwhile, is either 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, of 0xef. Put another way, the fourth byte’s first four bits are 1110.

In the last condition of your if statement:

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

you are checking if the 4th byte in the header is either 0xf0 or 0xe0. You should be checking to make sure the byte is between 0xe0 and 0xef. card.raw probably had jpgs with a 4th byte of 0xe0 which you happened to test for.

One way to test this is with two conditions to check the endpoints of the valid range:

buffer[3] >= 0xe0  &&  buffer[3] <= 0xef

For the condition to be True the byte would have to both be at least 0xe0 and at most 0xef which matches the above specification.

Another way to solve this, which the specification is hinting at by saying "the first four bits are 1110", is with a bitwise operator and a bitmask. Bit operations are one of the extremely powerful capabilities of C that make it well-suited for low-level programming.

| improve this answer | |
  • hehe, Robert, you beat me to the punch by seconds! ;-) And you're right, check50 uses a different data set. The hidden lesson here is that, at this stage, you need to think about what data might be missing from test data sets. – Cliff B Sep 24 '17 at 21:35
  • Thanks Robert and Cliff for the answer. I will try your fix after work. I have to double check but I thought that In the problem set walkthrough they tell everybody to use my current logic to check for a new jpg. – Richard Sep 26 '17 at 9:38

You must log in to answer this question.

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