]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_lookup.c
more tdb fixes
[netatalk.git] / libatalk / cnid / tdb / cnid_tdb_lookup.c
1 /*
2  * $Id: cnid_tdb_lookup.c,v 1.5 2009-11-20 19:25:05 didg Exp $
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8
9 #ifdef CNID_BACKEND_TDB
10
11 #include "cnid_tdb.h"
12 #include <atalk/logger.h>
13
14 cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, char *name, const size_t len)
15 {
16     char *buf;
17     struct _cnid_tdb_private *db;
18     TDB_DATA key, devdata, diddata;
19     int devino = 1, didname = 1;
20     cnid_t id = 0;
21
22     if (!cdb || !(db = cdb->_private) || !st || !name) {
23         return 0;
24     }
25
26     if ((buf = make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
27         LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
28         return 0;
29     }
30
31     memset(&key, 0, sizeof(key));
32     memset(&devdata, 0, sizeof(devdata));
33     memset(&diddata, 0, sizeof(diddata));
34
35     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
36     * only get a match in one of them, that means a file has moved. */
37     key.dptr = buf +CNID_DEVINO_OFS;
38     key.dsize  = CNID_DEVINO_LEN;
39     devdata = tdb_fetch(db->tdb_devino, key);
40     if (!devdata.dptr) {
41          devino = 0;
42     }
43     /* did/name now */
44     key.dptr = buf + CNID_DID_OFS;
45     key.dsize = CNID_DID_LEN + len + 1;
46     diddata = tdb_fetch(db->tdb_didname, key);
47     if (!diddata.dptr) {
48         didname = 0;
49     }
50     /* Set id.  Honor did/name over dev/ino as dev/ino isn't necessarily
51      * 1-1. */
52     if (didname) {
53         memcpy(&id, diddata.dptr, sizeof(id));
54     }
55     else if (devino) {
56         memcpy(&id, devdata.dptr, sizeof(id));
57     }
58     free(devdata.dptr);
59     free(diddata.dptr);
60     /* Either entries are in both databases or neither of them. */
61     if ((devino && didname) || !(devino || didname)) {
62         return id;
63     }
64
65     /* Fix up the database. */
66     cnid_tdb_update(cdb, id, st, did, name, len);
67     return id;
68 }
69
70 #endif