Reaching EOF before end of file on windows - c

#include <stdio.h>
#include <stdlib.h>
const int size = 512;
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: ./recover image\n");
return 1;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
fprintf(stderr, "Could not open file\n");
return 1;
}
unsigned char buffer[size];
int count = 0;
FILE *jpeg = NULL;
while(fread(buffer, size, 1, file))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
char image[7];
if (count != 0)
{
fclose(jpeg);
}
sprintf(image, "%03i.jpg", count);
jpeg = fopen(image, "w");
if (jpeg == NULL)
{
fprintf(stderr, "couldn't open file\n");
return 1;
}
count++;
}
if (count != 0)
{
fwrite(&buffer, size, 1, jpeg);
}
}
fclose(file);
}
This code look for jpeg in card.raw When i run above code on linux, its running correctly. but on windows code reads only first three block of 512 bytes of card.raw file.
what i'm doing wrong?
also i'm using clang on linux. and on windows i'm using gcc.

Firstly, binary files should be opened with binary mode. This means you should use "rb" and "wb" for fopen() mode instead of "r" and "w". Otherwise, newline characters may be unwantedly converted and they may stop at byte 0x1a.
Secondly, doing sprintf(image, "%03i.jpg", count); for the array char image[7]; is bad. The result of sprintf() will be (at least) 7 characters, so array with 8 elements or more is required to store the string including terminating null-character. for safety, you should use snprintf(), which accepts the buffer size.

Related

C recover compiles but return null for the files read

Trying to solve this problem i keep finding the same errors:
:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:( recovers 000.jpg correctly
000.jpg not found
:( recovers middle images correctly
001.jpg not found
:( recovers 049.jpg correctly
049.jpg not found
That makes me think that the files are not been read or opened at all and i can't find why because the code compiles.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main(int argc, char* argv[])
{
//checks if there is an input
if (argc != 2)
{
printf("./recover Usage: ./recover image \n");
return 1;
}
else
{
char* filename = argv[1];
FILE* input = fopen(filename, "r");
if (strcmp(filename, "card.raw") != 0)
{
printf("Unable to open: %s\n", filename);
return 2;
}
else
{
//Create buffer
uint8_t buffer[512];
//Create pointer for the buffer
FILE* output = NULL;
// create 8 bytes file
char files[8];
//Files counters
int jpeg_counter = 0;
//Check
while (fread(buffer, sizeof(buffer), 1, input))
{
//check 4 first bytes of file to see if they contain the jpg signature
if ((buffer[0] == 0xff) && (buffer[1] == 0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0))
{
if (output != NULL) {
// sprintf(char *str, const char *format, ...) and "03i" means 3 digits in format 001, 002...
sprintf(files, "%03i.jpg", jpeg_counter);
//use created pointer to save jpeg files from input folder card.raw
output = fopen(filename, "w");
//add jpeg to the new buffer using ouput pointer
fwrite(buffer, sizeof(buffer), 1, output);
// update counter
jpeg_counter++;
}
else //no more files to read(end of folder array) - or no images found.
{
printf("Could not open file\n");
return 0;
}
}
}
fclose(output);
fclose(input);
return 0;
}
}
}
Here is another attempt at a solution, however, it only writes out the first 512 bytes (unlike the original) but I don't think jpeg uses 512 bytes fixed chunks so neither the op or or #BarmakShemirani solution would work as expected. (buffer[3] & 0xf0) == 0xe0 means variable sized, application specific and there is a reference that data is laid out like TIFF, In either case op did not share card.raw so whatever format is used would be speculation:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME_LEN 8
int main(int argc, char* argv[]) {
int r = 0;
FILE *input = NULL;
if (argc != 2) {
printf("./recover Usage: ./recover image \n");
r = 1;
goto out;
}
char *filename = argv[1];
input = fopen(filename, "rb");
if (!strcmp(filename, "card.raw")) {
printf("Unable to open: %s\n", filename);
r = 2;
goto out;
}
for(int jpeg_counter = 0; !r; jpeg_counter++) {
uint8_t buffer[512];
size_t n = fread(buffer, sizeof(buffer), 1, input);
// use an existing library instead?
if(
n < 4 ||
buffer[0] != 0xff ||
buffer[1] != 0xd8 ||
buffer[2] != 0xff ||
(buffer[3] & 0xf0) != 0xe0
) {
printf("invalid header\n");
r = 3;
break;
}
char filename2[FILENAME_LEN];
if(snprintf(filename2, FILENAME_LEN, "%03i.jpg", jpeg_counter) >= FILENAME_LEN) {
printf("%s: output filename truncated", filename);
r = 4;
break;
};
FILE *output = fopen(filename2, "wb");
if(!output) {
printf("%s: fopen failed\n", filename);
r = 5;
break;
}
// TBD: replace with a loop once we figure out
// how a given file is terminated.
if(fwrite(buffer, n, 1, output) != n) {
printf("%s: write failed\n", filename);
r = 6;
}
fclose(output);
}
out:
if(input) fclose(input);
return r;
}
uint8_t buffer[512];
fread(buffer, sizeof(buffer), 1, input)
This should be change to: fread(buffer, 1, sizeof(buffer), input). This way fread will read up to 512 bytes. When it gets to the end of file, it reads whatever is left, for example 1 byte, and returns that number. Likewise, fwrite should change. It should write the same number which was read earlier.
Open the file in binary mode.
If fopen fails then stop immediately.
Check the file header only once, not every read loop.
Your condition for checking the file header may have a typo (buffer[3] & 0xf0) == 0xe0. Checking the first 3 bytes should be okay.
int main()
{
FILE* input = fopen("input.jpg", "rb");
if (!input)
{ perror("input error"); return 0; }
FILE* output = fopen("output.jpg", "wb");
if (!output)
{ perror("output error"); fclose(input); return 0; }
uint8_t buf[1000];
int check_header = 1;
while (1)
{
size_t read_count = fread(buf, 1, sizeof(buf), input);
if (!read_count)
break;
if (check_header)
{
if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff)
// && buf[3] == 0xe0 ?
{ printf("header is okay\n"); }
else
{ printf("not okay\n"); break; }
check_header = 0; //don't check header again
}
fwrite(buf, 1, read_count, output);
}
fclose(input);
fclose(output);
return 0;
}
Thanks for the help. Tried those and got the same error. What surprisingly worked for me was to refactor even more the code and give use of the counter for the if conditions as shown below.
int main(int argc, char* argv[])
{
//checks if there is an input
if (argc != 2)
{
printf(".Usage: Looking for card.raw \n");
return 1;
}
else
{
char* filename = argv[1];
FILE* input;
input = fopen(filename, "r");
//to track if it fails to open
if (input == NULL)
{
printf("Could not open file");
return 2;
}
//Create buffer. Unsigned int variable type. Array of 512 bytes
uint8_t buffer[512];
//Create pointer for the buffer.
FILE* output = NULL;
// create 8 bytes file
char files[8];
//Files counters
int jpeg_counter = 0;
//Check
while (fread(buffer, sizeof(buffer), 1, input))
{
//check 4 first bytes of file to see if they contain the jpg signature
if ((buffer[0] == 0xff) && (buffer[1] == 0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0))
{
if (jpeg_counter != 0)
{
fclose(output);
}
// sprintf(char *str, const char *format, ...) and "03i" means 3 digits in format 001, 002...
sprintf(files, "%03i.jpg", jpeg_counter);
//use created pointer to save jpeg files from input folder card.raw
output = fopen(files, "w");
//add jpeg to the new buffer using ouput pointer
fwrite(buffer, sizeof(buffer), 1, output);
// update counter
jpeg_counter++;
} else if (jpeg_counter != 0)
{
fwrite(buffer, sizeof(buffer), 1, output);
}
}
fclose(output);
return 0;
}
}

Why fread() throwing the 'segmentation fault' in this code

The program is to check raw file and identify jpg files. also raw file is formatted as FAT and therefore I must check it as 512 Byte chunks.
I made (?) 512 Bytes memory space with BYTE fats[512]; and used is in fread() as target memory slot, but in this process it throwing 'segmentation fault' error.
#include <stdio.h>
#include <stdlib.h>
#include <string.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 *dmgdFile = fopen(argv[1], "rb");
if (dmgdFile == NULL)
{
printf("Could not open file.\n");
return 1;
}
char name[7];
int counter = 0;
int discovered = 0;
FILE *outptr;
BYTE fats[512];
sprintf(name, "%03d.jpg", discovered);//name regeneration
while (fread(&fats, sizeof(fats), 1, dmgdFile)){
if (
discovered > 0 && //DISCOVERED ANOTHER JPG
fats[0] == 0xff &&
fats[1] == 0xd8 &&
fats[2] == 0xff &&
fats[3] >= 0xe0 && fats[3] <= 0xef) {
printf("repeated discovery");
fclose(outptr);
sprintf(name, "%03d.jpg", discovered);//name regeneration
outptr = fopen(name, "w"); //create next jpg file and open pointer
if (outptr == NULL)
{
fclose(dmgdFile);
fprintf(stderr, "Could not create %s.\n", name);
return 5;
}
counter ++;
discovered ++;
} else if(discovered > 0){ //ADDING JPG BODY TO PREVIOUS OPENED FILE
printf("body");
fwrite(fats, sizeof(fats), 1, outptr);
counter ++;
}else if (
discovered == 0 && //FIRST TIME DISCOVERING JPG HEADER
fats[0] == 0xff &&
fats[1] == 0xd8 &&
fats[2] == 0xff &&
fats[3] >= 0xe0 && fats[3] <= 0xef) {
printf("1st time discovered");
outptr = fopen(name, "w");
if (outptr == NULL)
{
fclose(dmgdFile);
fprintf(stderr, "Could not create %s.\n", name);
return 5;
}
fwrite(fats, sizeof(fats), 1, outptr);
counter ++;
discovered ++;
}
}
fclose(dmgdFile);
}
I tried fats with and without '&' in 'fread()' but it didn't helped.
sprintf(name, "%03d.jpg", discovered);
will write a string with at least 7 charactes to name, but the array name has only 7 elements. This will lead to out-of-range access, considering the terminating null-character. It looks like this out-of-range access broke the file pointer and lead to Segmentation Fault.
Allocate enough element and use snprintf() to avoid buffer overrun like this:
char name[32];
snprintf(name, sizeof(name), "%03d.jpg", discovered);

How can I properly print the bytes of a JPEG file? - CS50 PSET3 Recover

I am trying to use fread on a file containing multiple JPEGs and write the JPEGs into new files, but before I can do that I need to properly look through the file and look for the JPEGs based on their first bytes based on the if statement at the bottom of the code below.
I have not been able to get into the if statement, and have been trying to print out the bytes, but I have been running into issues in printing.
I'm looking to print just the 0 byte of the buffer, but my output is looking like this:
711151a6
cec117f0
7603c9a9
73599166
I'm very new to C and fread, and any help would be appreciated!
Code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// Check for 2 arguments, the name of the program and the file being read
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
else
{
//Open the file
FILE * fp;
fp = fopen(argv[1], "r");
//Get file length
fseek(fp, 0, SEEK_END);
int f_length = ftell(fp);
fseek(fp, 0, SEEK_SET);
// If not file is found then exit
if(fp == NULL)
{
printf("File not found\n");
return 2;
}
// Allocate buffer for fread function
int *buffer = (int*)malloc(f_length);
if (buffer == NULL)
{
printf("Buffer is null\n");
return 1;
}
// Read thorugh the file
while(fread(buffer, 512, 1, fp) == 1)
{
for (int i = 0; i < 1; i++)
{
printf("%x\n", buffer[i]);
}
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
printf("Found a jpg\n");
}
}
// Exit the program
return 0;
}
}
int *buffer is not correct because the intention is to deal with bytes and not ints. If int * is used, then for example, buffer[0] will be the first 4 bytes and not the first byte as intended. Change that to unsigned char *buffer.
So explicitly, that line should be the following (including removing the unnecessary cast):
unsigned char *buffer = malloc(f_length);

c's sprintf altering my counter

I'm working on an assignment for CS50 but i have a strange behaviour of a counter variable after running sprintf function:
//recover jpg files from memory
#include <stdio.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Please submit an input file\n");
return 1;
}
// remember filename
char *infile = argv[1];
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
// define the buffer as array of BYTEs
BYTE buffer[512];
// define the counter of images found
int counter = 0;
// declare the array for the filename
char filename[3];
while (fread(buffer, 512, 1, inptr)>0)
{
if (buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0)
{
sprintf(filename, "%03i.jpg", counter);
printf("%c%c%c\n", filename[0],filename[1],filename[2]);
counter++;
}
}
}
I tried the debug50 tool and i saw that after running fprintf variable counter passes from 0 to a big strange number.
Any suggestions on where is the problem and how to fix it?
Thanks to the comments I got the error:
I forgot to consider the right length of 'filename' variable, and when running sprintf i was exceeding the memory allowed for it

CS-50 pset4 recover: Why getting segmentation fault?

It's a solution of CS50-pset4 recover. But why I am getting segmentation fault?
I tried to not access any NULL pointer ar any uninitialized file, but can't figure the way out.
The intent was to copy block of 512B memory from a given file to another if it matches the condition of being a jpeg file. And it is assumed that the jpeg files are stored in a contiguous memory location.
$
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Usage: copy infile outfile\n");
return 1;
}
// remember filename
char *infile = argv[1];
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
FILE *img = NULL;
unsigned char buffer[512] = {0};
//char *jpgname = NULL;
string jpegname = "";
int jpegnum = 0; // for keep track of jpeg no.
//sprintf(jpgname, "%03d.jpg", jpegnum+1);
//jpegnum += 1;
while (fread(buffer, 512, 1, inptr) == 1)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff &&
((buffer[3] & 0xf0) == 0xe0))
{
if (jpegnum > 0) // if there exist a jpeg file, it should close first
{
fclose(img);
}
sprintf(jpegname, "%03d.jpg", (jpegnum+1));
jpegnum += 1;
img = fopen(jpegname, "w");
//fwrite(buffer, 512, 1, img);
}
else if (jpegnum == 0)
{
continue;
}
fwrite(buffer, 512, 1, img);
}
fclose(img);
fclose(inptr);
return 0;
}
$
A string literal "" is assigned to jpegname and it is passed to sprintf().
This is bad because
Modifying string literals is forbidden.
Even if modifying were allowed, "" has only 1 element (for the terminating null character) and it won't be enough for saving the filename.
Try using
char jpegname[512] = "";
instead of
string jpegname = "";
This change will give modifiable 512-byte buffer to jpegname, which will be enough for the filename.
Also note that passing img, whose value is NULL, to fclose() should be bad.

Resources