diff options
Diffstat (limited to 'modules/md/md_store_fs.c')
-rw-r--r-- | modules/md/md_store_fs.c | 426 |
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; + } +} |