|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* htcacheclean.c: simple program for cleaning of
|
|
Packit |
90a5c9 |
* the disk cache of the Apache HTTP server
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Contributed by Andreas Steinmetz <ast domdv.de>
|
|
Packit |
90a5c9 |
* 8 Oct 2004
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "apr.h"
|
|
Packit |
90a5c9 |
#include "apr_lib.h"
|
|
Packit |
90a5c9 |
#include "apr_strings.h"
|
|
Packit |
90a5c9 |
#include "apr_file_io.h"
|
|
Packit |
90a5c9 |
#include "apr_file_info.h"
|
|
Packit |
90a5c9 |
#include "apr_pools.h"
|
|
Packit |
90a5c9 |
#include "apr_hash.h"
|
|
Packit |
90a5c9 |
#include "apr_thread_proc.h"
|
|
Packit |
90a5c9 |
#include "apr_signal.h"
|
|
Packit |
90a5c9 |
#include "apr_getopt.h"
|
|
Packit |
90a5c9 |
#include "apr_md5.h"
|
|
Packit |
90a5c9 |
#include "apr_ring.h"
|
|
Packit |
90a5c9 |
#include "apr_date.h"
|
|
Packit |
90a5c9 |
#include "apr_buckets.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "../modules/cache/cache_common.h"
|
|
Packit |
90a5c9 |
#include "../modules/cache/cache_disk_common.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#if APR_HAVE_UNISTD_H
|
|
Packit |
90a5c9 |
#include <unistd.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#if APR_HAVE_STDLIB_H
|
|
Packit |
90a5c9 |
#include <stdlib.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* define the following for debugging */
|
|
Packit |
90a5c9 |
#undef DEBUG
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* Note: on Linux delays <= 2ms are busy waits without
|
|
Packit |
90a5c9 |
* scheduling, so never use a delay <= 2ms below
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define NICE_DELAY 10000 /* usecs */
|
|
Packit |
90a5c9 |
#define DELETE_NICE 10 /* be nice after this amount of delete ops */
|
|
Packit |
90a5c9 |
#define STAT_ATTEMPTS 10 /* maximum stat attempts for a file */
|
|
Packit |
90a5c9 |
#define STAT_DELAY 5000 /* usecs */
|
|
Packit |
90a5c9 |
#define HEADER 1 /* headers file */
|
|
Packit |
90a5c9 |
#define DATA 2 /* body file */
|
|
Packit |
90a5c9 |
#define TEMP 4 /* temporary file */
|
|
Packit |
90a5c9 |
#define HEADERDATA (HEADER|DATA)
|
|
Packit |
90a5c9 |
#define MAXDEVIATION 3600 /* secs */
|
|
Packit |
90a5c9 |
#define SECS_PER_MIN 60
|
|
Packit |
90a5c9 |
#define KBYTE 1024
|
|
Packit |
90a5c9 |
#define MBYTE 1048576
|
|
Packit |
90a5c9 |
#define GBYTE 1073741824
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define DIRINFO (APR_FINFO_MTIME|APR_FINFO_SIZE|APR_FINFO_TYPE|APR_FINFO_LINK)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct _direntry {
|
|
Packit |
90a5c9 |
APR_RING_ENTRY(_direntry) link;
|
|
Packit |
90a5c9 |
int type; /* type of file/fileset: TEMP, HEADER, DATA, HEADERDATA */
|
|
Packit |
90a5c9 |
apr_time_t htime; /* headers file modification time */
|
|
Packit |
90a5c9 |
apr_time_t dtime; /* body file modification time */
|
|
Packit |
90a5c9 |
apr_off_t hsize; /* headers file size */
|
|
Packit |
90a5c9 |
apr_off_t dsize; /* body or temporary file size */
|
|
Packit |
90a5c9 |
char *basename; /* file/fileset base name */
|
|
Packit |
90a5c9 |
} DIRENTRY;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct _entry {
|
|
Packit |
90a5c9 |
APR_RING_ENTRY(_entry) link;
|
|
Packit |
90a5c9 |
apr_time_t expire; /* cache entry exiration time */
|
|
Packit |
90a5c9 |
apr_time_t response_time; /* cache entry time of last response to client */
|
|
Packit |
90a5c9 |
apr_time_t htime; /* headers file modification time */
|
|
Packit |
90a5c9 |
apr_time_t dtime; /* body file modification time */
|
|
Packit |
90a5c9 |
apr_off_t hsize; /* headers file size */
|
|
Packit |
90a5c9 |
apr_off_t dsize; /* body or temporary file size */
|
|
Packit |
90a5c9 |
char *basename; /* fileset base name */
|
|
Packit |
90a5c9 |
} ENTRY;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int delcount; /* file deletion count for nice mode */
|
|
Packit |
90a5c9 |
static int interrupted; /* flag: true if SIGINT or SIGTERM occurred */
|
|
Packit |
90a5c9 |
static int realclean; /* flag: true means user said apache is not running */
|
|
Packit |
90a5c9 |
static int verbose; /* flag: true means print statistics */
|
|
Packit |
90a5c9 |
static int benice; /* flag: true means nice mode is activated */
|
|
Packit |
90a5c9 |
static int dryrun; /* flag: true means dry run, don't actually delete
|
|
Packit |
90a5c9 |
anything */
|
|
Packit |
90a5c9 |
static int deldirs; /* flag: true means directories should be deleted */
|
|
Packit |
90a5c9 |
static int listurls; /* flag: true means list cached urls */
|
|
Packit |
90a5c9 |
static int listextended;/* flag: true means list cached urls */
|
|
Packit |
90a5c9 |
static int baselen; /* string length of the path to the proxy directory */
|
|
Packit |
90a5c9 |
static apr_time_t now; /* start time of this processing run */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_file_t *errfile; /* stderr file handle */
|
|
Packit |
90a5c9 |
static apr_file_t *outfile; /* stdout file handle */
|
|
Packit |
90a5c9 |
static apr_off_t unsolicited; /* file size summary for deleted unsolicited
|
|
Packit |
90a5c9 |
files */
|
|
Packit |
90a5c9 |
static APR_RING_ENTRY(_entry) root; /* ENTRY ring anchor */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* short program name as called */
|
|
Packit |
90a5c9 |
static const char *shortname = "htcacheclean";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* what did we clean? */
|
|
Packit |
90a5c9 |
struct stats {
|
|
Packit |
90a5c9 |
apr_off_t total;
|
|
Packit |
90a5c9 |
apr_off_t sum;
|
|
Packit |
90a5c9 |
apr_off_t max;
|
|
Packit |
90a5c9 |
apr_off_t ntotal;
|
|
Packit |
90a5c9 |
apr_off_t nodes;
|
|
Packit |
90a5c9 |
apr_off_t inodes;
|
|
Packit |
90a5c9 |
apr_off_t etotal;
|
|
Packit |
90a5c9 |
apr_off_t entries;
|
|
Packit |
90a5c9 |
apr_off_t dfuture;
|
|
Packit |
90a5c9 |
apr_off_t dexpired;
|
|
Packit |
90a5c9 |
apr_off_t dfresh;
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#ifdef DEBUG
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* fake delete for debug purposes
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
#define apr_file_remove fake_file_remove
|
|
Packit |
90a5c9 |
static void fake_file_remove(char *pathname, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_finfo_t info;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* stat and printing to simulate some deletion system load and to
|
|
Packit |
90a5c9 |
display what would actually have happened */
|
|
Packit |
90a5c9 |
apr_stat(&info, pathname, DIRINFO, p);
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "would delete %s" APR_EOL_STR, pathname);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* called on SIGINT or SIGTERM
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void setterm(int unused)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
#ifdef DEBUG
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "interrupt" APR_EOL_STR);
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
interrupted = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* called in out of memory condition
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static int oom(int unused)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
static int called = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* be careful to call exit() only once */
|
|
Packit |
90a5c9 |
if (!called) {
|
|
Packit |
90a5c9 |
called = 1;
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return APR_ENOMEM;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* print purge statistics
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void printstats(char *path, struct stats *s)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char ttype, stype, mtype, utype;
|
|
Packit |
90a5c9 |
apr_off_t tfrag, sfrag, ufrag;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!verbose) {
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ttype = 'K';
|
|
Packit |
90a5c9 |
tfrag = ((s->total * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
s->total /= KBYTE;
|
|
Packit |
90a5c9 |
if (s->total >= KBYTE) {
|
|
Packit |
90a5c9 |
ttype = 'M';
|
|
Packit |
90a5c9 |
tfrag = ((s->total * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
s->total /= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
stype = 'K';
|
|
Packit |
90a5c9 |
sfrag = ((s->sum * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
s->sum /= KBYTE;
|
|
Packit |
90a5c9 |
if (s->sum >= KBYTE) {
|
|
Packit |
90a5c9 |
stype = 'M';
|
|
Packit |
90a5c9 |
sfrag = ((s->sum * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
s->sum /= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
mtype = 'K';
|
|
Packit |
90a5c9 |
s->max /= KBYTE;
|
|
Packit |
90a5c9 |
if (s->max >= KBYTE) {
|
|
Packit |
90a5c9 |
mtype = 'M';
|
|
Packit |
90a5c9 |
s->max /= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Cleaned %s. Statistics:" APR_EOL_STR, path);
|
|
Packit |
90a5c9 |
if (unsolicited) {
|
|
Packit |
90a5c9 |
utype = 'K';
|
|
Packit |
90a5c9 |
ufrag = ((unsolicited * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
unsolicited /= KBYTE;
|
|
Packit |
90a5c9 |
if (unsolicited >= KBYTE) {
|
|
Packit |
90a5c9 |
utype = 'M';
|
|
Packit |
90a5c9 |
ufrag = ((unsolicited * 10) / KBYTE) % 10;
|
|
Packit |
90a5c9 |
unsolicited /= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!unsolicited && !ufrag) {
|
|
Packit |
90a5c9 |
ufrag = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "unsolicited size %d.%d%c" APR_EOL_STR,
|
|
Packit |
90a5c9 |
(int)(unsolicited), (int)(ufrag), utype);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "size limit %" APR_OFF_T_FMT ".0%c" APR_EOL_STR,
|
|
Packit |
90a5c9 |
s->max, mtype);
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "inodes limit %" APR_OFF_T_FMT APR_EOL_STR,
|
|
Packit |
90a5c9 |
s->inodes);
|
|
Packit |
90a5c9 |
apr_file_printf(
|
|
Packit |
90a5c9 |
errfile,
|
|
Packit |
90a5c9 |
"total size was %" APR_OFF_T_FMT ".%" APR_OFF_T_FMT "%c, total size now "
|
|
Packit |
90a5c9 |
"%" APR_OFF_T_FMT ".%" APR_OFF_T_FMT "%c" APR_EOL_STR, s->total,
|
|
Packit |
90a5c9 |
tfrag, ttype, s->sum, sfrag, stype);
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "total inodes was %" APR_OFF_T_FMT
|
|
Packit |
90a5c9 |
", total %sinodes now "
|
|
Packit |
90a5c9 |
"%" APR_OFF_T_FMT APR_EOL_STR, s->ntotal, dryrun && deldirs ? "estimated "
|
|
Packit |
90a5c9 |
: "", s->nodes);
|
|
Packit |
90a5c9 |
apr_file_printf(
|
|
Packit |
90a5c9 |
errfile,
|
|
Packit |
90a5c9 |
"total entries was %" APR_OFF_T_FMT ", total entries now %" APR_OFF_T_FMT
|
|
Packit |
90a5c9 |
APR_EOL_STR, s->etotal, s->entries);
|
|
Packit |
90a5c9 |
apr_file_printf(
|
|
Packit |
90a5c9 |
errfile,
|
|
Packit |
90a5c9 |
"%" APR_OFF_T_FMT " entries deleted (%" APR_OFF_T_FMT " from future, %"
|
|
Packit |
90a5c9 |
APR_OFF_T_FMT " expired, %" APR_OFF_T_FMT " fresh)" APR_EOL_STR,
|
|
Packit |
90a5c9 |
(s->etotal - s->entries), s->dfuture, s->dexpired, s->dfresh);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Round the value up to the given threshold.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static apr_size_t round_up(apr_size_t val, apr_off_t round) {
|
|
Packit |
90a5c9 |
if (round > 1) {
|
|
Packit |
90a5c9 |
return (apr_size_t)(((val + round - 1) / round) * round);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return val;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* delete parent directories
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void delete_parent(const char *path, const char *basename,
|
|
Packit |
90a5c9 |
apr_off_t *nodes, apr_pool_t *pool)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *nextpath, *name;
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* temp pool, otherwise lots of memory could be allocated */
|
|
Packit |
90a5c9 |
apr_pool_create(&p, pool);
|
|
Packit |
90a5c9 |
name = apr_pstrdup(p, basename);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* If asked to delete dirs, do so now. We don't care if it fails.
|
|
Packit |
90a5c9 |
* If it fails, it likely means there was something else there.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (deldirs && !dryrun) {
|
|
Packit |
90a5c9 |
const char *vary;
|
|
Packit |
90a5c9 |
char *end = strrchr(name, '/');
|
|
Packit |
90a5c9 |
while (end) {
|
|
Packit |
90a5c9 |
*end = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* remove the directory */
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", name, NULL);
|
|
Packit |
90a5c9 |
if (!apr_dir_remove(nextpath, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* vary directory found? */
|
|
Packit |
90a5c9 |
vary = strstr(name, CACHE_VDIR_SUFFIX);
|
|
Packit |
90a5c9 |
if (vary && !vary[sizeof(CACHE_VDIR_SUFFIX) - 1]) {
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", apr_pstrndup(p, name, vary
|
|
Packit |
90a5c9 |
- name), NULL);
|
|
Packit |
90a5c9 |
if (!apr_file_remove(nextpath, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
end = strrchr(name, '/');
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(p);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
if (++delcount >= DELETE_NICE) {
|
|
Packit |
90a5c9 |
apr_sleep(NICE_DELAY);
|
|
Packit |
90a5c9 |
delcount = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* delete a single file
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void delete_file(char *path, char *basename, apr_off_t *nodes,
|
|
Packit |
90a5c9 |
apr_pool_t *pool)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *nextpath;
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* temp pool, otherwise lots of memory could be allocated */
|
|
Packit |
90a5c9 |
apr_pool_create(&p, pool);
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", basename, NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (dryrun) {
|
|
Packit |
90a5c9 |
apr_finfo_t finfo;
|
|
Packit |
90a5c9 |
if (!apr_stat(&finfo, nextpath, APR_FINFO_NLINK, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!apr_file_remove(nextpath, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(p);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
if (++delcount >= DELETE_NICE) {
|
|
Packit |
90a5c9 |
apr_sleep(NICE_DELAY);
|
|
Packit |
90a5c9 |
delcount = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
delete_parent(path, basename, nodes, pool);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* delete cache file set
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void delete_entry(char *path, char *basename, apr_off_t *nodes,
|
|
Packit |
90a5c9 |
apr_pool_t *pool)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char *nextpath;
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* temp pool, otherwise lots of memory could be allocated */
|
|
Packit |
90a5c9 |
apr_pool_create(&p, pool);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", basename, CACHE_HEADER_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
if (dryrun) {
|
|
Packit |
90a5c9 |
apr_finfo_t finfo;
|
|
Packit |
90a5c9 |
if (!apr_stat(&finfo, nextpath, APR_FINFO_NLINK, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!apr_file_remove(nextpath, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", basename, CACHE_DATA_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
if (dryrun) {
|
|
Packit |
90a5c9 |
apr_finfo_t finfo;
|
|
Packit |
90a5c9 |
if (!apr_stat(&finfo, nextpath, APR_FINFO_NLINK, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!apr_file_remove(nextpath, p)) {
|
|
Packit |
90a5c9 |
(*nodes)--;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(p);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
delcount += 2;
|
|
Packit |
90a5c9 |
if (delcount >= DELETE_NICE) {
|
|
Packit |
90a5c9 |
apr_sleep(NICE_DELAY);
|
|
Packit |
90a5c9 |
delcount = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
delete_parent(path, basename, nodes, pool);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* list the cache directory tree
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static int list_urls(char *path, apr_pool_t *pool, apr_off_t round)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_dir_t *dir;
|
|
Packit |
90a5c9 |
apr_finfo_t info;
|
|
Packit |
90a5c9 |
apr_size_t len;
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
apr_file_t *fd;
|
|
Packit |
90a5c9 |
const char *ext, *nextpath;
|
|
Packit |
90a5c9 |
char *url;
|
|
Packit |
90a5c9 |
apr_uint32_t format;
|
|
Packit |
90a5c9 |
disk_cache_info_t disk_info;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_create(&p, pool);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_dir_open(&dir, path, p) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (apr_dir_read(&info, APR_FINFO_TYPE, dir) == APR_SUCCESS && !interrupted) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (info.filetype == APR_DIR) {
|
|
Packit |
90a5c9 |
if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (list_urls(apr_pstrcat(p, path, "/", info.name, NULL), pool, round)) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
else if (info.filetype == APR_REG) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ext = strchr(info.name, '.');
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (ext && !strcasecmp(ext, CACHE_HEADER_SUFFIX)) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", info.name, NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_open(&fd, nextpath, APR_FOPEN_READ
|
|
Packit |
90a5c9 |
| APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
len = sizeof(format);
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &format, len, &len)
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (format == DISK_FORMAT_VERSION) {
|
|
Packit |
90a5c9 |
apr_off_t offset = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_seek(fd, APR_SET, &offset);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
len = sizeof(disk_cache_info_t);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &disk_info, len, &len)
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
len = disk_info.name_len;
|
|
Packit |
90a5c9 |
url = apr_palloc(p, len + 1);
|
|
Packit |
90a5c9 |
url[len] = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, url, len, &len)
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (listextended) {
|
|
Packit |
90a5c9 |
apr_finfo_t hinfo, dinfo;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* stat the header file */
|
|
Packit |
90a5c9 |
if (APR_SUCCESS != apr_file_info_get(
|
|
Packit |
90a5c9 |
&hinfo, APR_FINFO_SIZE, fd)) {
|
|
Packit |
90a5c9 |
/* ignore the file */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (disk_info.has_body && APR_SUCCESS
|
|
Packit |
90a5c9 |
!= apr_stat(
|
|
Packit |
90a5c9 |
&dinfo,
|
|
Packit |
90a5c9 |
apr_pstrcat(
|
|
Packit |
90a5c9 |
p,
|
|
Packit |
90a5c9 |
path,
|
|
Packit |
90a5c9 |
"/",
|
|
Packit |
90a5c9 |
apr_pstrndup(
|
|
Packit |
90a5c9 |
p,
|
|
Packit |
90a5c9 |
info.name,
|
|
Packit |
90a5c9 |
ext
|
|
Packit |
90a5c9 |
- info.name),
|
|
Packit |
90a5c9 |
CACHE_DATA_SUFFIX,
|
|
Packit |
90a5c9 |
NULL),
|
|
Packit |
90a5c9 |
APR_FINFO_SIZE
|
|
Packit |
90a5c9 |
| APR_FINFO_IDENT,
|
|
Packit |
90a5c9 |
p)) {
|
|
Packit |
90a5c9 |
/* ignore the file */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (disk_info.has_body && (dinfo.device
|
|
Packit |
90a5c9 |
!= disk_info.device
|
|
Packit |
90a5c9 |
|| dinfo.inode
|
|
Packit |
90a5c9 |
!= disk_info.inode)) {
|
|
Packit |
90a5c9 |
/* ignore the file */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_printf(
|
|
Packit |
90a5c9 |
outfile,
|
|
Packit |
90a5c9 |
"%s %" APR_SIZE_T_FMT
|
|
Packit |
90a5c9 |
" %" APR_SIZE_T_FMT
|
|
Packit |
90a5c9 |
" %d %" APR_SIZE_T_FMT
|
|
Packit |
90a5c9 |
" %" APR_TIME_T_FMT
|
|
Packit |
90a5c9 |
" %" APR_TIME_T_FMT
|
|
Packit |
90a5c9 |
" %" APR_TIME_T_FMT
|
|
Packit |
90a5c9 |
" %" APR_TIME_T_FMT
|
|
Packit |
90a5c9 |
" %d %d\n",
|
|
Packit |
90a5c9 |
url,
|
|
Packit |
90a5c9 |
round_up((apr_size_t)hinfo.size, round),
|
|
Packit |
90a5c9 |
round_up(
|
|
Packit |
90a5c9 |
disk_info.has_body ? (apr_size_t)dinfo.size
|
|
Packit |
90a5c9 |
: 0, round),
|
|
Packit |
90a5c9 |
disk_info.status,
|
|
Packit |
90a5c9 |
disk_info.entity_version,
|
|
Packit |
90a5c9 |
disk_info.date,
|
|
Packit |
90a5c9 |
disk_info.expire,
|
|
Packit |
90a5c9 |
disk_info.request_time,
|
|
Packit |
90a5c9 |
disk_info.response_time,
|
|
Packit |
90a5c9 |
disk_info.has_body,
|
|
Packit |
90a5c9 |
disk_info.header_only);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_finfo_t dinfo;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* stat the data file */
|
|
Packit |
90a5c9 |
if (disk_info.has_body && APR_SUCCESS
|
|
Packit |
90a5c9 |
!= apr_stat(
|
|
Packit |
90a5c9 |
&dinfo,
|
|
Packit |
90a5c9 |
apr_pstrcat(
|
|
Packit |
90a5c9 |
p,
|
|
Packit |
90a5c9 |
path,
|
|
Packit |
90a5c9 |
"/",
|
|
Packit |
90a5c9 |
apr_pstrndup(
|
|
Packit |
90a5c9 |
p,
|
|
Packit |
90a5c9 |
info.name,
|
|
Packit |
90a5c9 |
ext
|
|
Packit |
90a5c9 |
- info.name),
|
|
Packit |
90a5c9 |
CACHE_DATA_SUFFIX,
|
|
Packit |
90a5c9 |
NULL),
|
|
Packit |
90a5c9 |
APR_FINFO_SIZE
|
|
Packit |
90a5c9 |
| APR_FINFO_IDENT,
|
|
Packit |
90a5c9 |
p)) {
|
|
Packit |
90a5c9 |
/* ignore the file */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (disk_info.has_body && (dinfo.device
|
|
Packit |
90a5c9 |
!= disk_info.device
|
|
Packit |
90a5c9 |
|| dinfo.inode
|
|
Packit |
90a5c9 |
!= disk_info.inode)) {
|
|
Packit |
90a5c9 |
/* ignore the file */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_printf(outfile, "%s\n",
|
|
Packit |
90a5c9 |
url);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_dir_close(dir);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(p);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
apr_sleep(NICE_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* walk the cache directory tree
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static int process_dir(char *path, apr_pool_t *pool, apr_off_t *nodes)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_dir_t *dir;
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
apr_hash_t *h;
|
|
Packit |
90a5c9 |
apr_hash_index_t *i;
|
|
Packit |
90a5c9 |
apr_file_t *fd;
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
apr_finfo_t info;
|
|
Packit |
90a5c9 |
apr_size_t len;
|
|
Packit |
90a5c9 |
apr_time_t current, deviation;
|
|
Packit |
90a5c9 |
char *nextpath, *base, *ext;
|
|
Packit |
90a5c9 |
APR_RING_ENTRY(_direntry) anchor;
|
|
Packit |
90a5c9 |
DIRENTRY *d, *t, *n;
|
|
Packit |
90a5c9 |
ENTRY *e;
|
|
Packit |
90a5c9 |
int skip, retries;
|
|
Packit |
90a5c9 |
disk_cache_info_t disk_info;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
APR_RING_INIT(&anchor, _direntry, link);
|
|
Packit |
90a5c9 |
apr_pool_create(&p, pool);
|
|
Packit |
90a5c9 |
h = apr_hash_make(p);
|
|
Packit |
90a5c9 |
fd = NULL;
|
|
Packit |
90a5c9 |
deviation = MAXDEVIATION * APR_USEC_PER_SEC;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_dir_open(&dir, path, p) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) {
|
|
Packit |
90a5c9 |
if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
d = apr_pcalloc(p, sizeof(DIRENTRY));
|
|
Packit |
90a5c9 |
d->basename = apr_pstrcat(p, path, "/", info.name, NULL);
|
|
Packit |
90a5c9 |
APR_RING_INSERT_TAIL(&anchor, d, _direntry, link);
|
|
Packit |
90a5c9 |
(*nodes)++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_dir_close(dir);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
skip = baselen + 1;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (d = APR_RING_FIRST(&anchor);
|
|
Packit |
90a5c9 |
!interrupted && d != APR_RING_SENTINEL(&anchor, _direntry, link);
|
|
Packit |
90a5c9 |
d=n) {
|
|
Packit |
90a5c9 |
n = APR_RING_NEXT(d, link);
|
|
Packit |
90a5c9 |
base = strrchr(d->basename, '/');
|
|
Packit |
90a5c9 |
if (!base++) {
|
|
Packit |
90a5c9 |
base = d->basename;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ext = strchr(base, '.');
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* there may be temporary files which may be gone before
|
|
Packit |
90a5c9 |
* processing, always skip these if not in realclean mode
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (!ext && !realclean) {
|
|
Packit |
90a5c9 |
if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN)
|
|
Packit |
90a5c9 |
&& strlen(base) == AP_TEMPFILE_NAMELEN) {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* this may look strange but apr_stat() may return an error which
|
|
Packit |
90a5c9 |
* is system dependent and there may be transient failures,
|
|
Packit |
90a5c9 |
* so just blindly retry for a short while
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
retries = STAT_ATTEMPTS;
|
|
Packit |
90a5c9 |
status = APR_SUCCESS;
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_sleep(STAT_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
status = apr_stat(&info, d->basename, DIRINFO, p);
|
|
Packit |
90a5c9 |
} while (status != APR_SUCCESS && !interrupted && --retries);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* what may happen here is that apache did create a file which
|
|
Packit |
90a5c9 |
* we did detect but then does delete the file before we can
|
|
Packit |
90a5c9 |
* get file information, so if we don't get any file information
|
|
Packit |
90a5c9 |
* we will ignore the file in this case
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (!realclean && !interrupted) {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (info.filetype == APR_DIR) {
|
|
Packit |
90a5c9 |
if (process_dir(d->basename, pool, nodes)) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (info.filetype != APR_REG) {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!ext) {
|
|
Packit |
90a5c9 |
if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN)
|
|
Packit |
90a5c9 |
&& strlen(base) == AP_TEMPFILE_NAMELEN) {
|
|
Packit |
90a5c9 |
d->basename += skip;
|
|
Packit |
90a5c9 |
d->type = TEMP;
|
|
Packit |
90a5c9 |
d->dsize = info.size;
|
|
Packit |
90a5c9 |
apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(ext, CACHE_HEADER_SUFFIX)) {
|
|
Packit |
90a5c9 |
*ext = '\0';
|
|
Packit |
90a5c9 |
d->basename += skip;
|
|
Packit |
90a5c9 |
/* if a user manually creates a '.header' file */
|
|
Packit |
90a5c9 |
if (d->basename[0] == '\0') {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING);
|
|
Packit |
90a5c9 |
if (t) {
|
|
Packit |
90a5c9 |
d = t;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
d->type |= HEADER;
|
|
Packit |
90a5c9 |
d->htime = info.mtime;
|
|
Packit |
90a5c9 |
d->hsize = info.size;
|
|
Packit |
90a5c9 |
apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!strcasecmp(ext, CACHE_DATA_SUFFIX)) {
|
|
Packit |
90a5c9 |
*ext = '\0';
|
|
Packit |
90a5c9 |
d->basename += skip;
|
|
Packit |
90a5c9 |
/* if a user manually creates a '.data' file */
|
|
Packit |
90a5c9 |
if (d->basename[0] == '\0') {
|
|
Packit |
90a5c9 |
continue;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING);
|
|
Packit |
90a5c9 |
if (t) {
|
|
Packit |
90a5c9 |
d = t;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
d->type |= DATA;
|
|
Packit |
90a5c9 |
d->dtime = info.mtime;
|
|
Packit |
90a5c9 |
d->dsize = info.size;
|
|
Packit |
90a5c9 |
apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
path[baselen] = '\0';
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = apr_hash_first(p, h); i && !interrupted; i = apr_hash_next(i)) {
|
|
Packit |
90a5c9 |
void *hvalue;
|
|
Packit |
90a5c9 |
apr_uint32_t format;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_hash_this(i, NULL, NULL, &hvalue);
|
|
Packit |
90a5c9 |
d = hvalue;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
switch(d->type) {
|
|
Packit |
90a5c9 |
case HEADERDATA:
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", d->basename,
|
|
Packit |
90a5c9 |
CACHE_HEADER_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY,
|
|
Packit |
90a5c9 |
APR_OS_DEFAULT, p) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
len = sizeof(format);
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &format, len,
|
|
Packit |
90a5c9 |
&len) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (format == DISK_FORMAT_VERSION) {
|
|
Packit |
90a5c9 |
apr_off_t offset = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_seek(fd, APR_SET, &offset);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
len = sizeof(disk_cache_info_t);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &disk_info, len,
|
|
Packit |
90a5c9 |
&len) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
e = apr_palloc(pool, sizeof(ENTRY));
|
|
Packit |
90a5c9 |
APR_RING_INSERT_TAIL(&root, e, _entry, link);
|
|
Packit |
90a5c9 |
e->expire = disk_info.expire;
|
|
Packit |
90a5c9 |
e->response_time = disk_info.response_time;
|
|
Packit |
90a5c9 |
e->htime = d->htime;
|
|
Packit |
90a5c9 |
e->dtime = d->dtime;
|
|
Packit |
90a5c9 |
e->hsize = d->hsize;
|
|
Packit |
90a5c9 |
e->dsize = d->dsize;
|
|
Packit |
90a5c9 |
e->basename = apr_pstrdup(pool, d->basename);
|
|
Packit |
90a5c9 |
if (!disk_info.has_body) {
|
|
Packit |
90a5c9 |
delete_file(path, apr_pstrcat(p, path, "/",
|
|
Packit |
90a5c9 |
d->basename, CACHE_DATA_SUFFIX, NULL),
|
|
Packit |
90a5c9 |
nodes, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (format == VARY_FORMAT_VERSION) {
|
|
Packit |
90a5c9 |
apr_finfo_t finfo;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* This must be a URL that added Vary headers later,
|
|
Packit |
90a5c9 |
* so kill the orphaned .data file
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_stat(&finfo, apr_pstrcat(p, nextpath,
|
|
Packit |
90a5c9 |
CACHE_VDIR_SUFFIX, NULL), APR_FINFO_TYPE, p)
|
|
Packit |
90a5c9 |
|| finfo.filetype != APR_DIR) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
delete_file(path, apr_pstrcat(p, path, "/",
|
|
Packit |
90a5c9 |
d->basename, CACHE_DATA_SUFFIX, NULL),
|
|
Packit |
90a5c9 |
nodes, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
/* We didn't recognise the format, kill the files */
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
/* we have a somehow unreadable headers file which is associated
|
|
Packit |
90a5c9 |
* with a data file. this may be caused by apache currently
|
|
Packit |
90a5c9 |
* rewriting the headers file. thus we may delete the file set
|
|
Packit |
90a5c9 |
* either in realclean mode or if the headers file modification
|
|
Packit |
90a5c9 |
* timestamp is not within a specified positive or negative offset
|
|
Packit |
90a5c9 |
* to the current time.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
current = apr_time_now();
|
|
Packit |
90a5c9 |
if (realclean || d->htime < current - deviation
|
|
Packit |
90a5c9 |
|| d->htime > current + deviation) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
unsolicited += d->hsize;
|
|
Packit |
90a5c9 |
unsolicited += d->dsize;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* single data and header files may be deleted either in realclean
|
|
Packit |
90a5c9 |
* mode or if their modification timestamp is not within a
|
|
Packit |
90a5c9 |
* specified positive or negative offset to the current time.
|
|
Packit |
90a5c9 |
* this handling is necessary due to possible race conditions
|
|
Packit |
90a5c9 |
* between apache and this process
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
case HEADER:
|
|
Packit |
90a5c9 |
current = apr_time_now();
|
|
Packit |
90a5c9 |
nextpath = apr_pstrcat(p, path, "/", d->basename,
|
|
Packit |
90a5c9 |
CACHE_HEADER_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY,
|
|
Packit |
90a5c9 |
APR_OS_DEFAULT, p) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
len = sizeof(format);
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &format, len,
|
|
Packit |
90a5c9 |
&len) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (format == VARY_FORMAT_VERSION) {
|
|
Packit |
90a5c9 |
apr_time_t expires;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
len = sizeof(expires);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &expires, len,
|
|
Packit |
90a5c9 |
&len) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_finfo_t finfo;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_stat(&finfo, apr_pstrcat(p, nextpath,
|
|
Packit |
90a5c9 |
CACHE_VDIR_SUFFIX, NULL), APR_FINFO_TYPE, p)
|
|
Packit |
90a5c9 |
|| finfo.filetype != APR_DIR) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (expires < current) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (format == DISK_FORMAT_VERSION) {
|
|
Packit |
90a5c9 |
apr_off_t offset = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_file_seek(fd, APR_SET, &offset);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
len = sizeof(disk_cache_info_t);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_file_read_full(fd, &disk_info, len,
|
|
Packit |
90a5c9 |
&len) == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
e = apr_palloc(pool, sizeof(ENTRY));
|
|
Packit |
90a5c9 |
APR_RING_INSERT_TAIL(&root, e, _entry, link);
|
|
Packit |
90a5c9 |
e->expire = disk_info.expire;
|
|
Packit |
90a5c9 |
e->response_time = disk_info.response_time;
|
|
Packit |
90a5c9 |
e->htime = d->htime;
|
|
Packit |
90a5c9 |
e->dtime = d->dtime;
|
|
Packit |
90a5c9 |
e->hsize = d->hsize;
|
|
Packit |
90a5c9 |
e->dsize = d->dsize;
|
|
Packit |
90a5c9 |
e->basename = apr_pstrdup(pool, d->basename);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_file_close(fd);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (realclean || d->htime < current - deviation
|
|
Packit |
90a5c9 |
|| d->htime > current + deviation) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
unsolicited += d->hsize;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case DATA:
|
|
Packit |
90a5c9 |
current = apr_time_now();
|
|
Packit |
90a5c9 |
if (realclean || d->dtime < current - deviation
|
|
Packit |
90a5c9 |
|| d->dtime > current + deviation) {
|
|
Packit |
90a5c9 |
delete_entry(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
unsolicited += d->dsize;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* temp files may only be deleted in realclean mode which
|
|
Packit |
90a5c9 |
* is asserted above if a tempfile is in the hash array
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
case TEMP:
|
|
Packit |
90a5c9 |
delete_file(path, d->basename, nodes, p);
|
|
Packit |
90a5c9 |
unsolicited += d->dsize;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(p);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
apr_sleep(NICE_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* purge cache entries
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static void purge(char *path, apr_pool_t *pool, apr_off_t max,
|
|
Packit |
90a5c9 |
apr_off_t inodes, apr_off_t nodes, apr_off_t round)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ENTRY *e, *n, *oldest;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct stats s;
|
|
Packit |
90a5c9 |
s.sum = 0;
|
|
Packit |
90a5c9 |
s.entries = 0;
|
|
Packit |
90a5c9 |
s.dfuture = 0;
|
|
Packit |
90a5c9 |
s.dexpired = 0;
|
|
Packit |
90a5c9 |
s.dfresh = 0;
|
|
Packit |
90a5c9 |
s.max = max;
|
|
Packit |
90a5c9 |
s.nodes = nodes;
|
|
Packit |
90a5c9 |
s.inodes = inodes;
|
|
Packit |
90a5c9 |
s.ntotal = nodes;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (e = APR_RING_FIRST(&root);
|
|
Packit |
90a5c9 |
e != APR_RING_SENTINEL(&root, _entry, link);
|
|
Packit |
90a5c9 |
e = APR_RING_NEXT(e, link)) {
|
|
Packit |
90a5c9 |
s.sum += round_up((apr_size_t)e->hsize, round);
|
|
Packit |
90a5c9 |
s.sum += round_up((apr_size_t)e->dsize, round);
|
|
Packit |
90a5c9 |
s.entries++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
s.total = s.sum;
|
|
Packit |
90a5c9 |
s.etotal = s.entries;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((!s.max || s.sum <= s.max) && (!s.inodes || s.nodes <= s.inodes)) {
|
|
Packit |
90a5c9 |
printstats(path, &s);
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* process all entries with a timestamp in the future, this may
|
|
Packit |
90a5c9 |
* happen if a wrong system time is corrected
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (e = APR_RING_FIRST(&root);
|
|
Packit |
90a5c9 |
e != APR_RING_SENTINEL(&root, _entry, link) && !interrupted;) {
|
|
Packit |
90a5c9 |
n = APR_RING_NEXT(e, link);
|
|
Packit |
90a5c9 |
if (e->response_time > now || e->htime > now || e->dtime > now) {
|
|
Packit |
90a5c9 |
delete_entry(path, e->basename, &s.nodes, pool);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)e->hsize, round);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)e->dsize, round);
|
|
Packit |
90a5c9 |
s.entries--;
|
|
Packit |
90a5c9 |
s.dfuture++;
|
|
Packit |
90a5c9 |
APR_RING_REMOVE(e, link);
|
|
Packit |
90a5c9 |
if ((!s.max || s.sum <= s.max) && (!s.inodes || s.nodes <= s.inodes)) {
|
|
Packit |
90a5c9 |
if (!interrupted) {
|
|
Packit |
90a5c9 |
printstats(path, &s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
e = n;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* process all entries with are expired */
|
|
Packit |
90a5c9 |
for (e = APR_RING_FIRST(&root);
|
|
Packit |
90a5c9 |
e != APR_RING_SENTINEL(&root, _entry, link) && !interrupted;) {
|
|
Packit |
90a5c9 |
n = APR_RING_NEXT(e, link);
|
|
Packit |
90a5c9 |
if (e->expire != APR_DATE_BAD && e->expire < now) {
|
|
Packit |
90a5c9 |
delete_entry(path, e->basename, &s.nodes, pool);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)e->hsize, round);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)e->dsize, round);
|
|
Packit |
90a5c9 |
s.entries--;
|
|
Packit |
90a5c9 |
s.dexpired++;
|
|
Packit |
90a5c9 |
APR_RING_REMOVE(e, link);
|
|
Packit |
90a5c9 |
if ((!s.max || s.sum <= s.max) && (!s.inodes || s.nodes <= s.inodes)) {
|
|
Packit |
90a5c9 |
if (!interrupted) {
|
|
Packit |
90a5c9 |
printstats(path, &s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
e = n;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (interrupted) {
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* process remaining entries oldest to newest, the check for an empty
|
|
Packit |
90a5c9 |
* ring actually isn't necessary except when the compiler does
|
|
Packit |
90a5c9 |
* corrupt 64bit arithmetics which happened to me once, so better safe
|
|
Packit |
90a5c9 |
* than sorry
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
while (!((!s.max || s.sum <= s.max) && (!s.inodes || s.nodes <= s.inodes))
|
|
Packit |
90a5c9 |
&& !interrupted && !APR_RING_EMPTY(&root, _entry, link)) {
|
|
Packit |
90a5c9 |
oldest = APR_RING_FIRST(&root);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (e = APR_RING_NEXT(oldest, link);
|
|
Packit |
90a5c9 |
e != APR_RING_SENTINEL(&root, _entry, link);
|
|
Packit |
90a5c9 |
e = APR_RING_NEXT(e, link)) {
|
|
Packit |
90a5c9 |
if (e->dtime < oldest->dtime) {
|
|
Packit |
90a5c9 |
oldest = e;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
delete_entry(path, oldest->basename, &s.nodes, pool);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)oldest->hsize, round);
|
|
Packit |
90a5c9 |
s.sum -= round_up((apr_size_t)oldest->dsize, round);
|
|
Packit |
90a5c9 |
s.entries--;
|
|
Packit |
90a5c9 |
s.dfresh++;
|
|
Packit |
90a5c9 |
APR_RING_REMOVE(oldest, link);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!interrupted) {
|
|
Packit |
90a5c9 |
printstats(path, &s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t remove_directory(apr_pool_t *pool, const char *dir)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
apr_dir_t *dirp;
|
|
Packit |
90a5c9 |
apr_finfo_t dirent;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = apr_dir_open(&dirp, dir, pool);
|
|
Packit |
90a5c9 |
if (APR_STATUS_IS_ENOENT(rv)) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Could not open directory %s: %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
dir, &rv;;
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_TYPE, dirp)
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (dirent.filetype == APR_DIR) {
|
|
Packit |
90a5c9 |
if (strcmp(dirent.name, ".") && strcmp(dirent.name, "..")) {
|
|
Packit |
90a5c9 |
rv = remove_directory(pool, apr_pstrcat(pool, dir, "/",
|
|
Packit |
90a5c9 |
dirent.name, NULL));
|
|
Packit |
90a5c9 |
/* tolerate the directory not being empty, the cache may have
|
|
Packit |
90a5c9 |
* attempted to recreate the directory in the mean time.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (APR_SUCCESS != rv && APR_ENOTEMPTY != rv) {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
} else {
|
|
Packit |
90a5c9 |
const char *file = apr_pstrcat(pool, dir, "/", dirent.name, NULL);
|
|
Packit |
90a5c9 |
rv = apr_file_remove(file, pool);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS != rv) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile,
|
|
Packit |
90a5c9 |
"Could not remove file '%s': %pm" APR_EOL_STR, file,
|
|
Packit |
90a5c9 |
&rv;;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_dir_close(dirp);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (rv == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
rv = apr_dir_remove(dir, pool);
|
|
Packit |
90a5c9 |
if (APR_ENOTEMPTY == rv) {
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Could not remove directory %s: %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
dir, &rv;;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t find_directory(apr_pool_t *pool, const char *base,
|
|
Packit |
90a5c9 |
const char *rest)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
apr_dir_t *dirp;
|
|
Packit |
90a5c9 |
apr_finfo_t dirent;
|
|
Packit |
90a5c9 |
int found = 0, files = 0;
|
|
Packit |
90a5c9 |
const char *header = apr_pstrcat(pool, rest, CACHE_HEADER_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
const char *data = apr_pstrcat(pool, rest, CACHE_DATA_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
const char *vdir = apr_pstrcat(pool, rest, CACHE_HEADER_SUFFIX,
|
|
Packit |
90a5c9 |
CACHE_VDIR_SUFFIX, NULL);
|
|
Packit |
90a5c9 |
const char *dirname = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = apr_dir_open(&dirp, base, pool);
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Could not open directory %s: %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
base, &rv;;
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = APR_ENOENT;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_TYPE, dirp)
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
int len = strlen(dirent.name);
|
|
Packit |
90a5c9 |
int restlen = strlen(rest);
|
|
Packit |
90a5c9 |
if (dirent.filetype == APR_DIR && !strncmp(rest, dirent.name, len)) {
|
|
Packit |
90a5c9 |
dirname = apr_pstrcat(pool, base, "/", dirent.name, NULL);
|
|
Packit |
90a5c9 |
rv = find_directory(pool, dirname, rest + (len < restlen ? len
|
|
Packit |
90a5c9 |
: restlen));
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
found = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (dirent.filetype == APR_DIR) {
|
|
Packit |
90a5c9 |
if (!strcmp(dirent.name, vdir)) {
|
|
Packit |
90a5c9 |
files = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (dirent.filetype == APR_REG) {
|
|
Packit |
90a5c9 |
if (!strcmp(dirent.name, header) || !strcmp(dirent.name, data)) {
|
|
Packit |
90a5c9 |
files = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_dir_close(dirp);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (files) {
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
if (!dryrun) {
|
|
Packit |
90a5c9 |
const char *remove;
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
remove = apr_pstrcat(pool, base, "/", header, NULL);
|
|
Packit |
90a5c9 |
status = apr_file_remove(remove, pool);
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS && !APR_STATUS_IS_ENOENT(status)) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Could not remove file %s: %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
remove, &status);
|
|
Packit |
90a5c9 |
rv = status;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
remove = apr_pstrcat(pool, base, "/", data, NULL);
|
|
Packit |
90a5c9 |
status = apr_file_remove(remove, pool);
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS && !APR_STATUS_IS_ENOENT(status)) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Could not remove file %s: %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
remove, &status);
|
|
Packit |
90a5c9 |
rv = status;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
status = remove_directory(pool, apr_pstrcat(pool, base, "/", vdir, NULL));
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS && !APR_STATUS_IS_ENOENT(status)) {
|
|
Packit |
90a5c9 |
rv = status;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* If asked to delete dirs, do so now. We don't care if it fails.
|
|
Packit |
90a5c9 |
* If it fails, it likely means there was something else there.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (dirname && deldirs && !dryrun) {
|
|
Packit |
90a5c9 |
apr_dir_remove(dirname, pool);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (found) {
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Delete a specific URL from the cache.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static apr_status_t delete_url(apr_pool_t *pool, const char *proxypath, const char *url)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_md5_ctx_t context;
|
|
Packit |
90a5c9 |
unsigned char digest[16];
|
|
Packit |
90a5c9 |
char tmp[23];
|
|
Packit |
90a5c9 |
int i, k;
|
|
Packit |
90a5c9 |
unsigned int x;
|
|
Packit |
90a5c9 |
static const char enc_table[64] =
|
|
Packit |
90a5c9 |
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_md5_init(&context);
|
|
Packit |
90a5c9 |
apr_md5_update(&context, (const unsigned char *) url, strlen(url));
|
|
Packit |
90a5c9 |
apr_md5_final(digest, &context);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* encode 128 bits as 22 characters, using a modified uuencoding
|
|
Packit |
90a5c9 |
* the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
|
|
Packit |
90a5c9 |
* 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
for (i = 0, k = 0; i < 15; i += 3) {
|
|
Packit |
90a5c9 |
x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[x >> 18];
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[(x >> 12) & 0x3f];
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[(x >> 6) & 0x3f];
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[x & 0x3f];
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* one byte left */
|
|
Packit |
90a5c9 |
x = digest[15];
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */
|
|
Packit |
90a5c9 |
tmp[k++] = enc_table[(x << 4) & 0x3f];
|
|
Packit |
90a5c9 |
tmp[k] = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* automatically find the directory levels */
|
|
Packit |
90a5c9 |
return find_directory(pool, proxypath, tmp);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* usage info
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
#define NL APR_EOL_STR
|
|
Packit |
90a5c9 |
static void usage(const char *error)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (error) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "%s error: %s\n", shortname, error);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_file_printf(errfile,
|
|
Packit |
90a5c9 |
"%s -- program for cleaning the disk cache." NL
|
|
Packit |
90a5c9 |
"Usage: %s [-Dvtrn] -pPATH [-lLIMIT|-LLIMIT] [-PPIDFILE]" NL
|
|
Packit |
90a5c9 |
" %s [-nti] -dINTERVAL -pPATH [-lLIMIT|-LLIMIT] [-PPIDFILE]" NL
|
|
Packit |
90a5c9 |
" %s [-Dvt] -pPATH URL ..." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
"Options:" NL
|
|
Packit |
90a5c9 |
" -d Daemonize and repeat cache cleaning every INTERVAL minutes." NL
|
|
Packit |
90a5c9 |
" This option is mutually exclusive with the -D, -v and -r" NL
|
|
Packit |
90a5c9 |
" options." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -D Do a dry run and don't delete anything. This option is mutually" NL
|
|
Packit |
90a5c9 |
" exclusive with the -d option. When doing a dry run and deleting" NL
|
|
Packit |
90a5c9 |
" directories with -t, the inodes reported deleted in the stats" NL
|
|
Packit |
90a5c9 |
" cannot take into account the directories deleted, and will be" NL
|
|
Packit |
90a5c9 |
" marked as an estimate." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -v Be verbose and print statistics. This option is mutually" NL
|
|
Packit |
90a5c9 |
" exclusive with the -d option." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -r Clean thoroughly. This assumes that the Apache web server is " NL
|
|
Packit |
90a5c9 |
" not running. This option is mutually exclusive with the -d" NL
|
|
Packit |
90a5c9 |
" option and implies -t." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -n Be nice. This causes slower processing in favour of other" NL
|
|
Packit |
90a5c9 |
" processes." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -t Delete all empty directories. By default only cache files are" NL
|
|
Packit |
90a5c9 |
" removed, however with some configurations the large number of" NL
|
|
Packit |
90a5c9 |
" directories created may require attention." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -p Specify PATH as the root directory of the disk cache." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -P Specify PIDFILE as the file to write the pid to." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -R Specify amount to round sizes up to." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -l Specify LIMIT as the total disk cache size limit. Attach 'K'" NL
|
|
Packit |
90a5c9 |
" or 'M' to the number for specifying KBytes or MBytes." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -L Specify LIMIT as the total disk cache inode limit." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -i Be intelligent and run only when there was a modification of" NL
|
|
Packit |
90a5c9 |
" the disk cache. This option is only possible together with the" NL
|
|
Packit |
90a5c9 |
" -d option." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -a List the URLs currently stored in the cache. Variants of the" NL
|
|
Packit |
90a5c9 |
" same URL will be listed once for each variant." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
" -A List the URLs currently stored in the cache, along with their" NL
|
|
Packit |
90a5c9 |
" attributes in the following order: url, header size, body size," NL
|
|
Packit |
90a5c9 |
" status, entity version, date, expiry, request time," NL
|
|
Packit |
90a5c9 |
" response time, body present, head request." NL
|
|
Packit |
90a5c9 |
NL
|
|
Packit |
90a5c9 |
"Should an URL be provided on the command line, the URL will be" NL
|
|
Packit |
90a5c9 |
"deleted from the cache. A reverse proxied URL is made up as follows:" NL
|
|
Packit |
90a5c9 |
"http://<hostname>:<port><path>?[query]. So, for the path \"/\" on the" NL
|
|
Packit |
90a5c9 |
"host \"localhost\" and port 80, the URL to delete becomes" NL
|
|
Packit |
90a5c9 |
"\"http://localhost:80/?\". Note the '?' in the URL must always be" NL
|
|
Packit |
90a5c9 |
"specified explicitly, whether a query string is present or not." NL,
|
|
Packit |
90a5c9 |
shortname,
|
|
Packit |
90a5c9 |
shortname,
|
|
Packit |
90a5c9 |
shortname,
|
|
Packit |
90a5c9 |
shortname
|
|
Packit |
90a5c9 |
);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#undef NL
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void usage_repeated_arg(apr_pool_t *pool, char option) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool,
|
|
Packit |
90a5c9 |
"The option '%c' cannot be specified more than once",
|
|
Packit |
90a5c9 |
option));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void log_pid(apr_pool_t *pool, const char *pidfilename, apr_file_t **pidfile)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
pid_t mypid = getpid();
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (status = apr_file_open(pidfile, pidfilename,
|
|
Packit |
90a5c9 |
APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE |
|
|
Packit |
90a5c9 |
APR_FOPEN_DELONCLOSE, APR_FPROT_UREAD | APR_FPROT_UWRITE |
|
|
Packit |
90a5c9 |
APR_FPROT_GREAD | APR_FPROT_WREAD, pool))) {
|
|
Packit |
90a5c9 |
apr_file_printf(*pidfile, "%" APR_PID_T_FMT APR_EOL_STR, mypid);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
if (errfile) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile,
|
|
Packit |
90a5c9 |
"Could not write the pid file '%s': %pm" APR_EOL_STR,
|
|
Packit |
90a5c9 |
pidfilename, &status);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* main
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
int main(int argc, const char * const argv[])
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_off_t max, inodes, round;
|
|
Packit |
90a5c9 |
apr_time_t current, repeat, delay, previous;
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
apr_pool_t *pool, *instance;
|
|
Packit |
90a5c9 |
apr_getopt_t *o;
|
|
Packit |
90a5c9 |
apr_finfo_t info;
|
|
Packit |
90a5c9 |
apr_file_t *pidfile;
|
|
Packit |
90a5c9 |
int retries, isdaemon, limit_found, inodes_found, intelligent, dowork;
|
|
Packit |
90a5c9 |
char opt;
|
|
Packit |
90a5c9 |
const char *arg;
|
|
Packit |
90a5c9 |
char *proxypath, *path, *pidfilename;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
interrupted = 0;
|
|
Packit |
90a5c9 |
repeat = 0;
|
|
Packit |
90a5c9 |
isdaemon = 0;
|
|
Packit |
90a5c9 |
dryrun = 0;
|
|
Packit |
90a5c9 |
limit_found = 0;
|
|
Packit |
90a5c9 |
inodes_found = 0;
|
|
Packit |
90a5c9 |
max = 0;
|
|
Packit |
90a5c9 |
inodes = 0;
|
|
Packit |
90a5c9 |
round = 0;
|
|
Packit |
90a5c9 |
verbose = 0;
|
|
Packit |
90a5c9 |
realclean = 0;
|
|
Packit |
90a5c9 |
benice = 0;
|
|
Packit |
90a5c9 |
deldirs = 0;
|
|
Packit |
90a5c9 |
intelligent = 0;
|
|
Packit |
90a5c9 |
previous = 0; /* avoid compiler warning */
|
|
Packit |
90a5c9 |
proxypath = NULL;
|
|
Packit |
90a5c9 |
pidfilename = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_app_initialize(&argc, &argv, NULL) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
atexit(apr_terminate);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (argc) {
|
|
Packit |
90a5c9 |
shortname = apr_filepath_name_get(argv[0]);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_pool_abort_set(oom, pool);
|
|
Packit |
90a5c9 |
apr_file_open_stderr(&errfile, pool);
|
|
Packit |
90a5c9 |
apr_file_open_stdout(&outfile, pool);
|
|
Packit |
90a5c9 |
apr_signal(SIGINT, setterm);
|
|
Packit |
90a5c9 |
apr_signal(SIGTERM, setterm);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_getopt_init(&o, pool, argc, argv);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (1) {
|
|
Packit |
90a5c9 |
status = apr_getopt(o, "iDnvrtd:l:L:p:P:R:aA", &opt, &arg;;
|
|
Packit |
90a5c9 |
if (status == APR_EOF) {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
char *end;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
switch (opt) {
|
|
Packit |
90a5c9 |
case 'i':
|
|
Packit |
90a5c9 |
if (intelligent) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
intelligent = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'D':
|
|
Packit |
90a5c9 |
if (dryrun) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
dryrun = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'n':
|
|
Packit |
90a5c9 |
if (benice) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
benice = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 't':
|
|
Packit |
90a5c9 |
if (deldirs) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
deldirs = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'v':
|
|
Packit |
90a5c9 |
if (verbose) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
verbose = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'r':
|
|
Packit |
90a5c9 |
if (realclean) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
realclean = 1;
|
|
Packit |
90a5c9 |
deldirs = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'd':
|
|
Packit |
90a5c9 |
if (isdaemon) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
isdaemon = 1;
|
|
Packit |
90a5c9 |
repeat = apr_atoi64(arg);
|
|
Packit |
90a5c9 |
repeat *= SECS_PER_MIN;
|
|
Packit |
90a5c9 |
repeat *= APR_USEC_PER_SEC;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'l':
|
|
Packit |
90a5c9 |
if (limit_found) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
limit_found = 1;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
rv = apr_strtoff(&max, arg, &end, 10);
|
|
Packit |
90a5c9 |
if (rv == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if ((*end == 'K' || *end == 'k') && !end[1]) {
|
|
Packit |
90a5c9 |
max *= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if ((*end == 'M' || *end == 'm') && !end[1]) {
|
|
Packit |
90a5c9 |
max *= MBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if ((*end == 'G' || *end == 'g') && !end[1]) {
|
|
Packit |
90a5c9 |
max *= GBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (*end && /* neither empty nor [Bb] */
|
|
Packit |
90a5c9 |
((*end != 'B' && *end != 'b') || end[1])) {
|
|
Packit |
90a5c9 |
rv = APR_EGENERAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Invalid limit: %s"
|
|
Packit |
90a5c9 |
APR_EOL_STR APR_EOL_STR, arg));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
} while(0);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'L':
|
|
Packit |
90a5c9 |
if (inodes_found) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
inodes_found = 1;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
rv = apr_strtoff(&inodes, arg, &end, 10);
|
|
Packit |
90a5c9 |
if (rv == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if ((*end == 'K' || *end == 'k') && !end[1]) {
|
|
Packit |
90a5c9 |
inodes *= KBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if ((*end == 'M' || *end == 'm') && !end[1]) {
|
|
Packit |
90a5c9 |
inodes *= MBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if ((*end == 'G' || *end == 'g') && !end[1]) {
|
|
Packit |
90a5c9 |
inodes *= GBYTE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (*end && /* neither empty nor [Bb] */
|
|
Packit |
90a5c9 |
((*end != 'B' && *end != 'b') || end[1])) {
|
|
Packit |
90a5c9 |
rv = APR_EGENERAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Invalid limit: %s"
|
|
Packit |
90a5c9 |
APR_EOL_STR APR_EOL_STR, arg));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
} while(0);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'a':
|
|
Packit |
90a5c9 |
if (listurls) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
listurls = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'A':
|
|
Packit |
90a5c9 |
if (listurls) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
listurls = 1;
|
|
Packit |
90a5c9 |
listextended = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'p':
|
|
Packit |
90a5c9 |
if (proxypath) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
proxypath = apr_pstrdup(pool, arg);
|
|
Packit |
90a5c9 |
if ((status = apr_filepath_set(proxypath, pool)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Could not set filepath to '%s': %pm",
|
|
Packit |
90a5c9 |
proxypath, &status));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'P':
|
|
Packit |
90a5c9 |
if (pidfilename) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
pidfilename = apr_pstrdup(pool, arg);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 'R':
|
|
Packit |
90a5c9 |
if (round) {
|
|
Packit |
90a5c9 |
usage_repeated_arg(pool, opt);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
rv = apr_strtoff(&round, arg, &end, 10);
|
|
Packit |
90a5c9 |
if (rv == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (*end) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Invalid round value: %s"
|
|
Packit |
90a5c9 |
APR_EOL_STR APR_EOL_STR, arg));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (round < 0) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Round value must be positive: %s"
|
|
Packit |
90a5c9 |
APR_EOL_STR APR_EOL_STR, arg));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Invalid round value: %s"
|
|
Packit |
90a5c9 |
APR_EOL_STR APR_EOL_STR, arg));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
} /* switch */
|
|
Packit |
90a5c9 |
} /* else */
|
|
Packit |
90a5c9 |
} /* while */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (argc <= 1) {
|
|
Packit |
90a5c9 |
usage(NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!proxypath) {
|
|
Packit |
90a5c9 |
usage("Option -p must be specified");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (o->ind < argc) {
|
|
Packit |
90a5c9 |
int deleted = 0;
|
|
Packit |
90a5c9 |
int error = 0;
|
|
Packit |
90a5c9 |
if (isdaemon) {
|
|
Packit |
90a5c9 |
usage("Option -d cannot be used with URL arguments, aborting");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (intelligent) {
|
|
Packit |
90a5c9 |
usage("Option -i cannot be used with URL arguments, aborting");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (limit_found) {
|
|
Packit |
90a5c9 |
usage("Option -l cannot be used with URL arguments, aborting");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
while (o->ind < argc) {
|
|
Packit |
90a5c9 |
status = delete_url(pool, proxypath, argv[o->ind]);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == status) {
|
|
Packit |
90a5c9 |
if (verbose) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Removed: %s" APR_EOL_STR,
|
|
Packit |
90a5c9 |
argv[o->ind]);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
deleted = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (APR_ENOENT == status) {
|
|
Packit |
90a5c9 |
if (verbose) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Not cached: %s" APR_EOL_STR,
|
|
Packit |
90a5c9 |
argv[o->ind]);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
if (verbose) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Error while removed: %s" APR_EOL_STR,
|
|
Packit |
90a5c9 |
argv[o->ind]);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
error = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
o->ind++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return error ? 1 : deleted ? 0 : 2;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (isdaemon && repeat <= 0) {
|
|
Packit |
90a5c9 |
usage("Option -d must be greater than zero");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (isdaemon && (verbose || realclean || dryrun || listurls)) {
|
|
Packit |
90a5c9 |
usage("Option -d cannot be used with -v, -r, -L or -D");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!isdaemon && intelligent) {
|
|
Packit |
90a5c9 |
usage("Option -i cannot be used without -d");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!listurls && max <= 0 && inodes <= 0) {
|
|
Packit |
90a5c9 |
usage("At least one of option -l or -L must be greater than zero");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (apr_filepath_get(&path, 0, pool) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
usage(apr_psprintf(pool, "Could not get the filepath: %pm", &status));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
baselen = strlen(path);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (pidfilename) {
|
|
Packit |
90a5c9 |
log_pid(pool, pidfilename, &pidfile); /* before daemonizing, so we
|
|
Packit |
90a5c9 |
* can report errors
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (listurls) {
|
|
Packit |
90a5c9 |
list_urls(path, pool, round);
|
|
Packit |
90a5c9 |
return (interrupted != 0);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#ifndef DEBUG
|
|
Packit |
90a5c9 |
if (isdaemon) {
|
|
Packit |
90a5c9 |
apr_file_close(errfile);
|
|
Packit |
90a5c9 |
errfile = NULL;
|
|
Packit |
90a5c9 |
if (pidfilename) {
|
|
Packit |
90a5c9 |
apr_file_close(pidfile); /* delete original pidfile only in parent */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
|
|
Packit |
90a5c9 |
if (pidfilename) {
|
|
Packit |
90a5c9 |
log_pid(pool, pidfilename, &pidfile);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
apr_pool_create(&instance, pool);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
now = apr_time_now();
|
|
Packit |
90a5c9 |
APR_RING_INIT(&root, _entry, link);
|
|
Packit |
90a5c9 |
delcount = 0;
|
|
Packit |
90a5c9 |
unsolicited = 0;
|
|
Packit |
90a5c9 |
dowork = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
switch (intelligent) {
|
|
Packit |
90a5c9 |
case 0:
|
|
Packit |
90a5c9 |
dowork = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 1:
|
|
Packit |
90a5c9 |
retries = STAT_ATTEMPTS;
|
|
Packit |
90a5c9 |
status = APR_SUCCESS;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_sleep(STAT_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
status = apr_stat(&info, path, APR_FINFO_MTIME, instance);
|
|
Packit |
90a5c9 |
} while (status != APR_SUCCESS && !interrupted && --retries);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
previous = info.mtime;
|
|
Packit |
90a5c9 |
intelligent = 2;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
dowork = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
case 2:
|
|
Packit |
90a5c9 |
retries = STAT_ATTEMPTS;
|
|
Packit |
90a5c9 |
status = APR_SUCCESS;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_sleep(STAT_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
status = apr_stat(&info, path, APR_FINFO_MTIME, instance);
|
|
Packit |
90a5c9 |
} while (status != APR_SUCCESS && !interrupted && --retries);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (previous != info.mtime) {
|
|
Packit |
90a5c9 |
dowork = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
previous = info.mtime;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
intelligent = 1;
|
|
Packit |
90a5c9 |
dowork = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (dowork && !interrupted) {
|
|
Packit |
90a5c9 |
apr_off_t nodes = 0;
|
|
Packit |
90a5c9 |
if (!process_dir(path, instance, &nodes) && !interrupted) {
|
|
Packit |
90a5c9 |
purge(path, instance, max, inodes, nodes, round);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!isdaemon && !interrupted) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "An error occurred, cache cleaning "
|
|
Packit |
90a5c9 |
"aborted." APR_EOL_STR);
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (intelligent && !interrupted) {
|
|
Packit |
90a5c9 |
retries = STAT_ATTEMPTS;
|
|
Packit |
90a5c9 |
status = APR_SUCCESS;
|
|
Packit |
90a5c9 |
do {
|
|
Packit |
90a5c9 |
if (status != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
apr_sleep(STAT_DELAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
status = apr_stat(&info, path, APR_FINFO_MTIME, instance);
|
|
Packit |
90a5c9 |
} while (status != APR_SUCCESS && !interrupted && --retries);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
previous = info.mtime;
|
|
Packit |
90a5c9 |
intelligent = 2;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
intelligent = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_destroy(instance);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
current = apr_time_now();
|
|
Packit |
90a5c9 |
if (current < now) {
|
|
Packit |
90a5c9 |
delay = repeat;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (current - now >= repeat) {
|
|
Packit |
90a5c9 |
delay = repeat;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
delay = now + repeat - current;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* we can't sleep the whole delay time here apiece as this is racy
|
|
Packit |
90a5c9 |
* with respect to interrupt delivery - think about what happens
|
|
Packit |
90a5c9 |
* if we have tested for an interrupt, then get scheduled
|
|
Packit |
90a5c9 |
* before the apr_sleep() call and while waiting for the cpu
|
|
Packit |
90a5c9 |
* we do get an interrupt
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (isdaemon) {
|
|
Packit |
90a5c9 |
while (delay && !interrupted) {
|
|
Packit |
90a5c9 |
if (delay > APR_USEC_PER_SEC) {
|
|
Packit |
90a5c9 |
apr_sleep(APR_USEC_PER_SEC);
|
|
Packit |
90a5c9 |
delay -= APR_USEC_PER_SEC;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
apr_sleep(delay);
|
|
Packit |
90a5c9 |
delay = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
} while (isdaemon && !interrupted);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!isdaemon && interrupted) {
|
|
Packit |
90a5c9 |
apr_file_printf(errfile, "Cache cleaning aborted due to user "
|
|
Packit |
90a5c9 |
"request." APR_EOL_STR);
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|