summaryrefslogtreecommitdiffstats
path: root/modules/md/md_store_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/md/md_store_fs.c')
-rw-r--r--modules/md/md_store_fs.c426
1 files changed, 356 insertions, 70 deletions
diff --git a/modules/md/md_store_fs.c b/modules/md/md_store_fs.c
index f399cea..35c24b4 100644
--- a/modules/md/md_store_fs.c
+++ b/modules/md/md_store_fs.c
@@ -39,6 +39,7 @@
/* file system based implementation of md_store_t */
#define MD_STORE_VERSION 3
+#define MD_FS_LOCK_NAME "store.lock"
typedef struct {
apr_fileperms_t dir;
@@ -55,12 +56,13 @@ struct md_store_fs_t {
md_store_fs_cb *event_cb;
void *event_baton;
- const unsigned char *key;
- apr_size_t key_len;
+ md_data_t key;
int plain_pkey[MD_SG_COUNT];
int port_80;
int port_443;
+
+ apr_file_t *global_lock;
};
#define FS_STORE(store) (md_store_fs_t*)(((char*)store)-offsetof(md_store_fs_t, s))
@@ -78,12 +80,19 @@ static apr_status_t fs_remove(md_store_t *store, md_store_group_t group,
apr_pool_t *p, int force);
static apr_status_t fs_purge(md_store_t *store, apr_pool_t *p,
md_store_group_t group, const char *name);
+static apr_status_t fs_remove_nms(md_store_t *store, apr_pool_t *p,
+ apr_time_t modified, md_store_group_t group,
+ const char *name, const char *aspect);
static apr_status_t fs_move(md_store_t *store, apr_pool_t *p,
md_store_group_t from, md_store_group_t to,
const char *name, int archive);
+static apr_status_t fs_rename(md_store_t *store, apr_pool_t *p,
+ md_store_group_t group, const char *from, const char *to);
static apr_status_t fs_iterate(md_store_inspect *inspect, void *baton, md_store_t *store,
apr_pool_t *p, md_store_group_t group, const char *pattern,
const char *aspect, md_store_vtype_t vtype);
+static apr_status_t fs_iterate_names(md_store_inspect *inspect, void *baton, md_store_t *store,
+ apr_pool_t *p, md_store_group_t group, const char *pattern);
static apr_status_t fs_get_fname(const char **pfname,
md_store_t *store, md_store_group_t group,
@@ -92,23 +101,27 @@ static apr_status_t fs_get_fname(const char **pfname,
static int fs_is_newer(md_store_t *store, md_store_group_t group1, md_store_group_t group2,
const char *name, const char *aspect, apr_pool_t *p);
+static apr_time_t fs_get_modified(md_store_t *store, md_store_group_t group,
+ const char *name, const char *aspect, apr_pool_t *p);
+
+static apr_status_t fs_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait);
+static void fs_unlock_global(md_store_t *store, apr_pool_t *p);
+
static apr_status_t init_store_file(md_store_fs_t *s_fs, const char *fname,
apr_pool_t *p, apr_pool_t *ptemp)
{
md_json_t *json = md_json_create(p);
const char *key64;
- unsigned char *key;
apr_status_t rv;
md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
- s_fs->key_len = FS_STORE_KLEN;
- s_fs->key = key = apr_pcalloc(p, FS_STORE_KLEN);
- if (APR_SUCCESS != (rv = md_rand_bytes(key, s_fs->key_len, p))) {
+ md_data_pinit(&s_fs->key, FS_STORE_KLEN, p);
+ if (APR_SUCCESS != (rv = md_rand_bytes((unsigned char*)s_fs->key.data, s_fs->key.len, p))) {
return rv;
}
- key64 = md_util_base64url_encode((char *)key, s_fs->key_len, ptemp);
+ key64 = md_util_base64url_encode(&s_fs->key, ptemp);
md_json_sets(key64, json, MD_KEY_KEY, NULL);
rv = md_json_fcreatex(json, ptemp, MD_JSON_FMT_INDENT, fname, MD_FPROT_F_UONLY);
memset((char*)key64, 0, strlen(key64));
@@ -122,13 +135,12 @@ static apr_status_t rename_pkey(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
{
const char *from, *to;
apr_status_t rv = APR_SUCCESS;
- MD_CHK_VARS;
(void)baton;
(void)ftype;
if ( MD_OK(md_util_path_merge(&from, ptemp, dir, name, NULL))
&& MD_OK(md_util_path_merge(&to, ptemp, dir, MD_FN_PRIVKEY, NULL))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "renaming %s/%s to %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, p, "renaming %s/%s to %s",
dir, name, MD_FN_PRIVKEY);
return apr_file_rename(from, to, ptemp);
}
@@ -143,16 +155,15 @@ static apr_status_t mk_pubcert(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
apr_array_header_t *chain, *pubcert;
const char *fname, *fpubcert;
apr_status_t rv = APR_SUCCESS;
- MD_CHK_VARS;
(void)baton;
(void)ftype;
(void)p;
if ( MD_OK(md_util_path_merge(&fpubcert, ptemp, dir, MD_FN_PUBCERT, NULL))
- && MD_IS_ERR(md_chain_fload(&pubcert, ptemp, fpubcert), ENOENT)
+ && APR_STATUS_IS_ENOENT(rv = md_chain_fload(&pubcert, ptemp, fpubcert))
&& MD_OK(md_util_path_merge(&fname, ptemp, dir, name, NULL))
&& MD_OK(md_cert_fload(&cert, ptemp, fname))
- && MD_OK(md_util_path_merge(&fname, ptemp, dir, MD_FN_CHAIN, NULL))) {
+ && MD_OK(md_util_path_merge(&fname, ptemp, dir, "chain.pem", NULL))) {
rv = md_chain_fload(&chain, ptemp, fname);
if (APR_STATUS_IS_ENOENT(rv)) {
@@ -193,10 +204,9 @@ static apr_status_t read_store_file(md_store_fs_t *s_fs, const char *fname,
apr_pool_t *p, apr_pool_t *ptemp)
{
md_json_t *json;
- const char *key64, *key;
+ const char *key64;
apr_status_t rv;
double store_version;
- MD_CHK_VARS;
if (MD_OK(md_json_readf(&json, p, fname))) {
store_version = md_json_getn(json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
@@ -215,11 +225,10 @@ static apr_status_t read_store_file(md_store_fs_t *s_fs, const char *fname,
return APR_EINVAL;
}
- s_fs->key_len = md_util_base64url_decode(&key, key64, p);
- s_fs->key = (const unsigned char*)key;
- if (s_fs->key_len != FS_STORE_KLEN) {
+ md_util_base64url_decode(&s_fs->key, key64, p);
+ if (s_fs->key.len != FS_STORE_KLEN) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "key length unexpected: %" APR_SIZE_T_FMT,
- s_fs->key_len);
+ s_fs->key.len);
return APR_EINVAL;
}
@@ -237,8 +246,8 @@ static apr_status_t read_store_file(md_store_fs_t *s_fs, const char *fname,
if (APR_SUCCESS == rv) {
md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
rv = md_json_freplace(json, ptemp, MD_JSON_FMT_INDENT, fname, MD_FPROT_F_UONLY);
- }
- md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p, "migrated store");
+ }
+ md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p, "migrated store");
}
}
return rv;
@@ -249,10 +258,14 @@ static apr_status_t setup_store_file(void *baton, apr_pool_t *p, apr_pool_t *pte
md_store_fs_t *s_fs = baton;
const char *fname;
apr_status_t rv;
- MD_CHK_VARS;
(void)ap;
s_fs->plain_pkey[MD_SG_DOMAINS] = 1;
+ /* Added: the encryption of tls-alpn-01 certificate keys is not a security issue
+ * for these self-signed, short-lived certificates. Having them unencrypted let's
+ * use pass around the files insteak of an *SSL implementation dependent PKEY_something.
+ */
+ s_fs->plain_pkey[MD_SG_CHALLENGES] = 1;
s_fs->plain_pkey[MD_SG_TMP] = 1;
if (!MD_OK(md_util_path_merge(&fname, ptemp, s_fs->base, FS_STORE_JSON, NULL))) {
@@ -264,7 +277,7 @@ read:
rv = read_store_file(s_fs, fname, p, ptemp);
}
else if (APR_STATUS_IS_ENOENT(rv)
- && MD_IS_ERR(init_store_file(s_fs, fname, p, ptemp), EEXIST)) {
+ && APR_STATUS_IS_EEXIST(rv = init_store_file(s_fs, fname, p, ptemp))) {
goto read;
}
return rv;
@@ -274,7 +287,6 @@ apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *pa
{
md_store_fs_t *s_fs;
apr_status_t rv = APR_SUCCESS;
- MD_CHK_VARS;
s_fs = apr_pcalloc(p, sizeof(*s_fs));
@@ -282,11 +294,17 @@ apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *pa
s_fs->s.save = fs_save;
s_fs->s.remove = fs_remove;
s_fs->s.move = fs_move;
+ s_fs->s.rename = fs_rename;
s_fs->s.purge = fs_purge;
s_fs->s.iterate = fs_iterate;
+ s_fs->s.iterate_names = fs_iterate_names;
s_fs->s.get_fname = fs_get_fname;
s_fs->s.is_newer = fs_is_newer;
-
+ s_fs->s.get_modified = fs_get_modified;
+ s_fs->s.remove_nms = fs_remove_nms;
+ s_fs->s.lock_global = fs_lock_global;
+ s_fs->s.unlock_global = fs_unlock_global;
+
/* by default, everything is only readable by the current user */
s_fs->def_perms.dir = MD_FPROT_D_UONLY;
s_fs->def_perms.file = MD_FPROT_F_UONLY;
@@ -300,20 +318,34 @@ apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *pa
/* challenges dir and files are readable by all, no secrets involved */
s_fs->group_perms[MD_SG_CHALLENGES].dir = MD_FPROT_D_UALL_WREAD;
s_fs->group_perms[MD_SG_CHALLENGES].file = MD_FPROT_F_UALL_WREAD;
+ /* OCSP data is readable by all, no secrets involved */
+ s_fs->group_perms[MD_SG_OCSP].dir = MD_FPROT_D_UALL_WREAD;
+ s_fs->group_perms[MD_SG_OCSP].file = MD_FPROT_F_UALL_WREAD;
s_fs->base = apr_pstrdup(p, path);
-
- if (MD_IS_ERR(md_util_is_dir(s_fs->base, p), ENOENT)
- && MD_OK(apr_dir_make_recursive(s_fs->base, s_fs->def_perms.dir, p))) {
+
+ rv = md_util_is_dir(s_fs->base, p);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p,
+ "store directory does not exist, creating %s", s_fs->base);
+ rv = apr_dir_make_recursive(s_fs->base, s_fs->def_perms.dir, p);
+ if (APR_SUCCESS != rv) goto cleanup;
rv = apr_file_perms_set(s_fs->base, MD_FPROT_D_UALL_WREAD);
if (APR_STATUS_IS_ENOTIMPL(rv)) {
rv = APR_SUCCESS;
}
+ if (APR_SUCCESS != rv) goto cleanup;
}
-
- if ((APR_SUCCESS != rv) || !MD_OK(md_util_pool_vdo(setup_store_file, s_fs, p, NULL))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "init fs store at %s", path);
+ else if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
+ "not a plain directory, maybe a symlink? %s", s_fs->base);
+ }
+
+ rv = md_util_pool_vdo(setup_store_file, s_fs, p, NULL);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "init fs store at %s", s_fs->base);
}
+cleanup:
*pstore = (rv == APR_SUCCESS)? &(s_fs->s) : NULL;
return rv;
}
@@ -394,8 +426,8 @@ static void get_pass(const char **ppass, apr_size_t *plen,
*plen = 0;
}
else {
- *ppass = (const char *)s_fs->key;
- *plen = s_fs->key_len;
+ *ppass = (const char *)s_fs->key.data;
+ *plen = s_fs->key.len;
}
}
@@ -446,7 +478,6 @@ static apr_status_t pfs_load(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
md_store_group_t group;
void **pvalue;
apr_status_t rv;
- MD_CHK_VARS;
group = (md_store_group_t)va_arg(ap, int);
name = va_arg(ap, const char *);
@@ -460,7 +491,7 @@ static apr_status_t pfs_load(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
return rv;
}
-static apr_status_t dispatch(md_store_fs_t *s_fs, md_store_fs_ev_t ev, int group,
+static apr_status_t dispatch(md_store_fs_t *s_fs, md_store_fs_ev_t ev, unsigned int group,
const char *fname, apr_filetype_e ftype, apr_pool_t *p)
{
(void)ev;
@@ -477,25 +508,31 @@ static apr_status_t mk_group_dir(const char **pdir, md_store_fs_t *s_fs,
{
const perms_t *perms;
apr_status_t rv;
- MD_CHK_VARS;
perms = gperms(s_fs, group);
- if (MD_OK(fs_get_dname(pdir, &s_fs->s, group, name, p)) && (MD_SG_NONE != group)) {
- if ( !MD_OK(md_util_is_dir(*pdir, p))
- && MD_OK(apr_dir_make_recursive(*pdir, perms->dir, p))) {
- rv = dispatch(s_fs, MD_S_FS_EV_CREATED, group, *pdir, APR_DIR, p);
- }
-
- if (APR_SUCCESS == rv) {
- rv = apr_file_perms_set(*pdir, perms->dir);
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "mk_group_dir %s perm set", *pdir);
- if (APR_STATUS_IS_ENOTIMPL(rv)) {
- rv = APR_SUCCESS;
- }
- }
+ *pdir = NULL;
+ rv = fs_get_dname(pdir, &s_fs->s, group, name, p);
+ if ((APR_SUCCESS != rv) || (MD_SG_NONE == group)) goto cleanup;
+
+ rv = md_util_is_dir(*pdir, p);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "not a directory, creating %s", *pdir);
+ rv = apr_dir_make_recursive(*pdir, perms->dir, p);
+ if (APR_SUCCESS != rv) goto cleanup;
+ dispatch(s_fs, MD_S_FS_EV_CREATED, group, *pdir, APR_DIR, p);
+ }
+
+ rv = apr_file_perms_set(*pdir, perms->dir);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "mk_group_dir %s perm set", *pdir);
+ if (APR_STATUS_IS_ENOTIMPL(rv)) {
+ rv = APR_SUCCESS;
+ }
+cleanup:
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "mk_group_dir %d %s",
+ group, (*pdir? *pdir : (name? name : "(null)")));
}
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "mk_group_dir %d %s", group, name);
return rv;
}
@@ -507,7 +544,6 @@ static apr_status_t pfs_is_newer(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
apr_finfo_t inf1, inf2;
int *pnewer;
apr_status_t rv;
- MD_CHK_VARS;
(void)p;
group1 = (md_store_group_t)va_arg(ap, int);
@@ -527,7 +563,6 @@ static apr_status_t pfs_is_newer(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
return rv;
}
-
static int fs_is_newer(md_store_t *store, md_store_group_t group1, md_store_group_t group2,
const char *name, const char *aspect, apr_pool_t *p)
{
@@ -542,6 +577,44 @@ static int fs_is_newer(md_store_t *store, md_store_group_t group1, md_store_grou
return 0;
}
+static apr_status_t pfs_get_modified(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
+{
+ md_store_fs_t *s_fs = baton;
+ const char *fname, *name, *aspect;
+ md_store_group_t group;
+ apr_finfo_t inf;
+ apr_time_t *pmtime;
+ apr_status_t rv;
+
+ (void)p;
+ group = (md_store_group_t)va_arg(ap, int);
+ name = va_arg(ap, const char*);
+ aspect = va_arg(ap, const char*);
+ pmtime = va_arg(ap, apr_time_t*);
+
+ *pmtime = 0;
+ if ( MD_OK(fs_get_fname(&fname, &s_fs->s, group, name, aspect, ptemp))
+ && MD_OK(apr_stat(&inf, fname, APR_FINFO_MTIME, ptemp))) {
+ *pmtime = inf.mtime;
+ }
+
+ return rv;
+}
+
+static apr_time_t fs_get_modified(md_store_t *store, md_store_group_t group,
+ const char *name, const char *aspect, apr_pool_t *p)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+ apr_time_t mtime;
+ apr_status_t rv;
+
+ rv = md_util_pool_vdo(pfs_get_modified, s_fs, p, group, name, aspect, &mtime, NULL);
+ if (APR_SUCCESS == rv) {
+ return mtime;
+ }
+ return 0;
+}
+
static apr_status_t pfs_save(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
{
md_store_fs_t *s_fs = baton;
@@ -554,7 +627,6 @@ static apr_status_t pfs_save(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
const perms_t *perms;
const char *pass;
apr_size_t pass_len;
- MD_CHK_VARS;
group = (md_store_group_t)va_arg(ap, int);
name = va_arg(ap, const char*);
@@ -569,7 +641,7 @@ static apr_status_t pfs_save(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
&& MD_OK(mk_group_dir(&dir, s_fs, group, name, p))
&& MD_OK(md_util_path_merge(&fpath, ptemp, dir, aspect, NULL))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "storing in %s", fpath);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, ptemp, "storing in %s", fpath);
switch (vtype) {
case MD_SV_TEXT:
rv = (create? md_text_fcreatex(fpath, perms->file, p, value)
@@ -612,7 +684,6 @@ static apr_status_t pfs_remove(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va
int force;
apr_finfo_t info;
md_store_group_t group;
- MD_CHK_VARS;
(void)p;
group = (md_store_group_t)va_arg(ap, int);
@@ -624,7 +695,7 @@ static apr_status_t pfs_remove(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va
if ( MD_OK(md_util_path_merge(&dir, ptemp, s_fs->base, groupname, name, NULL))
&& MD_OK(md_util_path_merge(&fpath, ptemp, dir, aspect, NULL))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, ptemp, "start remove of md %s/%s/%s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "start remove of md %s/%s/%s",
groupname, name, aspect);
if (!MD_OK(apr_stat(&info, dir, APR_FINFO_TYPE, ptemp))) {
@@ -673,7 +744,6 @@ static apr_status_t pfs_purge(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_
const char *dir, *name, *groupname;
md_store_group_t group;
apr_status_t rv;
- MD_CHK_VARS;
(void)p;
group = (md_store_group_t)va_arg(ap, int);
@@ -685,7 +755,9 @@ static apr_status_t pfs_purge(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_
/* Remove all files in dir, there should be no sub-dirs */
rv = md_util_rm_recursive(dir, ptemp, 1);
}
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "purge %s/%s (%s)", groupname, name, dir);
+ if (!APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, ptemp, "purge %s/%s (%s)", groupname, name, dir);
+ }
return APR_SUCCESS;
}
@@ -706,7 +778,9 @@ typedef struct {
const char *aspect;
md_store_vtype_t vtype;
md_store_inspect *inspect;
+ const char *dirname;
void *baton;
+ apr_time_t ts;
} inspect_ctx;
static apr_status_t insp(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
@@ -716,15 +790,38 @@ static apr_status_t insp(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
apr_status_t rv;
void *value;
const char *fpath;
- MD_CHK_VARS;
(void)ftype;
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting value at: %s/%s", dir, name);
- if ( MD_OK(md_util_path_merge(&fpath, ptemp, dir, name, NULL))
- && MD_OK(fs_fload(&value, ctx->s_fs, fpath, ctx->group, ctx->vtype, p, ptemp))
- && !ctx->inspect(ctx->baton, name, ctx->aspect, ctx->vtype, value, ptemp)) {
- return APR_EOF;
- }
+ if (APR_SUCCESS == (rv = md_util_path_merge(&fpath, ptemp, dir, name, NULL))) {
+ rv = fs_fload(&value, ctx->s_fs, fpath, ctx->group, ctx->vtype, p, ptemp);
+ if (APR_SUCCESS == rv
+ && !ctx->inspect(ctx->baton, ctx->dirname, name, ctx->vtype, value, p)) {
+ return APR_EOF;
+ }
+ else if (APR_STATUS_IS_ENOENT(rv)) {
+ rv = APR_SUCCESS;
+ }
+ }
+ return rv;
+}
+
+static apr_status_t insp_dir(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
+ const char *dir, const char *name, apr_filetype_e ftype)
+{
+ inspect_ctx *ctx = baton;
+ apr_status_t rv;
+ const char *fpath;
+
+ (void)ftype;
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting dir at: %s/%s", dir, name);
+ if (MD_OK(md_util_path_merge(&fpath, p, dir, name, NULL))) {
+ ctx->dirname = name;
+ rv = md_util_files_do(insp, ctx, p, fpath, ctx->aspect, NULL);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ rv = APR_SUCCESS;
+ }
+ }
return rv;
}
@@ -745,7 +842,97 @@ static apr_status_t fs_iterate(md_store_inspect *inspect, void *baton, md_store_
ctx.baton = baton;
groupname = md_store_group_name(group);
- rv = md_util_files_do(insp, &ctx, p, ctx.s_fs->base, groupname, ctx.pattern, aspect, NULL);
+ rv = md_util_files_do(insp_dir, &ctx, p, ctx.s_fs->base, groupname, pattern, NULL);
+
+ return rv;
+}
+
+static apr_status_t insp_name(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
+ const char *dir, const char *name, apr_filetype_e ftype)
+{
+ inspect_ctx *ctx = baton;
+
+ (void)ftype;
+ (void)p;
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting name at: %s/%s", dir, name);
+ return ctx->inspect(ctx->baton, dir, name, 0, NULL, ptemp);
+}
+
+static apr_status_t fs_iterate_names(md_store_inspect *inspect, void *baton, md_store_t *store,
+ apr_pool_t *p, md_store_group_t group, const char *pattern)
+{
+ const char *groupname;
+ apr_status_t rv;
+ inspect_ctx ctx;
+
+ ctx.s_fs = FS_STORE(store);
+ ctx.group = group;
+ ctx.pattern = pattern;
+ ctx.inspect = inspect;
+ ctx.baton = baton;
+ groupname = md_store_group_name(group);
+
+ rv = md_util_files_do(insp_name, &ctx, p, ctx.s_fs->base, groupname, pattern, NULL);
+
+ return rv;
+}
+
+static apr_status_t remove_nms_file(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
+ const char *dir, const char *name, apr_filetype_e ftype)
+{
+ inspect_ctx *ctx = baton;
+ const char *fname;
+ apr_finfo_t inf;
+ apr_status_t rv = APR_SUCCESS;
+
+ (void)p;
+ if (APR_DIR == ftype) goto leave;
+ if (APR_SUCCESS != (rv = md_util_path_merge(&fname, ptemp, dir, name, NULL))) goto leave;
+ if (APR_SUCCESS != (rv = apr_stat(&inf, fname, APR_FINFO_MTIME, ptemp))) goto leave;
+ if (inf.mtime >= ctx->ts) goto leave;
+
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "remove_nms file: %s/%s", dir, name);
+ rv = apr_file_remove(fname, ptemp);
+
+leave:
+ return rv;
+}
+
+static apr_status_t remove_nms_dir(void *baton, apr_pool_t *p, apr_pool_t *ptemp,
+ const char *dir, const char *name, apr_filetype_e ftype)
+{
+ inspect_ctx *ctx = baton;
+ apr_status_t rv;
+ const char *fpath;
+
+ (void)ftype;
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "remove_nms dir at: %s/%s", dir, name);
+ if (MD_OK(md_util_path_merge(&fpath, p, dir, name, NULL))) {
+ ctx->dirname = name;
+ rv = md_util_files_do(remove_nms_file, ctx, p, fpath, ctx->aspect, NULL);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ rv = APR_SUCCESS;
+ }
+ }
+ return rv;
+}
+
+static apr_status_t fs_remove_nms(md_store_t *store, apr_pool_t *p,
+ apr_time_t modified, md_store_group_t group,
+ const char *name, const char *aspect)
+{
+ const char *groupname;
+ apr_status_t rv;
+ inspect_ctx ctx;
+
+ ctx.s_fs = FS_STORE(store);
+ ctx.group = group;
+ ctx.pattern = name;
+ ctx.aspect = aspect;
+ ctx.ts = modified;
+ groupname = md_store_group_name(group);
+
+ rv = md_util_files_do(remove_nms_dir, &ctx, p, ctx.s_fs->base, groupname, name, NULL);
return rv;
}
@@ -760,7 +947,6 @@ static apr_status_t pfs_move(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
md_store_group_t from, to;
int archive;
apr_status_t rv;
- MD_CHK_VARS;
(void)p;
from = (md_store_group_t)va_arg(ap, int);
@@ -802,7 +988,7 @@ static apr_status_t pfs_move(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
rv = md_util_is_dir(narch_dir, ptemp);
if (APR_STATUS_IS_ENOENT(rv)) {
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "using archive dir: %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, ptemp, "using archive dir: %s",
narch_dir);
break;
}
@@ -817,7 +1003,7 @@ static apr_status_t pfs_move(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
while (n < 1000) {
narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
if (MD_OK(apr_dir_make(narch_dir, MD_FPROT_D_UONLY, ptemp))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "using archive dir: %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, ptemp, "using archive dir: %s",
narch_dir);
break;
}
@@ -844,12 +1030,12 @@ static apr_status_t pfs_move(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
}
if (!MD_OK(apr_file_rename(to_dir, narch_dir, ptemp))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
to_dir, narch_dir);
goto out;
}
if (!MD_OK(apr_file_rename(from_dir, to_dir, ptemp))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
from_dir, to_dir);
apr_file_rename(narch_dir, to_dir, ptemp);
goto out;
@@ -860,7 +1046,7 @@ static apr_status_t pfs_move(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_l
}
else if (APR_STATUS_IS_ENOENT(rv)) {
if (APR_SUCCESS != (rv = apr_file_rename(from_dir, to_dir, ptemp))) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
from_dir, to_dir);
goto out;
}
@@ -881,3 +1067,103 @@ static apr_status_t fs_move(md_store_t *store, apr_pool_t *p,
md_store_fs_t *s_fs = FS_STORE(store);
return md_util_pool_vdo(pfs_move, s_fs, p, from, to, name, archive, NULL);
}
+
+static apr_status_t pfs_rename(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
+{
+ md_store_fs_t *s_fs = baton;
+ const char *group_name, *from_dir, *to_dir;
+ md_store_group_t group;
+ const char *from, *to;
+ apr_status_t rv;
+
+ (void)p;
+ group = (md_store_group_t)va_arg(ap, int);
+ from = va_arg(ap, const char*);
+ to = va_arg(ap, const char*);
+
+ group_name = md_store_group_name(group);
+ if ( !MD_OK(md_util_path_merge(&from_dir, ptemp, s_fs->base, group_name, from, NULL))
+ || !MD_OK(md_util_path_merge(&to_dir, ptemp, s_fs->base, group_name, to, NULL))) {
+ goto out;
+ }
+
+ if (APR_SUCCESS != (rv = apr_file_rename(from_dir, to_dir, ptemp))
+ && !APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
+ from_dir, to_dir);
+ goto out;
+ }
+out:
+ return rv;
+}
+
+static apr_status_t fs_rename(md_store_t *store, apr_pool_t *p,
+ md_store_group_t group, const char *from, const char *to)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+ return md_util_pool_vdo(pfs_rename, s_fs, p, group, from, to, NULL);
+}
+
+static apr_status_t fs_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+ apr_status_t rv;
+ const char *lpath;
+ apr_time_t end;
+
+ if (s_fs->global_lock) {
+ rv = APR_EEXIST;
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "already locked globally");
+ goto cleanup;
+ }
+
+ rv = md_util_path_merge(&lpath, p, s_fs->base, MD_FS_LOCK_NAME, NULL);
+ if (APR_SUCCESS != rv) goto cleanup;
+ end = apr_time_now() + max_wait;
+
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, p,
+ "acquire global lock: %s", lpath);
+ while (apr_time_now() < end) {
+ rv = apr_file_open(&s_fs->global_lock, lpath,
+ (APR_FOPEN_WRITE|APR_FOPEN_CREATE),
+ MD_FPROT_F_UALL_GREAD, p);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "unable to create/open lock file: %s",
+ lpath);
+ goto next_try;
+ }
+ rv = apr_file_lock(s_fs->global_lock,
+ APR_FLOCK_EXCLUSIVE|APR_FLOCK_NONBLOCK);
+ if (APR_SUCCESS == rv) {
+ goto cleanup;
+ }
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "unable to obtain lock on: %s",
+ lpath);
+
+ next_try:
+ if (s_fs->global_lock) {
+ apr_file_close(s_fs->global_lock);
+ s_fs->global_lock = NULL;
+ }
+ apr_sleep(apr_time_from_msec(100));
+ }
+ rv = APR_EGENERAL;
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "acquire global lock: %s", lpath);
+
+cleanup:
+ return rv;
+}
+
+static void fs_unlock_global(md_store_t *store, apr_pool_t *p)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+
+ (void)p;
+ if (s_fs->global_lock) {
+ apr_file_close(s_fs->global_lock);
+ s_fs->global_lock = NULL;
+ }
+}