From 71ec4b597b051519868286079eb4a27bbb1e0315 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Mon, 22 Nov 2010 17:14:44 +0100 Subject: [PATCH] Version check for CNID db version --- etc/cnid_dbd/dbd_add.c | 31 +++++++++++------ etc/cnid_dbd/dbif.c | 30 ++++++++++------ libatalk/cnid/cdb/cnid_cdb_open.c | 58 +++++++++---------------------- 3 files changed, 58 insertions(+), 61 deletions(-) diff --git a/etc/cnid_dbd/dbd_add.c b/etc/cnid_dbd/dbd_add.c index 41de278d..ce7bcf1b 100644 --- a/etc/cnid_dbd/dbd_add.c +++ b/etc/cnid_dbd/dbd_add.c @@ -83,22 +83,32 @@ int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply) { static cnid_t id; + static char buf[ROOTINFO_DATALEN]; DBT rootinfo_key, rootinfo_data; int rc; cnid_t hint; - - if (id == 0) { - memset(&rootinfo_key, 0, sizeof(rootinfo_key)); - memset(&rootinfo_data, 0, sizeof(rootinfo_data)); - rootinfo_key.data = ROOTINFO_KEY; - rootinfo_key.size = ROOTINFO_KEYLEN; - if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) <= 0) { + memset(&rootinfo_key, 0, sizeof(rootinfo_key)); + memset(&rootinfo_data, 0, sizeof(rootinfo_data)); + rootinfo_key.data = ROOTINFO_KEY; + rootinfo_key.size = ROOTINFO_KEYLEN; + + if (id == 0) { + if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) < 0) { rply->result = CNID_DBD_RES_ERR_DB; return -1; } - memcpy(&hint, (char *)rootinfo_data.data +CNID_TYPE_OFS, sizeof(hint)); - id = ntohl(hint); + if (rc == 0) { + /* no rootinfo key yet */ + memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); + id = CNID_START - 1; + } else { + memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN); + memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint)); + id = ntohl(hint); + if (id < CNID_START - 1) + id = CNID_START - 1; + } } /* If we've hit the max CNID allowed, we return an error. CNID @@ -108,9 +118,10 @@ int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply) return -1; } + rootinfo_data.data = buf; rootinfo_data.size = ROOTINFO_DATALEN; hint = htonl(id); - memcpy((char *)rootinfo_data.data + CNID_TYPE_OFS, &hint, sizeof(hint)); + memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint)); if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) { rply->result = CNID_DBD_RES_ERR_DB; diff --git a/etc/cnid_dbd/dbif.c b/etc/cnid_dbd/dbif.c index 6a11d359..22d9a2cf 100644 --- a/etc/cnid_dbd/dbif.c +++ b/etc/cnid_dbd/dbif.c @@ -530,13 +530,16 @@ int dbif_open(DBD *dbd, struct db_param *dbp, int reindex) if (reindex) LOG(log_info, logtype_cnid, "Reindexing name index..."); + int version = dbif_getversion(dbd); + if (version == -1) + return -1; if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, dbd->db_txn, dbd->db_table[DBIF_IDX_NAME].db, idxname, (reindex || - ((CNID_VERSION == CNID_VERSION_1) && (dbif_getversion(dbd) == CNID_VERSION_0))) + ((CNID_VERSION == CNID_VERSION_1) && (version == CNID_VERSION_0))) ? DB_CREATE : 0)) != 0) { LOG(log_error, logtype_cnid, "Failed to associate name index: %s", db_strerror(ret)); return -1; @@ -779,7 +782,7 @@ int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags) } /*! - * Return CNID database version number + * Initialize or return CNID database version number * @returns -1 on error, version number otherwise */ int dbif_getversion(DBD *dbd) @@ -794,15 +797,19 @@ int dbif_getversion(DBD *dbd) key.size = ROOTINFO_KEYLEN; switch (dbif_get(dbd, DBIF_CNID, &key, &data, 0)) { - case 1: + case 1: /* found */ memcpy(&version, (char *)data.data + CNID_DID_OFS, sizeof(version)); version = ntohl(version); LOG(log_debug, logtype_cnid, "CNID database version %u", version); ret = version; break; - default: - ret = -1; + case 0: /* not found */ + if (dbif_setversion(dbd, CNID_VERSION) != 0) + return -1; + ret = CNID_VERSION; break; + default: + return -1; } return ret; } @@ -813,8 +820,12 @@ int dbif_getversion(DBD *dbd) */ int dbif_setversion(DBD *dbd, int version) { + int ret; DBT key, data; uint32_t v; + char buf[ROOTINFO_DATALEN]; + + LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version); v = version; v = htonl(v); @@ -824,13 +835,12 @@ int dbif_setversion(DBD *dbd, int version) key.data = ROOTINFO_KEY; key.size = ROOTINFO_KEYLEN; - switch (dbif_get(dbd, DBIF_CNID, &key, &data, 0)) { - case 1: - break; - default: + if ((ret = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) == -1) return -1; + if (ret == 0) { + memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); + data.data = buf; } - memcpy((char *)data.data + CNID_DID_OFS, &v, sizeof(v)); data.size = ROOTINFO_DATALEN; if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) diff --git a/libatalk/cnid/cdb/cnid_cdb_open.c b/libatalk/cnid/cdb/cnid_cdb_open.c index bf501fd5..10ecc78d 100644 --- a/libatalk/cnid/cdb/cnid_cdb_open.c +++ b/libatalk/cnid/cdb/cnid_cdb_open.c @@ -1,7 +1,4 @@ /* - - * $Id: cnid_cdb_open.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $ - * * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. * @@ -40,6 +37,8 @@ #endif /* HAVE_CONFIG_H */ #ifdef CNID_BACKEND_CDB + +#include #include "cnid_cdb_private.h" #ifndef MIN @@ -55,14 +54,6 @@ #define DBHOMELEN 8 #define DBLEN 10 -/* we version the did/name database so that we can change the format - * if necessary. the key is in the form of a did/name pair. in this case, - * we use 0/0. */ -#define DBVERSION_KEY "\0\0\0\0\0" -#define DBVERSION_KEYLEN 5 -#define DBVERSION1 0x00000001U -#define DBVERSION DBVERSION1 - #define DBOPTIONS (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL) #define MAXITER 0xFFFF /* maximum number of simultaneously open CNID @@ -355,42 +346,27 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) goto fail_appinit; } -#if 0 - DBT key, pkey, data; /* ---------------------- */ - /* Check for version. This way we can update the database if we need - * to change the format in any way. */ - memset(&key, 0, sizeof(key)); - memset(&pkey, 0, sizeof(DBT)); - memset(&data, 0, sizeof(data)); - key.data = DBVERSION_KEY; - key.size = DBVERSION_KEYLEN; + /* Check for version. "cdb" only supports CNID_VERSION_0, cf cnid_private.h */ - if ((rc = db->db_didname->pget(db->db_didname, NULL, &key, &pkey, &data, 0)) != 0) { - int ret; - { - u_int32_t version = htonl(DBVERSION); + DBT key, data; + uint32_t version; - data.data = &version; - data.size = sizeof(version); - } - if ((ret = db->db_didname->put(db->db_cnid, NULL, &key, &data, - DB_NOOVERWRITE))) { - LOG(log_error, logtype_default, "cnid_open: Error putting new version: %s", - db_strerror(ret)); - db->db_didname->close(db->db_didname, 0); + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0)) == 0) { + /* If not found, ignore it */ + memcpy(&version, data.data + CNID_DID_OFS, sizeof(version)); + version = ntohl(version); + LOG(log_debug, logtype_default, "CNID db version %u", version); + if (version != CNID_VERSION_0) { + LOG(log_error, logtype_default, "Unsupported CNID db version %u, use CNID backend \"dbd\"", version); goto fail_appinit; } } -#endif - - /* TODO In the future we might check for version number here. */ -#if 0 - memcpy(&version, data.data, sizeof(version)); - if (version != ntohl(DBVERSION)) { - /* Do stuff here. */ - } -#endif /* 0 */ db_env_set_func_yield(my_yield); return cdb; -- 2.39.2