0

I have spent two evenings on recover but I just can not figure it out. For the first time I managed to recover everything but the first image without any problems, so I did some searching and following up other's walkthrough trying to figure out how to solve it.

This is my new code. When I try to run it the console reports segmentation fault and I am scratching my head like crazy for hours but just can not figure out why. I used the pointers from my last functional code and I have not changed a name, as well as most of the previous logic. Any help would be much appreciated.

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

typedef uint8_t BYTE;

// To define a variable type called BYTE to store one byte (8 bits) of data.

bool start_jpeg (BYTE buffer[]);

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover infile\n");
        return 1;
    }

    // If commandline argument is not exactly one, print usage message and return 1 to indicate errors.

    FILE *infile = fopen(argv[1], "r");
    if (infile == NULL)
    {
        printf("Unable to open the infile\n");
        return 1;
    }

    // If the infile inputed as the commandline argument can not be opened (i.e. hence making the pointer "infile" pointing to NULL),
    // printing error message and return 1. Note that the argument in the fopen "r" is to suggest the operation is read,
    // and for each operation type you need to use "" to include them.

    BYTE block_buffer_512bs[512 * sizeof(BYTE)];

    // Defining a buffer array of a size of 512 bytes to store the each 512 block read from the infile.
    // Note that the buffer variable type is BYTE, which indicates each element inside is one byte of data.
    // Last time you made this an integer, so it did not work. This is because when using it as a buffer for
    // fread and fwrite in this program you need to make sure that the 512 bytes of data read or written each time
    // aligns with the format in this array, so you need to make it is also a BYTE, but of a size of 512 bytes (for 512 elements).

    char *outfilename = malloc(8 * sizeof(char));
    int outfilename_counter = 0;

    // Defining a name for the outputed JPEG file. Note that it is a string because we want name the outputs in a manner of "000.jpg", "001.jpg", "002.jpg" and so on.
    // Also initializing a outfilename_counter to be used to record how many new JPEG files are produced and hence update it for the correct naming.
    // Note that how a string is initialized here, and has a space of 8 characters. This is to stroe the 7 characters from "000.jpg" and 1 character for the \0, the null terminator.
    // Also making it a string allows us to use sprintf to update the string each time a new file is created.

    FILE *new_img = NULL;

    // Defining a FILE pointer called new_img and for now assign it to NULL since here we do not have things needing its pointing to for now. It is used later.

    bool previous_jpeg = false;

    while (fread(block_buffer_512bs, sizeof(block_buffer_512bs), 1, infile) == 1)
    {
        if (start_jpeg(block_buffer_512bs) == true)
        {
            if (previous_jpeg == false)
            {
                previous_jpeg = true;
            }
            else
            {
                fclose(new_img);
            }

            sprintf(outfilename, "%03i.jpg", outfilename_counter++);
            new_img = fopen(outfilename, "w");
            fwrite(block_buffer_512bs, sizeof(block_buffer_512bs), 1, new_img);
        }
        else if (start_jpeg(block_buffer_512bs) == false)
        {
            fwrite(block_buffer_512bs, sizeof(block_buffer_512bs), 1, new_img);
        }
    }

    free(outfilename);
    fclose(infile);
    fclose(new_img);
    return 0;
}

bool start_jpeg (BYTE buffer[])
{
    if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xf0) == 0xe0))
    {
        return true;
    }

    else
    {
        return false;
    }
}

2

the cause is the following line, new_img is not a valid FILE pointer.

fwrite(block_buffer_512bs, sizeof(block_buffer_512bs), 1, new_img);

You use this link to debug segfaults. You just click "Run", it will compile and run recover card.raw automatically. The first run will take a little long, the rest will be much faster.

1
  • Thank you! The tool is really useful as it points out where the segmentation fault happens. Based on the results I have looked at the 4th fwrite syntax and realize that I wrote the if condition wrong. It should not be if (start_jpeg(block_buffer_512bs) == false) but if (previous_jpeg == true). Thanks again! – HAI LIN May 27 '20 at 2:14

You must log in to answer this question.

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