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

📄 get.c

📁 boa:Linux系统中的轻量级Web服务
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Boa, an http server *  Copyright (C) 1995 Paul Phillips <paulp@go2net.com> *  Some changes Copyright (C) 1996,99 Larry Doolittle <ldoolitt@boa.org> *  Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 1, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* $Id: get.c,v 1.76.2.5 2002/07/26 03:05:59 jnelson Exp $*/#include "boa.h"/* local prototypes */int get_cachedir_file(request * req, struct stat *statbuf);int index_directory(request * req, char *dest_filename);/* * Name: init_get * Description: Initializes a non-script GET or HEAD request. * * Return values: *   0: finished or error, request will be freed *   1: successfully initialized, added to ready queue */int init_get(request * req){    int data_fd, saved_errno;    struct stat statbuf;    volatile int bytes;    data_fd = open(req->pathname, O_RDONLY);    saved_errno = errno; /* might not get used */#ifdef GUNZIP    if (data_fd == -1 && errno == ENOENT) {        /* cannot open */        /* it's either a gunzipped file or a directory */        char gzip_pathname[MAX_PATH_LENGTH];        int len;        len = strlen(req->pathname);        memcpy(gzip_pathname, req->pathname, len);        memcpy(gzip_pathname + len, ".gz", 3);        gzip_pathname[len + 3] = '\0';        data_fd = open(gzip_pathname, O_RDONLY);        if (data_fd != -1) {            close(data_fd);            req->response_status = R_REQUEST_OK;            if (req->pathname)                free(req->pathname);            req->pathname = strdup(gzip_pathname);            if (!req->pathname) {                log_error_time();                perror("strdup");                send_r_error(req);                return 0;            }            if (!req->simple) {                req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n");                print_http_headers(req);                print_content_type(req);                print_last_modified(req);                req_write(req, "\r\n");                req_flush(req);            }            if (req->method == M_HEAD)                return 0;            return init_cgi(req);        }    }#endif    if (data_fd == -1) {        log_error_doc(req);        errno = saved_errno;        perror("document open");        if (saved_errno == ENOENT)            send_r_not_found(req);        else if (saved_errno == EACCES)            send_r_forbidden(req);        else            send_r_bad_request(req);        return 0;    }    fstat(data_fd, &statbuf);    if (S_ISDIR(statbuf.st_mode)) { /* directory */        close(data_fd);         /* close dir */        if (req->pathname[strlen(req->pathname) - 1] != '/') {            char buffer[3 * MAX_PATH_LENGTH + 128];            if (server_port != 80)                sprintf(buffer, "http://%s:%d%s/", server_name,                        server_port, req->request_uri);            else                sprintf(buffer, "http://%s%s/", server_name,                        req->request_uri);            send_r_moved_perm(req, buffer);            return 0;        }        data_fd = get_dir(req, &statbuf); /* updates statbuf */        if (data_fd == -1)      /* couldn't do it */            return 0;           /* errors reported by get_dir */        else if (data_fd <= 1)            /* data_fd == 0 -> close it down, 1 -> continue */            return data_fd;        /* else, data_fd contains the fd of the file... */    }    if (req->if_modified_since &&        !modified_since(&(statbuf.st_mtime), req->if_modified_since)) {        send_r_not_modified(req);        close(data_fd);        return 0;    }    req->filesize = statbuf.st_size;    req->last_modified = statbuf.st_mtime;    if (req->method == M_HEAD || req->filesize == 0) {        send_r_request_ok(req);        close(data_fd);        return 0;    }    if (req->filesize > MAX_FILE_MMAP) {        send_r_request_ok(req); /* All's well */        req->status = PIPE_READ;        req->cgi_status = CGI_BUFFER;        req->data_fd = data_fd;        req_flush(req);         /* this should *always* complete due to                                   the size of the I/O buffers */        req->header_line = req->header_end = req->buffer;        return 1;    }    if (req->filesize == 0) {  /* done */        send_r_request_ok(req);     /* All's well *so far* */        close(data_fd);        return 1;    }    /* NOTE: I (Jon Nelson) tried performing a read(2)     * into the output buffer provided the file data would     * fit, before mmapping, and if successful, writing that     * and stopping there -- all to avoid the cost     * of a mmap.  Oddly, it was *slower* in benchmarks.     */    req->mmap_entry_var = find_mmap(data_fd, &statbuf);    if (req->mmap_entry_var == NULL) {        req->buffer_end = 0;        if (errno == ENOENT)            send_r_not_found(req);        else if (errno == EACCES)            send_r_forbidden(req);        else            send_r_bad_request(req);        close(data_fd);        return 0;    }    req->data_mem = req->mmap_entry_var->mmap;    close(data_fd);             /* close data file */    if ((long) req->data_mem == -1) {        boa_perror(req, "mmap");        return 0;    }    send_r_request_ok(req);     /* All's well */    bytes = BUFFER_SIZE - req->buffer_end;    /* bytes is now how much the buffer can hold     * after the headers     */    if (bytes > 0) {        if (bytes > req->filesize)            bytes = req->filesize;        if (sigsetjmp(env, 1) == 0) {            handle_sigbus = 1;            memcpy(req->buffer + req->buffer_end, req->data_mem, bytes);            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);            fprintf(stderr, "%sGot SIGBUS in memcpy!\n", get_commonlog_time());            return 0;        }        req->buffer_end += bytes;        req->filepos += bytes;        if (req->filesize == req->filepos) {            req_flush(req);            req->status = DONE;        }    }    /* 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 int bytes_to_write;    bytes_to_write = req->filesize - req->filepos;    if (bytes_to_write > SOCKETBUF_SIZE)        bytes_to_write = SOCKETBUF_SIZE;    if (sigsetjmp(env, 1) == 0) {        handle_sigbus = 1;        bytes_written = write(req->fd, req->data_mem + req->filepos,                              bytes_to_write);        handle_sigbus = 0;        /* OK, SIGBUS **after** this point is very bad! */    } else {        /* sigbus! */        log_error_doc(req);        /* 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

⌨️ 快捷键说明

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