dbm.c revision 1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94a
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers/* ====================================================================
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * The Apache Software License, Version 1.1
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * Copyright (c) 2000 The Apache Software Foundation. All rights
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * reserved.
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * Redistribution and use in source and binary forms, with or without
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * modification, are permitted provided that the following conditions
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * are met:
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * 1. Redistributions of source code must retain the above copyright
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * notice, this list of conditions and the following disclaimer.
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * 2. Redistributions in binary form must reproduce the above copyright
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann * notice, this list of conditions and the following disclaimer in
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann * the documentation and/or other materials provided with the
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann * distribution.
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann *
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann * 3. The end-user documentation included with the redistribution,
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann * if any, must include the following acknowledgment:
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * "This product includes software developed by the
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * Apache Software Foundation (http://www.apache.org/)."
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers * Alternately, this acknowledgment may appear in the software itself,
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * if and wherever such third-party acknowledgments normally appear.
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann *
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * 4. The names "Apache" and "Apache Software Foundation" must
ba76ee29bc02879fb42c048132af8889b00220d5David Herrmann * not be used to endorse or promote products derived from this
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * software without prior written permission. For written
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * permission, please contact apache@apache.org.
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann *
b17de8449c3ce26031d5bb7dec1086b56e51ac9bDavid Herrmann * 5. Products derived from this software may not be called "Apache",
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * nor may "Apache" appear in their name, without prior written
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * permission of the Apache Software Foundation.
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek *
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * SUCH DAMAGE.
24a4501d70e60f15c074e9f5bda46a7fbc5735e5Peter Hutterer * ====================================================================
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek *
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * This software consists of voluntary contributions made by many
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * individuals on behalf of the Apache Software Foundation. For more
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * information on the Apache Software Foundation, please see
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek * <http://www.apache.org/>.
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek */
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek/*
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek** DAV extension module for Apache 2.0.*
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek** - Database support using DBM-style databases,
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek** part of the filesystem repository implementation
fa9d4be3f1f4a792b2f3624c2a08fe9cc6ce6e54Zbigniew Jędrzejewski-Szmek*/
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers/*
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers** This implementation uses a SDBM or GDBM database per file and directory to
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers** record the properties. These databases are kept in a subdirectory (of
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers** the directory in question or the directory that holds the file in
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt** question) named by the macro DAV_FS_STATE_DIR (.DAV). The filename of the
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers** database is equivalent to the target filename, and is
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers** DAV_FS_STATE_FILE_FOR_DIR (.state_for_dir) for the directory itself.
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers*/
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifdef DAV_USE_GDBM
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#include <gdbm.h>
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#else
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers/* ### need to APR-ize */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#include <fcntl.h> /* for O_RDONLY, O_WRONLY */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#include <sys/stat.h> /* for S_IRUSR, etc */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#include "sdbm.h"
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers/* ### this is still needed for sdbm_open()...
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers * sdbm should be APR-ized really. */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifndef WIN32
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#define DAV_FS_MODE_FILE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#else /* WIN32 */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#define DAV_FS_MODE_FILE (_S_IREAD | _S_IWRITE)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#endif /* WIN32 */
42a9de1c2513aa348df369080cdd941ef4ab00abMartin Pitt
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers#endif
84a122a008e06901ce2d1d3941864afce8fd5d15Kay Sievers
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#include "mod_dav.h"
90e633a7901060063e62bf53948c4c239a9f55d1Jason St. John#include "repos.h"
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#ifdef DAV_USE_GDBM
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitttypedef GDBM_FILE dav_dbm_file;
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_CLOSE(f) gdbm_close(f)
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#define DAV_DBM_FETCH(f, k) gdbm_fetch((f), (k))
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#define DAV_DBM_STORE(f, k, v) gdbm_store((f), (k), (v), GDBM_REPLACE)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_DELETE(f, k) gdbm_delete((f), (k))
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_FIRSTKEY(f) gdbm_firstkey(f)
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#define DAV_DBM_NEXTKEY(f, k) gdbm_nextkey((f), (k))
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_CLEARERR(f) if (0) ; else /* stop "no effect" warning */
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_FREEDATUM(f, d) ((d).dptr ? free((d).dptr) : 0)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#else
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitttypedef DBM *dav_dbm_file;
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_CLOSE(f) sdbm_close(f)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_FETCH(f, k) sdbm_fetch((f), (k))
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_STORE(f, k, v) sdbm_store((f), (k), (v), DBM_REPLACE)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_DELETE(f, k) sdbm_delete((f), (k))
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#define DAV_DBM_FIRSTKEY(f) sdbm_firstkey(f)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_NEXTKEY(f, k) sdbm_nextkey(f)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_CLEARERR(f) sdbm_clearerr(f)
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#define DAV_DBM_FREEDATUM(f, d) if (0) ; else /* stop "no effect" warning */
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt#endif
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pitt
c5b7838ddeae1fcd5c613ea15f04918b945823e5Martin Pittstruct dav_db {
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers ap_pool_t *pool;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers dav_dbm_file file;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers};
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#define D2G(d) (*(datum*)&(d))
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sieversvoid dav_dbm_get_statefiles(ap_pool_t *p, const char *fname,
2dd30e7da94b32df03451df8cf602e9454a376cbKay Sievers const char **state1, const char **state2)
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers{
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers char *work;
1e091c1285b59d0fbab58e6e5113ad111bc08794Martin Pitt
1e091c1285b59d0fbab58e6e5113ad111bc08794Martin Pitt if (fname == NULL)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers fname = DAV_FS_STATE_FILE_FOR_DIR;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifndef DAV_USE_GDBM
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers fname = ap_pstrcat(p, fname, DIRFEXT, NULL);
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers#endif
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *state1 = fname;
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifdef DAV_USE_GDBM
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers *state2 = NULL;
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers#else
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers {
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int extension;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers work = ap_pstrdup(p, fname);
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers
33e74db2667103e33f7e47277378612dcdbdfaa5Martin Pitt /* we know the extension is 4 characters -- len(DIRFEXT) */
e55edb22a71e67f01534d28f91c6aa27bba48fc1Martin Pitt extension = strlen(work) - 4;
4e3deeedc15b03197d591850061316289245c9a9Martin Pitt memcpy(&work[extension], PAGFEXT, 4);
90e633a7901060063e62bf53948c4c239a9f55d1Jason St. John *state2 = work;
33e74db2667103e33f7e47277378612dcdbdfaa5Martin Pitt }
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#endif
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_fs_dbm_error(dav_db *db, ap_pool_t *p)
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int save_errno = errno;
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers int errcode;
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers const char *errstr;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_error *err;
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers p = db ? db->pool : p;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifdef DAV_USE_GDBM
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers errcode = gdbm_errno;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers errstr = gdbm_strerror(gdbm_errno);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#else
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* There might not be a <db> if we had problems creating it. */
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers errcode = !db || sdbm_error(db->file);
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers if (errcode)
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers errstr = "I/O error occurred.";
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers else
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers errstr = "No error.";
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#endif
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, errstr);
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann err->save_errno = save_errno;
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goede return err;
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goede}
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goede
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goede/* ensure that our state subdirectory is present */
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goede/* ### does this belong here or in dav_fs_repos.c ?? */
fc1ae82cae69d8dbbd9e7a31938810a486fac782Hans de Goedevoid dav_fs_ensure_state_dir(ap_pool_t * p, const char *dirname)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers const char *pathname = ap_pstrcat(p, dirname, "/" DAV_FS_STATE_DIR, NULL);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* ### do we need to deal with the umask? */
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* just try to make it, ignoring any resulting errors */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers (void) ap_make_dir(pathname, APR_OS_DEFAULT, p);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers/* dav_dbm_open_direct: Opens a *dbm database specified by path.
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers * ro = boolean read-only flag.
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversdav_error * dav_dbm_open_direct(ap_pool_t *p, const char *pathname, int ro,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_db **pdb)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_dbm_file file;
42a9de1c2513aa348df369080cdd941ef4ab00abMartin Pitt
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers *pdb = NULL;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* NOTE: stupid cast to get rid of "const" on the pathname */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifdef DAV_USE_GDBM
42a9de1c2513aa348df369080cdd941ef4ab00abMartin Pitt file = gdbm_open((char *) pathname,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers 0,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers ro ? GDBM_READER : GDBM_WRCREAT,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_FS_MODE_FILE,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers NULL);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#else
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers file = sdbm_open((char *) pathname,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers ro ? O_RDONLY : (O_RDWR | O_CREAT),
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_FS_MODE_FILE);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#endif
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* we can't continue if we couldn't open the file and we need to write */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers if (file == NULL && !ro) {
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return dav_fs_dbm_error(NULL, p);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers }
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers /* may be NULL if we tried to open a non-existent db as read-only */
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers if (file != NULL) {
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers /* we have an open database... return it */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers *pdb = ap_pcalloc(p, sizeof(**pdb));
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers (*pdb)->pool = p;
aba248ee6b1eb10baf3d89eca2ad7569459af6abHans de Goede (*pdb)->file = file;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers }
aba248ee6b1eb10baf3d89eca2ad7569459af6abHans de Goede
aba248ee6b1eb10baf3d89eca2ad7569459af6abHans de Goede return NULL;
aba248ee6b1eb10baf3d89eca2ad7569459af6abHans de Goede}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sieversstatic dav_error * dav_dbm_open(ap_pool_t * p, const dav_resource *resource,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int ro, dav_db **pdb)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers const char *dirpath;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers const char *fname;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers const char *pathname;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* Get directory and filename for resource */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_fs_dir_file_name(resource, &dirpath, &fname);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* If not opening read-only, ensure the state dir exists */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers if (!ro) {
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers /* ### what are the perf implications of always checking this? */
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers dav_fs_ensure_state_dir(p, dirpath);
3f42b51f21171a3166200af3d9966812f1ddd0f0Martin Pitt }
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers pathname = ap_pstrcat(p,
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers dirpath,
42a9de1c2513aa348df369080cdd941ef4ab00abMartin Pitt "/" DAV_FS_STATE_DIR "/",
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers fname ? fname : DAV_FS_STATE_FILE_FOR_DIR,
24119cf10c7ed58a8fc0851745149dcc6dd5757fStefan Brüns NULL);
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
24119cf10c7ed58a8fc0851745149dcc6dd5757fStefan Brüns /* ### readers cannot open while a writer has this open; we should
4f70555d76c90ffdc5a5e4f75bbc08b38022c911Zbigniew Jędrzejewski-Szmek ### perform a few retries with random pauses. */
24119cf10c7ed58a8fc0851745149dcc6dd5757fStefan Brüns
1f6d36f267186c0e3184bab4c7eca48481c6faabHui Wang /* ### do we need to deal with the umask? */
1f6d36f267186c0e3184bab4c7eca48481c6faabHui Wang
d946bb53f94713241004810de92cc37f1e19c2d2Martin Pitt return dav_dbm_open_direct(p, pathname, ro, pdb);
1f6d36f267186c0e3184bab4c7eca48481c6faabHui Wang}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic void dav_dbm_close(dav_db *db)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_DBM_CLOSE(db->file);
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_dbm_fetch(dav_db *db, dav_datum key, dav_datum *pvalue)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers *(datum *) pvalue = DAV_DBM_FETCH(db->file, D2G(key));
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* we don't need the error; we have *pvalue to tell */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_DBM_CLEARERR(db->file);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return NULL;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_dbm_store(dav_db *db, dav_datum key, dav_datum value)
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int rv;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers rv = DAV_DBM_STORE(db->file, D2G(key), D2G(value));
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* ### fetch more specific error information? */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* we don't need the error; we have rv to tell */
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers DAV_DBM_CLEARERR(db->file);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers if (rv == -1) {
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return dav_fs_dbm_error(db, NULL);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers }
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return NULL;
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_dbm_delete(dav_db *db, dav_datum key)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int rv;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers rv = DAV_DBM_DELETE(db->file, D2G(key));
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* ### fetch more specific error information? */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* we don't need the error; we have rv to tell */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_DBM_CLEARERR(db->file);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers if (rv == -1) {
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return dav_fs_dbm_error(db, NULL);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers }
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return NULL;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic int dav_dbm_exists(dav_db *db, dav_datum key)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers int exists;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#ifdef DAV_USE_GDBM
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers exists = gdbm_exists(db->file, D2G(key)) != 0;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#else
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers {
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers datum value = sdbm_fetch(db->file, D2G(key));
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers sdbm_clearerr(db->file); /* unneeded */
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers exists = value.dptr != NULL;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers }
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers#endif
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return exists;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_dbm_firstkey(dav_db *db, dav_datum *pkey)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers *(datum *) pkey = DAV_DBM_FIRSTKEY(db->file);
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek /* we don't need the error; we have *pkey to tell */
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek DAV_DBM_CLEARERR(db->file);
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers return NULL;
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek}
0787758d26337ec897d9553fe962678fbf0a0962Zbigniew Jędrzejewski-Szmek
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic dav_error * dav_dbm_nextkey(dav_db *db, dav_datum *pkey)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers *(datum *) pkey = DAV_DBM_NEXTKEY(db->file, D2G(*pkey));
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers /* we don't need the error; we have *pkey to tell */
b26e4ced91d0ac0eabdce1c505228ccafc65a23fDavid Herrmann DAV_DBM_CLEARERR(db->file);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers return NULL;
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversstatic void dav_dbm_freedatum(dav_db *db, dav_datum data)
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers DAV_DBM_FREEDATUM(db, data);
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers}
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sieversconst dav_hooks_db dav_hooks_db_dbm =
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers{
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_dbm_open,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_dbm_close,
aedc2eddd16e48d468e6ad0aea2caf00c7d37365Kay Sievers dav_dbm_fetch,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers dav_dbm_store,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers dav_dbm_delete,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers dav_dbm_exists,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers dav_dbm_firstkey,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers dav_dbm_nextkey,
9a3d3aace311e85627115d89e4dfe1d71c01b7e3Kay Sievers dav_dbm_freedatum,
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers};
0c959b39175b126fdb70ae00de37ca6d9c8ca3a1Kay Sievers