1

I changed the code from the first time I asked this question, so I decided to make a new thread. Sorry if this is not a good idea.

Anyway, I'm still getting a Seg fault here.

And even if that weren't the case, I do have trouble figuring out how to check for when the current JPEG ends and the next one starts. I do know what bytes can potentially be used in the signature of a JPEG, and I also know that they're stored contiguously in a CF card. But I'm not really sure how to check for it. I was thinking of making an array to store the four bytes after each 512 minus 4 bytes and checking if the bytes in the array represent the signature of a JPEG. But I'll need to see how to write that in actual code as right now it's just in my head and I'm having trouble figuring out how to express it in code. Like, for instance, if the buffer of 512 bytes from the card.raw file that I'm reading into each time through the loop is an array of uint8_t called "buffer," do I add the first four bytes from that into an array and check if it's the right signature, and if it is, I look at the next 512th byte after that and the next three bytes after it? But will the cursor move if I do that, or will I not have to worry about that?

Here's the updated code:

/**
 * recover.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Recovers JPEGs from a forensic image.
 */

/**
 * psuedo code
* open card file
*  repeat until end of file
*   read 512 bytes into a buffer
*   start of a new jpg?
*       yes -->
*       no  -->
*   already found a jpg?
*       no  -->
*       yes -->
* close last jpg
* close card file
*/

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

typedef uint8_t BYTE;

int main()
{
    // open card file
    FILE* infile = fopen("card.raw", "r");

    // test if it was properly opened
    if (infile == NULL)
    {
        printf("Could not open %s.\n", "card.raw");
        return 1;
    }

    // create a string variable used 
    // when opening output file to write jpeg
    char* title = malloc(8);

    // create a boolean variable for checking 
    // if a new jpeg was found
    int newimg = 1;

    // buffer array to store being read or written
   BYTE* buffer = malloc(512);

    int img_number = 0;

    // create file pointer to store
    // to represent output file
    FILE* img;

    // repeat until end of file
    while (!feof(infile) && fread(&buffer, 512, 1, infile) == 1)
    {
        // in this if and
        // in the one nested in it
        // check if a new jpeg is found
        // and check if it's really
        // a jpeg
        if (newimg)
        {
            if (buffer[0] == 0xff && buffer[1] == 0xf8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 || buffer[3] <= 0xef))
            {
                // yes
                // found jpeg
                // reset boolean
                newimg = 0;

                // write the name of the jpeg to output file
                sprintf(title, "%3d.jpg", img_number);

                // open file and write jpeg img data to it
                img = fopen(title, "a");
                fwrite(&buffer, 512, 1, img);
            }
        }
        // checking if a jpeg was already found
        else
        {
            // yes
            if (buffer[0] == 0xff && buffer[1] == 0xf8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 || buffer[3] <= 0xef))
            {   
                // close the output file to stop reading into it
                fclose(img);

                // update img_number variable
                // so that the next image's file name
                // has one number greater in it as part of the
                // file name
                img_number++;

                // write the name of the jpeg to the output file
                // with the update number from img_number
                sprintf(title, "%3d.jpg", img_number);

                // open a new file to store the next jpeg
                img = fopen(title, "a");

                // write the data to the new file
                fwrite(&buffer, 512, 1, img);
            }
            // no
            else
            {
                // keep writing to current jpeg
                // because we haven't found a new
                // jpeg yet
                fwrite(&buffer, 512, 1, img);
            }
        }
    }

    // no more sets of 512 bytes left to read
    // close last jpg file
    fclose(img);
    // close card.raw
    fclose(infile);

    free(buffer);
    free(title);
    return 0;
}

Also, how do I fix the way I'm formatting the filename for the JPEGs, if it's currently incorrect?

Edit: I'm editing this to add the newly updated code.

/**
 * recover.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Recovers JPEGs from a forensic image.
 */

/**
 * psuedo code
 * open card file
 *  repeat until end of file
 *   read 512 bytes into a buffer
 *   start of a new jpg?
 *       yes -->
 *       no  -->
 *   already found a jpg?
 *       no  -->
 *       yes -->
 * close last jpg
 * close card file
 */

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

typedef uint8_t BYTE;

int main()
{
    // open card file
    FILE* infile = fopen("card.raw", "r");

    // test if it was properly opened
    if (infile == NULL)
    {
        printf("Could not open %s.\n", "card.raw");
        return 1;
    }

    // create a string variable used 
    // when opening output file to write jpeg
    char* title = malloc(8);

    // create a boolean variable for checking 
    // if a new jpeg was found
    int newimg = 1;

    // buffer array to store being read or written
    BYTE* buffer = malloc(512);

    int img_number = 0;

    // create file pointer to store
    // to represent output file
    FILE* img;

    // repeat until end of file
    while (!feof(infile) && fread(&buffer, 512, 1, infile) == 1)
    {
        // in this if and
        // in the one nested in it
        // check if a new jpeg is found
        // and check if it's really
        // a jpeg
        if (newimg)
        {
            if (buffer[0] == 0xff && buffer[1] == 0xf8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef))
            {
                // yes
                // found jpeg
                // reset boolean
                newimg = 0;

                // write the name of the jpeg to output file
                sprintf(title, "%03d.jpg", img_number);

                // open file and write jpeg img data to it
                if (fopen(title, "w") != NULL && img != NULL)
                {
                    img = fopen(title, "w");
                    fwrite(buffer, 512, 1, img);
                }
            }
        }
        // checking if a jpeg was already found
        else
        {
            // yes
            if (buffer[0] == 0xff && buffer[1] == 0xf8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef))
            {   
                // close the output file to stop reading into it
                fclose(img);

                // update img_number variable
                // so that the next image's file name
                // has one number greater in it as part of the
                // file name
                img_number++;

                // write the name of the jpeg to the output file
                // with the update number from img_number
                sprintf(title, "%03d.jpg", img_number);

                if (fopen(title, "w") != NULL && img != NULL)
                {
                    // open a new file to store the next jpeg
                    img = fopen(title, "w");

                    // write the data to the new file
                    fwrite(buffer, 512, 1, img);
                }
            }
            // no
            else
            {
                if (img != NULL)
                {
                    // keep writing to current jpeg
                    // because we haven't found a new
                    // jpeg yet
                    fwrite(buffer, 512, 1, img);
                }
            }
        }
    }

    // no more sets of 512 bytes left to read
    if (!fclose(img))
    {
        // close last jpg file
        fclose(img);
    }
    // close card.raw
    fclose(infile);

    free(buffer);
    free(title);
    return 0;
}
1

Instead of

(buffer[3] >= 0xe0 || buffer[3] <= 0xef)

use

(buffer[3] >= 0xe0 && buffer[3] <= 0xef)

(parentheses then optional)

Instead of

img = fopen(title, "a");

use

img = fopen(title, "w");

(a means "append", w means "write", they are the same only if the file does not exist)

buffer is a pointer already, so use buffer instead of &buffer (a pointer to a pointer, this is where you probably segfault)

And you might want to use "%03d.jpg" instead of "%3d.jpg" (first pads with zeroes, second with spaces), and maybe check if img points to open file before closing at the end (in case there was no image in the raw file). And if you don't have write permissions for current directory, it could happen that you cannot write a file, then fopen would return NULL, and the next fwrite would dereference a null pointer, resulting in another segfault.

| improve this answer | |
  • How do I check for whether it points to an open file? With "if (!fopen(filename)"? Or maybe the opposite? And how do I check for whether I have write permissions or not? Thanks for the reply, by the way. – Osman Zakir Nov 9 '16 at 16:19
  • I've made some changes to the code, so I'll update it in the original post. It's still Seg faulting, though. – Osman Zakir Nov 9 '16 at 16:30
  • In your edited code, there are still &buffer, and you now have too many fopens. Use fopen, store the result, then check that variable if it is NULL (then the fopen failed). – Blauelf Nov 10 '16 at 13:56
  • Yeah, I was able to fix it. One of the first three bytes I was checking for was also wrong. I fixed everything and now it works. Thanks. – Osman Zakir Nov 11 '16 at 23:04

You must log in to answer this question.

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