Exemple #1
0
Fichier : log.c Projet : gpg/boa
void log_error_doc(request * req)
{
    int errno_save = errno;
    char *escaped_pathname;

    if (virtualhost) {
        fprintf(stderr, "%s ", req->local_ip_addr);
    } else if (vhost_root) {
        fprintf(stderr, "%s ", (req->host ? req->host : "(null)"));
    }
    escaped_pathname = escape_pathname(req->pathname);
    print_remote_ip (req, stderr);
    if (vhost_root) {
        fprintf(stderr, " - - %srequest [%s] \"%s\" (\"%s\"): ",
                get_commonlog_time(),
                (req->header_host ? req->header_host : "(null)"),
                (req->logline ? req->logline : "(null)"),
                (escaped_pathname ? escaped_pathname : "(null)"));
    } else {
        fprintf(stderr, " - - %srequest \"%s\" (\"%s\"): ",
                get_commonlog_time(),
                (req->logline ? req->logline : "(null)"),
                (escaped_pathname ? escaped_pathname : "(null)"));
    }
    free(escaped_pathname);

    errno = errno_save;
}
Exemple #2
0
void log_error_doc(request * req)
{
    int errno_save = errno;

    if (virtualhost) {
        fprintf(stderr, "%s ", req->local_ip_addr);
    } else if (vhost_root) {
        fprintf(stderr, "%s ", (req->host ? req->host : "(null)"));
    }
    if (vhost_root) {
        fprintf(stderr, "%s - - %srequest [%s] \"%s\" (\"%s\"): ",
                req->remote_ip_addr,
                get_commonlog_time(),
                (req->header_host ? req->header_host : "(null)"),
                (req->logline ? req->logline : "(null)"),
                (req->pathname ? req->pathname : "(null)"));
    } else {
        fprintf(stderr, "%s - - %srequest \"%s\" (\"%s\"): ",
                req->remote_ip_addr,
                get_commonlog_time(),
                (req->logline ? req->logline : "(null)"),
                (req->pathname ? req->pathname : "(null)"));
    }

    errno = errno_save;
}
Exemple #3
0
void log_access(request * req)
{
    if (!access_log_name)
        return;

    if (virtualhost) {
        printf("%s ", req->local_ip_addr);
    } else if (vhost_root) {
        printf("%s ", (req->host ? req->host : "(null)"));
    }

    if(req->logline==0 || (req->logline!=0 && strstr(req->logline, "SetStatus")!=0))
    {//by steve
	    printf("%s - - %s\"%s\" %d %ld \"%s\" \"%s\"\n",
	           req->remote_ip_addr,
	           get_commonlog_time(),
	           req->logline ? req->logline : "-",
	           req->response_status,
	           req->bytes_written,
	           (req->header_referer ? req->header_referer : "-"),
	           (req->header_user_agent ? req->header_user_agent : "-"));
    }
    else
    	printf("-");
}
Exemple #4
0
void log_error_mesg(const char *file, int line, const char *mesg)
{
    int errno_save = errno;
    fprintf(stderr, "%s%s:%d - ", get_commonlog_time(), file, line);
    errno = errno_save;
    perror(mesg);
    errno = errno_save;
}
Exemple #5
0
Fichier : log.c Projet : gpg/boa
void log_error_mesg_fatal(const char *file, int line, const char *func, const char *mesg)
{
    int errno_save = errno;
    fprintf(stderr, "%s%s:%d (%s) - ", get_commonlog_time(), file, line, func);
    errno = errno_save;
    perror(mesg);
    exit(EXIT_FAILURE);
}
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
         * 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.
         */
        req->status = DEAD;
        fprintf(stderr, "%sGot SIGBUS in write(2)!\n", get_commonlog_time());
        return 0;
    }

    if (bytes_written < 0) {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
            return -1;
        /* request blocked at the pipe level, but keep going */
        else {
            if (errno != EPIPE) {
                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->filepos += bytes_written;

    if (req->filepos == req->filesize) { /* EOF */
        return 0;
    } else
        return 1;               /* more to do */
}
Exemple #7
0
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;
        
    } else {
        
        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
         * 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.
         */
        req->status = DEAD;
        fprintf(stderr, "%sGot SIGBUS in write(2)!\n", get_commonlog_time());
        return 0;
    }

    if (bytes_written < 0) {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
            return -1;
        
        else {
            if (errno != EPIPE) {
                log_error_doc(req);
                
                perror("write");
                
            }
            req->status = DEAD;
            return 0;
        }
    }
    req->filepos += bytes_written;

    if (req->filepos == req->filesize) { 
        return 0;
    } else
        return 1;               
}
Exemple #8
0
Fichier : log.c Projet : gpg/boa
void log_access(request * req)
{
    if (!access_log_name)
        return;

    if (virtualhost) {
        printf("%s ", req->local_ip_addr);
    } else if (vhost_root) {
        printf("%s ", (req->host ? req->host : "(null)"));
    }
    print_remote_ip (req, stdout);
    printf(" - - %s\"%s\" %d %zu \"%s\" \"%s\"\n",
           get_commonlog_time(),
           req->logline ? req->logline : "-",
           req->response_status,
           req->bytes_written,
           (req->header_referer ? req->header_referer : "-"),
           (req->header_user_agent ? req->header_user_agent : "-"));
}
Exemple #9
0
void log_error(const char *mesg)
{
    fprintf(stderr, "%s%s", get_commonlog_time(), mesg);
}
Exemple #10
0
void log_error_time(void)
{
    int errno_save = errno;
    fputs(get_commonlog_time(), stderr);
    errno = errno_save;
}
Exemple #11
0
Fichier : get.c Projet : gpg/boa
int process_get(request * req)
{
    off_t bytes_written;
    volatile off_t 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|O_LARGEFILE);

        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|O_LARGEFILE);
        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." PRINTF_OFF_T_ARG, cachedir,
             (int) statbuf->st_dev, statbuf->st_ino);
    data_fd = open(pathname_with_index, O_RDONLY|O_LARGEFILE);

    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|O_LARGEFILE); /* 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. */

}
Exemple #12
0
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;
#ifdef SERVER_SSL
	if(req->ssl == NULL){
#endif /*SERVER_SSL*/
        bytes_written = write(req->fd, req->data_mem + req->filepos,
                              bytes_to_write);
#ifdef SERVER_SSL
	}else{
		bytes_written = SSL_write(req->ssl, req->data_mem + req->filepos, bytes_to_write);
#if 0
		printf("SSL_write\n");
#endif /*0*/
	}
#endif /*SERVER_SSL*/
        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
         * 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.
         */
        req->status = DEAD;
        fprintf(stderr, "%sGot SIGBUS in write(2)!\n", get_commonlog_time());
        return 0;
    }

    if (bytes_written < 0) {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
            return -1;
        /* request blocked at the pipe level, but keep going */
        else {
            if (errno != EPIPE) {
                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->filepos += bytes_written;
	req->busy_flag = BUSY_FLAG_AUDIO|BUSY_FLAG_VIDEO;
    if (req->filepos == req->filesize) { /* EOF */

#ifdef DAVINCI_IPCAM
        if (req->http_stream == URI_STREAM_MJPEG) {
#if 1
#if 0
            while (audio_get(req) > 0);
            if (req->audio_length >= AUDIO_SEND_SIZE) {
                audio_send(req);
                return 1;
            }
#else
            if (audio_get(req, FMT_MJPEG) > 0)
			return 1;
#endif
#else
		req->busy_flag &= ~BUSY_FLAG_AUDIO;
#endif
            if (req->serial_lock) {
                GetAVData(AV_OP_UNLOCK_MJPEG, req->serial_lock, NULL);
                req->serial_lock = 0;
            }
            GetAVData(AV_OP_GET_MJPEG_SERIAL, -1, &req->av_data);
            if (req->av_data.serial < req->serial_book) {
                req->busy_flag &= ~BUSY_FLAG_VIDEO;
                return 1;
            }
            GetAVData(AV_OP_LOCK_MJPEG, req->av_data.serial, &req->av_data );
            req->data_mem = req->av_data.ptr;
            req->filesize = req->av_data.size+16;
            req->filepos = 0;
            req->serial_lock = req->av_data.serial;
            req->serial_book = req->av_data.serial+1;
            reset_output_buffer(req);
            req_write(req, "\r\n");
            print_mjpeg_headers(req);
            return 1;
        }
        if (req->http_stream == URI_STREAM_MPEG4 || req->http_stream == URI_STREAM_AVC) {
            int ret;
#if 1
#if 0
		while (audio_get(req) > 0);
		if (req->audio_length > AUDIO_SEND_SIZE) {
			req->busy_flag |= BUSY_FLAG_AUDIO;
			audio_send(req);
      		      return 1;
		}
#else
            if (audio_get(req, FMT_MPEG4) > 0)
			return 1;
#endif
#else
		req->busy_flag &= ~BUSY_FLAG_AUDIO;
#endif
            ret = GetAVData(AV_OP_LOCK_MP4, req->serial_book, &req->av_data);
            if (ret == RET_SUCCESS) {
                GetAVData(AV_OP_UNLOCK_MP4, req->serial_lock, NULL);
                req->data_mem = req->av_data.ptr;
                req->filesize = req->av_data.size+16;
                req->filepos = 0;

                req->serial_lock = req->av_data.serial;
                req->serial_book = req->av_data.serial+1;

                reset_output_buffer(req);
                req_write(req, "\r\n");
				if (req->http_stream == URI_STREAM_AVC)
                { print_avc_headers(req); }
				else
				{ print_mpeg4_headers(req); }
                return 1;
            }
            else if (ret == RET_NO_VALID_DATA) {
                req->busy_flag &= ~BUSY_FLAG_VIDEO;
                return 1;
            }
            else {
                GetAVData(AV_OP_GET_MPEG4_SERIAL, -1, &req->av_data );
                req->serial_book = req->av_data.serial;
                dbg("lock error ret=%d\n", ret);
                return 1;
            }
        }
        if (req->http_stream == URI_STREAM_MPEG4CIF || req->http_stream == URI_STREAM_AVCCIF) {
            int ret;
#if 1
#if 0
		while (audio_get(req) > 0);
		if (req->audio_length > AUDIO_SEND_SIZE) {
			audio_send(req);
      		      return 1;
		}
#else
            if (audio_get(req, FMT_MPEG4_EXT) > 0)
			return 1;
#endif
#else
		req->busy_flag &= ~BUSY_FLAG_AUDIO;
#endif
            ret = GetAVData(AV_OP_LOCK_MP4_CIF, req->serial_book, &req->av_data);
            if (ret == RET_SUCCESS) {
                GetAVData(AV_OP_UNLOCK_MP4_CIF, req->serial_lock, NULL);
                req->data_mem = req->av_data.ptr;
                req->filesize = req->av_data.size+16;
                req->filepos = 0;

                req->serial_lock = req->av_data.serial;
                req->serial_book = req->av_data.serial+1;

                reset_output_buffer(req);
                req_write(req, "\r\n");
				if (req->http_stream == URI_STREAM_AVCCIF)
                { print_avc_headers(req); }
				else
				{ print_mpeg4_headers(req); }
                return 1;
            }
            else if (ret == RET_NO_VALID_DATA) {
                req->busy_flag &= ~BUSY_FLAG_VIDEO;
                return 1;
            }
            else {
                GetAVData(AV_OP_GET_MPEG4_CIF_SERIAL, -1, &req->av_data );
                req->serial_book = req->av_data.serial;
                dbg("lock error ret=%d\n", ret);
                return 1;
            }
        }
#endif  // DAVINCI_IPCAM
        return 0;
    } else
        return 1;               /* more to do */
}
Exemple #13
0
int init_get(request * req)
{
    int data_fd, saved_errno, dynamic=0;
    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... */
    }
#ifdef DAVINCI_IPCAM
    if (req->http_uri && (req->http_uri->uri_flag & URI_FLAG_NEED_PARSE))
        dynamic = 1;
#endif
    if (req->if_modified_since && !dynamic &&
        !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;
    }

#ifdef DAVINCI_IPCAM
    if (dynamic) {
            char *addr = (char *)malloc(req->filesize + 1025);
            if (addr) {
                req->mem_flag |= MFLAG_IS_MEMORY;
                req->mmap_ptr = req->data_mem;
                req->mmap_size = req->filesize;
                memcpy(addr+1024, req->data_mem, req->filesize);
                addr[req->filesize+1024] = '\0';
                req->data_mem = addr;
                req->filesize = html_argument_parse(req->authority, addr+1024, req->data_mem);
                send_request_ok_no_cache(req);     /* All's well */
                return 1;
            }
    }
#endif  // DAVINCI_IPCAM

    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;
}
Exemple #14
0
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; 

#ifdef GUNZIP
    if (data_fd == -1 && errno == ENOENT) {
        
        
        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)) { 
        close(data_fd);         

        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); 

        if (data_fd == -1)      
            return 0;           
        else if (data_fd <= 1)
            
            return data_fd;
        
    }
    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); 
        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) {  
        send_r_request_ok(req);     
        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);             

    if ((long) req->data_mem == -1) {
        boa_perror(req, "mmap");
        return 0;
    }

    send_r_request_ok(req);     

    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;
            
        } else {
            
            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;
        }
    }

    
    return 1;
}