0

Seems like others also had the same problem of a Segmentation Fault when trying to do solve this, but I'm not going to look at those. I already liked at another person's code while I was stuck trying to figure out how to get a file name for the output file and how to check if I've found the next JPEG yet or not. I don't want to look at another person's code again for this pset.

Anyway, with that being said, I, too, have a Segmentation Fault problem with recover.c. Here's my 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
    // 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);
            }
            else
            {
                // no
                printf("nothing\n");
            }
        }
        // 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;
}

Sorry for the long if-conditions for the code for checking for a JPEG's signature. I just wanted to be sure to check for all of the possible bytes that could be used as a JPEG's signature. Zamyla's walkthroughs only mentioned 0xe0 and 0xe1, but David mentioned a few others in the recover.c's specs. So I went with David's (or at least tried to).

Edit: I just made some changes to the code. It's still Seg faulting, though. So give me some more tips if possible. And if my JPEG file names aren't being formed right, how do I fix it? We need room for 3 digits, so I thought %3d would work.

0

You're getting a seg fault because your logic structuring isn't right. The two fclose calls at the bottom are contained inside the while loop when they shouldn't. Also, the placement of that last else doesn't make logical sense. Combine these, and you'll find that the fclose(img); at the end is seg faulting because the file hasn't been opened.

Note that you don't need to have an else clause that does nothing. Just make sure the curly braces are properly placed for nested if/else blocks.

One big problem: This code will never find a signature until you search for the correct signature. You have an error in the signature data. You can also shrink the size of your if test by making good use of >= and <= instead of 16 different == tests.

Finally, the file names aren't being formed right.

This should get you going. If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

3
  • So I can just check if a byte is less than or equal to 0xef and greater than or equal to 0xe0 for the fourth byte of the signature? That's what you're saying, right? If so, I'll try that. And I wonder if I should malloc the buffer and title arrays? Maybe using free() when I haven't used malloc() yet is also causing problems Nov 9 '16 at 10:38
  • I just made some changes to my original post. It's still Seg Faulting with the current changes, so please take another look. Nov 9 '16 at 11:34
  • I'll ask the question again, though I'm still getting a Seg fault, since I did change the code a bit. Nov 9 '16 at 12:51

You must log in to answer this question.

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