1/* 2 * $Id: cnid_cdb_lookup.c,v 1.6 2009-11-20 17:22:11 didg Exp $ 3 */ 4 5#ifdef HAVE_CONFIG_H 6#include "config.h" 7#endif /* HAVE_CONFIG_H */ 8 9#ifdef CNID_BACKEND_CDB 10#include "cnid_cdb_private.h" 11 12#define LOGFILEMAX 100 /* kbytes */ 13#define CHECKTIMEMAX 30 /* minutes */ 14 15/* This returns the CNID corresponding to a particular file. It will 16 * also fix up the various databases if there's a problem. */ 17cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, 18 char *name, const size_t len) 19{ 20 unsigned char *buf; 21 CNID_private *db; 22 DBT key, devdata, diddata; 23 char dev[CNID_DEV_LEN]; 24 char ino[CNID_INO_LEN]; 25 int devino = 1, didname = 1; 26 u_int32_t type_devino = (unsigned)-1; 27 u_int32_t type_didname = (unsigned)-1; 28 u_int32_t type; 29 int update = 0; 30 cnid_t id_devino, id_didname,id = 0; 31 int rc; 32 33 if (!cdb || !(db = cdb->_private) || !st || !name) { 34 return 0; 35 } 36 37 if ((buf = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) { 38 LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long"); 39 return 0; 40 } 41 42 memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type)); 43 type = ntohl(type); 44 45 memset(&key, 0, sizeof(key)); 46 memset(&diddata, 0, sizeof(diddata)); 47 memset(&devdata, 0, sizeof(devdata)); 48 49 /* Look for a CNID for our did/name */ 50 key.data = buf +CNID_DEVINO_OFS; 51 key.size = CNID_DEVINO_LEN; 52 53 memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN); 54 memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN); 55 56 if (0 != (rc = db->db_didname->get(db->db_devino, NULL, &key, &devdata, 0 )) ) { 57 if (rc != DB_NOTFOUND) { 58 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s", 59 did, name, db_strerror(rc)); 60 return 0; 61 } 62 devino = 0; 63 } 64 else { 65 memcpy(&id_devino, devdata.data, sizeof(cnid_t)); 66 memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino)); 67 type_devino = ntohl(type_devino); 68 } 69 70 buf = make_cnid_data(cdb->flags, st, did, name, len); 71 key.data = buf +CNID_DID_OFS; 72 key.size = CNID_DID_LEN + len + 1; 73 74 if (0 != (rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0 ) ) ) { 75 if (rc != DB_NOTFOUND) { 76 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s", 77 did, name, db_strerror(rc)); 78 return 0; 79 } 80 didname = 0; 81 } 82 else { 83 memcpy(&id_didname, diddata.data, sizeof(cnid_t)); 84 memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname)); 85 type_didname = ntohl(type_didname); 86 } 87 88 if (!devino && !didname) { 89 return 0; 90 } 91 92 if (devino && didname && id_devino == id_didname && type_devino == type) { 93 /* the same */ 94 return id_didname; 95 } 96 97 if (didname) { 98 id = id_didname; 99 /* we have a did:name 100 * if it's the same dev or not the same type 101 * just delete it 102 */ 103 if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) || 104 type_didname != type) { 105 if (cnid_cdb_delete(cdb, id) < 0) { 106 return 0; 107 } 108 } 109 else { 110 update = 1; 111 } 112 } 113 114 if (devino) { 115 id = id_devino; 116 if (type_devino != type) { 117 /* same dev:inode but not same type one is a folder the other 118 * is a file,it's an inode reused, delete the record 119 */ 120 if (cnid_cdb_delete(cdb, id) < 0) { 121 return 0; 122 } 123 } 124 else { 125 update = 1; 126 } 127 } 128 if (!update) { 129 return 0; 130 } 131 /* Fix up the database. assume it was a file move and rename */ 132 cnid_cdb_update(cdb, id, st, did, name, len); 133 134#ifdef DEBUG 135 LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id)); 136#endif 137 return id; 138} 139 140#endif /* CNID_BACKEND_CDB */ 141