2 * $Id: cnid_lookup.c,v 1.11 2002-01-04 04:45:48 sibaz Exp $
7 #endif /* HAVE_CONFIG_H */
12 #include <sys/param.h>
14 #include <atalk/logger.h>
18 #include <netatalk/endian.h>
19 #include <atalk/adouble.h>
20 #include <atalk/cnid.h>
22 #include "cnid_private.h"
24 #define LOGFILEMAX 100 /* kbytes */
25 #define CHECKTIMEMAX 30 /* minutes */
27 /* This returns the CNID corresponding to a particular file. It will
28 * also fix up the various databases if there's a problem. */
29 cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did,
30 const char *name, const int len)
34 DBT key, devdata, diddata;
35 int devino = 1, didname = 1;
39 if (!(db = CNID) || !st || !name) {
43 /* Do a little checkpointing if necessary. I stuck it here as cnid_lookup
44 * gets called when we do directory lookups. Only do this if we're using
45 * a read-write database. */
46 if ((db->flags & CNIDFLAG_DB_RO) == 0) {
48 LOG(log_info, logtype_default, "cnid_lookup: Running database checkpoint");
50 switch (rc = txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
55 LOG(log_error, logtype_default, "cnid_lookup: txn_checkpoint: %s",
61 if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
62 LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
66 memset(&key, 0, sizeof(key));
67 memset(&devdata, 0, sizeof(devdata));
68 memset(&diddata, 0, sizeof(diddata));
70 /* Look for a CNID. We have two options: dev/ino or did/name. If we
71 * only get a match in one of them, that means a file has moved. */
73 key.size = CNID_DEVINO_LEN;
74 while ((rc = db->db_devino->get(db->db_devino, NULL, &key, &devdata, 0))) {
75 if (rc == DB_LOCK_DEADLOCK) {
79 if (rc == DB_NOTFOUND) {
84 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s",
85 st->st_dev, st->st_ino, db_strerror(rc));
90 key.data = buf + CNID_DEVINO_LEN;
91 key.size = CNID_DID_LEN + len + 1;
92 while ((rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0))) {
93 if (rc == DB_LOCK_DEADLOCK) {
97 if (rc == DB_NOTFOUND) {
102 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID %u, name %s: %s",
103 ntohl(did), name, db_strerror(rc));
107 /* Set id. Honor did/name over dev/ino as dev/ino isn't necessarily
110 memcpy(&id, diddata.data, sizeof(id));
113 memcpy(&id, devdata.data, sizeof(id));
116 /* Either entries are in both databases or neither of them. */
117 if ((devino && didname) || !(devino || didname)) {
119 LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u",
120 ntohl(did), name, ntohl(id));
125 /* Fix up the database. */
126 cnid_update(db, id, st, did, name, len);
128 LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));