summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2005-06-20 23:37:01 +0000
committerrelyea%netscape.com <devnull@localhost>2005-06-20 23:37:01 +0000
commit7b5ffad0b9007e773f2ace4ba585af5bb604102d (patch)
tree1d65e103b6a19b37568991f3f737e4581434e59f
parent99b3c71261551ff665582e08895d5bd6aad14c5d (diff)
downloadnss-hg-7b5ffad0b9007e773f2ace4ba585af5bb604102d.tar.gz
Multiaccess database stub file. Copy {LIBPREFIX}rdb.{SHLIB_SUFFIX} and sqlite3
(again with the appropriate prefix and suffix) into your library path, then open "multiaccess:{group}:{old NSS configdir path}" as your configuration directory to access the shared NSS directory.
-rw-r--r--security/nss/lib/rdb/Makefile80
-rw-r--r--security/nss/lib/rdb/config.mk82
-rw-r--r--security/nss/lib/rdb/manifest.mn56
-rw-r--r--security/nss/lib/rdb/rdb.c760
-rw-r--r--security/nss/lib/rdb/rdb.def59
-rw-r--r--security/nss/lib/rdb/rdb.rc101
6 files changed, 1138 insertions, 0 deletions
diff --git a/security/nss/lib/rdb/Makefile b/security/nss/lib/rdb/Makefile
new file mode 100644
index 000000000..a41aa72c6
--- /dev/null
+++ b/security/nss/lib/rdb/Makefile
@@ -0,0 +1,80 @@
+#! gmake
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+export:: private_export
+
diff --git a/security/nss/lib/rdb/config.mk b/security/nss/lib/rdb/config.mk
new file mode 100644
index 000000000..85f2e7844
--- /dev/null
+++ b/security/nss/lib/rdb/config.mk
@@ -0,0 +1,82 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifdef NISCC_TEST
+DEFINES += -DNISCC_TEST
+endif
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+# don't want the 32 in the shared library name
+SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
+
+RES = $(OBJDIR)/$(LIBRARY_NAME).res
+RESNAME = $(LIBRARY_NAME).rc
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lsqlite3 \
+ $(NULL)
+else # ! NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ $(DIST)/lib/sqlite3.lib \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ -lsqlite3 \
+ $(NULL)
+
+ifeq ($(OS_ARCH), BeOS)
+EXTRA_SHARED_LIBS += -lbe
+endif
+
+ifeq ($(OS_TARGET),SunOS)
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+
+endif
diff --git a/security/nss/lib/rdb/manifest.mn b/security/nss/lib/rdb/manifest.mn
new file mode 100644
index 000000000..947955b12
--- /dev/null
+++ b/security/nss/lib/rdb/manifest.mn
@@ -0,0 +1,56 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+CORE_DEPTH = ../../..
+
+# DEFINES = -DTRACE
+
+MODULE = rdb
+MAPFILE = $(OBJDIR)/rdb.def
+
+CSRCS = \
+ rdb.c \
+ $(NULL)
+
+
+REQUIRES = dbm nss sqlite3
+
+ifdef NSS_ENABLE_ECC
+DEFINES += -DNSS_ENABLE_ECC
+endif
+
+LIBRARY_NAME = rdb
+#LIBRARY_VERSION = 3
diff --git a/security/nss/lib/rdb/rdb.c b/security/nss/lib/rdb/rdb.c
new file mode 100644
index 000000000..2a122fdd6
--- /dev/null
+++ b/security/nss/lib/rdb/rdb.c
@@ -0,0 +1,760 @@
+/*
+ * the following data structures are from rdb.h.
+ */
+#include "sqlite3.h"
+#include "mcom_db.h"
+#include "errno.h"
+#include "malloc.h"
+#include "stdlib.h"
+#include "string.h"
+#include "sys/stat.h"
+#include "fcntl.h"
+#include "direct.h"
+#ifdef _WINDOWS
+#define usleep(x)
+#endif
+
+#define STATIC_CMD_SIZE 2048
+struct RDBStr {
+ DB db;
+ int (*xactstart)(DB *db);
+ int (*xactdone)(DB *db, PRBool abort);
+ int version;
+ int (*dbinitcomplete)(DB *db);
+ int flags;
+ int index;
+ unsigned char *dataPool;
+ int dataPoolSize;
+ unsigned char *keyPool;
+ int keyPoolSize;
+ sqlite3_stmt *delStmt;
+ sqlite3_stmt *getStmt;
+ sqlite3_stmt *seqStmt;
+ sqlite3_stmt *insertStmt;
+ sqlite3_stmt *replaceStmt;
+ sqlite3_stmt *beginStmt;
+ sqlite3_stmt *rollbackStmt;
+ sqlite3_stmt *commitStmt;
+};
+
+
+typedef struct RDBStr RDB;
+#define DB_RDB ((DBTYPE) 0xff)
+#define RDB_RDONLY 1
+#define RDB_RDWR 2
+#define RDB_CREATE 4
+
+#define DBM_OK 0
+#define DBM_ERROR -1
+#define DBM_END 1
+
+#define DEL_CMD "DELETE FROM nssTable WHERE key=$KEY;"
+#define GET_CMD "SELECT ALL * FROM nssTable WHERE key=$KEY;"
+#define SEQ_CMD "SELECT ALL * FROM nssTable LIMIT 1 OFFSET $OFFSET;"
+#define INSERT_CMD "INSERT INTO nssTable VALUES ( $KEY, $DATA );"
+#define REPLACE_CMD "REPLACE INTO nssTable VALUES ( $KEY, $DATA );"
+#define BEGIN_CMD "BEGIN EXCLUSIVE TRANSACTION;"
+#define ROLLBACK_CMD "ROLLBACK TRANSACTION;"
+#define COMMIT_CMD "COMMIT TRANSACTION;"
+#define INIT_CMD \
+ "CREATE TABLE nssTable (Key PRIMARY KEY UNIQUE ON CONFLICT ABORT, Data);"
+#define IN_INIT_CMD "CREATE TABLE nssInit (dummy);"
+#define DONE_INIT_CMD "DROP TABLE nssInit;"
+#define CHECK_TABLE_CMD "SELECT ALL * FROM %s LIMIT 0;"
+
+static int rdbupdateStmt(sqlite3 *db, sqlite3_stmt **stmt, const char *cmd)
+{
+ sqlite3_finalize(*stmt);
+ return sqlite3_prepare(db, cmd, -1, stmt, NULL);
+}
+
+#define MAX_RETRIES 10
+static int rdbdone(int err, int *count)
+{
+ /* allow as many rows as the database wants to give */
+ if (err == SQLITE_ROW) {
+ *count = 0;
+ return 0;
+ }
+ if (err != SQLITE_BUSY) {
+ return 1;
+ }
+ /* err == SQLITE_BUSY, Dont' retry forever in this case */
+ if (++(*count) >= MAX_RETRIES) {
+ return 1;
+ }
+ return 0;
+}
+
+static int rdbmapSQLError(sqlite3 *db, int sqlerr)
+{
+ if ((sqlerr == SQLITE_OK) ||
+ (sqlerr == SQLITE_DONE)) {
+ return DBM_OK;
+ } else {
+#ifdef DEBUG
+ char *errorStr =sqlite3_errmsg(db);
+#endif
+ return DBM_ERROR;
+ }
+}
+
+int rdbxactstart(DB *db)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int sqlerr;
+
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ if (rdb->flags == RDB_RDONLY) {
+ errno = EPERM;
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->beginStmt, BEGIN_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = rdb->beginStmt;
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ } while (!rdbdone(sqlerr,&retry));
+ sqlite3_reset(stmt);
+
+ //sqlite3_clear_bindings(stmt);
+
+ return rdbmapSQLError(psqlDB, sqlerr);
+}
+
+int rdbxactdone(DB *db, PRBool abort)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int sqlerr;
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ if (rdb->flags == RDB_RDONLY) {
+ errno = EPERM;
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->rollbackStmt, ROLLBACK_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->commitStmt, COMMIT_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = abort ? rdb->rollbackStmt : rdb->commitStmt;
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ } while (!rdbdone(sqlerr,&retry));
+ sqlite3_reset(stmt);
+
+ //sqlite3_clear_bindings(stmt);
+
+ return rdbmapSQLError(psqlDB, sqlerr);
+}
+
+int rdbclose(DB *db)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ int sqlerr = SQLITE_OK;
+
+ sqlite3_finalize(rdb->delStmt);
+ sqlite3_finalize(rdb->getStmt);
+ sqlite3_finalize(rdb->seqStmt);
+ sqlite3_finalize(rdb->insertStmt);
+ sqlite3_finalize(rdb->replaceStmt);
+ sqlite3_finalize(rdb->beginStmt);
+ sqlite3_finalize(rdb->rollbackStmt);
+ sqlite3_finalize(rdb->commitStmt);
+
+ sqlerr = sqlite3_close(psqlDB);
+ /* assert sqlerr == SQLITE_OK */
+ free(rdb);
+ return DBM_OK;
+}
+
+
+int rdbdel(const DB *db, const DBT *key, uint flags)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int sqlerr;
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ if (rdb->flags == RDB_RDONLY) {
+ errno = EPERM;
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->delStmt, DEL_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = rdb->delStmt;
+
+ sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ } while (!rdbdone(sqlerr,&retry));
+ sqlite3_reset(stmt);
+
+ //sqlite3_clear_bindings(stmt);
+ sqlite3_bind_null(stmt,1);
+
+ return rdbmapSQLError(psqlDB, sqlerr);
+}
+
+void
+setData(DBT *dbt,const char *blobData, int blobSize,
+ unsigned char **poolPtr, int *poolSizePtr)
+{
+ int size = blobSize < 2048 ? blobSize : 2048;
+
+ if (size > *poolSizePtr) {
+ *poolPtr = realloc(*poolPtr,size);
+ *poolSizePtr = size;
+ }
+ memcpy(*poolPtr, blobData, blobSize);
+ dbt->data = *poolPtr;
+ dbt->size = blobSize;
+}
+
+
+int rdbget(const DB *db, const DBT *key, DBT *data, uint flags)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int found = 0;
+ int sqlerr;
+ int ret;
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->getStmt, GET_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = rdb->getStmt;
+
+ sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ /* we only asked for 1, this will return the last one */
+ int blobSize = sqlite3_column_bytes(stmt, 1);
+ const char *blobData = sqlite3_column_blob(stmt, 1);
+ setData(data,blobData,blobSize, &rdb->dataPool, &rdb->dataPoolSize);
+ found = 1;
+ }
+ } while (!rdbdone(sqlerr,&retry));
+
+ sqlite3_reset(stmt);
+ sqlite3_bind_null(stmt,1);
+
+ ret = rdbmapSQLError(psqlDB, sqlerr);
+ if ((ret == 0) && (!found)) {
+ ret = DBM_END;
+ }
+
+ return ret;
+}
+
+int rdbput(const DB *db, const DBT *key, const DBT *data, uint flag)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int sqlerr;
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ if (rdb->flags == RDB_RDONLY) {
+ errno = EPERM;
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->insertStmt, INSERT_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->replaceStmt, REPLACE_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = (flag == R_NOOVERWRITE) ? rdb->insertStmt : rdb->replaceStmt;
+
+ sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
+ sqlite3_bind_blob(stmt, 2, data->data, data->size, SQLITE_STATIC);
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ } while (!rdbdone(sqlerr,&retry));
+
+ sqlite3_reset(stmt);
+ sqlite3_bind_null(stmt,1);
+ sqlite3_bind_null(stmt,0);
+
+ return rdbmapSQLError(psqlDB, sqlerr);
+}
+
+int rdbseq(const DB *db, DBT *key, DBT *data, uint flags)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ RDB *rdb = (RDB *)db;
+ sqlite3_stmt *stmt;
+ int retry = 0;
+ int found = 0;
+ int sqlerr;
+ int ret;
+
+ if (psqlDB == NULL) {
+ return DBM_ERROR;
+ }
+ if (flags == R_FIRST) {
+ rdb->index = 0;
+ } else if (flags == R_NEXT) {
+ rdb->index++;
+ } else {
+ errno = EINVAL;
+ return DBM_ERROR;
+ }
+ sqlerr = rdbupdateStmt(psqlDB, &rdb->seqStmt, SEQ_CMD);
+ if (sqlerr != SQLITE_OK) {
+ return DBM_ERROR;
+ }
+ stmt = rdb->seqStmt;
+
+ sqlite3_bind_int(stmt, 1, rdb->index);
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ usleep(5);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ /* we only asked for 1, this will return the last one */
+ int blobSize = sqlite3_column_bytes(stmt, 0);
+ const char *blobData = sqlite3_column_blob(stmt, 0);
+ setData(key,blobData,blobSize, &rdb->keyPool, &rdb->keyPoolSize);
+ blobSize = sqlite3_column_bytes(stmt, 1);
+ blobData = sqlite3_column_blob(stmt, 1);
+ setData(data,blobData,blobSize, &rdb->dataPool, &rdb->dataPoolSize);
+ found = 1;
+ }
+ } while (!rdbdone(sqlerr,&retry));
+
+ sqlite3_reset(stmt);
+ sqlite3_bind_null(stmt,1);
+
+ ret = rdbmapSQLError(psqlDB, sqlerr);
+ if ((ret == 0) && (!found)) {
+ ret = DBM_END;
+ }
+ return ret;
+}
+
+
+int rdbsync(const DB *db, uint flags)
+{
+ return DBM_OK;
+}
+
+
+int rdbfd(const DB *db)
+{
+ errno = EINVAL;
+ return DBM_ERROR;
+}
+
+int rdbinitcomplete(DB *db)
+{
+ sqlite3 *psqlDB = (sqlite3 *)db->internal;
+ int sqlerr;
+
+ sqlerr = sqlite3_exec(psqlDB, DONE_INIT_CMD, NULL, 0, NULL);
+ /* deal with the error! */
+ return DBM_OK;
+}
+
+
+static int grdbstatus = 0;
+int rdbstatus(void)
+{
+ return grdbstatus;
+}
+
+static int tableExists(sqlite3 *sqlDB, const char *tableName)
+{
+ int sqlerr;
+ char * cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
+
+ if (cmd == NULL) {
+ return 0;
+ }
+
+ sqlerr =
+ sqlite3_exec(sqlDB, cmd, NULL, 0, 0);
+ sqlite3_free(cmd);
+
+ return (sqlerr == SQLITE_OK) ? 1 : 0;
+}
+
+
+static int rdbIsDirectory(const char *dir)
+{
+ struct stat sbuf;
+ int rc;
+
+ rc = stat(dir,&sbuf);
+ if (rc == 0) {
+ return ((sbuf.st_mode & S_IFDIR) == S_IFDIR);
+ }
+ return 0;
+}
+
+static int rdbRmFile(const char *fileName)
+{
+ int rc = unlink(fileName);
+ if ((rc < 0) && (errno == EPERM)) {
+ chmod(fileName,0644);
+ rc = unlink(fileName);
+ }
+ return rc;
+}
+
+#define MAX_RECURSE_LEVEL 15
+#define DIR_MODE 0755
+#ifdef _WINDOWS
+#define MKDIR(x,y) mkdir(x)
+#else
+#define MKDIR(x,y) mkdir(x,y)
+#endif
+
+/*
+ * Create a directory. Create any missing or broken
+ * components we need along the way. If we already have a
+ * directory, return success.
+ */
+int rdbMakedir(const char *directory, int level, int mode)
+{
+ int rc;
+ char *buf, *cp;
+#ifdef _WINDOWS
+ char *cp1;
+#endif
+
+ /* prevent arbitrary stack overflow */
+ if (level > MAX_RECURSE_LEVEL) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ umask(0);
+
+ /* just try it first */
+ rc = MKDIR(directory, mode);
+ if (rc != 0) {
+ if (errno == EEXIST) {
+ if (rdbIsDirectory(directory)) {
+ /* we have a directory, use it */
+ return 0;
+ } else { /* must be a file */
+ /* remove the file and try again */
+ rc = rdbRmFile(directory);
+ if (rc == 0) {
+ rc = MKDIR(directory, mode);
+ }
+ return rc;
+ }
+ }
+ /* if we fail because on of the subdirectory entries was a
+ * file, or one of the subdirectory entries didn't exist,
+ * move back one component and try the whole thing again
+ */
+ if ((errno != ENOENT) && (errno != ENOTDIR)) {
+ return rc;
+ }
+ buf = (char *)malloc(strlen(directory)+1);
+ strcpy(buf,directory);
+ cp = strrchr(buf,'/');
+#ifdef _WINDOWS
+ cp1 = strrchr(buf,'\\');
+ if (cp1 > cp) {
+ cp = cp1;
+ }
+#endif
+ if (cp) {
+ *cp = 0;
+ rc = rdbMakedir(buf,level+1, mode);
+ if (rc == 0) {
+ rc = MKDIR(directory, mode);
+ }
+ }
+ free(buf);
+ }
+ return rc;
+}
+
+static char *rdbBuildFileName(const char *appName, const char *prefix,
+ const char *type, int flags)
+{
+ const char *home = getenv("HOME");
+ char *dir, *dbname;
+ char *prefixDir = NULL;
+ const char *prefixName = NULL;
+
+ /*
+ * build up the name of our database file.
+ * if create is set, make sure the directory path exists.
+ */
+ if (prefix) {
+ /*
+ * prefix may have directory elements in it. If it does, we need
+ * to break out the directory versus the actual prefix portions
+ * so we can make sure the directory is created before we try to
+ * create the db file.
+ */
+ const char *end = strrchr(prefix,'/');
+#ifdef WINDOWS
+ /* windows has two possible directory field separators. Make sure
+ * we pick the one that is furthest down the string. (this code
+ * will also pick the non-null value. */
+ const char *end2 = strrchr(prefix,'\\');
+ /* find the last directory path element */
+ if (end2 > end) {
+ end = end2;
+ }
+#endif
+ /* if the directory path exists, split the components */
+ if (end) {
+ prefixDir = strdup(prefix);
+ if (prefixDir == NULL) return NULL;
+ prefixDir[prefix-end] = 0;
+ prefixName = end+1;
+ } else {
+ prefixName = prefix;
+ }
+ }
+ /* build the directory portion */
+ if (prefixDir) {
+ dir = sqlite3_mprintf("%s/.nssdb/%s/%s",home,appName,prefixDir);
+ free(prefixDir);
+ } else {
+ dir = sqlite3_mprintf("%s/.nssdb/%s",home,appName);
+ }
+ if (dir == NULL) return NULL;
+ /* if we are creating, make sure the directory is created as well */
+ if (flags == RDB_CREATE) {
+ rdbMakedir(dir,0, DIR_MODE);
+ }
+ /* build the full dbname */
+ dbname = sqlite3_mprintf("%s/%s%sS.sqldb",dir,prefixName? prefixName:"",type);
+ sqlite3_free(dir);
+ return dbname;
+}
+
+
+
+/* rdbopen */
+DB * rdbopen(const char *appName, const char *prefix, const char *type,
+ int flags)
+{
+ char *name = rdbBuildFileName(appName, prefix, type, flags);
+ sqlite3 *psqlDB = NULL;
+ RDB *rdb = NULL;
+ int sqlerr = SQLITE_OK;
+ int inTransaction = 0;
+ int inInit = 0;
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ sqlerr = sqlite3_open(name,&psqlDB );
+ sqlite3_free(name);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+
+ sqlerr = sqlite3_busy_timeout(psqlDB, 1000);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+
+
+ sqlerr = sqlite3_exec(psqlDB, BEGIN_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ inTransaction = 1;
+
+ if (!tableExists(psqlDB,"nssTable")) {
+ if (flags != RDB_CREATE) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_exec(psqlDB, INIT_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ /* hack. don't create the init on secmod db files */
+ if (strcmp(type,"secmod") != 0) {
+ sqlerr = sqlite3_exec(psqlDB, IN_INIT_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ }
+ } else {
+ /* if the nssInit table exists, then someone else is initing the
+ * nss database. We don't want to complete the open until the init
+ * is completed. */
+ if (tableExists(psqlDB,"nssInit")) {
+ inInit = 1;
+ }
+ }
+ rdb = (RDB *) malloc(sizeof(RDB));
+ rdb->db.internal = psqlDB;
+ rdb->db.type = DB_RDB;
+ rdb->db.close = rdbclose;
+ rdb->db.del = rdbdel;
+ rdb->db.get = rdbget;
+ rdb->db.put = rdbput;
+ rdb->db.seq = rdbseq;
+ rdb->db.sync = rdbsync;
+ rdb->db.fd = rdbfd;
+ rdb->version = 1;
+ rdb->index = 0;
+ rdb->flags = flags;
+ rdb->xactstart = rdbxactstart;
+ rdb->xactdone = rdbxactdone;
+ rdb->dbinitcomplete = rdbinitcomplete;
+ rdb->dataPool = NULL;
+ rdb->dataPoolSize = 0;
+ rdb->keyPool = NULL;
+ rdb->keyPoolSize = 0;
+ sqlerr = sqlite3_prepare(psqlDB, DEL_CMD, sizeof(DEL_CMD),
+ &rdb->delStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, GET_CMD, sizeof(GET_CMD),
+ &rdb->getStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, SEQ_CMD, sizeof(SEQ_CMD),
+ &rdb->seqStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, INSERT_CMD, sizeof(INSERT_CMD),
+ &rdb->insertStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, REPLACE_CMD, sizeof(REPLACE_CMD),
+ &rdb->replaceStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, BEGIN_CMD, sizeof(BEGIN_CMD),
+ &rdb->beginStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, ROLLBACK_CMD, sizeof(ROLLBACK_CMD),
+ &rdb->rollbackStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_prepare(psqlDB, COMMIT_CMD, sizeof(COMMIT_CMD),
+ &rdb->commitStmt, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ sqlerr = sqlite3_exec(psqlDB, COMMIT_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ inTransaction = 0;
+ if (inInit) {
+ while (tableExists(psqlDB,"nssInit")) {
+ usleep(5);
+ }
+ }
+ return &rdb->db;
+
+cleanup:
+ /* lots of stuff to do */
+ if (inTransaction) {
+ sqlerr = sqlite3_exec(psqlDB, ROLLBACK_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ goto cleanup;
+ }
+ }
+ if (rdb) {
+ if (rdb->delStmt) {
+ sqlite3_finalize(rdb->delStmt);
+ }
+ if (rdb->getStmt) {
+ sqlite3_finalize(rdb->getStmt);
+ }
+ if (rdb->seqStmt) {
+ sqlite3_finalize(rdb->seqStmt);
+ }
+ if (rdb->insertStmt) {
+ sqlite3_finalize(rdb->insertStmt);
+ }
+ if (rdb->replaceStmt) {
+ sqlite3_finalize(rdb->replaceStmt);
+ }
+ if (rdb->beginStmt) {
+ sqlite3_finalize(rdb->beginStmt);
+ }
+ if (rdb->rollbackStmt) {
+ sqlite3_finalize(rdb->rollbackStmt);
+ }
+ if (rdb->commitStmt) {
+ sqlite3_finalize(rdb->commitStmt);
+ }
+ free(rdb);
+ }
+ if (psqlDB) {
+ sqlite3_close(psqlDB);
+ }
+ return NULL;
+
+};
diff --git a/security/nss/lib/rdb/rdb.def b/security/nss/lib/rdb/rdb.def
new file mode 100644
index 000000000..5496c7c2a
--- /dev/null
+++ b/security/nss/lib/rdb/rdb.def
@@ -0,0 +1,59 @@
+;+#
+;+# ***** BEGIN LICENSE BLOCK *****
+;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;+#
+;+# The contents of this file are subject to the Mozilla Public License Version
+;+# 1.1 (the "License"); you may not use this file except in compliance with
+;+# the License. You may obtain a copy of the License at
+;+# http://www.mozilla.org/MPL/
+;+#
+;+# Software distributed under the License is distributed on an "AS IS" basis,
+;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+;+# for the specific language governing rights and limitations under the
+;+# License.
+;+#
+;+# The Original Code is the Netscape security libraries.
+;+#
+;+# The Initial Developer of the Original Code is
+;+# Netscape Communications Corporation.
+;+# Portions created by the Initial Developer are Copyright (C) 2000
+;+# the Initial Developer. All Rights Reserved.
+;+#
+;+# Contributor(s):
+;+#
+;+# Alternatively, the contents of this file may be used under the terms of
+;+# either the GNU General Public License Version 2 or later (the "GPL"), or
+;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+;+# in which case the provisions of the GPL or the LGPL are applicable instead
+;+# of those above. If you wish to allow use of your version of this file only
+;+# under the terms of either the GPL or the LGPL, and not to allow others to
+;+# use your version of this file under the terms of the MPL, indicate your
+;+# decision by deleting the provisions above and replace them with the notice
+;+# and other provisions required by the GPL or the LGPL. If you do not delete
+;+# the provisions above, a recipient may use your version of this file under
+;+# the terms of any one of the MPL, the GPL or the LGPL.
+;+#
+;+# ***** END LICENSE BLOCK *****
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+
+;+RDB_1.0 { # RDB 1.0
+;+ global:
+LIBRARY rdb ;-
+EXPORTS ;-
+rdbopen;
+rdbstatus;
+;+ local:
+;+*;
+;+};
diff --git a/security/nss/lib/rdb/rdb.rc b/security/nss/lib/rdb/rdb.rc
new file mode 100644
index 000000000..5dc6ca62a
--- /dev/null
+++ b/security/nss/lib/rdb/rdb.rc
@@ -0,0 +1,101 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nss.h"
+#include <winver.h>
+
+#define MY_LIBNAME "rdb"
+#define MY_FILEDESCRIPTION "NSS Multiaccess Database Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if NSS_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#endif
+
+#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
+ PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", NSS_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 2005 Red Hat, Inc.\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Network Security Services\0"
+ VALUE "ProductVersion", NSS_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END