2 * $Id: cnid_lookup.c,v 1.7 2001-09-21 15:08:37 jmarcus Exp $
7 #endif /* HAVE_CONFIG_H */
12 #include <sys/param.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,
30 const struct stat *st, const cnid_t did,
31 const char *name, const int len)
35 DBT key, devdata, diddata;
36 int devino = 1, didname = 1;
42 if (!(db = CNID) || !st || !name)
45 /* do a little checkpointing if necessary. i stuck it here as
46 * cnid_lookup gets called when we do directory lookups. only do
47 * this if we're using a read-write database. */
48 if ((db->flags & CNIDFLAG_DB_RO) == 0) {
49 rc = txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0);
50 while (rc == DB_INCOMPLETE)
51 rc = txn_checkpoint(db->dbenv, 0, 0, 0);
53 syslog(LOG_ERR, "cnid_lookup: txn_checkpoint failed with: %d", rc);
58 if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
59 syslog(LOG_ERR, "cnid_lookup: path name too long");
63 memset(&key, 0, sizeof(key));
64 memset(&devdata, 0, sizeof(devdata));
66 /* look for a CNID. we have two options: dev/ino or did/name. if we
67 only get a match on one of them, that means a file has moved. */
68 key.data = buf; /* dev/ino is the first part of the buffer */
69 key.size = CNID_DEVINO_LEN;
70 while ((rc = db->db_devino->get(db->db_devino, NULL,
71 &key, &devdata, 0))) {
72 if (rc == DB_LOCK_DEADLOCK)
75 if (rc == DB_NOTFOUND) {
80 syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u/%u) (%d)",
81 st->st_dev, st->st_ino, rc);
85 /* did/name is right afterwards. */
86 key.data = buf + CNID_DEVINO_LEN;
87 key.size = CNID_DID_LEN + len + 1;
88 memset(&diddata, 0, sizeof(diddata));
89 while ((rc = db->db_didname->get(db->db_didname, NULL,
90 &key, &diddata, 0))) {
91 if (rc == DB_LOCK_DEADLOCK)
94 if (rc == DB_NOTFOUND) {
99 syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u:%s) (%d)",
104 /* set id. honor did/name over dev/ino as dev/ino isn't necessarily
107 memcpy(&id, diddata.data, sizeof(id));
109 memcpy(&id, devdata.data, sizeof(id));
112 /* either entries in both databases exist or neither of them do. */
113 if ((devino && didname) || !(devino || didname)) {
115 syslog(LOG_ERR, "cnid_lookup: looked up did %d, name %s as %d", did, name, id);
118 /* fix up the databases */
119 cnid_update(db, id, st, did, name, len);
121 syslog(LOG_ERR, "cnid_lookup: looked up did %d, name %s as %d (needed update)", did, name, id);