dbm.c revision edab53cc0be707fa71968a95c696b19f0e6c4736
d7759bdad133e1e92fe41aab75dd8c1584eda38cjim/* Licensed to the Apache Software Foundation (ASF) under one or more
d7759bdad133e1e92fe41aab75dd8c1584eda38cjim * contributor license agreements. See the NOTICE file distributed with
d7759bdad133e1e92fe41aab75dd8c1584eda38cjim * this work for additional information regarding copyright ownership.
4e191199a0aeab09d78df8f5579e745572e8b7bcwsanchez * The ASF licenses this file to You under the Apache License, Version 2.0
f3a5934ca0fb0f0f813bd9d9d06af8937e3f401fjim * (the "License"); you may not use this file except in compliance with
f3a5934ca0fb0f0f813bd9d9d06af8937e3f401fjim * the License. You may obtain a copy of the License at
d7759bdad133e1e92fe41aab75dd8c1584eda38cjim * Unless required by applicable law or agreed to in writing, software
b3155b9e3b06b20030ec6c16d98f8dabf12ead9cianh * distributed under the License is distributed on an "AS IS" BASIS,
b3155b9e3b06b20030ec6c16d98f8dabf12ead9cianh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b3155b9e3b06b20030ec6c16d98f8dabf12ead9cianh * See the License for the specific language governing permissions and
b3155b9e3b06b20030ec6c16d98f8dabf12ead9cianh * limitations under the License.
b3155b9e3b06b20030ec6c16d98f8dabf12ead9cianh** DAV extension module for Apache 2.0.*
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh** - Database support using DBM-style databases,
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh** part of the filesystem repository implementation
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh** This implementation uses a SDBM database per file and directory to
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh** record the properties. These databases are kept in a subdirectory (of
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh** the directory in question or the directory that holds the file in
b999f6ba2a266bf9a92687f31bb7e76021ac5891ianh** question) named by the macro DAV_FS_STATE_DIR (.DAV). The filename of the
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe** database is equivalent to the target filename, and is
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe** DAV_FS_STATE_FILE_FOR_DIR (.state_for_dir) for the directory itself.
43ea154f46345c9722c2b25b2b9f5086ec79eaeeorlikowski /* when used as a property database: */
0c233c76f21b358f4a0d81e0f956339ca727c14cchuck apr_hash_t *uri_index; /* map URIs to (1-based) table indices */
c1635d9f723f28fed4b95e5d9693e554a79e8d77orlikowski/* -------------------------------------------------------------------------
c1635d9f723f28fed4b95e5d9693e554a79e8d77orlikowski * GENERIC DBM ACCESS
c1635d9f723f28fed4b95e5d9693e554a79e8d77orlikowski * For the most part, this just uses the APR DBM functions. They are wrapped
4f7dd0949d92462a8adc31eee8aff266eea55204chuck * a bit with some error handling (using the mod_dav error functions).
4f7dd0949d92462a8adc31eee8aff266eea55204chuckvoid dav_dbm_get_statefiles(apr_pool_t *p, const char *fname,
68bcde9c52e9e749482df2800dbdff09559115e0chuckstatic dav_error * dav_fs_dbm_error(dav_db *db, apr_pool_t *p,
68bcde9c52e9e749482df2800dbdff09559115e0chuck const char *errstr;
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* There might not be a <db> if we had problems creating it. */
68bcde9c52e9e749482df2800dbdff09559115e0chuck ap_log_error(APLOG_MARK, APLOG_CRIT, status, ap_server_conf, APLOGNO(00576)
68bcde9c52e9e749482df2800dbdff09559115e0chuck "The DBM driver could not be loaded");
68bcde9c52e9e749482df2800dbdff09559115e0chuck (void) apr_dbm_geterror(db->file, &errcode, errbuf, sizeof(errbuf));
68bcde9c52e9e749482df2800dbdff09559115e0chuck err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, status, errstr);
68bcde9c52e9e749482df2800dbdff09559115e0chuck/* ensure that our state subdirectory is present */
0c233c76f21b358f4a0d81e0f956339ca727c14cchuck/* ### does this belong here or in dav_fs_repos.c ?? */
0c233c76f21b358f4a0d81e0f956339ca727c14cchuckvoid dav_fs_ensure_state_dir(apr_pool_t * p, const char *dirname)
68bcde9c52e9e749482df2800dbdff09559115e0chuck const char *pathname = apr_pstrcat(p, dirname, "/" DAV_FS_STATE_DIR, NULL);
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* ### do we need to deal with the umask? */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* just try to make it, ignoring any resulting errors */
68bcde9c52e9e749482df2800dbdff09559115e0chuck/* dav_dbm_open_direct: Opens a *dbm database specified by path.
68bcde9c52e9e749482df2800dbdff09559115e0chuck * ro = boolean read-only flag.
68bcde9c52e9e749482df2800dbdff09559115e0chuckdav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* ### do something with 'status' */
0c233c76f21b358f4a0d81e0f956339ca727c14cchuck /* we can't continue if we couldn't open the file
68bcde9c52e9e749482df2800dbdff09559115e0chuck and we need to write */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* may be NULL if we tried to open a non-existent db as read-only */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* we have an open database... return it */
68bcde9c52e9e749482df2800dbdff09559115e0chuckstatic dav_error * dav_dbm_open(apr_pool_t * p, const dav_resource *resource,
0c233c76f21b358f4a0d81e0f956339ca727c14cchuck const char *dirpath;
68bcde9c52e9e749482df2800dbdff09559115e0chuck const char *fname;
68bcde9c52e9e749482df2800dbdff09559115e0chuck const char *pathname;
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* Get directory and filename for resource */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* ### should test this result value... */
68bcde9c52e9e749482df2800dbdff09559115e0chuck (void) dav_fs_dir_file_name(resource, &dirpath, &fname);
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* If not opening read-only, ensure the state dir exists */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* ### what are the perf implications of always checking this? */
68bcde9c52e9e749482df2800dbdff09559115e0chuck pathname = apr_pstrcat(p, dirpath, "/" DAV_FS_STATE_DIR "/",
0c233c76f21b358f4a0d81e0f956339ca727c14cchuck /* ### readers cannot open while a writer has this open; we should
68bcde9c52e9e749482df2800dbdff09559115e0chuck ### perform a few retries with random pauses. */
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* ### do we need to deal with the umask? */
68bcde9c52e9e749482df2800dbdff09559115e0chuckdav_error * dav_dbm_fetch(dav_db *db, apr_datum_t key, apr_datum_t *pvalue)
68bcde9c52e9e749482df2800dbdff09559115e0chuck /* no key could be created (namespace not known) => no value */
68bcde9c52e9e749482df2800dbdff09559115e0chuckdav_error * dav_dbm_store(dav_db *db, apr_datum_t key, apr_datum_t value)
68bcde9c52e9e749482df2800dbdff09559115e0chuck apr_status_t status = apr_dbm_store(db->file, key, value);
68bcde9c52e9e749482df2800dbdff09559115e0chuckdav_error * dav_dbm_delete(dav_db *db, apr_datum_t key)
unsigned char major;
unsigned char minor;
#define DAV_DBVSN_MINOR 0
short ns_count;
struct dav_deadprop_rollback {
struct dav_namespace_map {
int *ns_map;
l_ns = 0;
if (ns_id == 0) {
return key;
return err;
return err;
dav_propdb_metadata m = {
long ns;
const char *uri;
(void *)ns);
return NULL;
int ns;
return NULL;
int *found)
return err;
*found = 0;
return NULL;
return NULL;
int *pmap;
const char **puri;
if (ns_id == 0) {
*mapping = m;
return NULL;
while (ns_id--)
if (s == NULL) {
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
if (!rollback) {
return NULL;