⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 get.c

📁 用于移植到嵌入式linux系统的boa http服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
        /* 256 bytes for the **trailing** headers */        /* bytes is now how much the buffer can hold         * after the headers         */    }    if (req->data_mem && bytes_free > 256) {        unsigned int want;        Range *r;        r = req->ranges;        want = (r->stop - r->start) + 1;        if (bytes_free > want)            bytes_free = want;        else {            /* bytes_free <= want */            ;        }        if (setjmp(env) == 0) {            handle_sigbus = 1;            memcpy(req->buffer + req->buffer_end,                   req->data_mem + r->start, bytes_free);            handle_sigbus = 0;            /* OK, SIGBUS **after** this point is very bad! */        } else {            /* sigbus! */            log_error_doc(req);            reset_output_buffer(req);            send_r_error(req);            log_error("Got SIGBUS in memcpy\n");            return 0;        }        req->buffer_end += bytes_free;        req->bytes_written += bytes_free;        r->start += bytes_free;        if (bytes_free == want) {            /* this will fit due to the 256 extra bytes_free */            return complete_response(req);        }    }    /* We lose statbuf here, so make sure response has been sent */    return 1;}/* * Name: process_get * Description: Writes a chunk of data to the socket. * * Return values: *  -1: request blocked, move to blocked queue *   0: EOF or error, close it down *   1: successful write, recycle in ready queue */int process_get(request * req){    int bytes_written;    volatile unsigned int bytes_to_write;    if (req->method == M_HEAD) {        return complete_response(req);    }    bytes_to_write = (req->ranges->stop - req->ranges->start) + 1;    if (bytes_to_write > system_bufsize)        bytes_to_write = system_bufsize;    if (setjmp(env) == 0) {        handle_sigbus = 1;        bytes_written = write(req->fd, req->data_mem + req->ranges->start,                              bytes_to_write);        handle_sigbus = 0;        /* OK, SIGBUS **after** this point is very bad! */    } else {        /* sigbus! */        req->status = DEAD;        log_error_doc(req);        fprintf(stderr, "%sGot SIGBUS in write(2)!\n",                get_commonlog_time());        /* sending an error here is inappropriate         * if we are here, the file is mmapped, and thus,         * a content-length has been sent. If we send fewer bytes         * the client knows there has been a problem.         * We run the risk of accidentally sending the right number         * of bytes (or a few too many) and the client         * won't be the wiser.         */        return 0;    }    if (bytes_written < 0) {        if (errno == EWOULDBLOCK || errno == EAGAIN)            return -1;        /* request blocked at the pipe level, but keep going */        else {#ifdef QUIET_DISCONNECT            if (errno != EPIPE) {#else            if (1) {#endif                log_error_doc(req);                /* Can generate lots of log entries, */                perror("write");                /* OK to disable if your logs get too big */            }            req->status = DEAD;            return 0;        }    }    req->bytes_written += bytes_written;    req->ranges->start += bytes_written;    if ((req->ranges->stop + 1 - req->ranges->start) == 0) {        return complete_response(req);    }    return 1;               /* more to do */}/* * Name: get_dir * Description: Called from process_get if the request is a directory. * statbuf must describe directory on input, since we may need its *   device, inode, and mtime. * statbuf is updated, since we may need to check mtimes of a cache. * returns: *  -1 error *  0  cgi (either gunzip or auto-generated) *  >0  file descriptor of file */int get_dir(request * req, struct stat *statbuf){    char pathname_with_index[MAX_PATH_LENGTH];    int data_fd;    if (directory_index) {      /* look for index.html first?? */        unsigned int l1, l2;        l1 = strlen(req->pathname);        l2 = strlen(directory_index);#ifdef GUNZIP        if (l1 + l2 + 3 + 1 > sizeof(pathname_with_index)) { /* for .gz */#else        if (l1 + l2 + 1 > sizeof(pathname_with_index)) {#endif            errno = ENOMEM;            boa_perror(req, "pathname_with_index not large enough for pathname + index");            return -1;        }        memcpy(pathname_with_index, req->pathname, l1); /* doesn't copy NUL */        memcpy(pathname_with_index + l1, directory_index, l2 + 1); /* does */        data_fd = open(pathname_with_index, O_RDONLY);        if (data_fd != -1) {    /* user's index file */            /* We have to assume that directory_index will fit, because             * if it doesn't, well, that's a huge configuration problem.             * this is only the 'index.html' pathname for mime type             */            memcpy(req->request_uri, directory_index, l2 + 1); /* for mimetype */            fstat(data_fd, statbuf);            return data_fd;        }        if (errno == EACCES) {            send_r_forbidden(req);            return -1;        } else if (errno != ENOENT) {            /* if there is an error *other* than EACCES or ENOENT */            send_r_not_found(req);            return -1;        }#ifdef GUNZIP        /* if we are here, trying index.html didn't work         * try index.html.gz         */        strcat(pathname_with_index, ".gz");        data_fd = open(pathname_with_index, O_RDONLY);        if (data_fd != -1) {    /* user's index file */            close(data_fd);            req->response_status = R_REQUEST_OK;            SQUASH_KA(req);            if (req->pathname)                free(req->pathname);            req->pathname = strdup(pathname_with_index);            if (!req->pathname) {                boa_perror(req, "strdup of pathname_with_index for .gz files " __FILE__ ":" STR(__LINE__));                return 0;            }            if (req->http_version != HTTP09) {                req_write(req, http_ver_string(req->http_version));                req_write(req, " 200 OK-GUNZIP" CRLF);                print_http_headers(req);                print_last_modified(req);                req_write(req, "Content-Type: ");                req_write(req, get_mime_type(directory_index));                req_write(req, CRLF CRLF);                req_flush(req);            }            if (req->method == M_HEAD)                return 0;            return init_cgi(req);        }#endif    }    /* only here if index.html, index.html.gz don't exist */    if (dirmaker != NULL) {     /* don't look for index.html... maybe automake? */        req->response_status = R_REQUEST_OK;        SQUASH_KA(req);        /* the indexer should take care of all headers */        if (req->http_version != HTTP09) {            req_write(req, http_ver_string(req->http_version));            req_write(req, " 200 OK" CRLF);            print_http_headers(req);            print_last_modified(req);            req_write(req, "Content-Type: text/html" CRLF CRLF);            req_flush(req);        }        if (req->method == M_HEAD)            return 0;        return init_cgi(req);        /* in this case, 0 means success */    } else if (cachedir) {        return get_cachedir_file(req, statbuf);    } else {                    /* neither index.html nor autogenerate are allowed */        send_r_forbidden(req);        return -1;              /* nothing worked */    }}static int get_cachedir_file(request * req, struct stat *statbuf){    char pathname_with_index[MAX_PATH_LENGTH];    int data_fd;    time_t real_dir_mtime;    real_dir_mtime = statbuf->st_mtime;    /* the sizeof() doesn't need a -1 because snprintf will     * include the NUL when calculating if the size is enough     */    snprintf(pathname_with_index, sizeof(pathname_with_index),             "%s/dir.%d.%ld", cachedir,             (int) statbuf->st_dev, statbuf->st_ino);    data_fd = open(pathname_with_index, O_RDONLY);    if (data_fd != -1) {        /* index cache */        fstat(data_fd, statbuf);        if (statbuf->st_mtime > real_dir_mtime) {            statbuf->st_mtime = real_dir_mtime; /* lie */            strcpy(req->request_uri, directory_index); /* for mimetype */            return data_fd;        }        close(data_fd);        unlink(pathname_with_index); /* cache is stale, delete it */    }    if (index_directory(req, pathname_with_index) == -1)        return -1;    data_fd = open(pathname_with_index, O_RDONLY); /* Last chance */    if (data_fd != -1) {        strcpy(req->request_uri, directory_index); /* for mimetype */        fstat(data_fd, statbuf);        statbuf->st_mtime = real_dir_mtime; /* lie */        return data_fd;    }    boa_perror(req, "re-opening dircache");    return -1;                  /* Nothing worked. */}/* * Name: index_directory * Description: Called from get_cachedir_file if a directory html * has to be generated on the fly * returns -1 for problem, else 0 * This version is the fastest, ugliest, and most accurate yet. * It solves the "stale size or type" problem by not ever giving * the size or type.  This also speeds it up since no per-file * stat() is required. */static int index_directory(request * req, char *dest_filename){    DIR *request_dir;    FILE *fdstream;    struct dirent *dirbuf;    int bytes = 0;    char *escname = NULL;    if (chdir(req->pathname) == -1) {        if (errno == EACCES || errno == EPERM) {            send_r_forbidden(req);        } else {            log_error_doc(req);            perror("chdir");            send_r_bad_request(req);        }        return -1;    }    request_dir = opendir(".");    if (request_dir == NULL) {        int errno_save = errno;        send_r_error(req);        log_error_doc(req);        fprintf(stderr, "opendir failed on directory \"%s\": ", req->pathname);        errno = errno_save;        perror("opendir");        return -1;    }    fdstream = fopen(dest_filename, "w");    if (fdstream == NULL) {        boa_perror(req, "dircache fopen");        closedir(request_dir);        return -1;    }    bytes += fprintf(fdstream,                     "<HTML><HEAD>\n<TITLE>Index of %s</TITLE>\n</HEAD>\n\n",                     req->request_uri);    bytes += fprintf(fdstream, "<BODY>\n\n<H2>Index of %s</H2>\n\n<PRE>\n",                     req->request_uri);    while ((dirbuf = readdir(request_dir))) {        if (!strcmp(dirbuf->d_name, "."))            continue;        if (!strcmp(dirbuf->d_name, "..")) {            bytes += fprintf(fdstream,                             " [DIR] <A HREF=\"../\">Parent Directory</A>\n");            continue;        }        /* FIXME: ought to use (as-yet unwritten) html_escape_string */        escname = escape_string(dirbuf->d_name, NULL);        if (escname != NULL) {            bytes += fprintf(fdstream, " <A HREF=\"%s\">%s</A>\n",                             escname, dirbuf->d_name);            free(escname);            escname = NULL;        }    }    closedir(request_dir);    bytes += fprintf(fdstream, "</PRE>\n\n</BODY>\n</HTML>\n");    fclose(fdstream);    chdir(server_root);    req->filesize = bytes;      /* for logging transfer size */    return 0;                   /* success */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -