I have been trying to do this problem for at least a week now, and can't seem to understand where is the problem, I already checked everything in google, and dont know any programmer in real life to ask them personaly, so if anyone can help me it would be great.
None of the images generated load, and it doesnt recover 50 as it is suposed to, it recovers 986.
I get this results in check50:
:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:( recovers 000.jpg correctly
recovered image does not match
:( recovers middle images correctly
recovered image does not match
:( recovers 049.jpg correctly
recovered image does not match
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <cs50.h>
typedef uint8_t BYTE;
#define BLOCK_SIZE 512
int main(int argc, char *argv[])
{
//it only accepts one comand argument in the name of an image
if (argc != 2)
{
printf("Usage: ./recover IMAGE");
return 1;
}
//check if it can open the image
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
printf("The image cannot be opened");
return 1;
}
bool jpg_before = false;
int counter = 0;
FILE *image = NULL;
char name[8];
unsigned char buffer[BLOCK_SIZE];
//while there is still jpegs in the file
while (fread(buffer, BLOCK_SIZE, 1, file) == 1)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xe0) == 0xe0)
{
jpg_before = true;
}
if(jpg_before == true)
{
sprintf(name, "%03i.jpg", counter);
counter++;
image = fopen(name, "a");
fwrite(buffer, BLOCK_SIZE, 1, image);
fclose(image);
}
}
fclose(file);
}
(also please keep in mind I'm new to programming, 16 years old and english is not my first lenguage)
jpg_before. But, you never clear it.name[8]is a bit too small. The compiler will complain because theintcould [in theory] be 10 or so digits, so thesprintfcould overflow. Don't be stingy--use (e.g.):char name[20];"w"instead of"a". If the program is run twice, the second time, the output file(s) will be incorrect.Here is the refactored code:
UPDATE:
From the comments below:
If
His header andDis data, for an input of (e.g):H1,D1,D2,D3,D4,H2,D5,D6,D7:Instead of two output files:
F0:H1,D1,D2,D3,D4andF1:H2,D5,D6,D7We'd have:
F0:H1,F1:D1,F2:D2,F3:D3,F4:D4,F5:H2,F6:D5,F7:D6,F8:D7Although my refactored code was correct, the top section of my answer had an incorrect analysis of what OP's code was actually doing.
I've fixed that. But, to make user4581301's make sense, here is the original analysis:
jpg_before. But, you never clear it.name[8]is a bit too small. The compiler will complain because theintcould [in theory] be 10 or so digits, so thesprintfcould overflow. Don't be stingy--use (e.g.):char name[20];"w"instead of"a". If the program is run twice, the second time, the output file(s) will be incorrect.UPDATE #2:
From code inspection, the only place that could segfault is the
fwritecall (i.e.imageisNULL).I confirmed this by running the program under
gdb[I have the cs50 recover input file]. When the program faults, just dotbto get a stack traceback.imagecould beNULLfor the following reasons:The
fopenfor output file could fail (due to permissions, space, etc.) and returnNULL. There was no check after the call as there was for opening the input file.imagestarts out beingNULL. If there is some sort of extra file data/file header before the first jpg header (e.g. beforeFF/D8/FF/E0) theifwill not match on the first block read. Thefwritewill be called even with a NULL inimage.Option (2) is what actually occurred because cs50's file has an extra header at the top of the file. You can see this by examining the file with a hex editor/dumper (e.g.)
odorxxd:The code will not see a valid header (i.e. the
ifmatches) until offset 400. So, there are two extraneousfreadcalls at the start until things sync up.The fix is to change:
Into:
I've written a few answers on this problem before. However, I forgot to include this. I just wrote the code but did not test it ;-)
To round things out, I've added more return code checking and added
"rb"and"wb"to thefopencalls, just in case you're running on Windoze.Here is the updated/fixed code (I've tested it this time ;-):