0

I'm almost done with this one. However I have one more bug that I can't resolve.

fseek is returning -1 only for some cases. errno's value is 29 after ftell, if that helps.

check50 says:

$ check50 2015.fall.pset6.server2 server.c
:) server.c exists
:) server compiles
:) Requesting cat.jpg returns 200, image/jpeg, and correct image
:) Requesting cat.html returns 200, text/html, and correct file
:) Requesting cat2.HTML returns 200, text/html, and correct file
:) Requesting cat3.HtMl returns 200, text/html, and correct file
:) Requesting cat.gif returns 200, image/gif, and correct file
:) Requesting favicon.ico returns 200, image/x-icon, and correct file
:) Requesting test.css returns 200, text/css, and correct file
:) Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:( Requesting hello.php? returns 200, text/html, and correct output
   \ expected output, not an exit code of 0
:) Requesting hello.php?name=Alice returns 200, text/html, and correct output
:) Requesting /test redirects to /test/
:( Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php
   \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
:) Requesting two files in a row (cat.html then cat.jpg) succeeds
https://sandbox.cs50.net/checks/8d80ab75c04942cca7498603f6a2005b

load is:

bool load(FILE *file, char **content, int64_t *length)
{
    if (fseek(file, 0 , SEEK_END) != 0) {
DBG_Print("\n%i\n", __LINE__);
        return false;
    }
    *length = ftell(file);
    if (*length == -1) {
DBG_Print("\n%i\n", __LINE__);
        return false;
    }
DBG_Print("\n%i-%zi\n", __LINE__, *length);
DBG_Pause;
    *content = calloc(*length, sizeof(**content));
DBG_Print("\n%i-%zi\n", __LINE__, *length);
DBG_Pause;
    fseek(file, 0, SEEK_SET);
    fread(*content, *length, 1, file);
    return true;
}

I found that in the cases that check50 is sad, load is returning in the first if, and I printed the value of errno after ftell (commenting the return) and found it was 29.

EDIT: I saw an answer to a similar error on stackoverflow that said that getc works with pipes, and tried to implement it. However, it got worse!

New check50:

$ check50 2015.fall.pset6.server2 server.c
:) server.c exists
:) server compiles
:( Requesting cat.jpg returns 200, image/jpeg, and correct image
:) Requesting cat.html returns 200, text/html, and correct file
:) Requesting cat2.HTML returns 200, text/html, and correct file
:) Requesting cat3.HtMl returns 200, text/html, and correct file
:( Requesting cat.gif returns 200, image/gif, and correct file
:) Requesting favicon.ico returns 200, image/x-icon, and correct file
:) Requesting test.css returns 200, text/css, and correct file
:) Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:( Requesting hello.php? returns 200, text/html, and correct output
   \ expected output, not an exit code of 0
:) Requesting hello.php?name=Alice returns 200, text/html, and correct output
:) Requesting /test redirects to /test/
:( Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php
   \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
:( Requesting two files in a row (cat.html then cat.jpg) succeeds
https://sandbox.cs50.net/checks/2adf0753ff3a46bb980b4198320ebf82

New load: (EDIT2: char c -> int c)

bool load(FILE *file, char **content, int64_t *length)
{
    int64_t len;
    int16_t blk = 1;
    char *buff = calloc(blk * BYTES, sizeof(char));
    void *tmp = NULL;
    int c;

    for (len = 0; (c = getc(file)) != EOF; len++) {
        if (!(blk * BYTES -len)) {
            blk++;
            tmp = realloc(buff, blk * BYTES * sizeof(char));
            if (!tmp) {
                free(buff);
                return false;
            }
            buff = tmp;
        }
        buff[len] = c;
    }
    *length = len;
    if (*length <= 0) {
DBG_Print("\n%i\n", __LINE__);
        return false;
    }
DBG_Print("\n%i-%zi\n", __LINE__, *length);
DBG_Pause;
    tmp = realloc(buff, len * sizeof(char));
    if (!tmp) {
        free(buff);
        return false;
    }
    *content = tmp;
    tmp = NULL;
    return true;
}

EDIT 2:

New check50 (int c):

$ check50 2015.fall.pset6.server2 server.c
:) server.c exists
:) server compiles
:) Requesting cat.jpg returns 200, image/jpeg, and correct image
:) Requesting cat.html returns 200, text/html, and correct file
:) Requesting cat2.HTML returns 200, text/html, and correct file
:) Requesting cat3.HtMl returns 200, text/html, and correct file
:) Requesting cat.gif returns 200, image/gif, and correct file
:) Requesting favicon.ico returns 200, image/x-icon, and correct file
:) Requesting test.css returns 200, text/css, and correct file
:) Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:( Requesting hello.php? returns 200, text/html, and correct output
   \ expected output, not an exit code of 0
:) Requesting hello.php?name=Alice returns 200, text/html, and correct output
:) Requesting /test redirects to /test/
:( Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php
   \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
:) Requesting two files in a row (cat.html then cat.jpg) succeeds
https://sandbox.cs50.net/checks/d32a20c06b574947b0e470741c292d2b

EDIT 3:

Parse:

bool parse(const char* line, char* abs_path, char* query)
{
    char line_cp[strlen(line) + 1];
    strcpy(line_cp, line);

    int i;
    int x;
    for (i = 0, x = 0; line[i]; i++) {
        if (line[i] == ' ') {
            x++;
        }
    }
    if (x != 2) {
        error(400);
        return false;
    }

    char *mth_t = strtok(line_cp, " ");
    char mth[strlen(mth_t) + 1];
    strcpy(mth, mth_t);

    char *rqt_t = strtok(NULL, " ");
    char rqt[strlen(rqt_t) + 1];
    strcpy(rqt, rqt_t);

    char *ver_t = strtok(NULL, "\r\n\r\n");
    char ver[strlen(ver_t) + 1];
    strcpy(ver, ver_t);

    if (strcmp(mth, "GET")) {
        error(405);
        return false;
    }

    if (rqt[0] != '/') {
        error(501);
        return false;
    }

    for (i = 0, x = 0; rqt[i]; i++) {
        if (rqt[i] == '"') {
            x++;
        }
    }
    if (x) {
        error(400);
        return false;
    }

    if (strcmp(ver, "HTTP/1.1")) {
        error(505);
        return false;
    }

    for (i = 0, x = 0; rqt[i]; i++) {
        if (rqt[i] == '?') {
            x++;
        }
    }
    if (x == 1) {
        char *pth_t = strtok(rqt, "?");
        //char pth[strlen(pth_t) + 1];
        strcpy(abs_path, pth_t);

        char *qry_t = strtok(NULL, "?");
        //char qry[strlen(qry_t) + 1];
        strcpy(query, qry_t);
        return true;
    } else if (!x) {
        strcpy(abs_path, rqt);
        strcpy(query, "");
        return true;
    } else {
        error(501);
        return false;
    }

    error(501);
    return true;
}

EDIT 4: Conclussion: Bug 1 (load) was solved, but Bug 2 (parse) will be solved in another thread.

1 Answer 1

1

First, I love cacahuetes.

Second:

I can tell you one problem right away. This part won't work with pipe streams like php files:

    if (fseek(file, 0 , SEEK_END) != 0) {
DBG_Print("\n%i\n", __LINE__);
        return false;
    }
    *length = ftell(file);

To get the load() function working correctly 100% of the time, one usually needs to read from the stream progressively and use realloc() when needed.

DinoCoderSaurus gave some advice about it here: pset6 (webserver) - hello.php not loading properly


EDIT to analyze the code update:

Now... you need to use int c = fgetc(...) instead of char c = fgetc(), otherwise you'll get false EOF detections:

4.1 Using fgetc(), etc. incorrectly

The fgetc(), getc() and getchar() functions all return back an integer value. For example, the prototype of fgetc() is:

int fgetc( FILE * );

Sometimes this integer value is really a simple character, but there is one very important case where the return value is not a character!

What is this value? EOF A common misconception of students is that files have a special EOF character at the end. There is no special character stored at the end of a file. EOF is an integer error code returned by a function. Here is the wrong way to use fgetc():

int count_line_size( FILE * fp )
{
char ch;
int cnt = 0;

while( (ch = fgetc(fp)) != EOF && ch != '\n')
cnt++;
return cnt;
}

What is wrong with this? The problem occurs in the condition of the while > loop. To illustrate, here is the loop rewritten to show what C will do behind the scenes.

while( (int) ( ch = (char) fgetc(fp) ) != EOF && ch != '\n')
cnt++;

The return value of fgetc(fp) is cast to char to store the result into ch. Then the value of ch must be cast back to an int to compare it with EOF. So what? Casting an int value to a char and then back to an int may not give back the original int value. This means in the example above that if fgetc() returns back the EOF value, the casting may change the value so that the comparison later with EOF would be false.

What is the solution? Make the ch variable an int as below:

int count_line_size( FILE * fp )
{
int ch;
int cnt = 0;

while( (ch = fgetc(fp)) != EOF && ch != '\n')
cnt++;
return cnt;
}

Now the only hidden cast is in the second comparison.

while( (ch = fgetc(fp)) != EOF && ch != ((int) '\n') )
cnt++;

This cast has no harmful effects at all! So, the moral of all this is: always use an int variable to store the result of the fgetc(), getc() and getchar().

http://www.drpaulcarter.com/cs/common-c-errors.php#4.1

14
  • Tried to solve it with an answer I saw that solved it using 'getc', but now it looks worse. I will EDIT the question with the new results. Commented Nov 11, 2016 at 19:34
  • Ok... I have added some info about fgetc() and EOF Commented Nov 11, 2016 at 19:40
  • Ohhhh right! Forgot that. Something in my mind told me that checking EOF which is not a char wasn't right. Thank you. Commented Nov 11, 2016 at 19:42
  • If you get your code to work, please accept this answer clicking the check mark, otherwise it will roam this forum forever as a zombie question Commented Nov 11, 2016 at 19:46
  • I now get the same results as the first ones. php still resists getc Commented Nov 11, 2016 at 19:47

You must log in to answer this question.

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