I'm working on the recover program of the CS50 course. Here are the instructions:
Implement your program in a file called recover.c in a directory called recover.
Your program should accept exactly one command-line argument, the name of a forensic image from which to recover JPEGs.
If your program is not executed with exactly one command-line argument, it should remind the user of correct usage, and main should
return 1.
If the forensic image cannot be opened for reading, your program should inform the user as much, and main should return 1.
Your program, if it uses malloc, must not leak any memory.
I think my code is supposed to work, but it doesn't. In fact, it doesn't output any images at all! Here's the code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE * pFile = NULL;
unsigned char *buffer = malloc(512);
char* filename = NULL;
int filenumber = 0;
//If user didn't print 2 items
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
//Open the file
pFile = fopen(argv[1], "r");
if (!pFile)
{
fprintf(stderr, "File cannot be opened\n");
return 2;
}
int j=0;
// checking the card by 512b chunks
//loop (i=0, i++);
while (pFile)
{
int i =0;
i++;
//k=fread (buffer, 512, i, *file);
int k = fread(buffer, 512, i, pFile);
// if 512 byte block is jpeg, make new jpeg file
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if it's not the first file, we should close the last one
if (filename != NULL)
{
fclose(pFile);
}
//sprintf
sprintf(filename, "%03i.jpg", 2);
//FILE = fopen (W)
pFile = fopen(filename, "w");
// fwrite (buffer, 512, j, *file1)
fwrite (buffer, 512, j, pFile);
//j=j+1
j = j + 1;
}
// if k<512 - end of the loop
if (k < 512)
{
return 0;
}
}
free(buffer);
}
I don't understand it, but I see no new files or JPEGs pop-up in my files. When I try to double-click on the file, which is called card.raw, it doesn't let me open it.
You have a load of problems. Running your code in a debugger should reveal most of them within a second.
Let's take a look:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE * pFile = NULL;
unsigned char *buffer = malloc(512);
char* filename = NULL; <<==== You never allocate any memory for this. Use an array.
int filenumber = 0;
//If user didn't print 2 items
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
//Open the file
pFile = fopen(argv[1], "r");
if (!pFile)
{
fprintf(stderr, "File cannot be opened\n");
return 2;
}
int j=0;
// checking the card by 512b chunks
//loop (i=0, i++); <<== No information provided by this comment.
while (pFile) <<== pFile is your input file. This should never change. ???
{
int i =0;
i++;
//k=fread (buffer, 512, i, *file); <<== Useless comment. Nearly same as code below but causes compiler error
int k = fread(buffer, 512, i, pFile); <<== i is always 1 and must be 1. Don't use variable.
<<== BTW: You should check k **before** using the buffer.
// if 512 byte block is jpeg, make new jpeg file
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if it's not the first file, we should close the last one
if (filename != NULL)
{
fclose(pFile); <<== Yikes!!! This is your input file.
}
//sprintf <<== Yes, that's obvious. Useless comment.
sprintf(filename, "%03i.jpg", 2); <<== Yikes!! You never allocate memory. NULL pointer!!
<<== Why do you always print 2? you have a counter.
//FILE = fopen (W) <<== Again no useful information in comment
pFile = fopen(filename, "w"); <<== Feed NULL into fopen and kill pFile.
// fwrite (buffer, 512, j, *file1) <<== you know what I mean...
fwrite (buffer, 512, j, pFile); <<== You only have 1 buffer, why write j blocks?
//j=j+1 <<== obvious
j = j + 1;
}
// if k<512 - end of the loop
if (k < 512) <<== fread returns number of elements, i.e. 1, not number of bytes.
{
<< you return without
- closing files
- freeing buffer
return 0;
}
<<== Now you go back to top of the loop and want to read next block from your raw file but pFile was killed in the loop.
}
free(buffer);
}
Related
I'm writing this code to be able to recover(JPEGs_ memory from a memory card that has deleted them.
My code compiles and is able to run; however, the output images never load.
I tried doing debugging, but I can't seem to see what the issue could be.
Perhaps some pointers on how to debug code that only appears to indicate a problem after the code has produced an output would be useful. (if this indeed is what I am missing)
What is there that I could be missing?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
const int BLOCKSIZE = 512;
FILE *img = NULL;
int main(int argc, char *argv[])
{
//Check if there is only 1 argument entered
if (argc != 2)
{
printf("Usage: ./recover ###.jpg\n");
return 1;
}
//open memorry card and ensure that it's readable
FILE *raw_memory = fopen(argv[1], "r");
if (raw_memory == NULL)
{
printf("Could not open file\n");
return 2;
}
//Repeat until the end of card:
uint8_t *buffer = malloc(BLOCKSIZE);
int jpg_counter = 0;
bool jpg_found = false;
while (true) //Read 512 bytes into a buffer
{
size_t bytes_read = fread (buffer, 1, BLOCKSIZE, raw_memory);
// If end of raw_memory reached, exit loop
if (bytes_read < BLOCKSIZE)
{
break;
}
// If start of new JPG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
//Open new raw_memory and start writing
//If first JPG raw_memory
if (jpg_counter == 0)
{
//Open new raw_memory and start writing
char str[100];
sprintf(str, "%03i.jpg", jpg_counter);
img = fopen(str, "w");
if (img == NULL)
{
printf("Could not open jpeg file\n");
return 3;
}
fwrite(buffer, sizeof(buffer), 1, img);
jpg_counter++;
jpg_found = true;
}
else //close previously file and open a new one
{
fclose(img);
jpg_found = false;
char str[100];
sprintf(str, "%03i.jpg", jpg_counter);
img = fopen(str, "w");
if (img == NULL)
{
printf("Could not open jpeg file\n");
return 4;
}
fwrite(buffer, sizeof(buffer), 1, img);
jpg_found = true;
jpg_counter++;
}
}
else
{
if (jpg_found)
{
fwrite(buffer, sizeof(buffer), 1, img);
}
}
}
fclose(img);
fclose(raw_memory);
free(buffer);
}
A) Since you need 512 elements, instead of uint8_t *buffer = malloc(BLOCKSIZE); do at global level
uint8_t tmp[BLOCKSIZE];
uint8_t *buffer = &tmp[0];
B) Instead of fread (buffer, 1, BLOCKSIZE, raw_memory); do fread(buffer, sizeof(uint8_t), BLOCKSIZE, raw_memory); The same applies for fwrite(buffer, sizeof(buffer), 1, img); to fwrite(buffer, sizeof(uint8_t), BLOCKSIZE, img); This per documentation https://manual.cs50.io/3/fwrite
C) I think that many problems arise from the design of what is inside of this if statement (line 45)
// If start of new JPG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
//Open new raw_memory and start writing
//If first JPG raw_memory
if (jpg_counter == 0)
{
Try:
Changing if (jpg_counter == 0) for if (jpg_counter > 0) simplifying the if statements so only if there are already photo files you can close them, no else.
Getting rid of char str[100]; Instead try char str[8]; since 000.jpg is 7 chars long + '\0'.
You don't need jpg_found = false; on line 70, since that var is only useful before finding the first image.
Hope that's useful...
Edit 1: since buffer needs to be a pointer in fread and fwrite of BlOCKSIZE times the type, better that buffer points to an uint8_t array of size BLOCKSIZE, instead of using malloc.
Edit 2: Thus, no further need of free(buffer);
buffer is a pointer, so sizeof(buffer) is the size of a pointer, not the number of bytes in the buffer. If you declare the buffer as an array uint8_t buffer[BLOCKSIZE]; then the malloc and free aren't needed, and sizeof(buffer) will work as expected
Replacing sizeofbuffer with BLOCKSIZE should allocate enough bytes for the code to work
(credit: #user3386109)
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;
}
}
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);
I am doing a problem set provided by Harvard's online lecture.
I've finally made a solution to recover a set of JPEG images from a file (card.raw).
It seems like the code itself does not throw errors, but it is returning distorted image and I am a little clueless to why it might be happening.
[Link to an image example] https://prnt.sc/q0tb4f
Here's my code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
//check usage
if (argc != 2)
{
return 1;
}
// open file
FILE* input = fopen(argv[1], "r");
// return error if file does not existS
if (!input)
{
return 1;
printf("file does not exists");
}
// create an array with 512 bytess of bytes
unsigned char bytes[512];
// create count variable
int count = 0;
// create an empty string for filename
char filename[7];
// create an empty output file
FILE* output = NULL;
// repeat until end of input
while (fread(bytes, 1, sizeof(bytes), input) != 0)
{
// read 1 block of 512 bytes at a time
fread(bytes, 1, sizeof(bytes), input);
// check if beginning of jpeg file
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0)
{
// if already found a jpeg, close the file
if (count > 0)
{
fclose(output);
}
// name file
sprintf(filename, "%03i.jpg", count);
// open file
output = fopen(filename, "w");
// write file
fwrite(bytes, 1, sizeof(bytes), output);
// increment count
count++;
}
if (output != NULL)
{
// keep writing if jpeg header is already found
fwrite(bytes, 1, sizeof(bytes), output);
}
}
fclose(output);
fclose(input);
}
My uneducated assumption is unable to see why it might be happening.
I can only imagine that this might be happening from opening and closing files in improper step.
This is the problem:
while (fread(bytes, 1, sizeof(bytes), input) != 0)
{
// read 1 block of 512 bytes at a time
fread(bytes, 1, sizeof(bytes), input);
You're calling fread twice per loop. As a result, the body of the loop only sees the odd-numbered blocks. Remove the second fread.
A second problem (as #SteveFriedl points out) is that the buffer the code uses for the filename is too small.
char filename[7];
sprintf(filename, "%03i.jpg", count);
You need at least 8 bytes for a file name like "123.jpg", because you need room for the NUL terminator. However, note that
"%03i" uses at least 3 characters. It could use more, e.g. if count reaches 1000. So I would declare the buffer as char filename[32]; to avoid any chance of buffer overflow.
You've also got two fwrites when only one is needed:
output = fopen(filename, "w");
// write file
fwrite(bytes, 1, sizeof(bytes), output);
// increment count
count++;
}
if (output != NULL)
{
// keep writing if jpeg header is already found
fwrite(bytes, 1, sizeof(bytes), output);
}
After opening a new file, the code writes the first block, and then writes it again. Remove the first fwrite and let the second fwrite take care of the first block.
Another problem is that the code makes an implicit assumption that if fread doesn't return 0, then it's read a full block. That assumption is OK if the file size is a multiple of the block size, but it's better not to make any assumptions. So the condition in the while loop should be
while (fread(bytes, 1, sizeof(bytes), input) == sizeof(bytes))
here is recover working.
#include <stdio.h>
#include <stdlib.h>
int isAJpg(unsigned char bytes[]);
int main(int argc, char *argv[])
{
if (argc != 2)
{
return 1;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
return 1;
}
char filename[10];
int count = 0;
unsigned char bytes[512];
FILE *output;
int jpgfound = 0;
while (fread(bytes, 512, 1, file) != 0)
{
// if it is a jpg
if (isAJpg(bytes) == 1)
{
if (jpgfound == 1)
{
fclose(output);
}
else
{
jpgfound = 1;
}
// name file
sprintf(filename, "%03d.jpg", count);
// open file
output = fopen(filename, "a");
count++;
}
if (jpgfound == 1)
{
// writes to a file
fwrite(&bytes, 512, 1, output);
}
}
//close the files
fclose(output);
fclose(file);
}
// check in it is a jpg
int isAJpg(unsigned char bytes[])
{
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0)
{
return 1;
}
return 0;
}
I am trying to scan a file looking for 1MB JPEGs that would be stored contiguously. My approach is create a structure to match the first 4 bytes with the JPEG signature and, if true, write the entire 512 buffer to a named file until I find another jpeg signature then I create a new file. The code below creates 2 files, neither of which are readable as the first few bytes are not part of the jpeg signature. Any ideas where I went wrong? I tried variations of my if statement where I test for the signature but no luck thus far.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
typedef struct
{
BYTE first;
BYTE second;
BYTE third;
BYTE fourth;
}
JPGTEST;
int main(int argc, char* argv[])
{
FILE* inptr = fopen("card.raw", "r");
if (inptr == NULL)
{
printf("Could not open file\n");
return 2;
}
FILE* outptr;
//initialize jpeg count and variable for filename
int count = 0;
char name[8];
//allocate memory
char buffer[512];
JPGTEST myjpg;
int is_open = 0;
while (fread(&buffer, 512, 1, inptr) != 0)
{
//test first 4 bytes to see if jpeg
fread(&myjpg, sizeof(JPGTEST), 1, inptr);
//if match, name and write to file
if (myjpg.first == 0xff && myjpg.second == 0xd8 && myjpg.third == 0xff && (myjpg.fourth == 0xe0 || myjpg.fourth == 0xe1))
{
sprintf(name, "%03d.jpg", count);
if (is_open == 0)
{
outptr = fopen(name, "w");
fwrite(buffer, sizeof(buffer),1,outptr);
is_open = 1;
}
if (is_open == 1)
{
fclose(outptr);
outptr = fopen(name, "w");
fwrite(buffer, sizeof(buffer),1,outptr);
count++;
}
}
else
{
if (is_open == 1)
{
fwrite(buffer, sizeof(buffer),1,outptr);
}
}
}
fclose(inptr);
fclose(outptr);
return 0;
}
You are opening the files in text mode. You need to open them in binary mode instead:
FILE* inptr = fopen("card.raw", "rb");
outptr = fopen(name, "wb");
Aside from that, you are calling fread() too many times, and just generally not managing the files correctly.
Try something more this instead:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
#pragma pack(push, 1)
typedef struct
{
BYTE first;
BYTE second;
BYTE third;
BYTE fourth;
}
JPGTEST;
#pragma pack(pop)
int main(int argc, char* argv[])
{
FILE* inptr = fopen("card.raw", "rb");
if (inptr == NULL)
{
printf("Could not open file\n");
return 2;
}
FILE* outptr = NULL;
//initialize jpeg count and variable for filename
int count = 0;
char name[8];
//allocate memory
char buffer[512];
JPGTEST myjpg;
while (fread(buffer, sizeof(buffer), 1, inptr) > 0)
{
//test first 4 bytes to see if jpeg
memcpy(&myjpg, buffer, sizeof(JPGTEST));
//if match, name and write to file
if ((myjpg.first == 0xff) && (myjpg.second == 0xd8) && (myjpg.third == 0xff) && ((myjpg.fourth == 0xe0) || (myjpg.fourth == 0xe1)))
{
if (outptr != NULL)
{
fclose(outptr);
outptr = NULL;
}
++count;
sprintf(name, "%03d.jpg", count);
outptr = fopen(name, "wb");
}
if (outptr != NULL)
fwrite(buffer, sizeof(buffer), 1, outptr);
}
fclose(inptr);
if (outptr != NULL)
fclose(outptr);
return 0;
}
Replace your second fread inside the loop with the below:
memcpy((void *)&myjpg, (void *) buffer, sizeof(JPGTEST));
And include string.h header file in your code for memcpy function.
What you are doing wrong is that after reading first 512 you are not making any use of them rather you are again reading 4 bytes without checking first 4 bytes of previously read 512 bytes.
The problem is you are not resetting the file position indicator after you read into buffer, to do so use, fseek. I.e.:
//test first 4 bytes to see if jpeg
fseek (inptr, SEEK_SET, 0);
fread(&myjpg, sizeof(JPGTEST), 1, inptr);
That will provide you with a test of the jpg header in myjpg:
sizeof (myjpg): 4
first: ff second: d8 third ff fourth: e0
However, that will also cause logic issues you will have to rework. It is better to simply read the values from buffer as suggested by the other answer.
You can do something like the following to simplify your signature comparisons:
#include ...
#define JPEG_SIGNATURE 0xFFD8
void
reverse_bytes (void const *data, long unsigned size)
{
char *ptr = (char *)data;
int i = 0;
while (i < size / 2)
{
char temp = ptr[i];
ptr[i] = ptr[size - i - 1];
ptr[size - i - 1] = temp;
i++;
}
}
int
main()
{
FILE *fptr = fopen("path/to/image.jpeg", "rb");
short bytes = 0;
fread(&bytes, sizeof(char), sizeof(bytes), fptr);
reverse_bytes(bytes, sizeof(bytes)); // Refer to [1]
switch (bytes)
{
case JPEG_SIGNATURE:
printf("JPEG image!");
break;
default:
printf("Unknown format!");
break;
}
return 0;
}
This can be extended to many different formats by adding more cases in the switch statement and a little more work.
This is indeed not a full or proper answer but, I hope it is helpful for others who come through this post!
NOTE: I omitted things like exception handling for brevity!
References:
Why is Fread reading unsigned-int in reverse order?