2 * $Id: dbd_lookup.c,v 1.6 2009-05-06 11:54:24 franklahm Exp $
4 * Copyright (C) Joerg Lenneis 2003
5 * All Rights Reserved. See COPYING.
10 #endif /* HAVE_CONFIG_H */
15 #include <sys/param.h>
17 #include <netatalk/endian.h>
18 #include <atalk/logger.h>
19 #include <atalk/cnid_dbd_private.h>
26 * This returns the CNID corresponding to a particular file. It will also fix
27 * up the database if there's a problem.
30 int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
33 DBT key, devdata, diddata;
34 char dev[CNID_DEV_LEN];
36 char ino[CNID_INO_LEN];
38 int devino = 1, didname = 1;
40 cnid_t id_devino, id_didname;
41 u_int32_t type_devino = (unsigned)-1;
42 u_int32_t type_didname = (unsigned)-1;
46 memset(&key, 0, sizeof(key));
47 memset(&diddata, 0, sizeof(diddata));
48 memset(&devdata, 0, sizeof(devdata));
53 buf = pack_cnid_data(rqst);
54 memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
56 /* FIXME: ino is not needed later on, remove? */
57 memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
60 /* Look for a CNID. We have two options: dev/ino or did/name. If we
61 only get a match in one of them, that means a file has moved. */
62 key.data = buf + CNID_DEVINO_OFS;
63 key.size = CNID_DEVINO_LEN;
65 if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0)) < 0) {
66 LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
67 ntohl(rqst->did), rqst->name);
68 rply->result = CNID_DBD_RES_ERR_DB;
75 memcpy(&id_devino, devdata.data, sizeof(rply->cnid));
76 memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
77 type_devino = ntohl(type_devino);
80 key.data = buf + CNID_DID_OFS;
81 key.size = CNID_DID_LEN + rqst->namelen + 1;
83 if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0)) < 0) {
84 LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
85 ntohl(rqst->did), rqst->name);
86 rply->result = CNID_DBD_RES_ERR_DB;
93 memcpy(&id_didname, diddata.data, sizeof(rply->cnid));
94 memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
95 type_didname = ntohl(type_didname);
98 if (!devino && !didname) {
101 LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino 0x%llx/0x%llx did %u name %s neither in devino nor didname",
102 ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name);
104 rply->result = CNID_DBD_RES_NOTFOUND;
108 if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
111 LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u",
112 ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name, ntohl(id_didname));
114 rply->cnid = id_didname;
115 rply->result = CNID_DBD_RES_OK;
120 rqst->cnid = id_didname;
121 /* we have a did:name
122 * if it's the same dev or not the same type
125 if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
126 type_didname != rqst->type) {
127 if (dbd_delete(dbd, rqst, rply) < 0) {
137 rqst->cnid = id_devino;
138 if (type_devino != rqst->type) {
139 /* same dev:inode but not same type one is a folder the other
140 * is a file,it's an inode reused, delete the record
142 if (dbd_delete(dbd, rqst, rply) < 0) {
151 rply->result = CNID_DBD_RES_NOTFOUND;
154 /* Fix up the database. assume it was a file move and rename */
155 rc = dbd_update(dbd, rqst, rply);
157 rply->cnid = rqst->cnid;
160 LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u (needed update)",
161 ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name, ntohl(rply->cnid));