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