cfile-iojpegeoffat32

Reaching EOF before end of file on windows


#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.


Solution

  • 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.