0

The title explains the issue, not really sure why the test case is failing because the logic seems to work. I'm assuming it has to do with reading some unnecessary bytes near the end, but I haven't been able to find a workaround for it. Also, some null file keeps popping up in my directory every time I compile the code, it may be related.

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

int found_jpeg(unsigned char* buffer);
int get_bytesread(FILE* infileptr);

int main(int argc, char *argv[])
{
//Check for correct number of command line arguments
if (argc != 2)
{
    fprintf(stderr, "Usage: recover (infile)\n");
    return 1;
}

//Open memory card file
FILE* infile;
infile = fopen(argv[1], "r");

//Check if file can be opened
if (infile == NULL)
{
    fprintf(stderr, "Could not open file.\n");
    return 2;
}

//Initialize variables
FILE* outfile = NULL;
unsigned char fileblock[512];
char filename[8];
int filenumber = 0;

//Loop through jpeg files until end of file
while (get_bytesread(infile) == 512)
{
    //Find first jpeg file
    while (found_jpeg(fileblock) == 1)
    {
        fread(fileblock, 512, 1, infile);
    }

    //Open empty file to write into
    sprintf(filename, "%03d.jpg", filenumber);
    outfile = fopen(filename, "w");

    //Write into file until new jpeg header is found
    fwrite(fileblock, 512, 1, outfile);
    fread(fileblock, 512, 1, infile);

    while ((found_jpeg(fileblock) == 1) && (get_bytesread(infile) == 512))
    {
        fwrite(fileblock, 512, 1, outfile);
        fread(fileblock, 512, 1, infile);
    }

    //Close outfile if present and iterates filenumber
    if (outfile != NULL)
    {
        fclose(outfile);
        filenumber += 1;
    }
}

//Close memory card file
fclose(infile);

//Program finished successfully
return 0;
}

//Check if values are consistent with a jpeg header
int found_jpeg(unsigned char* buffer)
{
    if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && 
       (buffer[3] & 0xf0) == 0xe0)
    {
        return 0;
    }
    return 1;
}


//Return how many bytes have been read
int get_bytesread(FILE* infileptr)
{
    unsigned char temp_fileblock[512];

    int bytes_read = fread(temp_fileblock, 1, 512, infileptr);
    int temp = bytes_read;
    fseek(infileptr, -temp, SEEK_CUR);
    return temp;
}
1

Quick question, which I think may be the answer. What guarantee do you have the last block of bytes read will be 512 bytes? For your last image are you sure you are writing the entire amount of data? Sorry to answer your question with a question, but I suggest you have one last chunk of data left to be written out to the last img file.

1
  • Yep, that was the issue. The last block wasn't taking up a full 512 bytes, I didn't realize fread would fill the rest of the array with zeroes on the last check, which allows fwrite to write the final 512 bytes. – Edward Dec 31 '19 at 2:27
0
    if (get_bytesread(infile) != 512)
    {
        fread(fileblock, 512, 1, infile);
        fwrite(fileblock, 512, 1, outfile);
        fclose(outfile);
        break;
    }

Added this line after the write loop, so it'll write the final 512 bytes properly. Thanks to Nicknapoli82 for pointing out that the last 512 bytes weren't guaranteed to be read.

You must log in to answer this question.

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