summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/back-ldbm/dbverify.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/dbverify.c')
-rw-r--r--ldap/servers/slapd/back-ldbm/dbverify.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/ldap/servers/slapd/back-ldbm/dbverify.c b/ldap/servers/slapd/back-ldbm/dbverify.c
new file mode 100644
index 00000000..bd3ec2e0
--- /dev/null
+++ b/ldap/servers/slapd/back-ldbm/dbverify.c
@@ -0,0 +1,231 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* dbverify.c - verify database files */
+
+#include "back-ldbm.h"
+#include "dblayer.h"
+
+static int
+dbverify_ext( ldbm_instance *inst, int verbose )
+{
+ char dbdir[MAXPATHLEN];
+ char *filep = NULL;
+ PRDir *dirhandle = NULL;
+ PRDirEntry *direntry = NULL;
+ backend *be = inst->inst_be;
+ DB *dbp = NULL;
+ int tmplen = 0;
+ int filelen = 0;
+ int rval = 1;
+ int rval_main = 0;
+ struct ldbminfo *li = inst->inst_li;
+ dblayer_private *priv = (dblayer_private*)li->li_dblayer_private;
+ struct dblayer_private_env *pEnv = priv->dblayer_env;
+
+ dbdir[sizeof(dbdir)-1] = '\0';
+ PR_snprintf(dbdir, sizeof(dbdir), "%s/%s", inst->inst_parent_dir_name,
+ inst->inst_dir_name);
+ if ('\0' != dbdir[sizeof(dbdir)-1]) /* overflown */
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "db path too long: %s/%s\n",
+ inst->inst_parent_dir_name, inst->inst_dir_name, 0);
+ return 1;
+ }
+ tmplen = strlen(dbdir);
+ filep = dbdir + tmplen;
+ filelen = sizeof(dbdir) - tmplen;
+
+ /* run dbverify on each each db file */
+ dirhandle = PR_OpenDir(dbdir);
+ if (! dirhandle)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "PR_OpenDir (%s) failed (%d): %s\n",
+ dbdir, PR_GetError(),slapd_pr_strerror(PR_GetError()));
+ return 1;
+ }
+ while (NULL !=
+ (direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT)))
+ {
+ /* struct attrinfo *ai = NULL; */
+ char *p = NULL;
+ dbp = NULL;
+
+ if (!direntry->name)
+ {
+ break;
+ }
+ if (!strstr(direntry->name, LDBM_FILENAME_SUFFIX)) /* non db file */
+ {
+ continue;
+ }
+ if (sizeof(direntry->name) + 2 > filelen)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "db path too long: %s/%s%s\n",
+ dbdir, direntry->name, 0);
+ continue;
+ }
+ PR_snprintf(filep, filelen, "/%s", direntry->name);
+ rval = db_create(&dbp, pEnv->dblayer_DB_ENV, 0);
+ if (0 != rval)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "Unable to create id2entry db file %d\n", rval);
+ return rval;
+ }
+#define VLVPREFIX "vlv#"
+ if ((0 != strncmp(direntry->name, ID2ENTRY, strlen(ID2ENTRY))) &&
+ (0 != strncmp(direntry->name, VLVPREFIX, strlen(VLVPREFIX))))
+ {
+ rval = dbp->set_flags(dbp, DB_DUP | DB_DUPSORT);
+ if (0 != rval)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "Unable to set DUP flags to db %d\n", rval);
+ return rval;
+ }
+
+ rval = dbp->set_dup_compare(dbp, idl_new_compare_dups);
+ if (0 != rval)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "Unable to set dup_compare to db %d\n", rval);
+ return rval;
+ }
+ }
+#undef VLVPREFIX
+ rval = dbp->verify(dbp, dbdir, NULL, NULL, 0);
+ if (0 == rval)
+ {
+ if (verbose)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "%s: ok\n", dbdir);
+ }
+ }
+ else
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "DB verify",
+ "verify failed(%d): %s\n", rval, dbdir);
+ }
+ rval_main |= rval;
+ *filep = '\0';
+ }
+ PR_CloseDir(dirhandle);
+
+ return rval_main;
+}
+
+int
+ldbm_back_dbverify( Slapi_PBlock *pb )
+{
+ struct ldbminfo *li = NULL;
+ Object *inst_obj = NULL;
+ ldbm_instance *inst = NULL;
+ int verbose = 0;
+ int rval = 1;
+ int rval_main = 0;
+ char **instance_names = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, "verify DB", "Verifying db files...\n");
+ slapi_pblock_get(pb, SLAPI_BACKEND_INSTANCE_NAME, &instance_names);
+ slapi_pblock_get(pb, SLAPI_SEQ_VAL, &verbose);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li);
+ ldbm_config_load_dse_info(li);
+ ldbm_config_internal_set(li, CONFIG_DB_TRANSACTION_LOGGING, "off");
+ /* no write needed; choose EXPORT MODE */
+ if (0 != dblayer_start(li, DBLAYER_EXPORT_MODE))
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "verify DB",
+ "dbverify: Failed to init database\n");
+ return rval;
+ }
+
+ /* server is up */
+ slapi_log_error(SLAPI_LOG_TRACE, "verify DB", "server is up\n");
+ if (instance_names) /* instance is specified */
+ {
+ char **inp = NULL;
+ for (inp = instance_names; inp && *inp; inp++)
+ {
+ inst = ldbm_instance_find_by_name(li, *inp);
+ if (inst)
+ {
+ rval_main |= dbverify_ext(inst, verbose);
+ }
+ else
+ {
+ rval_main |= 1; /* no such instance */
+ }
+ }
+ }
+ else /* all instances */
+ {
+ for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj))
+ {
+ inst = (ldbm_instance *)object_get_data(inst_obj);
+ /* check if an import/restore is already ongoing... */
+ if (instance_set_busy(inst) != 0)
+ {
+ /* standalone, only. never happens */
+ slapi_log_error(SLAPI_LOG_FATAL, "upgrade DB",
+ "ldbm: '%s' is already in the middle of "
+ "another task and cannot be disturbed.\n",
+ inst->inst_name);
+ continue; /* skip this instance and go to the next*/
+ }
+ rval_main |= dbverify_ext(inst, verbose);
+ }
+ }
+
+ /* close the database down again */
+ rval = dblayer_post_close(li, DBLAYER_EXPORT_MODE);
+ if (0 != rval)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL,
+ "verify DB", "Failed to close database\n");
+ }
+
+ return rval_main;
+}