1/* 2 * $Id: cnid_cdb_rebuild_add.c,v 1.6 2009-11-20 17:22:11 didg Exp $ 3 * 4 * All Rights Reserved. See COPYRIGHT. 5 * 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#ifdef CNID_BACKEND_CDB 13#include "cnid_cdb_private.h" 14 15#define tid NULL 16#define DEBUG 1 17 18#include "cnid_cdb.h" 19 20/* ----------------------------- */ 21static cnid_t set_max_cnid(CNID_private *db, cnid_t hint) 22{ 23 DBT rootinfo_key, rootinfo_data; 24 int rc; 25 char buf[ROOTINFO_DATALEN]; 26 cnid_t id, id1; 27 time_t t; 28 29 memset(&rootinfo_key, 0, sizeof(rootinfo_key)); 30 memset(&rootinfo_data, 0, sizeof(rootinfo_data)); 31 32 rootinfo_key.data = ROOTINFO_KEY; 33 rootinfo_key.size = ROOTINFO_KEYLEN; 34 35 switch ((rc = db->db_cnid->get(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) { 36 case 0: 37 memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN); 38 break; 39 case DB_NOTFOUND: 40 /* FIXME: This duplicates stuff from cnid_cdb_add.c. 41 We also implicitely assume that sizeof(time_t) <= CNID_DEV_LEN */ 42 memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); 43 t = time(NULL); 44 memset(buf + CNID_DEV_OFS, 0, CNID_DEV_LEN); 45 memcpy(buf + CNID_DEV_OFS, &t, sizeof(time_t)); 46 id = htonl(CNID_START); 47 memcpy(buf + CNID_TYPE_OFS, &id, sizeof(id)); 48 break; 49 default: 50 LOG(log_error, logtype_default, "set_max_cnid: Unable to read rootinfo: %s", db_strerror(rc)); 51 errno = CNID_ERR_DB; 52 goto cleanup; 53 } 54 55 memcpy(&id, buf + CNID_TYPE_OFS, sizeof(id)); 56 id = ntohl(id); 57 id1 = ntohl(hint); 58 59 if (id1 > id) { 60 memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint)); 61 rootinfo_data.data = buf; 62 rootinfo_data.size = ROOTINFO_DATALEN; 63 if ((rc = db->db_cnid->put(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) { 64 LOG(log_error, logtype_default, "set_max_cnid: Unable to write rootinfo: %s", db_strerror(rc)); 65 errno = CNID_ERR_DB; 66 goto cleanup; 67 } 68 } 69 70 return hint; 71 72cleanup: 73 return CNID_INVALID; 74} 75 76/* ------------------------ */ 77cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st, 78 const cnid_t did, char *name, const size_t len, 79 cnid_t hint) 80{ 81 CNID_private *db; 82 DBT key, data; 83 int rc; 84 85 if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) { 86 errno = CNID_ERR_PARAM; 87 return CNID_INVALID; 88 } 89 90#if 0 91 /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */ 92 /* Do a lookup. */ 93 id = cnid_cdb_lookup(cdb, st, did, name, len); 94 /* ... Return id if it is valid, or if Rootinfo is read-only. */ 95 if (id || (db->flags & CNIDFLAG_DB_RO)) { 96#ifdef DEBUG 97 LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id)); 98#endif 99 return id; 100 } 101#endif 102 103 /* Initialize our DBT data structures. */ 104 memset(&key, 0, sizeof(key)); 105 memset(&data, 0, sizeof(data)); 106 107 if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) { 108 LOG(log_error, logtype_default, "cnid_add: Path name is too long"); 109 errno = CNID_ERR_PATH; 110 return CNID_INVALID; 111 } 112 data.size = CNID_HEADER_LEN + len + 1; 113 114 memcpy(data.data, &hint, sizeof(hint)); 115 116 key.data = &hint; 117 key.size = sizeof(hint); 118 119 /* Now we need to add the CNID data to the databases. */ 120 if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) { 121 LOG(log_error, logtype_default 122 , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 123 name, ntohl(hint), db_strerror(rc)); 124 errno = CNID_ERR_DB; 125 goto cleanup; 126 } 127 128 if (set_max_cnid(db, hint) == CNID_INVALID) { 129 errno = CNID_ERR_DB; 130 goto cleanup; 131 } 132 133#ifdef DEBUG 134 LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); 135#endif 136 137 return hint; 138 139cleanup: 140 return CNID_INVALID; 141} 142 143#endif /* CNID_BACKEND_CDB */ 144