Skip to content

Instantly share code, notes, and snippets.

@CraigRodrigues
Created July 7, 2016 16:50
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CraigRodrigues/8f831e9ea1003d9ad14f608d24cc1ba3 to your computer and use it in GitHub Desktop.
Save CraigRodrigues/8f831e9ea1003d9ad14f608d24cc1ba3 to your computer and use it in GitHub Desktop.
CS50 pset4 - "Recover"
/**
* recover.c
*
* Computer Science 50
* Problem Set 4
*
* Recovers JPEGs from a forensic image.
*/
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 512
int main(void)
{
// open memory card file
FILE* input = fopen("card.raw", "r");
if (input == NULL)
{
printf("Could not open card.raw.\n");
return 2;
}
// create buffer
unsigned char buffer[BUFFER_SIZE];
// filename counter
int filecount = 0;
FILE* picture = NULL;
// check if we've found a jpeg yet or not
int jpg_found = 0; //false
// go through cardfile until there aren't any blocks left
while (fread(buffer, BUFFER_SIZE, 1, input) == 1)
{
// read first 4 bytes of buffer and see if jpg signature using bitwise on last byte
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xe0) == 0xe0)
{
if (jpg_found == 1)
{
// We found the start of a new pic so close out current picture
fclose(picture);
}
else
{
// jpg discovered and now we have the green light to write
jpg_found = 1;
}
char filename[8];
sprintf(filename, "%03d.jpg", filecount);
picture = fopen(filename, "a");
filecount++;
}
if (jpg_found == 1)
{
// write 512 bytes to file once we start finding jpgs
fwrite(&buffer, BUFFER_SIZE, 1, picture);
}
}
// close files
fclose(input);
fclose(picture);
return 0;
}
@thucnhu
Copy link

thucnhu commented Apr 14, 2020

char filename[8]; Hi, could you please explain why it is '8'? Thanks in advance

@UffanMehmoodKhan
Copy link

It is to allocate enough characters to write "###.jpg". Since a string like this needs a null character, in the end, it is 8 along with 7 characters of ###.jpg.

@janikaoh
Copy link

hello! could you please explain why the first fread uses buffer while the next fread at the end uses &buffer instead? thank you!

@aryanptl01
Copy link

Hey there! How are you using jpg_found? Cuz you have initialised it to ''0'' and haven't incremented it anywhere. Thanks!

@Swifty4444
Copy link

Hey there! How are you using jpg_found? Cuz you have initialised it to ''0'' and haven't incremented it anywhere. Thanks!

if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xe0) == 0xe0)
{
if (jpg_found == 1)
{
// We found the start of a new pic so close out current picture
fclose(picture);
}
else
{
// jpg discovered and now we have the green light to write
jpg_found = 1;

This else condition sets jpg_found = 1. In this problem, as all the jpegs are back-to-back we never expect a blank space where a different file might be so once we've found the first jpeg we can just carry on until the end of the file, writing a new file everytime we discover a new jpg.

@karp05
Copy link

karp05 commented May 19, 2020

why the &buffer ?

@jt-manful
Copy link

hello! could you please explain the thought process used to create the if else statements in your while loop

@lauraew
Copy link

lauraew commented Jun 13, 2020

Could you please explain here why the 3 argument is 1, and why we have == 1?
while (fread(buffer, BUFFER_SIZE, 1, input) == 1)

@RhFortuna
Copy link

RhFortuna commented Jun 14, 2020

Why can't I use fclose(picture) after fwrite?
jpg_found will always be = 1 after find the "magical numbers", isn't? So, can't I avoid if-else in any way?

PS: Oh, I got it, a picture only should be fclosed when another is found!

@00Seben30
Copy link

char filename[8]; Hi, could you please explain why it is '8'? Thanks in advance

to create memory space for the filename

@bhavitshahop
Copy link

why is while(........ = 1 ) for fread

@bib-1
Copy link

bib-1 commented Jun 29, 2020

why is while(........ = 1 ) for fread

to stop executing if it didn't find block of 512 bytes in the memory

@RhFortuna
Copy link

why is while(........ = 1 ) for fread

to stop executing if it didn't find block of 512 bytes in the memory

Does this mean something like "while fread is true: ..." ?

@azw123
Copy link

azw123 commented Jul 7, 2020

Why do you need the cs50 library

@doodoodoododoo
Copy link

hello! could you please explain why the first fread uses buffer while the next fread at the end uses &buffer instead? thank you!

@jdecuirm
Copy link

jdecuirm commented Sep 3, 2020

Hey nice work! You could also avoid the boolean flag just by checking the image file! if it is NULL then you can start writing, otherwise you close the file and create a new image! just to simplify the code!

@Student3153
Copy link

Student3153 commented Sep 22, 2020

~/pset4/recover/ $ ./a.out
Could not open card.raw.
someone help!

@doodoodoododoo
Copy link

@Student3153 Are you using this code?

@YellowSailor
Copy link

Hey, thank you for sharing your solution. Can you please explain to me, why in line 60 another if statement is needed? I would have used else, however, that does not work and it is giving me segmentation faults.
Thank you.

@ushiradineth
Copy link

Hey, thank you for sharing your solution. Can you please explain to me, why in line 60 another if statement is needed? I would have used else, however, that does not work and it is giving me segmentation faults.

The "if (jpg_found == 1)" in line 60 is used for writing the bytes on an already existing jpg file
the if condition in 43 checks if a new file was found so you cant use a else condition because the 43 and 60 works together

@frjimbow
Copy link

frjimbow commented Dec 11, 2020

~/pset4/recover/ $ ./a.out
Could not open card.raw.
someone help!

you need to put your file's name as follow :
FILE* file = fopen("card.raw", "r");

@Student3153
Copy link

@frjimbow I’m already done with the entire course

@frjimbow
Copy link

@frjimbow I’m already done with the entire course

sounds great. Have you become a professional developer ?

@recepkrty
Copy link

why the &buffer ?

just buffer is ok

@Caroline-100
Copy link

hello,

      if (jpg_found == 1)
            {
                // We found the start of a new pic so close out current picture
                fclose(picture);
            }

i delete and it s work,
why it s important these lines

i think we close already here
// close files
fclose(input);
fclose(picture);

@atifali10
Copy link

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

#define BLK_SIZE 512

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not be opened %s\n", argv[1]);
return 1;
}
FILE *output = NULL;
int imgcount = 0;

BYTE bytes[BLK_SIZE];
while(fread(bytes, sizeof(BYTE), BLK_SIZE, input) || feof(input))
{
    if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0)
    {
        if (output != NULL)
        {
            fclose(output);
        }
        char filename[8];
        sprintf(filename, "%03i.jpg", imgcount);
        output = fopen(filename, "w");
        imgcount++;
    }
    if(output!=NULL)
    {
        fwrite(bytes, sizeof(BYTE), 1, output);
    }
}
if (input == NULL)
{
    fclose(input);
}
if(output == NULL)
{
    fclose(output);
}
return 0;

}

:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:( recovers 000.jpg correctly
timed out while waiting for program to exit
:( recovers middle images correctly
timed out while waiting for program to exit
:( recovers 049.jpg correctly
timed out while waiting for program to exit

can someone help me understand whats going on?
Thank you :)

Copy link

ghost commented Apr 8, 2021

Hello,

The following code is not working, could you please help?
Results :
:) 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 <cs50.h>
#include <string.h>
#include <ctype.h>

#define BLOCK 512
#define FILENAME_LENGTH 8

bool isJPEG(unsigned char buffer[]){

if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
    return true;
}

return false;

}

int main(int argc, char *argv[])
{

//argv[1]
FILE *inFile = fopen(argv[1], "rb");

if (argc != 2)
{
    return 1;
}

if (argv[1] == NULL)
{
    fprintf(stderr, "Usage: ./recover image");
    return 1;
}

//each JPEG file start with a distinct header
//all first 3 bytes in JPEG files are the same : 0xff - 0xd8 - 0xff
// the fourth byte : 0xe0, 0xe1, 0xe2, ...., or 0xef
//the JPEG files are stored back to back in the memory card
//each block is 512 bytes


int count = 0;
unsigned char buffer[BLOCK];
bool found = false;

FILE *outFile;

//read until the end
while (fread(buffer, sizeof(buffer), 1, inFile) == 1)
{

    if (isJPEG(buffer) == true)
    {

        if (found == true)
        {
            // Close outfile
            fclose(outFile);
        }
        else
        {
            found = true;
        }

        char outFileName[FILENAME_LENGTH];

        sprintf(outFileName, "%03i.jpg", count);

        outFile = fopen(outFileName, "wb");

        count++;

        if (found == true)
        {
            if (fwrite(buffer, sizeof(buffer), 1, outFile) != 1)
            {
                fprintf(stderr, "error writing");
            }
        }

    }

}

fclose(outFile);
fclose(inFile);

return 0;

}

Thanks!

@ShivangM
Copy link

ShivangM commented Oct 3, 2021

hello! could you please explain why the first fread uses buffer while the next fread at the end uses &buffer instead? thank you!

Hi, I had the same doubt. i guess this will help you out, after a bit research i found this answer helpful.
https://stackoverflow.com/a/53471904

@Seif2005
Copy link

why the &buffer ?

it is useless since the buffer array is already a pointer holding the address of the first element in it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment