How could count number of data blocks that have a file? - c

I have to make a program that extract images from a RAW file. It's specified that the system file is fat32 and blocks of data are 512 bytes. The below program works, at least with the file that is provided for testing, but when i try to use RAW files that I found on the internet, not works and yields a segmentation fault error. Valgrind report some bytes still reachable.
I think I'm reading less or more bytes that the block size for data in the file, so:
How could I know the size of each block data inside the file?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// Check for two arguments
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
// Open the forensic image
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
fprintf(stderr, "It's not possible open the file :(\n");
return 2;
}
// Initialize values
int count = 0;
BYTE buffer[512];
char filename[8];
FILE *out = NULL;
// Read blocks of data from forensic image
while (fread(&buffer, sizeof(BYTE), sizeof(buffer), file))
{
// Check if there is a JPG signature
if (buffer[0] == 0xff && buffer[1] == 0xd8
&& buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// If isn't first loop, close previous output file
if (count != 0)
{
fclose(out);
}
// Save name for current output file
sprintf(filename, "%03i.jpg", count++);
// Open output file
out = fopen(filename, "w");
// Check if file is right
if (out == NULL)
{
fprintf(stderr, "File could not open :(\n");
return 3;
}
// Write data to output file
fwrite(&buffer, sizeof(BYTE), sizeof(buffer), out);
}
// If isn't first loop, write data
else if (count != 0)
{
fwrite(&buffer, sizeof(BYTE), sizeof(buffer), out);
}
}
fclose(out);
fclose(file);
}

Related

Recover functions recovers only 4 images instead of 50

I wrote this code to recover 50 images from cs50 pset4 recover. The code can only retrieve 4 images all of which are not the right ones. It is compiling fine. When i use printf to debug it seems like the if(found) piece of code runs many times when name_count == 0 more than it is supposed to.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t BYTE;
const int BLOCK_SIZE = 152;
bool is_a_jpeg(BYTE *buffer);
int main(int argc, char *argv[])
{
//Check if there are exactly two commandline arguments
if (argc != 2)
{
printf("usage: ./IMAGE\n");
return 1;
}
//Open a storage device and chack if it has data
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
fclose(input);
printf("Could not open file.\n");
return 2;
}
//Create a file to write into and clear it
FILE *img = NULL;
//Declar an interger of counting images
int name_count = 0;
// create buffer
BYTE buffer[BLOCK_SIZE];
//Declare space for saving the filename
char filename[8];
//Declare a bolean variable used to check for already found images
bool found = false;
//A function for reading through the device looking for images
while (fread(buffer, BLOCK_SIZE, 1, input))
{
//If a jpeg image is found notify the program(set found = true)
//and start writing the data to a new file
if (is_a_jpeg(buffer))
{
found = true;
//If we are not writing the first image, close the previous one
if (name_count > 0)
{
fclose(img);
}
//Create incrementing filenames for each new picture i.e 000.jpg, 001.jpg etc.
sprintf(filename, "%03d.jpg", name_count);
//Open an initially created empty file and start writing to it
img = fopen (filename, "w");
name_count++;
fwrite(buffer, BLOCK_SIZE, 1, img);
}
//Continue writing to a file as soon as it is found until another JPEG image is found
if(found)
{
fwrite(buffer, BLOCK_SIZE, 1, img);
}
}
//Close all the files
fclose(input);
fclose(img);
return 0;
}
//Function to check for a JPEG Image
bool is_a_jpeg(BYTE *buffer)
{
return buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0;
}
cs50 results for check50
printing dot everytime if(found) code runs. The code unnecessarily spends a lot of time on the first image before closing it
There are some problems in the posted code:
the block size should be 512 bytes, not 152.
you should not fclose(file) if fopen failed. This has undefined behavior.
you unconditionally close img at the end, which may have undefined behavior if no JPG file was found or if the last JPG file could not be open.
both the disk image file and the jpg destination files must be open in binary mode. This may explain unexpected behavior if you are working on Windows.
Here is a modified version:
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef uint8_t BYTE;
const int BLOCK_SIZE = 512;
bool is_a_jpeg(const BYTE *buffer);
int main(int argc, char *argv[]) {
//Check if there are exactly two commandline arguments
if (argc != 2) {
printf("usage: ./IMAGE\n");
return 1;
}
//Open a storage device and check if it has data
FILE *input = fopen(argv[1], "rb");
if (input == NULL) {
fprintf(stderr, "Could not open file %s: %s.\n", argv[1], strerror(errno));
return 2;
}
//Create a file to write into and clear it
FILE *img = NULL;
//Declare an integer of counting images
int name_count = 0;
// create buffer
BYTE buffer[BLOCK_SIZE];
//Declare space for saving the filename
char filename[16];
//A function for reading through the device looking for images
while (fread(buffer, BLOCK_SIZE, 1, input)) {
//If a jpeg image is found notify the program(set found = true)
//and start writing the data to a new file
if (is_a_jpeg(buffer)) {
//close the current image file if any
if (img) {
fclose(img);
img = NULL;
}
//Create incrementing filenames for each new picture i.e 000.jpg, 001.jpg etc.
sprintf(filename, "%03d.jpg", name_count);
name_count++;
//Create an empty file and start writing to it
img = fopen(filename, "wb");
if (img == NULL) {
fprintf(stderr, "Could not open output file %s: %s.\n", filename, strerror(errno));
}
}
//Continue writing to a file as soon as it is found until another JPEG image is found
if (img) {
if (!fwrite(buffer, BLOCK_SIZE, 1, img)) {
fprintf(stderr, "Error writing to %s: %s.\n", filename, strerror(errno));
fclose(img);
img = NULL;
}
}
}
//Close all the files
fclose(input);
if (img)
fclose(img);
return 0;
}
//Function to check for a JPEG Image
bool is_a_jpeg(const BYTE *buffer) {
return buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0;
}

CS50 pset04 - handles lack of forensic image - segmentation fault

Problem
The program is supposed to recover images from a memory chunk with the following requirements:
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 car
each block is 512 bytes
It's compiled and runs smoothly on my local machine. But fail when I use check50. Anybody has an idea why? Please help
:( handles lack of forensic image // failed to execute program due to segmentation fault
Code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define FAT 512
typedef unsigned char BYTE;
int main(int argc, char *argv[])
{
// program must accept only one argument
if (argc > 2)
{
printf("Usage: ./recover [image disk]\n");
return 1;
}
// open forentic file
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
fclose(input);
printf("Could not open %s.\n", argv[1]);
return 2;
}
// create a buffer
BYTE buffer[FAT];
int fcount = -1;
char pic_name[8];
FILE *output;
while (fread(buffer, FAT, 1, input))
{
// check if the buffer started with the 04 signed digits of jpeg
if (buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xe0) == 0xe0)
{
// if it's not the first picture, we need to close the connection
// to create a new image.
if (fcount > -1)
{
fclose(output);
}
fcount++;
sprintf(pic_name, "%03i.jpg", fcount);
output = fopen(pic_name, "w");
if (output == NULL)
{
fclose(input);
printf("Could not create %s.\n", pic_name);
return 3;
}
}
if (fcount > -1)
{
fwrite(buffer, FAT, 1, output);
}
}
fclose(input);
fclose(output);
return 0;
}

recover problem: file format not supported error

I'm trying to solve this problem which consists of reading data from a "memory card" and write it into new readable jpg files.
I'm getting 50 files named correctly as far as I can tell but their data is incorrect. to me it looks like it should be writing into each jpg the data read into the buffer from the card or argv[1] but I'm guessing I'm missing something and I can't figure out what.
this is what I wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int is_jpg(BYTE(buffer[]))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xe0) == 0xe0)
{
return 1;
}
else
{
return 0;
}
}
int main(int argc, char *argv[])
{
BYTE buffer[512];
//checks argument validity
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
FILE *file = fopen(argv[1], "r");
//printf("continuing program\n");
//checks if the file exists
if (file == NULL)
{
printf("No file found\n");
return 2;
}
int file_count = 0;
char file_name[8];
//sprintf(file_name, "%03d.jpg", file_count);
FILE *image;
while (fread(buffer, 512, 1, file) == 1)
{
if (is_jpg(buffer) == 1)
{
if (file_count != 0)
{
fclose(image);
}
sprintf(file_name, "%03d.jpg", file_count);
image = fopen(file_name, "w");
fread(&buffer, 512, 1 , file);
fwrite(&buffer, 512, 1, image);
file_count++;
}
else if (file_count > 0)
{
fwrite(buffer, 512, 1, image);
}
//fwrite(&buffer, 512, 1, image);
}
}
When you detect the header, you do an extra fread [after the image = fopen(file_name, "w"); call].
You want to write the header to the output file/stream. But, the extra fread trashes the header data and the first block of the file is data and not the header as you desire.
You only want the fread at the top of the loop.

Invalid or Unsupported Image Format Recover CS50

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// open memory card
if(argc > 2 )
{
printf("Usage: ./recover image");
return 1;
}
FILE *file = fopen(argv[1], "r");
FILE *img;
// repeat until end
int i = 0;
// 512 bytes into buffer
uint8_t buffer[2048];
char *filename = malloc(8);
// if start of new jpeg
while(fread(&buffer, 512, 4, file)) // read card
{
if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) // if start new jpeg
{
// if first
i++;
sprintf(filename, "%03i.jpg", i);
img = fopen(filename, "w");
fwrite(&buffer, sizeof(uint8_t), 1, img); // fixed
}
//else
else
{
// if still reading jpeg
if(img != NULL)
{
fwrite(&buffer, sizeof(uint8_t), 1, img);
}
}
}
//close
free(filename);
fclose(file);
return 0;
}
I think my code is pretty close to being done but the images returned are invalid or unsupported image format. It compiles fine and it returns 12 images. I do not want to look at a solution to fix this. Where did my code mess up?

cs50 pset4 recover.c need advice

I could use some guidance on this pset from cs50. Below is the code i have so far. I am stuck at this point where i have no idea how to proceed. When i run the program it does output 16 jpg files but i cannot view them so something must be wrong. Any tips are welcome.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// create buffer to store in
unsigned char buffer[512];
// array for filename is 8 for "000.jpg"
char jpgName[8];
// declaring counter for amount of jpegs
int jpgcounter = 0;
// open memory card file
FILE* inptr = fopen("card.raw", "r");
FILE* outptr = NULL;
if (inptr == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 1;
}
// repeat until end of card
while(fread(buffer, sizeof(buffer), 1, inptr) == 1)
{
// find beginning of jpg
if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] == 0xe0 || buffer[3] == 0xe1))
{
// if allready a outptr file is open close it
if (outptr != NULL)
{
fclose(outptr);
}
// create filename for jpegs
sprintf(jpgName,"%03d.jpg", jpgcounter);
// open a new file with name defined by sprintf
FILE* outptr = fopen(jpgName, "w");
// write into the outfile from buffer
fwrite(&buffer, sizeof(buffer), 1, outptr);
// increment counter for jpegs
jpgcounter++;
}
}
fclose(inptr);
return 0;
}
If I understood your task correctly, you want something like this-please see below.
Hint: what are you planning to do if it is not beginning of jpg file?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned char buffer[512] = {0};
char jpgName[8] = {0};
int jpgcounter = 0;
FILE* outptr = NULL;
// open memory card file
FILE* inptr = fopen("card.raw", "rb");
if (inptr == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 1;
}
// Start reading
while(fread(buffer, sizeof(buffer), 1, inptr) == 1)
{
// Find beginning of jpg
if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] == 0xe0 || buffer[3] == 0xe1))
{
if(NULL!=outptr)
{
fclose(outptr);
outptr=NULL;
}
// Create filename for jpegs
sprintf(jpgName,"%03d.jpg", jpgcounter);
// Open a new file with name defined by sprintf
outptr = fopen(jpgName, "wb");
if (NULL == outptr)
{
printf("Could not open %s.\n", jpgName);
return 1;
}
// Write into the outfile from buffer
fwrite(buffer, sizeof(buffer), 1, outptr);
// Increment counter for jpegs
jpgcounter++;
}
else
{
// Continue writing to old file if it is not beginning of file
if(NULL!=outptr)
fwrite(buffer, sizeof(buffer), 1, outptr);
}
}
if(NULL!=outptr)
fclose(outptr);
if(NULL!=inptr)
fclose(inptr);
return 0;
}
This can't work:
while(fread(buffer, sizeof(buffer), 1, inptr) == 1)
{
// read 512 bytes from inptr and store them in buffer
fread(&buffer, sizeof(buffer) , 1, inptr);
as you use fread twice and the data read by the first get overwritten by the second. It looks as if this loses the first 512 bytes of every kB in the original file.
You should get further if you delete the second fread().

Resources