2
* $Id: cnid_lookup.c,v 1.14.2.1 2003/02/08 03:16:53 jmarcus 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) {
44
/* Do a little checkpointing if necessary. I stuck it here as cnid_lookup
45
* gets called when we do directory lookups. Only do this if we're using
46
* a read-write database. */
47
if ((db->flags & CNIDFLAG_DB_RO) == 0) {
49
LOG(log_info, logtype_default, "cnid_lookup: Running database checkpoint");
51
#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
52
db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)
54
#if DB_VERSION_MAJOR >= 4
55
switch (rc = db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
57
switch (rc = txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
58
#endif /* DB_VERSION_MAJOR >= 4 */
63
LOG(log_error, logtype_default, "cnid_lookup: txn_checkpoint: %s",
68
#endif /* DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) */
69
#endif /* CNID_DB_CDB */
71
if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
72
LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
76
memset(&key, 0, sizeof(key));
77
memset(&devdata, 0, sizeof(devdata));
78
memset(&diddata, 0, sizeof(diddata));
80
/* Look for a CNID. We have two options: dev/ino or did/name. If we
81
* only get a match in one of them, that means a file has moved. */
83
key.size = CNID_DEVINO_LEN;
84
while ((rc = db->db_devino->get(db->db_devino, NULL, &key, &devdata, 0))) {
86
if (rc == DB_LOCK_DEADLOCK) {
89
#endif /* CNID_DB_CDB */
91
if (rc == DB_NOTFOUND) {
96
LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s",
97
st->st_dev, st->st_ino, db_strerror(rc));
102
key.data = buf + CNID_DEVINO_LEN;
103
key.size = CNID_DID_LEN + len + 1;
104
while ((rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0))) {
106
if (rc == DB_LOCK_DEADLOCK) {
109
#endif /* CNID_DB_CDB */
111
if (rc == DB_NOTFOUND) {
116
LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID %u, name %s: %s",
117
ntohl(did), name, db_strerror(rc));
121
/* Set id. Honor did/name over dev/ino as dev/ino isn't necessarily
124
memcpy(&id, diddata.data, sizeof(id));
127
memcpy(&id, devdata.data, sizeof(id));
130
/* Either entries are in both databases or neither of them. */
131
if ((devino && didname) || !(devino || didname)) {
133
LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u",
134
ntohl(did), name, ntohl(id));
139
/* Fix up the database. */
140
cnid_update(db, id, st, did, name, len);
142
LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));