krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom, char *fileto, char *lockto, int magic) { osa_adb_db_t fromdb, todb; krb5_error_code ret; /* make sure todb exists */ if ((ret = osa_adb_create_db(fileto, lockto, magic)) && ret != EEXIST) return ret; if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic))) return ret; if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) { (void) osa_adb_fini_db(fromdb, magic); return ret; } if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) { (void) osa_adb_fini_db(fromdb, magic); (void) osa_adb_fini_db(todb, magic); return ret; } if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) { (void) osa_adb_fini_db(fromdb, magic); (void) osa_adb_fini_db(todb, magic); return ret; } if ((rename(filefrom, fileto) < 0)) { (void) osa_adb_fini_db(fromdb, magic); (void) osa_adb_fini_db(todb, magic); return errno; } /* * Do not release the lock on fromdb because it is being renamed * out of existence; no one can ever use it again. */ if ((ret = osa_adb_release_lock(todb))) { (void) osa_adb_fini_db(fromdb, magic); (void) osa_adb_fini_db(todb, magic); return ret; } (void) osa_adb_fini_db(fromdb, magic); (void) osa_adb_fini_db(todb, magic); return 0; }
/* Create the database, assuming it's not there. */ static krb5_error_code create_db(krb5_context context, char *db_name) { krb5_error_code retval = 0; char *okname; char *db_name2 = NULL; int fd; krb5_db2_context *db_ctx; DB *db; char policy_db_name[1024], policy_lock_name[1024]; retval = k5db2_init_context(context); if (retval != 0) return retval; db_ctx = context->dal_handle->db_context; db = k5db2_dbopen(db_ctx, db_name, O_RDWR | O_CREAT | O_EXCL, 0600, db_ctx->tempdb); if (db == NULL) return errno; (*db->close)(db); 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 { fd = open(okname, O_CREAT | O_RDWR | O_TRUNC, 0600); if (fd < 0) retval = errno; else close(fd); free_dbsuffix(okname); } snprintf(policy_db_name, sizeof(policy_db_name), "%s.kadm5", db_name2); snprintf(policy_lock_name, sizeof(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; }
/* Initialize dbc by locking and creating the DB. If the DB already exists, * clear it out if dbc->tempdb is set; otherwise return EEXIST. */ static krb5_error_code ctx_create_db(krb5_context context, krb5_db2_context *dbc) { krb5_error_code retval = 0; char *dbname = NULL, *polname = NULL, *plockname = NULL; retval = ctx_allfiles(dbc, &dbname, &dbc->db_lf_name, &polname, &plockname); if (retval) return retval; dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC, 0600); if (dbc->db_lf_file < 0) { retval = errno; goto cleanup; } retval = krb5_lock_file(context, dbc->db_lf_file, KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK); if (retval != 0) goto cleanup; set_cloexec_fd(dbc->db_lf_file); dbc->db_lock_mode = KRB5_LOCKMODE_EXCLUSIVE; dbc->db_locks_held = 1; if (dbc->tempdb) { /* Temporary DBs are locked for their whole lifetime. Since we have * the lock, any remnant files can be safely destroyed. */ (void) destroy_file(dbname); (void) unlink(polname); (void) unlink(plockname); } dbc->db = open_db(dbc, O_RDWR | O_CREAT | O_EXCL, 0600); if (dbc->db == NULL) { retval = errno; goto cleanup; } /* Create the policy database, initialize a handle to it, and lock it. */ retval = osa_adb_create_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC); if (retval) goto cleanup; retval = osa_adb_init_db(&dbc->policy_db, polname, plockname, OSA_ADB_POLICY_DB_MAGIC); if (retval) goto cleanup; retval = osa_adb_get_lock(dbc->policy_db, KRB5_DB_LOCKMODE_EXCLUSIVE); if (retval) goto cleanup; dbc->db_inited = 1; cleanup: if (retval) { if (dbc->db != NULL) dbc->db->close(dbc->db); if (dbc->db_locks_held > 0) { (void) krb5_lock_file(context, dbc->db_lf_file, KRB5_LOCKMODE_UNLOCK); } if (dbc->db_lf_file >= 0) close(dbc->db_lf_file); ctx_clear(dbc); } free(dbname); free(polname); free(plockname); return retval; }