2 * $Id: cmd_dbd_lookup.c,v 1.3 2009-10-14 01:38:28 didg Exp $
4 * Copyright (C) Frank Lahm 2009
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>
28 whatever you change here, also change cmd_dbd_lookup.c !
29 cmd_dbd_lookup has an read-only mode, but besides that it's the same.
34 * This returns the CNID corresponding to a particular file and logs any inconsitencies.
35 * If roflags == 1 we only scan, if roflag == 0, we modify i.e. call dbd_update
36 * FIXME: realign this wih dbd_lookup.
39 int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
42 DBT key, devdata, diddata;
44 int devino = 1, didname = 1;
46 cnid_t id_devino, id_didname;
47 u_int32_t type_devino = (unsigned)-1;
48 u_int32_t type_didname = (unsigned)-1;
51 memset(&key, 0, sizeof(key));
52 memset(&diddata, 0, sizeof(diddata));
53 memset(&devdata, 0, sizeof(devdata));
58 buf = pack_cnid_data(rqst);
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 dbd_log( LOGSTD, "dbd_search: 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 dbd_log( LOGSTD, "dbd_search: 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) {
100 dbd_log( LOGDEBUG, "name: '%s/%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database",
101 cwdbuf, rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
102 rply->result = CNID_DBD_RES_NOTFOUND;
106 if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
108 rply->cnid = id_didname;
109 rply->result = CNID_DBD_RES_OK;
114 Order matters for the next 2 ifs because both found a CNID but they didn't match.
115 So in order to pick the CNID from "didname" it must come after devino.
116 See test cases laid out in dbd_lookup.c.
119 dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name);
120 rqst->cnid = id_devino;
121 if (type_devino != rqst->type) {
122 /* same dev/inode but not same type: it's an inode reused, delete the record */
124 if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
132 dbd_log( LOGSTD, "CNID resolve problem: changed dev/ino for '%s/%s'", cwdbuf, rqst->name);
133 rqst->cnid = id_didname;
134 /* we have a did/name.
135 If it's the same dev or not the same type, e.g. a remove followed by a new file
136 with the same name */
137 if (!memcmp(&dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
138 type_didname != rqst->type) {
140 if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
148 if (!update || roflag) {
149 rply->result = CNID_DBD_RES_NOTFOUND;
152 /* Fix up the database. assume it was a file move and rename */
153 rc = dbd_update(dbd, rqst, rply);
155 rply->cnid = rqst->cnid;
158 dbd_log( LOGSTD, "CNID database needed update: dev/ino: 0x%llx/0x%llx, did: %u, name: '%s/%s' --> CNID: %u",
159 (unsigned long long)rqst->dev, (unsigned long long)rqst->ino,
160 ntohl(rqst->did), cwdbuf, rqst->name, ntohl(rply->cnid));
166 This is taken from dbd_add.c, but this func really is only "add", dbd_add calls dbd_lookup
168 FIXME: realign with dbd_add using e.g. using a new arg like "int lookup".
170 int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
172 if (get_cnid(dbd, rply) < 0) {
173 if (rply->result == CNID_DBD_RES_ERR_MAX) {
174 dbd_log( LOGSTD, "FATAL: CNID database has reached its limit.");
175 /* This will cause an abort/rollback if transactions are used */
178 dbd_log( LOGSTD, "Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
183 if (add_cnid(dbd, rqst, rply) < 0) {
184 if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
185 dbd_log( LOGSTD, "Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
186 /* abort/rollback, see above */
189 dbd_log( LOGSTD, "Failed to add CNID for %s to database", rqst->name);
193 dbd_log( LOGDEBUG, "Add to CNID database: did: %u, cnid: %u, name: '%s', dev/ino: 0x%llx/0x%llx",
194 ntohl(rqst->did), ntohl(rply->cnid), rqst->name,
195 (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
197 rply->result = CNID_DBD_RES_OK;