--- /dev/null
+## Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+dnl check for --with-tdb option
+AC_DEFUN([SQUID_CHECK_LIBTDB],[
+AC_ARG_WITH(tdb,
+ AS_HELP_STRING([--without-tdb],
+ [Do not use Samba TrivialDB. Default: auto-detect]), [
+case "$with_tdb" in
+ yes|no|auto)
+ : # Nothing special to do here
+ ;;
+ *)
+ AS_IF([test ! -d "$withval"],
+ AC_MSG_ERROR([--with-tdb path ($with_tdb) does not point to a directory])
+ )
+ LIBTDB_PATH="-L$withval/lib"
+ CPPFLAGS="-I$withval/include $CPPFLAGS"
+ ;;
+esac
+])
+AH_TEMPLATE(USE_TRIVIALDB,[Samba TrivialDB support is available])
+AS_IF([test "x$with_tdb" != "xno"],[
+ SQUID_STATE_SAVE(squid_libtdb_state)
+ LIBS="$LIBS $LIBTDB_PATH"
+ PKG_CHECK_MODULES([LIBTDB],[tdb],[CPPFLAGS="$CPPFLAGS $LIBTDB_CFLAGS"],[:])
+ AC_CHECK_HEADERS([sys/stat.h tdb.h],,,[
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ])
+ SQUID_STATE_ROLLBACK(squid_libtdb_state) #de-pollute LIBS
+
+ AS_IF([test "x$with_tdb" = "xyes" -a "x$LIBTDB_LIBS" = "x"],
+ AC_MSG_ERROR([Required TrivialDB library not found])
+ )
+ AS_IF([test "x$LIBTDB_LIBS" != "x"],[
+ CXXFLAGS="$LIBTDB_CFLAGS $CXXFLAGS"
+ LIBTDB_LIBS="$LIBTDB_PATH $LIBTDB_LIBS"
+ AC_DEFINE_UNQUOTED(USE_TRIVIALDB, HAVE_TDB_H, [Samba TrivialDB support is available])
+ ],[with_tdb=no])
+])
+AC_MSG_NOTICE([Samba TrivialDB library support: ${with_tdb:=auto} ${LIBTDB_PATH} ${LIBTDB_LIBS}])
+AC_SUBST(LIBTDB_LIBS)
+])
m4_include([acinclude/krb5.m4])
m4_include([acinclude/pam.m4])
m4_include([acinclude/pkg.m4])
+m4_include([acinclude/tdb.m4])
m4_include([acinclude/lib-checks.m4])
m4_include([acinclude/ax_cxx_compile_stdcxx_11.m4])
m4_include([acinclude/ax_cxx_0x_types.m4])
<sect1>New options<label id="newoptions">
<p>
<descrip>
- <p>No new options in this version.
+ <tag>--without-tdb</tag>
+ <p>New option to determine whether TrivialDB support is used, and
+ build against local custom installs.
+ <p>Samba TrivialDB is now the preferred database used by the
+ <em>ext_session_acl</em> and <em>ext_time_quota_acl</em> helpers,
+ deprecating use of BerkleyDB.
</descrip>
ext_session_acl.cc
ext_session_acl_LDADD = \
$(COMPAT_LIB) \
- -ldb
+ $(LIBBDB_LIBS) \
+ $(LIBTDB_LIBS)
EXTRA_DIST= ext_session_acl.8 required.m4
#endif
#include <sys/types.h>
#include <sys/stat.h>
+#if HAVE_TDB_H
+#include <tdb.h>
+#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
char *db_path = NULL;
const char *program_name;
+#if USE_BERKLEYDB
DB *db = NULL;
DB_ENV *db_env = NULL;
+typedef DBT DB_ENTRY;
+
+#elif USE_TRIVIALDB
+TDB_CONTEXT *db = nullptr;
+typedef TDB_DATA DB_ENTRY;
+
+#endif
+
+static void
+shutdown_db()
+{
+ if (db) {
+#if USE_BERKLEYDB
+ db->close(db, 0);
+ }
+ if (db_env) {
+ db_env->close(db_env, 0);
+
+#elif USE_TRIVIALDB
+ if (tdb_close(db) != 0) {
+ fprintf(stderr, "%s| WARNING: error closing session db '%s'\n", program_name, db_path);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ }
+ xfree(db_path);
+}
static void init_db(void)
{
if (db_path) {
if (!stat(db_path, &st_buf)) {
if (S_ISDIR (st_buf.st_mode)) {
+#if USE_BERKLEYDB
/* If directory then open database environment. This prevents sync problems
between different processes. Otherwise fallback to single file */
db_env_create(&db_env, 0);
exit(EXIT_FAILURE);
}
db_create(&db, db_env, 0);
+#elif USE_TRIVIALDB
+ std::string newPath(db_path);
+ newPath.append("session", 7);
+ db_path = xstrdup(newPath.c_str());
+#endif
}
}
}
+#if USE_BERKLEYDB
if (db_env) {
if (db->open(db, NULL, "session", NULL, DB_BTREE, DB_CREATE, 0666)) {
fprintf(stderr, "FATAL: %s: Failed to open db file '%s' in dir '%s'\n",
} else {
db_create(&db, NULL, 0);
if (db->open(db, NULL, db_path, NULL, DB_BTREE, DB_CREATE, 0666)) {
- fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
- exit(EXIT_FAILURE);
+ db = nullptr;
}
}
+#elif USE_TRIVIALDB
+ db = tdb_open(db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT|O_DSYNC, 0666);
+#endif
+ if (!db) {
+ fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
+ shutdown_db();
+ exit(EXIT_FAILURE);
+ }
}
-static void shutdown_db(void)
+int session_is_active = 0;
+
+static size_t
+dataSize(DB_ENTRY *data)
{
- db->close(db, 0);
- if (db_env) {
- db_env->close(db_env, 0);
- }
+#if USE_BERKLEYDB
+ return data->size;
+#elif USE_TRIVIALDB
+ return data->dsize;
+#endif
}
-int session_is_active = 0;
+static bool
+fetchKey(/*const*/ DB_ENTRY &key, DB_ENTRY *data)
+{
+#if USE_BERKLEYDB
+ return (db->get(db, nullptr, &key, data, 0) == 0);
+#elif USE_TRIVIALDB
+ // NP: API says returns NULL on errors, but return is a struct type WTF??
+ *data = tdb_fetch(db, key);
+ return (data->dptr != nullptr);
+#endif
+}
+
+static void
+deleteEntry(/*const*/ DB_ENTRY &key)
+{
+#if USE_BERKLEYDB
+ db->del(db, nullptr, &key, 0);
+#elif USE_TRIVIALDB
+ tdb_delete(db, key);
+#endif
+}
+
+static void
+copyValue(void *dst, const DB_ENTRY *src, size_t sz)
+{
+#if USE_BERKLEYDB
+ memcpy(dst, src->data, sz);
+#elif USE_TRIVIALDB
+ memcpy(dst, src->dptr, sz);
+#endif
+}
static int session_active(const char *details, size_t len)
{
+#if USE_BERKLEYDB
DBT key = {0};
DBT data = {0};
key.data = (void *)details;
key.size = len;
- if (db->get(db, NULL, &key, &data, 0) == 0) {
+#elif USE_TRIVIALDB
+ TDB_DATA key;
+ TDB_DATA data;
+#endif
+ if (fetchKey(key, &data)) {
time_t timestamp;
- if (data.size != sizeof(timestamp)) {
+ if (dataSize(&data) != sizeof(timestamp)) {
fprintf(stderr, "ERROR: %s: CORRUPTED DATABASE (%s)\n", program_name, details);
- db->del(db, NULL, &key, 0);
+ deleteEntry(key);
return 0;
}
- memcpy(×tamp, data.data, sizeof(timestamp));
+ copyValue(×tamp, &data, sizeof(timestamp));
if (timestamp + session_ttl >= time(NULL))
return 1;
}
return 0;
}
-static void session_login(const char *details, size_t len)
+static void
+session_login(/*const*/ char *details, size_t len)
{
- DBT key = {0};
- DBT data = {0};
- key.data = (void *)details;
+ DB_ENTRY key = {0};
+ DB_ENTRY data = {0};
+ time_t now = time(0);
+#if USE_BERKLEYDB
+ key.data = static_cast<decltype(key.data)>(details);
key.size = len;
- time_t now = time(NULL);
data.data = &now;
data.size = sizeof(now);
db->put(db, NULL, &key, &data, 0);
+#elif USE_TRIVIALDB
+ key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+ key.dsize = len;
+ data.dptr = reinterpret_cast<decltype(data.dptr)>(&now);
+ data.dsize = sizeof(now);
+ tdb_store(db, key, data, 0);
+#endif
}
-static void session_logout(const char *details, size_t len)
+static void
+session_logout(/*const*/ char *details, size_t len)
{
- DBT key = {0};
- key.data = (void *)details;
+ DB_ENTRY key = {0};
+#if USE_BERKLEYDB
+ key.data = static_cast<decltype(key.data)>(details);
key.size = len;
- db->del(db, NULL, &key, 0);
+#elif USE_TRIVIALDB
+ key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+ key.dsize = len;
+#endif
+ deleteEntry(key);
}
static void usage(void)
session_ttl = strtol(optarg, NULL, 0);
break;
case 'b':
- db_path = optarg;
+ db_path = xstrdup(optarg);
break;
case 'a':
default_action = 0;
## Please see the COPYING and CONTRIBUTORS files for details.
##
-AC_CHECK_HEADERS(db.h,[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
- DB_ENV *db_env = nullptr;
- db_env_create(&db_env, 0);
- ]])],[
+SQUID_CHECK_LIBTDB
+if test "$with_tdb" != "no"; then
BUILD_HELPER="session"
- ],[])
-])
+fi
+
+LIBBDB_LIBS=
+AH_TEMPLATE(USE_BERKLEYDB,[BerkleyDB support is available])
+if test "x$with_tdb" = "xno"; then
+ AC_CHECK_HEADERS(db.h,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
+ DB_ENV *db_env = nullptr;
+ db_env_create(&db_env, 0);
+ ]])],[
+ AC_DEFINE_UNQUOTED(USE_BERKLEYDB, HAVE_DB_H, [BerkleyDB support is available])
+ BUILD_HELPER="session"
+ LIBBDB_LIBS="-ldb"
+ ],[])
+ ])
+fi
+AC_SUBST(LIBBDB_LIBS)
ext_time_quota_acl.cc
ext_time_quota_acl_LDADD = \
$(COMPAT_LIB) \
- -ldb
+ $(LIBTDB_LIBS)
EXTRA_DIST= ext_time_quota_acl.8 required.m4
#if HAVE_GETOPT_H
#include <getopt.h>
#endif
-
-/* At this point all Bit Types are already defined, so we must
- protect from multiple type definition on platform where
- __BIT_TYPES_DEFINED__ is not defined.
- */
-#ifndef __BIT_TYPES_DEFINED__
-#define __BIT_TYPES_DEFINED__
-#endif
-
-#if HAVE_DB_185_H
-#include <db_185.h>
-#elif HAVE_DB_H
-#include <db.h>
+#if HAVE_TDB_H
+#include <tdb.h>
#endif
#ifndef DEFAULT_QUOTA_DB
const char *db_path = DEFAULT_QUOTA_DB;
const char *program_name;
-DB *db = NULL;
+TDB_CONTEXT *db = nullptr;
#define KEY_LAST_ACTIVITY "last-activity"
#define KEY_PERIOD_START "period-start"
static void init_db(void)
{
log_info("opening time quota database \"%s\".\n", db_path);
- db = dbopen(db_path, O_CREAT | O_RDWR, 0666, DB_BTREE, NULL);
+ db = tdb_open(db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT | O_RDWR, 0666);
if (!db) {
log_fatal("Failed to open time_quota db '%s'\n", db_path);
exit(EXIT_FAILURE);
static void shutdown_db(void)
{
- db->close(db);
+ tdb_close(db);
}
-static void writeTime(const char *user_key, const char *sub_key, time_t t)
+static char *KeyString(int &len, const char *user_key, const char *sub_key)
{
- char keybuffer[TQ_BUFFERSIZE];
- DBT key, data;
+ static char keybuffer[TQ_BUFFERSIZE];
+ *keybuffer = 0;
+
+ len = snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+ if (len < 0) {
+ log_error("Cannot add entry: %s-%s", user_key, sub_key);
+ len = 0;
- if ( strlen(user_key) + strlen(sub_key) + 1 + 1 > sizeof(keybuffer) ) {
+ } else if (static_cast<size_t>(len) >= sizeof(keybuffer)) {
log_error("key too long (%s,%s)\n", user_key, sub_key);
- } else {
- snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+ len = 0;
+ }
+
+ return keybuffer;
+}
+
+static void writeTime(const char *user_key, const char *sub_key, time_t t)
+{
+ int len = 0;
+ if (/* const */ char *keybuffer = KeyString(len, user_key, sub_key)) {
+
+ TDB_DATA key, data;
+
+ key.dptr = reinterpret_cast<unsigned char *>(keybuffer);
+ key.dsize = len;
- key.data = (void *)keybuffer;
- key.size = strlen(keybuffer);
- data.data = &t;
- data.size = sizeof(t);
- db->put(db, &key, &data, 0);
+ data.dptr = reinterpret_cast<unsigned char *>(&t);
+ data.dsize = sizeof(t);
+
+ tdb_store(db, key, data, TDB_REPLACE);
log_debug("writeTime(\"%s\", %d)\n", keybuffer, t);
}
}
static time_t readTime(const char *user_key, const char *sub_key)
{
- char keybuffer[TQ_BUFFERSIZE];
- DBT key, data;
- time_t t = 0;
+ int len = 0;
+ if (/* const */ char *keybuffer = KeyString(len, user_key, sub_key)) {
- if ( strlen(user_key) + 1 + strlen(sub_key) + 1 > sizeof(keybuffer) ) {
- log_error("key too long (%s,%s)\n", user_key, sub_key);
- } else {
- snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+ TDB_DATA key;
+ key.dptr = reinterpret_cast<unsigned char *>(keybuffer);
+ key.dsize = len;
- key.data = (void *)keybuffer;
- key.size = strlen(keybuffer);
- if (db->get(db, &key, &data, 0) == 0) {
- if (data.size != sizeof(t)) {
- log_error("CORRUPTED DATABASE (%s)\n", keybuffer);
- } else {
- memcpy(&t, data.data, sizeof(t));
- }
+ auto data = tdb_fetch(db, key);
+
+ time_t t = 0;
+ if (data.dsize != sizeof(t)) {
+ log_error("CORRUPTED DATABASE (%s)\n", keybuffer);
+ } else {
+ memcpy(&t, data.dptr, sizeof(t));
}
+
log_debug("readTime(\"%s\")=%d\n", keybuffer, t);
+ return t;
}
- return t;
+ return 0;
}
static void parseTime(const char *s, time_t *secs, time_t *start)
log_debug("ERR %s\n", message);
SEND_ERR("Time budget exceeded.");
}
-
- db->sync(db, 0);
}
static void usage(void)
## Please see the COPYING and CONTRIBUTORS files for details.
##
-AC_CHECK_HEADERS(db_185.h,[BUILD_HELPER="time_quota"],[
- AC_CHECK_HEADERS(db.h,[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
- DB *db = dbopen("/tmp", O_CREAT | O_RDWR, 0666, DB_BTREE, NULL);
- ]])],[
- BUILD_HELPER="time_quota"
- ],[])
- ])
-])
+SQUID_CHECK_LIBTDB
+if test "$with_tdb" != "no"; then
+ BUILD_HELPER="time_quota"
+fi
--without-gnutls \
--without-openssl \
--without-po2html \
+ --without-tdb \
"
# Fix the distclean testing.
# --enable-win32-service \
# --with-valgrind-debug \
# --with-gnutls \
+# --with-tdb \
#
# --enable-cpu-profiling \ Requires CPU support.
#