* kdb_db2.c: Don't include kdb_compat.h.
authorKen Raeburn <raeburn@mit.edu>
Fri, 30 Jun 2006 21:05:21 +0000 (21:05 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 30 Jun 2006 21:05:21 +0000 (21:05 +0000)
(OLD_COMPAT_VERSION_1): Don't define.
(krb5_db2_db_create): For temporary db, use different names for all files.
(krb5_db2_open, krb5_db2_create, krb5_db2_destroy): Fix check for "temporary"
in supplied db_args.
(krb5_db2_db_rename): New function, restored from pre-DAL code and hacked up
a lot to mostly work.
(krb5_db2_promote_db): New function.
* db2_exp.c: Add promote_db entry.

ticket: 3964
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18295 dc483132-0cff-0310-8789-dd5450dbe970

src/plugins/kdb/db2/db2_exp.c
src/plugins/kdb/db2/kdb_db2.c

index a84e55a192acde983409e2679589006df8c99a64..c922eafd06406db60841551a2f1fd7145d86cb99 100644 (file)
@@ -192,6 +192,9 @@ WRAP_K (krb5_db2_set_master_key_ext,
 WRAP_K (krb5_db2_db_get_mkey,
        ( krb5_context context, krb5_keyblock **key),
        (context, key));
+WRAP_K (krb5_db2_promote_db,
+       ( krb5_context kcontext, char *conf_section, char **db_args ),
+       (kcontext, conf_section, db_args));
 
 static krb5_error_code
 hack_init ()
@@ -246,5 +249,7 @@ kdb_vftabl kdb_function_table = {
   /* db_alloc */                               wrap_krb5_db2_alloc,
   /* db_free */                                wrap_krb5_db2_free,
   /* set_master_key */                        wrap_krb5_db2_set_master_key_ext,
-  /* get_master_key */                        wrap_krb5_db2_db_get_mkey
+  /* get_master_key */                        wrap_krb5_db2_db_get_mkey,
+  /* blah blah blah */ 0,0,0,0,0,0,
+  /* promote_db */                            wrap_krb5_db2_promote_db,
 };
index 60c6763668b13acce3a9d912cbfa72843d45215e..0316c7153f99ae609a5eb1946e93fe7c8ca91ea5 100644 (file)
 
 #define KDB_DB2_DATABASE_NAME "database_name"
 
-#define OLD_COMPAT_VERSION_1
-
-#ifdef OLD_COMPAT_VERSION_1
-#include "kdb_compat.h"
-#endif
-
 #include "kdb_db2.h"
 
 static char *gen_dbsuffix(char *, char *);
@@ -681,6 +675,7 @@ krb5_db2_db_create(krb5_context context, char *db_name, krb5_int32 flags)
     register krb5_error_code retval = 0;
     kdb5_dal_handle *dal_handle;
     char   *okname;
+    char   *db_name2 = NULL;
     int     fd;
     krb5_db2_context *db_ctx;
     DB     *db;
@@ -710,7 +705,11 @@ krb5_db2_db_create(krb5_context context, char *db_name, krb5_int32 flags)
     else
        (*db->close) (db);
     if (retval == 0) {
-       okname = gen_dbsuffix(db_name, KDB2_LOCK_EXT);
+
+       db_name2 = db_ctx->tempdb ? gen_dbsuffix(db_name, "~") : strdup(db_name);
+       if (db_name2 == NULL)
+           return ENOMEM;
+       okname = gen_dbsuffix(db_name2, KDB2_LOCK_EXT);
        if (!okname)
            retval = ENOMEM;
        else {
@@ -723,12 +722,12 @@ krb5_db2_db_create(krb5_context context, char *db_name, krb5_int32 flags)
        }
     }
 
-    sprintf(policy_db_name, "%s.kadm5", db_name);
+    sprintf(policy_db_name, "%s.kadm5", db_name2);
     sprintf(policy_lock_name, "%s.lock", policy_db_name);
 
     retval = osa_adb_create_db(policy_db_name,
                               policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
-
+    free(db_name2);
     return retval;
 }
 
@@ -1260,7 +1259,7 @@ krb5_db2_open(krb5_context kcontext,
            if (dbname) free(dbname);
            dbname = strdup(val);
        }
-       else if (opt && strcmp(opt, "temporary") ) {
+       else if (!opt && !strcmp(val, "temporary") ) {
            tempdb = 1;
        }
        /* ignore hash argument. Might have been passed from create */
@@ -1335,7 +1334,7 @@ krb5_db2_create(krb5_context kcontext, char *conf_section, char **db_args)
        if (opt && !strcmp(opt, "dbname")) {
            db_name = strdup(val);
        }
-       else if (opt && strcmp(opt, "temporary")) {
+       else if (!opt && !strcmp(val, "temporary")) {
            tempdb = 1;
        }
        else if (opt && !strcmp(opt, "hash")) {
@@ -1424,7 +1423,7 @@ krb5_db2_destroy(krb5_context kcontext, char *conf_section, char **db_args)
        if (opt && !strcmp(opt, "dbname")) {
            db_name = strdup(val);
        }
-       else if (opt && strcmp(opt, "temporary")) {
+       else if (!opt && !strcmp(val, "temporary")) {
            tempdb = 1;
        }
        /* ignore hash argument. Might have been passed from create */
@@ -1598,3 +1597,167 @@ krb5_db2_free_policy(krb5_context kcontext, osa_policy_ent_t entry)
 {
     osa_free_policy_ent(entry);
 }
+
+
+/* */
+
+krb5_error_code
+krb5_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args)
+{
+    krb5_error_code status = 0;
+    char *db_name = NULL;
+    char *temp_db_name = NULL;
+
+    krb5_clear_error_message (kcontext);
+
+    {
+       kdb5_dal_handle *dal_handle = kcontext->db_context;
+       krb5_db2_context *db_ctx = dal_handle->db_context;
+       db_name = strdup(db_ctx->db_name);
+    }
+
+    assert(kcontext->db_context != NULL);
+    temp_db_name = gen_dbsuffix(db_name, "~");
+    if (temp_db_name == NULL) {
+       status = ENOMEM;
+       goto clean_n_exit;
+    }
+
+    status = krb5_db2_db_rename (kcontext, temp_db_name, db_name);
+    if (status)
+       goto clean_n_exit;
+
+clean_n_exit:
+    if (db_name)
+       free(db_name);
+    if (temp_db_name)
+       free(temp_db_name);
+    return status;
+}
+
+/* Retrieved from pre-DAL code base.  */
+/*
+ * "Atomically" rename the database in a way that locks out read
+ * access in the middle of the rename.
+ *
+ * Not perfect; if we crash in the middle of an update, we don't
+ * necessarily know to complete the transaction the rename, but...
+ *
+ * Since the rename operation happens outside the init/fini bracket, we
+ * have to go through the same stuff that we went through up in db_destroy.
+ */
+krb5_error_code
+krb5_db2_db_rename(context, from, to)
+    krb5_context context;
+    char *from;
+    char *to;
+{
+    DB *db;
+    char *fromok;
+    krb5_error_code retval;
+    krb5_db2_context *s_context, *db_ctx;
+    kdb5_dal_handle *dal_handle = context->db_context;
+
+    s_context = dal_handle->db_context;
+    dal_handle->db_context = NULL;
+    if ((retval = k5db2_init_context(context)))
+       return retval;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    /*
+     * Create the database if it does not already exist; the
+     * files must exist because krb5_db2_db_lock, called below,
+     * will fail otherwise.
+     */
+    db = k5db2_dbopen(db_ctx, to, O_RDWR|O_CREAT, 0600, 0);
+    if (db == NULL) {
+       retval = errno;
+       goto errout;
+    }
+    else
+       (*db->close)(db);
+    /*
+     * Set the database to the target, so that other processes sharing
+     * the target will stop their activity, and notice the new database.
+     */
+    retval = krb5_db2_db_set_name(context, to, 0);
+    if (retval)
+       goto errout;
+
+    retval = krb5_db2_db_init(context);
+    if (retval)
+       goto errout;
+
+    {
+       /* Ugly brute force hack.
+
+          Should be going through nice friendly helper routines for
+          this, but it's a mess of jumbled so-called interfaces right
+          now.  */
+       char    policy[2048], new_policy[2048];
+       assert (strlen(db_ctx->db_name) < 2000);
+       sprintf(policy, "%s.kadm5", db_ctx->db_name);
+       sprintf(new_policy, "%s~.kadm5", db_ctx->db_name);
+       if (0 != rename(new_policy, policy)) {
+           retval = errno;
+           goto errout;
+       }
+       strcat(new_policy, ".lock");
+       (void) unlink(new_policy);
+    }
+
+    db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT);
+    if (db_ctx->db_lf_name == NULL) {
+       retval = ENOMEM;
+       goto errout;
+    }
+    db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600);
+    if (db_ctx->db_lf_file < 0) {
+       retval = errno;
+       goto errout;
+    }
+
+    db_ctx->db_inited = 1;
+
+    retval = krb5_db2_db_get_age(context, NULL, &db_ctx->db_lf_time);
+    if (retval)
+       goto errout;
+
+    fromok = gen_dbsuffix(from, KDB2_LOCK_EXT);
+    if (fromok == NULL) {
+       retval = ENOMEM;
+       goto errout;
+    }
+
+    if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
+       goto errfromok;
+
+    if ((retval = krb5_db2_db_start_update(context)))
+       goto errfromok;
+
+    if (rename(from, to)) {
+       retval = errno;
+       goto errfromok;
+    }
+    if (unlink(fromok)) {
+       retval = errno;
+       goto errfromok;
+    }
+    retval = krb5_db2_db_end_update(context);
+errfromok:
+    free_dbsuffix(fromok);
+errout:
+    if (dal_handle->db_context) {
+       if (db_ctx->db_lf_file >= 0) {
+           krb5_db2_db_unlock(context);
+           close(db_ctx->db_lf_file);
+       }
+       k5db2_clear_context((krb5_db2_context *) dal_handle->db_context);
+       free(dal_handle->db_context);
+    }
+
+    dal_handle->db_context = s_context;
+    (void) krb5_db2_db_unlock(context);        /* unlock saved context db */
+
+    return retval;
+}