# ./pullrev.sh 1912477 1912571 1912718 1913654 1914438
http://svn.apache.org/viewvc?view=revision&revision=1912477
http://svn.apache.org/viewvc?view=revision&revision=1912571
http://svn.apache.org/viewvc?view=revision&revision=1912718
http://svn.apache.org/viewvc?view=revision&revision=1913654
http://svn.apache.org/viewvc?view=revision&revision=1914438

Upstream-Status: in trunk, not proposed for 2.4.x

--- httpd-2.4.58/modules/dav/fs/config6.m4.r1912477+
+++ httpd-2.4.58/modules/dav/fs/config6.m4
@@ -20,4 +20,10 @@
 
 APACHE_MODULE(dav_fs, DAV provider for the filesystem.  --enable-dav also enables mod_dav_fs., $dav_fs_objects, , $dav_fs_enable,,dav)
 
+if test "x$enable_dav_fs" = "xshared"; then
+    # The only symbol which needs to be exported is the module
+    # structure, so ask libtool to hide everything else:
+    APR_ADDTO(MOD_DAV_FS_LDADD, [-export-symbols-regex dav_fs_module])
+fi
+
 APACHE_MODPATH_FINISH
--- httpd-2.4.58/modules/dav/fs/dbm.c.r1912477+
+++ httpd-2.4.58/modules/dav/fs/dbm.c
@@ -47,6 +47,10 @@
 #include "http_log.h"
 #include "http_main.h"      /* for ap_server_conf */
 
+#ifndef DEFAULT_PROPDB_DBM_TYPE
+#define DEFAULT_PROPDB_DBM_TYPE "default"
+#endif
+
 APLOG_USE_MODULE(dav_fs);
 
 struct dav_db {
@@ -100,7 +104,7 @@
     /* There might not be a <db> if we had problems creating it. */
     if (db == NULL) {
         errcode = 1;
-        errstr = "Could not open property database.";
+        errstr = "Could not open database.";
         if (APR_STATUS_IS_EDSOOPEN(status))
             ap_log_error(APLOG_MARK, APLOG_CRIT, status, ap_server_conf, APLOGNO(00576)
             "The DBM driver could not be loaded");
@@ -129,10 +133,10 @@
 /* dav_dbm_open_direct:  Opens a *dbm database specified by path.
  *    ro = boolean read-only flag.
  */
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
-                                dav_db **pdb)
+dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname,
+                                const char *dbmtype, int ro, dav_db **pdb)
 {
-#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
+#if APR_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
     const apr_dbm_driver_t *driver;
     const apu_err_t *err;
 #endif
@@ -141,13 +145,13 @@
 
     *pdb = NULL;
 
-#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
-    if ((status = apr_dbm_get_driver(&driver, NULL, &err, p)) != APR_SUCCESS) {
+#if APR_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
+    if ((status = apr_dbm_get_driver(&driver, dbmtype, &err, p)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf, APLOGNO(10289)
-                     "mod_dav_fs: The DBM library '%s' could not be loaded: %s",
-                             err->reason, err->msg);
+                     "mod_dav_fs: The DBM library '%s' for '%s' could not be loaded: %s",
+                     err->reason, dbmtype, err->msg);
         return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 1, status,
-                "Could not load library for property database.");
+                "Could not load library for database.");
     }
     if ((status = apr_dbm_open2(&file, driver, pathname,
                                ro ? APR_DBM_READONLY : APR_DBM_RWCREATE,
@@ -156,7 +160,7 @@
         return dav_fs_dbm_error(NULL, p, status);
     }
 #else
-    if ((status = apr_dbm_open(&file, pathname,
+    if ((status = apr_dbm_open_ex(&file, dbmtype, pathname,
                                ro ? APR_DBM_READONLY : APR_DBM_RWCREATE,
                                APR_OS_DEFAULT, p))
                 != APR_SUCCESS
@@ -206,7 +210,7 @@
 
     /* ### do we need to deal with the umask? */
 
-    return dav_dbm_open_direct(p, pathname, ro, pdb);
+    return dav_dbm_open_direct(p, pathname, DEFAULT_PROPDB_DBM_TYPE, ro, pdb);
 }
 
 void dav_dbm_close(dav_db *db)
--- httpd-2.4.58/modules/dav/fs/lock.c.r1912477+
+++ httpd-2.4.58/modules/dav/fs/lock.c
@@ -181,8 +181,7 @@
 {
     request_rec *r;                  /* for accessing the uuid state */
     apr_pool_t *pool;                /* a pool to use */
-    const char *lockdb_path;         /* where is the lock database? */
-
+    const dav_fs_server_conf *conf;  /* lock database config & metadata */
     int opened;                      /* we opened the database */
     dav_db *db;                      /* if non-NULL, the lock database */
 };
@@ -292,6 +291,19 @@
     return dav_compare_locktoken(lt1, lt2);
 }
 
+static apr_status_t dav_fs_lockdb_cleanup(void *data)
+{
+    dav_lockdb *lockdb = data;
+
+    apr_global_mutex_unlock(lockdb->info->conf->lockdb_mutex);
+
+    if (lockdb->info->db) {
+        dav_dbm_close(lockdb->info->db);
+    }
+    
+    return APR_SUCCESS;
+}
+
 /*
 ** dav_fs_really_open_lockdb:
 **
@@ -300,15 +312,27 @@
 static dav_error * dav_fs_really_open_lockdb(dav_lockdb *lockdb)
 {
     dav_error *err;
+    apr_status_t rv;
 
     if (lockdb->info->opened)
         return NULL;
 
+    rv = apr_global_mutex_lock(lockdb->info->conf->lockdb_mutex);
+    if (rv) {
+        return dav_new_error(lockdb->info->pool,
+                             HTTP_INTERNAL_SERVER_ERROR,
+                             DAV_ERR_LOCK_OPENDB, rv,
+                             "Could not lock mutex for lock database.");
+    }
+    
     err = dav_dbm_open_direct(lockdb->info->pool,
-                              lockdb->info->lockdb_path,
+                              lockdb->info->conf->lockdb_path,
+                              lockdb->info->conf->lockdb_type,
                               lockdb->ro,
                               &lockdb->info->db);
     if (err != NULL) {
+        apr_global_mutex_unlock(lockdb->info->conf->lockdb_mutex);
+        
         return dav_push_error(lockdb->info->pool,
                               HTTP_INTERNAL_SERVER_ERROR,
                               DAV_ERR_LOCK_OPENDB,
@@ -316,6 +340,10 @@
                               err);
     }
 
+    apr_pool_cleanup_register(lockdb->info->pool, lockdb,
+                              dav_fs_lockdb_cleanup,
+                              dav_fs_lockdb_cleanup);
+
     /* all right. it is opened now. */
     lockdb->info->opened = 1;
 
@@ -341,9 +369,9 @@
     comb->pub.info = &comb->priv;
     comb->priv.r = r;
     comb->priv.pool = r->pool;
-
-    comb->priv.lockdb_path = dav_get_lockdb_path(r);
-    if (comb->priv.lockdb_path == NULL) {
+    comb->priv.conf = dav_fs_get_server_conf(r);
+    
+    if (comb->priv.conf == NULL || comb->priv.conf->lockdb_path == NULL) {
         return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
                              DAV_ERR_LOCK_NO_DB, 0,
                              "A lock database was not specified with the "
@@ -369,8 +397,8 @@
 */
 static void dav_fs_close_lockdb(dav_lockdb *lockdb)
 {
-    if (lockdb->info->db != NULL)
-        dav_dbm_close(lockdb->info->db);
+    apr_pool_cleanup_run(lockdb->info->pool, lockdb,
+                         dav_fs_lockdb_cleanup);
 }
 
 /*
--- httpd-2.4.58/modules/dav/fs/mod_dav_fs.c.r1912477+
+++ httpd-2.4.58/modules/dav/fs/mod_dav_fs.c
@@ -14,31 +14,35 @@
  * limitations under the License.
  */
 
+#if !defined(_MSC_VER) && !defined(NETWARE)
+#include "ap_config_auto.h"
+#endif
+
 #include "httpd.h"
 #include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
 #include "apr_strings.h"
 
 #include "mod_dav.h"
 #include "repos.h"
 
-/* per-server configuration */
-typedef struct {
-    const char *lockdb_path;
-
-} dav_fs_server_conf;
-
 extern module AP_MODULE_DECLARE_DATA dav_fs_module;
 
 #ifndef DEFAULT_DAV_LOCKDB
 #define DEFAULT_DAV_LOCKDB "davlockdb"
 #endif
+#ifndef DEFAULT_DAV_LOCKDB_TYPE
+#define DEFAULT_DAV_LOCKDB_TYPE "default"
+#endif
 
-const char *dav_get_lockdb_path(const request_rec *r)
-{
-    dav_fs_server_conf *conf;
+static const char dav_fs_mutexid[] = "dav_fs-lockdb";
 
-    conf = ap_get_module_config(r->server->module_config, &dav_fs_module);
-    return conf->lockdb_path;
+static apr_global_mutex_t *dav_fs_lockdb_mutex;
+
+const dav_fs_server_conf *dav_fs_get_server_conf(const request_rec *r)
+{
+    return ap_get_module_config(r->server->module_config, &dav_fs_module);
 }
 
 static void *dav_fs_create_server_config(apr_pool_t *p, server_rec *s)
@@ -57,15 +61,50 @@
 
     newconf->lockdb_path =
         child->lockdb_path ? child->lockdb_path : parent->lockdb_path;
+    newconf->lockdb_type =
+        child->lockdb_type ? child->lockdb_type : parent->lockdb_type;
 
     return newconf;
 }
 
+static int dav_fs_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
+{
+    if (ap_mutex_register(pconf, dav_fs_mutexid, NULL, APR_LOCK_DEFAULT, 0))
+        return !OK;
+    return OK;
+}
+
+static void dav_fs_child_init(apr_pool_t *p, server_rec *s)
+{
+    apr_status_t rv;
+    
+    rv = apr_global_mutex_child_init(&dav_fs_lockdb_mutex,
+                                     apr_global_mutex_lockfile(dav_fs_lockdb_mutex),
+                                     p);
+    if (rv) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                     APLOGNO(10488) "child init failed for mutex");
+    }                     
+}
+
 static apr_status_t dav_fs_post_config(apr_pool_t *p, apr_pool_t *plog,
                                        apr_pool_t *ptemp, server_rec *base_server)
 {
     server_rec *s;
+    apr_status_t rv;
 
+    /* Ignore first pass through the config. */
+    if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
+        return OK;
+
+    rv = ap_global_mutex_create(&dav_fs_lockdb_mutex, NULL, dav_fs_mutexid, NULL,
+                                base_server, p, 0);
+    if (rv) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, rv, base_server,
+                     APLOGNO(10489) "could not create lock mutex");
+        return !OK;
+    }                     
+    
     for (s = base_server; s; s = s->next) {
         dav_fs_server_conf *conf;
 
@@ -74,6 +113,13 @@
         if (!conf->lockdb_path) {
             conf->lockdb_path = ap_state_dir_relative(p, DEFAULT_DAV_LOCKDB);
         }
+        if (!conf->lockdb_type) {
+            conf->lockdb_type = DEFAULT_DAV_LOCKDB_TYPE;
+        }
+
+        /* Mutex is common across all vhosts, but could have one per
+         * vhost if required. */
+        conf->lockdb_mutex = dav_fs_lockdb_mutex;
     }
 
     return OK;
@@ -98,19 +144,36 @@
     return NULL;
 }
 
+/*
+ * Command handler for the DAVLockDBType directive, which is TAKE1
+ */
+static const char *dav_fs_cmd_davlockdbtype(cmd_parms *cmd, void *config,
+                                        const char *arg1)
+{
+    dav_fs_server_conf *conf = ap_get_module_config(cmd->server->module_config,
+                                                    &dav_fs_module);
+    conf->lockdb_type = arg1;
+
+    return NULL;
+}
+
 static const command_rec dav_fs_cmds[] =
 {
     /* per server */
     AP_INIT_TAKE1("DAVLockDB", dav_fs_cmd_davlockdb, NULL, RSRC_CONF,
                   "specify a lock database"),
+    AP_INIT_TAKE1("DAVLockDBType", dav_fs_cmd_davlockdbtype, NULL, RSRC_CONF,
+                  "specify a lock database DBM type"),
 
     { NULL }
 };
 
 static void register_hooks(apr_pool_t *p)
 {
+    ap_hook_pre_config(dav_fs_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_config(dav_fs_post_config, NULL, NULL, APR_HOOK_MIDDLE);
-
+    ap_hook_child_init(dav_fs_child_init, NULL, NULL, APR_HOOK_MIDDLE);
+    
     dav_hook_gather_propsets(dav_fs_gather_propsets, NULL, NULL,
                              APR_HOOK_MIDDLE);
     dav_hook_find_liveprop(dav_fs_find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
--- httpd-2.4.58/modules/dav/fs/repos.h.r1912477+
+++ httpd-2.4.58/modules/dav/fs/repos.h
@@ -25,6 +25,8 @@
 #ifndef _DAV_FS_REPOS_H_
 #define _DAV_FS_REPOS_H_
 
+#include "util_mutex.h"
+
 /* the subdirectory to hold all DAV-related information for a directory */
 #define DAV_FS_STATE_DIR                ".DAV"
 #define DAV_FS_STATE_FILE_FOR_DIR       ".state_for_dir"
@@ -53,8 +55,8 @@
 /* DBM functions used by the repository and locking providers */
 extern const dav_hooks_db dav_hooks_db_dbm;
 
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
-                                dav_db **pdb);
+dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname,
+                                const char *dbmtype, int ro, dav_db **pdb);
 void dav_dbm_get_statefiles(apr_pool_t *p, const char *fname,
                             const char **state1, const char **state2);
 dav_error * dav_dbm_delete(dav_db *db, apr_datum_t key);
@@ -64,8 +66,15 @@
 int dav_dbm_exists(dav_db *db, apr_datum_t key);
 void dav_dbm_close(dav_db *db);
 
-/* where is the lock database located? */
-const char *dav_get_lockdb_path(const request_rec *r);
+/* Per-server configuration. */
+typedef struct {
+    const char *lockdb_path;
+    const char *lockdb_type;
+    apr_global_mutex_t *lockdb_mutex;
+} dav_fs_server_conf;
+
+/* Returns server configuration for the request. */
+const dav_fs_server_conf *dav_fs_get_server_conf(const request_rec *r);
 
 const dav_hooks_locks *dav_fs_get_lock_hooks(request_rec *r);
 const dav_hooks_propdb *dav_fs_get_propdb_hooks(request_rec *r);
