X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=support%2Fhtcacheclean.c;h=43d5117dd2f021916e592b32c50fe0e9d468f428;hb=55f3e480134c1b9d79285e3976132eda08ea787a;hp=83b0b3affbd473ba40835e078ee32cd267d77c96;hpb=1e9e5a69cbdaaca861dbb9fc4f103b972c850dcb;p=apache diff --git a/support/htcacheclean.c b/support/htcacheclean.c index 83b0b3affb..43d5117dd2 100644 --- a/support/htcacheclean.c +++ b/support/htcacheclean.c @@ -1,9 +1,9 @@ -/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as - * applicable. - * - * Licensed 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 +/* 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 * @@ -34,6 +34,8 @@ #include "apr_getopt.h" #include "apr_ring.h" #include "apr_date.h" +#include "apr_buckets.h" +#include "../modules/cache/mod_disk_cache.h" #if APR_HAVE_UNISTD_H #include @@ -42,55 +44,6 @@ #include #endif -/* mod_disk_cache.c extract start */ - -#define VARY_FORMAT_VERSION 1 -#define DISK_FORMAT_VERSION 2 - -typedef struct { - /* Indicates the format of the header struct stored on-disk. */ - apr_uint32_t format; - /* The HTTP status code returned for this response. */ - int status; - /* The size of the entity name that follows. */ - apr_size_t name_len; - /* The number of times we've cached this entity. */ - apr_size_t entity_version; - /* Miscellaneous time values. */ - apr_time_t date; - apr_time_t expire; - apr_time_t request_time; - apr_time_t response_time; -} disk_cache_info_t; - -#define CACHE_HEADER_SUFFIX ".header" -#define CACHE_DATA_SUFFIX ".data" -/* mod_disk_cache.c extract end */ - -/* mod_disk_cache.c related definitions start */ - -/* - * this is based on #define AP_TEMPFILE "/aptmpXXXXXX" - * - * the above definition could be reworked into the following: - * - * #define AP_TEMPFILE_PREFIX "/" - * #define AP_TEMPFILE_BASE "aptmp" - * #define AP_TEMPFILE_SUFFIX "XXXXXX" - * #define AP_TEMPFILE_BASELEN strlen(AP_TEMPFILE_BASE) - * #define AP_TEMPFILE_NAMELEN strlen(AP_TEMPFILE_BASE AP_TEMPFILE_SUFFIX) - * #define AP_TEMPFILE AP_TEMPFILE_PREFIX AP_TEMPFILE_BASE AP_TEMPFILE_SUFFIX - * - * these definitions would then match the definitions below: - */ - -#define AP_TEMPFILE_BASE "aptmp" -#define AP_TEMPFILE_SUFFIX "XXXXXX" -#define AP_TEMPFILE_BASELEN strlen(AP_TEMPFILE_BASE) -#define AP_TEMPFILE_NAMELEN strlen(AP_TEMPFILE_BASE AP_TEMPFILE_SUFFIX) - -/* mod_disk_cache.c related definitions end */ - /* define the following for debugging */ #undef DEBUG @@ -111,6 +64,7 @@ typedef struct { #define SECS_PER_MIN 60 #define KBYTE 1024 #define MBYTE 1048576 +#define GBYTE 1073741824 #define DIRINFO (APR_FINFO_MTIME|APR_FINFO_SIZE|APR_FINFO_TYPE|APR_FINFO_LINK) @@ -388,7 +342,7 @@ static int process_dir(char *path, apr_pool_t *pool) } } - /* this may look strange but apr_stat() may return errno which + /* this may look strange but apr_stat() may return an error which * is system dependent and there may be transient failures, * so just blindly retry for a short while */ @@ -497,10 +451,10 @@ static int process_dir(char *path, apr_pool_t *pool) case HEADERDATA: nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); - if (apr_file_open(&fd, nextpath, APR_READ, APR_OS_DEFAULT, - p) == APR_SUCCESS) { + if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, + APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); - if (apr_file_read_full(fd, &format, len, + if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == DISK_FORMAT_VERSION) { apr_off_t offset = 0; @@ -520,9 +474,7 @@ static int process_dir(char *path, apr_pool_t *pool) e->dtime = d->dtime; e->hsize = d->hsize; e->dsize = d->dsize; - e->basename = apr_palloc(pool, - strlen(d->basename) + 1); - strcpy(e->basename, d->basename); + e->basename = apr_pstrdup(pool, d->basename); break; } else { @@ -530,13 +482,14 @@ static int process_dir(char *path, apr_pool_t *pool) } } else if (format == VARY_FORMAT_VERSION) { - /* This must be a URL that added Vary headers later, + /* This must be a URL that added Vary headers later, * so kill the orphaned .data file */ apr_file_close(fd); - apr_file_remove(apr_pstrcat(p, path, "/", d->basename, + apr_file_remove(apr_pstrcat(p, path, "/", d->basename, CACHE_DATA_SUFFIX, NULL), p); + break; } } else { @@ -570,24 +523,26 @@ static int process_dir(char *path, apr_pool_t *pool) current = apr_time_now(); nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); - if (apr_file_open(&fd, nextpath, APR_READ, APR_OS_DEFAULT, - p) == APR_SUCCESS) { + if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, + APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); - if (apr_file_read_full(fd, &format, len, + if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == VARY_FORMAT_VERSION) { apr_time_t expires; len = sizeof(expires); - apr_file_read_full(fd, &expires, len, &len); + if (apr_file_read_full(fd, &expires, len, + &len) == APR_SUCCESS) { - apr_file_close(fd); + apr_file_close(fd); - if (expires < current) { - delete_entry(path, d->basename, p); + if (expires < current) { + delete_entry(path, d->basename, p); + } + break; } - break; } } apr_file_close(fd); @@ -746,12 +701,15 @@ static void purge(char *path, apr_pool_t *pool, apr_off_t max) * usage info */ #define NL APR_EOL_STR -static void usage(void) +static void usage(const char *error) { + if (error) { + apr_file_printf(errfile, "%s error: %s\n", shortname, error); + } apr_file_printf(errfile, "%s -- program for cleaning the disk cache." NL - "Usage: %s [-Dvtrn] -pPATH -lLIMIT" NL - " %s [-nti] -dINTERVAL -pPATH -lLIMIT" NL + "Usage: %s [-Dvtrn] -pPATH -lLIMIT [-PPIDFILE]" NL + " %s [-nti] -dINTERVAL -pPATH -lLIMIT [-PPIDFILE]" NL NL "Options:" NL " -d Daemonize and repeat cache cleaning every INTERVAL minutes." NL @@ -777,6 +735,8 @@ static void usage(void) NL " -p Specify PATH as the root directory of the disk cache." NL NL + " -P Specify PIDFILE as the file to write the pid to." NL + NL " -l Specify LIMIT as the total disk cache size limit. Attach 'K'" NL " or 'M' to the number for specifying KBytes or MBytes." NL NL @@ -792,6 +752,12 @@ static void usage(void) } #undef NL +static void usage_repeated_arg(apr_pool_t *pool, char option) { + usage(apr_psprintf(pool, + "The option '%c' cannot be specified more than once", + option)); +} + /* * main */ @@ -806,7 +772,8 @@ int main(int argc, const char * const argv[]) int retries, isdaemon, limit_found, intelligent, dowork; char opt; const char *arg; - char *proxypath, *path; + char *proxypath, *path, *pidfile; + char errmsg[1024]; interrupted = 0; repeat = 0; @@ -821,6 +788,7 @@ int main(int argc, const char * const argv[]) intelligent = 0; previous = 0; /* avoid compiler warning */ proxypath = NULL; + pidfile = NULL; if (apr_app_initialize(&argc, &argv, NULL) != APR_SUCCESS) { return 1; @@ -842,53 +810,53 @@ int main(int argc, const char * const argv[]) apr_getopt_init(&o, pool, argc, argv); while (1) { - status = apr_getopt(o, "iDnvrtd:l:L:p:", &opt, &arg); + status = apr_getopt(o, "iDnvrtd:l:L:p:P:", &opt, &arg); if (status == APR_EOF) { break; } else if (status != APR_SUCCESS) { - usage(); + usage(NULL); } else { switch (opt) { case 'i': if (intelligent) { - usage(); + usage_repeated_arg(pool, opt); } intelligent = 1; break; case 'D': if (dryrun) { - usage(); + usage_repeated_arg(pool, opt); } dryrun = 1; break; case 'n': if (benice) { - usage(); + usage_repeated_arg(pool, opt); } benice = 1; break; - + case 't': if (deldirs) { - usage(); + usage_repeated_arg(pool, opt); } deldirs = 1; break; case 'v': if (verbose) { - usage(); + usage_repeated_arg(pool, opt); } verbose = 1; break; case 'r': if (realclean) { - usage(); + usage_repeated_arg(pool, opt); } realclean = 1; deldirs = 1; @@ -896,7 +864,7 @@ int main(int argc, const char * const argv[]) case 'd': if (isdaemon) { - usage(); + usage_repeated_arg(pool, opt); } isdaemon = 1; repeat = apr_atoi64(arg); @@ -906,7 +874,7 @@ int main(int argc, const char * const argv[]) case 'l': if (limit_found) { - usage(); + usage_repeated_arg(pool, opt); } limit_found = 1; @@ -922,50 +890,74 @@ int main(int argc, const char * const argv[]) else if ((*end == 'M' || *end == 'm') && !end[1]) { max *= MBYTE; } + else if ((*end == 'G' || *end == 'g') && !end[1]) { + max *= GBYTE; + } else if (*end && /* neither empty nor [Bb] */ ((*end != 'B' && *end != 'b') || end[1])) { rv = APR_EGENERAL; } } if (rv != APR_SUCCESS) { - apr_file_printf(errfile, "Invalid limit: %s" - APR_EOL_STR APR_EOL_STR, arg); - usage(); + usage(apr_psprintf(pool, "Invalid limit: %s" + APR_EOL_STR APR_EOL_STR, arg)); } } while(0); break; case 'p': if (proxypath) { - usage(); + usage_repeated_arg(pool, opt); } proxypath = apr_pstrdup(pool, arg); - if (apr_filepath_set(proxypath, pool) != APR_SUCCESS) { - usage(); + if ((status = apr_filepath_set(proxypath, pool)) != APR_SUCCESS) { + usage(apr_psprintf(pool, "Could not set filepath to '%s': %s", + proxypath, apr_strerror(status, errmsg, sizeof errmsg))); } break; + + case 'P': + if (pidfile) { + usage_repeated_arg(pool, opt); + } + pidfile = apr_pstrdup(pool, arg); + break; + } /* switch */ } /* else */ } /* while */ + if (argc <= 1) { + usage(NULL); + } + if (o->ind != argc) { - usage(); + usage("Additional parameters specified on the command line, aborting"); + } + + if (isdaemon && repeat <= 0) { + usage("Option -d must be greater than zero"); } - if (isdaemon && (repeat <= 0 || verbose || realclean || dryrun)) { - usage(); + if (isdaemon && (verbose || realclean || dryrun)) { + usage("Option -d cannot be used with -v, -r or -D"); } if (!isdaemon && intelligent) { - usage(); + usage("Option -i cannot be used without -d"); + } + + if (!proxypath) { + usage("Option -p must be specified"); } - if (!proxypath || max <= 0) { - usage(); + if (max <= 0) { + usage("Option -l must be greater than zero"); } if (apr_filepath_get(&path, 0, pool) != APR_SUCCESS) { - usage(); + usage(apr_psprintf(pool, "Could not get the filepath: %s", + apr_strerror(status, errmsg, sizeof errmsg))); } baselen = strlen(path); @@ -976,6 +968,21 @@ int main(int argc, const char * const argv[]) } #endif + if (pidfile) { + apr_file_t *file; + pid_t mypid = getpid(); + if (APR_SUCCESS == (status = apr_file_open(&file, pidfile, APR_WRITE + | APR_CREATE | APR_TRUNCATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, pool))) { + apr_file_printf(file, "%" APR_PID_T_FMT APR_EOL_STR, mypid); + } + else if (!isdaemon) { + apr_file_printf(errfile, + "Could not write the pid file '%s': %s" APR_EOL_STR, + pidfile, apr_strerror(status, errmsg, sizeof errmsg)); + } + } + do { apr_pool_create(&instance, pool);