Search code examples
cnulljpegfopenrecover

Why does open return null in this loop? C


I am working on pset4's recover of Harvard's cs50x and I'm stuck because open keeps returning NULL.

// Read each 512 bytes until end of file is reached
FILE* img = NULL;

while (fread(&data, 512, 1, diskptr) == 1)
{
    // Check for jpeg start
    if (checkStart(data, jStart, jStartOE) == true)
    {
        jFound++;
        if (jFound == 1)
        {
            printf("newfound\n");
            // Name and open the first jpeg file
            char title[12];
            sprintf(title, "%03d.jpg", jFound - 1);
            FILE* img = fopen(title, "w");
            fwrite(&data, 512, 1, img);
        }
        else if (img != NULL)
        {
            printf("closed\n");
            // Close old file
            fclose(img);

            // Open new file
            char title[12];
            sprintf(title, "%03d.jpg", jFound - 1);
            FILE* img = fopen(title, "w");
            fwrite(&data, 512, 1, img);
        } 
    }
    else if (jFound > 0 && img != NULL)
    {
        printf("written\n");
        fwrite(&data, 512, 1, img);
    }
}

I added those printfs to see if those else if blocks were ever executed and when I run it newfound prints once and then nothing else prints. For some reason open is returning NULL and the other blocks of code are never executed.

For some context: The aim of this program is to recover deleted jpegs from a .raw file. checkStart is just a simple function that I made that determines if the first four bytes of the 512 bytes block contain the jpeg signature values. If they do it returns true signalling that the current block is the start of a new jpeg and if they don't it returns false. jFound is just a variable that I used to keep track of how many jpegs the program has found so it can name them properly and write if the first jpeg has already been found.


Solution

  • this line:

    FILE* img = fopen(title, "w");
    

    declares the variable 'img' inside the scope of the code block started with

    if( iFound == 1 ) and if( img != NULL ) 
    

    The variable 'img' is different within each code block.

    These declarations mask the declaration at the top of the posted code.

    Suggest

    img = fopen(title, "w");
    

    (so does not declare a new 'img' variable)

    This problem occurs in two places in the posted code.

    I also added some error checking for the calls to fopen()

    I also removed the convolutions in the logic

    however, the code will not always catch the end of the actual .jpg file when any other files are also in the same area of the disk.

    And if any of the file segments have been overwritten, the code will not catch that fact.

    I.E. the code may fail to properly extract the .jpg file(s) and writing extracted copies of the files may result in overwriting part(s) of the deleted files that you want to extract. I.E. place the new files on a different disk

    FILE* img = NULL;
    
    while (fread(&data, 512, 1, diskptr) == 1)
    {
        // Check for jpeg start
        if (checkStart(data, jStart, jStartOE))
        {
    
            if (img != NULL)
            {
                printf("closed\n");
                // Close old file
                fclose(img);
            }
    
            // Open new file
            char title[12];
            sprintf(title, "%03d.jpg", jFound - 1);
    
            if( NULL == (img = fopen(title, "w") ) )
            { // then fopen failed
                perror( "fopen for output file failed");
                exit( EXIT_FAILURE );
            }
    
            // implied else, fopen successful
    
            fwrite(&data, 512, 1, img);
        }
    
        else if (img != NULL)
        {
            printf("written\n");
            fwrite(&data, 512, 1, img);
        }
    }