0

Alright. I'm becoming crazy, so here I come.

I finished the pset, and everything works. At least that's what check50 tells me.

When I launch the server and try each file, they work, except for hello.php, where I get a 500 Internal Server Error.

First, I tried to change the query handling part of the parse function, but the problem definitely doesn't come from there. I'm almost certain it comes from the load function.

Here it is :

/**
 * Loads a file into memory dynamically allocated on heap.
 * Stores address thereof in *content and length thereof in *length.
 */
bool load(FILE* file, BYTE** content, size_t* length)
{
    struct stat st;

    /* Finds out the size of 'file' in bytes */
    fstat(fileno(file), &st);
    *length = st.st_size;

    /* Allocates memory for 'content' */
    *content = malloc(*length * sizeof(BYTE));

    /* Returns true if fread indeed read 'length' bytes, false otherwise */
    return fread(*content, *length, 1, file) == 1 ? true : false;
}

Here's the weird part. The debugger seems to tell me that for every file but hello.php, the length that fstat finds out is the right one. For hello.php however, with or without a query part, the length is zero.

I tried everything I knew and found on the internet - using a for loop with putc, one with fread, and using fseek and ftell. None of this works for hello.php.

EDIT : Okay so I realized the difference between the php file and the others. For the php one, the interpret function is used and so the file is not opened with fopen, but with popen. But still, it's a FILE* stream, it should work the same, shouldn't it?

0

It seems that streams opened with popen can't have their size found by stat or fstat. So I've just made this :

/**
 * Loads a file into memory dynamically allocated on heap.
 * Stores address thereof in *content and length thereof in *length.
 */
bool load(FILE* file, BYTE** content, size_t* length)
{
    struct stat st;
    BYTE *bytes;

    /* Finds out the size of 'file' in bytes */
    fstat(fileno(file), &st);
    *length = st.st_size;

    if(!(*length))
    {
        /* fstat didn't find the length. This means that 'file' was opened with
        ** popen, and that it contains hello.php. */

        int c;

        (*length) = 0;

        /* 'bytes' will contains the content of 'file' */
        bytes = malloc(sizeof(BYTE));

        /* For every char in 'file' */
        while((c = fgetc(file)) != EOF)
        {
            /* Allocates one more byte to 'bytes', copies the new byte */
            bytes = realloc(bytes, ((*length) + 1) * sizeof(BYTE));
            bytes[(*length)] = c;

            /* Length is incremented for the next loop */
            (*length)++;
        }

        /* Length was incremented for nothing */
        (*length)--;

        *content = bytes;

        return true;
    }

    /* Allocates memory for 'content' */
    bytes = malloc((*length) * sizeof(BYTE));

    /* Returns true if fread indeed read 'length' bytes, false otherwise */
    if(fread(bytes, *length, 1, file) != 1)
    {
        free(bytes);
        return false;
    }

    *content = bytes;
    return true;
}

Which now works. Notice how I have to proceed in two different ways depending on the type of file I'm given.

I couldn't just use fgetc in a loop in order to get the size and then use fread as I do with normal files, since when I rewind after using fgetc, it just doesn't rewind at all, the bytes seem to have been erased.

Phew!

You must log in to answer this question.

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