9 #include <netatalk/endian.h>
10 #include <atalk/adouble.h>
11 #include <atalk/cnid.h>
13 #include "cnid_private.h"
15 #define LOGFILEMAX 100 /* kbytes */
16 #define CHECKTIMEMAX 30 /* minutes */
18 /* this returns the cnid corresponding to a particular file. it will
19 also fix up the various databases if there's a problem. */
20 cnid_t cnid_lookup(void *CNID,
21 const struct stat *st, const cnid_t did,
22 const char *name, const int len)
26 DBT key, devdata, diddata;
28 int devino = 1, didname = 1;
31 if (!(db = CNID) || !st || !name)
34 /* do a little checkpointing if necessary. i stuck it here as
35 * cnid_lookup gets called when we do directory lookups. only do
36 * this if we're using a read-write database. */
37 if ((db->flags & CNIDFLAG_DB_RO) == 0) {
38 txnp = db->dbenv.tx_info;
39 errno = txn_checkpoint(txnp, LOGFILEMAX, CHECKTIMEMAX);
40 while (errno == DB_INCOMPLETE)
41 errno = txn_checkpoint(txnp, 0, 0);
44 if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
45 syslog(LOG_ERR, "cnid_lookup: path name too long");
49 memset(&key, 0, sizeof(key));
50 memset(&devdata, 0, sizeof(devdata));
52 /* look for a CNID. we have two options: dev/ino or did/name. if we
53 only get a match on one of them, that means a file has moved. */
54 key.data = buf; /* dev/ino is the first part of the buffer */
55 key.size = CNID_DEVINO_LEN;
56 while (errno = db->db_devino->get(db->db_devino, NULL,
61 if (errno == DB_NOTFOUND) {
66 syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u/%u)",
67 st->st_dev, st->st_ino);
71 /* did/name is right afterwards. */
72 key.data = buf + CNID_DEVINO_LEN;
73 key.size = CNID_DID_LEN + len + 1;
74 memset(&diddata, 0, sizeof(diddata));
75 while (errno = db->db_didname->get(db->db_didname, NULL,
80 if (errno == DB_NOTFOUND) {
85 syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u:%s)",
90 /* set id. honor did/name over dev/ino as dev/ino isn't necessarily
93 memcpy(&id, diddata.data, sizeof(id));
95 memcpy(&id, devdata.data, sizeof(id));
98 /* either entries in both databases exist or neither of them do. */
99 if ((devino && didname) || !(devino || didname))
102 /* fix up the databases */
103 cnid_update(db, id, st, did, name, len);