0

My code compiles and saves 50 JPG images with proper names, but when I try to open any one of them, I get the 'Invalid or Unsupported Image Format' error. What I'm doing wrong?

Here is pseudo-code:

- try to read 512 bytes from memory card
  - failure: 
    - exit
  - success: 
    - check first four bytes
        - not JPG's first four
          - output file already opened?
            - no: 
              - go to start (read next 512 bytes)
            - yes:
              - write to that file
        - JPG's first four:
          - output file already opened?
            - no: 
              - open new 
              - write to file
              - go to start
            - yes: 
              - close already opened output file
              - open new file
              - write to file
              - go to start

Here is actual code:

// recovers 'deleted' JPEGs from memory card

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// generate new file name
char *fileName(int i)
{
    char *filenamePointer = malloc(7);
    sprintf(filenamePointer, "%03i.jpg", i);
    return filenamePointer;
}

// open file
FILE *openNewFile(int i)
{
    return fopen(fileName(i), "w");
}

int main(int argc, char *argv[])
{
    // ensure proper usage
    if (argc != 2)
    {
        fprintf(stderr, "Provide a path to forensic image.\n");
        return 1;
    }

    char *infile = argv[1];

    // open input file
    FILE *inPointer = fopen(infile, "r");
    if (inPointer == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 2;
    }

    unsigned char buffer[512];
    // char *newFile;
    int i = -1;
    int number;

    do
    {
        number = fread(buffer, 1, 512, inPointer); // ucitava u buffer 512 bajtova iz inPointera

        // check first 4 bytes
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
        {
            // already opened?
            FILE *newFilePointer = fopen(fileName(i), "r"); // kreira outFile pointer
            if (newFilePointer != NULL) // ako ne moze da ga otvori, to znaci da fajl nije kreiran
            {
                // yes:
                // close file
                fclose(newFilePointer); // zatvara fajl
                // open new file;
                i++;
                newFilePointer = openNewFile(i); // kreira n
            }
            else
            {
                // no:
                // open new file
                i++;
                newFilePointer = openNewFile(i);
            }
            // write to outputFile
            fwrite(inPointer, 1, number, newFilePointer);
        }
        else
        {
            // alredy opened?
            FILE *newFilePointer = fopen(fileName(i), "r");
            if (newFilePointer != NULL)
            {
                // yes:
                // write to outputFile
                fwrite(inPointer, 1, number, newFilePointer);
            }
                // no:
                // next read
        }
    } while (number == 512);

    fclose(inPointer);
    return 0;
}
2

In fwrite(inPointer, 1, number, newFilePointer);, inPointer should be buffer, you don't want to write the content of the FILE structure to disk, but the bytes you read.

Interesting part is - your pseudo code looks fine, nothing like your actual code.

I don't get why you are fopening output files for reading text "r" instead of only writing binary "wb". Operating systems might (but don't have to) silently convert line breaks when using text mode, mentioning b suppresses that behaviour, as we don't deal with text.

You seem to call fopen more times than fclose, leaving open files everywhere. You could greatly reduce these calls if you declared the output file handle variable outside of the loop, and had it fclose on finding next header or after the loop. Also, a regular while rather than do..while might do better, you can even include the fread in the condition, like while (fread(buffer, 1, 512, inPointer) == 512), or while ((number = fread(buffer, 1, 512, inPointer)) > 0), or similar. With that, there's no need to enter the loop body if nothing could be read.

A string of 7 characters needs 8 bytes, don't forget the null terminator. Also, you seem to malloc memory you never free.

  • Thank you for your detailed answer! I resolved all issues you've pointed out (buffer variable, wb mode instead of r, closing file after finding start of a new jpg and outside of the loop, extracting condition outside of the loop, freeing memory after malloc) but i still have problem. All JPGs are created, but they are blank, just grid. When I run 'check50', I get segmentation fault error. Any other suggestion? – 11223342124 Nov 10 '18 at 14:59
  • Do you have a link to your current code? – Blauelf Nov 10 '18 at 23:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .