CS50 Recover - memory issue - c

I'm a bit stymied by this problem, so I'd love any advice or insight into what I'm doing wrong.
In short, when submitting the below Recover code to CS50's CHECK50, I pass every test except the last one. Instead, I get this error in the CHECK50 terminal:
checking that program exited with status 0...checking for valgrind errors...
472 bytes in 1 blocks are still reachable in loss record 1 of 1: (file: recover.c, line: 28)
That error seems straightforward to me. I'm allocating something in memory that I'm not freeing by the end of the code. Here's the operation at line 28 that that the error readout is pointing to:
FILE *mem_card = fopen(argv[1], "r");
From that, I thought all I would have to do is is free(mem_card); at the end of recover.c. However, doing that gave me a huge amount of new Valgrind errors. So I'm a bit stuck and not sure how to approach this, as I don't know what I'm doing wrong.
I've removed the comments from my recover.c code and included it here for more context:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
int BLOCK_SIZE = 512;
int jpeg_count = 0;
BYTE buffer[BLOCK_SIZE];
FILE *img;
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
FILE *mem_card = fopen(argv[1], "r"); // CHECK50/Valgrind issue here
if (mem_card == NULL)
{
printf("Could not open for reading %s.\n", argv[1]);
return 1;
}
char filename[8] = {};
while (fread(buffer, 1, BLOCK_SIZE, mem_card) == BLOCK_SIZE)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
sprintf(filename, "%03i.jpg", jpeg_count);
if (jpeg_count == 0)
{
jpeg_count++;
img = fopen(filename, "w");
fwrite(buffer, 1, BLOCK_SIZE, img);
}
else if (jpeg_count > 0)
{
jpeg_count++;
fclose(img);
img = fopen(filename, "w");
fwrite(buffer, 1, BLOCK_SIZE, img);
}
}
else if (jpeg_count > 0)
{
fwrite(buffer, 1, BLOCK_SIZE, img);
}
else
{
}
}
fclose(img);
//free(mem_card);
return 0;
}

You opened the file and saved its file pointer to mem_card.
Therefore, you should close the file:
fclose(mem_card);

Related

CS50 pset4 recover > program is free of memory errors

I finished writing the program that recovers photos from a memory card and it's working properly
But there is an error closing the "output"file.
I just want to know where to write another "fclose"
This is the error:
:( program is free of memory errors
Cause
valgrind tests failed; see log for more information.
Log
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmpie2_4mb5 -- ./recover card.raw...
checking that program exited with status 0...
checking for valgrind errors...
23,128 bytes in 49 blocks are still reachable in loss record 1 of 1: (file: recover.c, line: 35)
the problem in " output = fopen(fileName, "w"); "
`
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BLOCK_SIZE 512
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
// Open files and determine scaling factor
FILE* input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
FILE* output = NULL; //output_file
typedef uint8_t BYTE;
BYTE buffer[BLOCK_SIZE]; //buffer = 512
char fileName[8]; // =malloc
int count = 0; //count image
while (fread(buffer, BLOCK_SIZE, sizeof(BYTE), input))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer [3] & 0xf0) == 0xe0)
{
sprintf(fileName, "%03i.jpg", count);
output = fopen(fileName, "w");
count++;
}
if (output != NULL)
{
fwrite(buffer, BLOCK_SIZE, sizeof(BYTE), output);
}
}
fclose(input);
fclose(output);
return 0;
}
`

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

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);
}

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?

Segmentation Fault in CS50 recover

I have been trying to find out what is the issue with my code for hours. I referred to other people's code but I still don't know what's wrong. The code compiles fine but the debugger says that the segmentation fault occurs at line 44 (below the comment). Suggestions to improve my code are welcome too. Please help and thank you.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
FILE *f = fopen(argv[1],"r");
if (!f)
{
return 2;
}
BYTE buffer[512];
FILE* img = NULL;
int i = 0;
while (fread(buffer, 512, 1, f) == 1)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff
&& (buffer[3] & 0xf0) == 0xe0)
{
//create jpeg
char filename[8];
if (img != NULL)
{
fclose(img);
i++;
sprintf(filename, "%03i.jpg",i);
img = fopen(filename, "w");
fwrite(buffer, 512 , 1, img);
}
else
{
sprintf(filename, "%03i.jpg",i);
img = fopen(filename, "w");
//error in the line below :(
fwrite(buffer, 512 , 1, img);
}
}
else if (i > 0)
{
fwrite(buffer, 512 , 1, img);
}
}
fclose(img);
fclose(f);
}
It looks like the most likely failure reason for that line you call out, is that the file handle could be invalid. Hence the first thing I would be doing is checking that every file opens correctly, something like:
img = fopen(filename, "w");
if (img == NULL) {
printf("Error opening file '%s'\n", filename);
exit(1);
}
It's generally a good idea to check for failure conditions in functions than can fail, and this also includes the fwrite calls:
if (fwrite(buffer, 512 , 1, img) != 1) {
printf("Error writing to file\n");
exit(1);
}

Resources