conf->etag_remove = ETAG_UNSET;
conf->enable_mmap = ENABLE_MMAP_UNSET;
+ conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
return (void *)conf;
}
conf->enable_mmap = new->enable_mmap;
}
+ if (new->enable_sendfile != ENABLE_SENDFILE_UNSET) {
+ conf->enable_sendfile = new->enable_sendfile;
+ }
+
return (void*)conf;
}
return NULL;
}
+static const char *set_enable_sendfile(cmd_parms *cmd, void *d_,
+ const char *arg)
+{
+ core_dir_config *d = d_;
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ d->enable_sendfile = ENABLE_SENDFILE_ON;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ d->enable_sendfile = ENABLE_SENDFILE_OFF;
+ }
+ else {
+ return "parameter must be 'on' or 'off'";
+ }
+
+ return NULL;
+}
+
static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
{
core_dir_config *c = c_;
"Specify components used to construct a file's ETag"),
AP_INIT_TAKE1("EnableMMAP", set_enable_mmap, NULL, OR_FILEINFO,
"Controls whether memory-mapping may be used to read files"),
+AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO,
+ "Controls whether sendfile may be used to transmit files"),
/* Old server config file commands */
}
}
- if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY, 0,
- r->pool)) != APR_SUCCESS) {
+
+ if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY
+#if APR_HAS_SENDFILE
+ | ((d->enable_sendfile == ENABLE_SENDFILE_OFF)
+ ? 0 : APR_OPEN_FOR_SENDFILE)
+#endif
+ , 0, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
"file permissions deny server access: %s", r->filename);
return HTTP_FORBIDDEN;
}
bb = apr_brigade_create(r->pool, c->bucket_alloc);
-#if APR_HAS_LARGE_FILES
- if (r->finfo.size > AP_MAX_SENDFILE) {
+#if APR_HAS_SENDFILE && APR_HAS_LARGE_FILES
+ if ((d->enable_sendfile != ENABLE_SENDFILE_OFF) &&
+ (r->finfo.size > AP_MAX_SENDFILE)) {
/* APR_HAS_LARGE_FILES issue; must split into mutiple buckets,
* no greater than MAX(apr_size_t), and more granular than that
* in case the brigade code/filters attempt to read it directly.
}
#if APR_HAS_SENDFILE
- if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) {
- /* Prepare the socket to be reused */
- flags |= APR_SENDFILE_DISCONNECT_SOCKET;
- }
+ if (apr_file_flags_get(fd) & APR_OPEN_FOR_SENDFILE) {
- rv = sendfile_it_all(net, /* the network information */
- fd, /* the file to send */
- &hdtr, /* header and trailer iovecs */
- foffset, /* offset in the file to begin
- sending from */
- flen, /* length of file */
- nbytes + flen, /* total length including
- headers */
- flags); /* apr_sendfile flags */
-
- /* If apr_sendfile() returns APR_ENOTIMPL, call emulate_sendfile().
- * emulate_sendfile() is useful to enable the same Apache binary
- * distribution to support Windows NT/2000 (supports TransmitFile)
- * and Win95/98 (do not support TransmitFile)
- */
- if (rv == APR_ENOTIMPL)
+ if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) {
+ /* Prepare the socket to be reused */
+ flags |= APR_SENDFILE_DISCONNECT_SOCKET;
+ }
+
+ rv = sendfile_it_all(net, /* the network information */
+ fd, /* the file to send */
+ &hdtr, /* header and trailer iovecs */
+ foffset, /* offset in the file to begin
+ sending from */
+ flen, /* length of file */
+ nbytes + flen, /* total length including
+ headers */
+ flags); /* apr_sendfile flags */
+ }
+ else
#endif
{
apr_size_t unused_bytes_sent;