0

I having some problems with PSET4 recover I can recover all 50 photos successfully, open and see them as well. The code runs very quickly and with no errors. But for any reason when I run check50 I get: :) 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 recovered image does not match

Does anyone have a clue? Thanks in advance

Here's my code:

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

typedef uint8_t  BYTE;
typedef uint32_t DWORD;
typedef int32_t  LONG;
typedef uint16_t WORD;


/**
 * JPG start
 */
typedef struct
{
BYTE first;
BYTE second;
BYTE third;
BYTE fourth;
} __attribute__((__packed__))
JPGheader;


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

// remember filenames
char *infile = argv[1];
//printf("%s\n", infile);

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



JPGheader jpg;
jpg.first = 0xff;
jpg.second = 0xd8;
jpg.third = 0xff;
jpg.fourth = 0xe0;

int jpg_fourth_top = (jpg.fourth >> 4) & ((1 << 4) - 1);
//printf("original: %i%i%i%i  %i\n", jpg.first, jpg.second, jpg.third, jpg.fourth, jpg_fourth_top);

int jpg_order = 0;
//char *jpg_ext = ".jpg";
char *BLOCK = malloc(sizeof(BYTE)*512);
bool JPG = false;
FILE *outptr;

//while (jpg_order<49){
while (jpg_order<51){


    JPGheader raw_read;
    fread(&raw_read, sizeof(JPGheader), 1, inptr); 
    //printf("%i%i%i%i\n", raw_read.first, raw_read.second, raw_read.third, raw_read.fourth);
    int raw_read_fourth_top = (raw_read.fourth >> 4) & ((1 << 4) - 1);

    fseek(inptr, -(sizeof(JPGheader)), SEEK_CUR);

    if(jpg.first == raw_read.first && jpg.second == raw_read.second && jpg.third == raw_read.third && jpg_fourth_top == raw_read_fourth_top){
        if (JPG){
            fclose(outptr);
            jpg_order++;
            JPG = false;
        }

            //int raw_read_fourth_top = (raw_read.fourth >> 4) & ((1 << 4) - 1);
            //printf("%i%i%i%i  %i\n", raw_read.first, raw_read.second, raw_read.third, raw_read.fourth, raw_read_fourth_top);


        // open output file
        char fileSpec[10];
        sprintf(fileSpec, "%03i.jpg" ,jpg_order );
        printf("%s found!\n", fileSpec);

        outptr = fopen(fileSpec, "w"); //FILE *
        if (outptr == NULL){
            fclose(inptr);
            fprintf(stderr, "Could not create %s.\n", fileSpec);
            return 3;
        }
        JPG = true;

    }

    if (JPG){
        fread(&BLOCK, sizeof(BLOCK), 1, inptr);
        fwrite(&BLOCK, sizeof(BLOCK), 1, outptr);
    }
    else
        fseek(inptr, sizeof(BLOCK), SEEK_CUR);

    if(feof(inptr)){
        break;
    }



}

fclose(outptr);
fclose(inptr);

// success
return 0;
}
1

[EDIT: Note: From year to year, the psets get redesigned and tests and data files can and do change. Some of this information may no longer be true as time passes. Keep this in mind while reading. Cliff B. 12/26/2019]

First, understand that check50 uses a different input file than the one that is provided. (There's a history to that, but that's another long discussion. ) It processes a different number of files. It also has one or two traps built into it. ;-)

Now, let's explore some issues. The code is supposed to check the first 4 bytes of a 512 byte block and, if no signature is found, move on to the next block. The move is implemented with this code:

else
    fseek(inptr, sizeof(BLOCK), SEEK_CUR);

The problem is that this will only move 8 bytes. sizeof(BLOCK) returns the size of the pointer BLOCK, not the size of what it points at. A pointer is 8 bytes in a 64 bit architecture. The result is that it actually finds a false positive signature in the middle of a block.

About that false positive: There is, in fact a false positive deliberately buried in check50's test data. If code is checking for signatures where it shouldn't, it will produce an extra file. That is exactly what is happening with your code, so the middle and last files don't match.

Now, an opinion. The pset spec says you can count on 50 images (at the time this is written). In my opinion, it would be better if it said to write the program for an undetermined number of files. Also, the test data in check50 uses a different number of images. So, writing for an undetermined number of output files, in my opinion, gives practice in dealing with EOF and undetermined potential results. (My understanding is that this may change next year.)

There may be other issues, but these are the big ones. If this answers your question (or at least kicks you down the right road), please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
  • Hi Cliff, thanks in advance for your answer! But I think you misunderstood my code, I don't read every 4 bytes, once it does not match, I jump to the next block (512 bytes). Besides that, I did change some parts of the code to make it simple and now it's working perfectly! Thanks again for your help! Cheers! – Marcus Nov 20 '17 at 0:48
  • Well, it turned out we were both a little wrong. See my edited answer. – Cliff B Nov 20 '17 at 1:45
  • as per 2019 pset3 says: "Moreover, rather than read my memory card’s bytes one at a time, you can read 512 of them at a time into a buffer for efficiency’s sake. Thanks to FAT, you can trust that JPEGs' signatures will be "block-aligned." That is, you need only look for those signatures in a block’s first four bytes." so apparently there's no need at all to fseek, just fread 512 bytes. please correct me if I'm wrong. – iair Sep 3 '19 at 2:56

You must log in to answer this question.

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