/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "apr_file_io.h" #include "httpd.h" #include "http_config.h" #include "http_request.h" /* * Test Apache handling of file truncation * * 1. load this module (full config below) * 2. create directory /tmp/mod_trunc * 3. issue a request with "truncate" in the query args * example: http://127.0.0.1/index.html?truncate * * if sendfile is enabled and apr_socket_sendfile() doesn't * give retcode feedback, expect a busy loop/swapfest. */ /* Config to use with this: loadmodule trunc_module modules/mod_trunc.so AllowOverride None = 2.3> Require all granted Order Allow,Deny Allow from all Order Allow,Deny Allow from all */ static int trunc_translate_name(request_rec *r) { if (r->args && strstr(r->args, "truncate")) { apr_status_t rv; apr_file_t *f; r->filename = "/tmp/mod_trunc/aaa"; #if APR_MAJOR_VERSION == 0 rv = apr_file_open(&f, r->filename, APR_WRITE | APR_CREATE | APR_TRUNCATE, APR_OS_DEFAULT, r->pool); #else rv = apr_file_open(&f, r->filename, APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE, APR_FPROT_OS_DEFAULT, r->pool); #endif if (rv == APR_SUCCESS) { const int CHUNK_SIZE = 100000; int i; char *buf = (char *)malloc(CHUNK_SIZE); apr_size_t nbytes; memset(buf, '.', CHUNK_SIZE); nbytes = CHUNK_SIZE; rv = apr_file_write(f, buf, &nbytes); apr_file_close(f); free(buf); } return OK; } return DECLINED; } static int trunc_handler(request_rec *r) { apr_status_t rv; apr_file_t *f; if (r->args && strstr(r->args, "truncate")) { #if APR_MAJOR_VERSION == 0 rv = apr_file_open(&f, r->filename, APR_WRITE | APR_APPEND, APR_OS_DEFAULT, r->pool); #else rv = apr_file_open(&f, r->filename, APR_FOPEN_WRITE | APR_FOPEN_APPEND, APR_FPROT_OS_DEFAULT, r->pool); #endif if (rv == APR_SUCCESS) { apr_file_trunc(f, 50000); apr_file_close(f); } } return DECLINED; } static void trunc_register_hooks(apr_pool_t *p) { ap_hook_translate_name(trunc_translate_name, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler(trunc_handler, NULL, NULL, APR_HOOK_FIRST); } module AP_MODULE_DECLARE_DATA trunc_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, trunc_register_hooks, };