]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_lookup.c
fixes for tdb remaining errors vs cdb
[netatalk.git] / libatalk / cnid / tdb / cnid_tdb_lookup.c
1 /*
2  * $Id: cnid_tdb_lookup.c,v 1.6 2009-11-21 11:12:49 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, cniddata;
19     int devino = 1, didname = 1;
20     char dev[CNID_DEV_LEN];
21     char ino[CNID_INO_LEN];  
22     u_int32_t type_devino  = (unsigned)-1;
23     u_int32_t type_didname = (unsigned)-1;
24     u_int32_t type;
25     int update = 0;
26     cnid_t id_devino = 0, id_didname = 0,id = 0;
27
28     if (!cdb || !(db = cdb->_private) || !st || !name) {
29         return 0;
30     }
31
32     if ((buf = make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
33         LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
34         return 0;
35     }
36     memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
37     type = ntohl(type);
38
39     memset(&key, 0, sizeof(key));
40     memset(&devdata, 0, sizeof(devdata));
41     memset(&diddata, 0, sizeof(diddata));
42     memset(&cniddata, 0, sizeof(cniddata));
43
44     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
45     * only get a match in one of them, that means a file has moved. */
46     memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
47     memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
48
49     key.dptr = buf +CNID_DEVINO_OFS;
50     key.dsize  = CNID_DEVINO_LEN;
51     cniddata = tdb_fetch(db->tdb_devino, key);
52     if (!cniddata.dptr) {
53          devino = 0;
54     }
55     else {
56         
57         key.dptr = cniddata.dptr;
58         key.dsize = sizeof(id);
59
60         devdata = tdb_fetch(db->tdb_cnid, key);
61         free(cniddata.dptr);
62         if (devdata.dptr) {
63             memcpy(&id_devino, devdata.dptr, sizeof(cnid_t));
64             memcpy(&type_devino, (char *)devdata.dptr +CNID_TYPE_OFS, sizeof(type_devino));
65             type_devino = ntohl(type_devino);
66         }
67         else {
68              devino = 0;
69         }
70     }
71
72     /* did/name now */
73     key.dptr = buf + CNID_DID_OFS;
74     key.dsize = CNID_DID_LEN + len + 1;
75     cniddata = tdb_fetch(db->tdb_didname, key);
76     if (!cniddata.dptr) {
77         didname = 0;
78     }
79     else {
80         
81         key.dptr = cniddata.dptr;
82         key.dsize = sizeof(id);
83
84         diddata = tdb_fetch(db->tdb_cnid, key);
85         free(cniddata.dptr);
86         if (diddata.dptr) {
87             memcpy(&id_didname, diddata.dptr, sizeof(cnid_t));
88             memcpy(&type_didname, (char *)diddata.dptr +CNID_TYPE_OFS, sizeof(type_didname));
89             type_didname = ntohl(type_didname);
90         }
91         else {
92              didname = 0;
93         }
94     }
95     /* Set id.  Honor did/name over dev/ino as dev/ino isn't necessarily
96      * 1-1. */
97     if (!devino && !didname) {  
98         free(devdata.dptr);
99         free(diddata.dptr);
100         return 0;
101     }
102
103     if (devino && didname && id_devino == id_didname && type_devino == type) {
104         /* the same */
105         free(devdata.dptr);
106         free(diddata.dptr);
107         return id_didname;
108     }
109  
110     if (didname) {
111         id = id_didname;
112         /* we have a did:name 
113          * if it's the same dev or not the same type
114          * just delete it
115         */
116         if (!memcmp(dev, (char *)diddata.dptr + CNID_DEV_OFS, CNID_DEV_LEN) ||
117                    type_didname != type) {
118             if (cnid_tdb_delete(cdb, id) < 0) {
119                 free(devdata.dptr);
120                 free(diddata.dptr);
121                 return 0;
122             }
123         }
124         else {
125             update = 1;
126         }
127     }
128
129     if (devino) {
130         id = id_devino;
131         if (type_devino != type) {
132             /* same dev:inode but not same type one is a folder the other 
133              * is a file,it's an inode reused, delete the record
134             */
135             if (cnid_tdb_delete(cdb, id) < 0) {
136                 free(devdata.dptr);
137                 free(diddata.dptr);
138                 return 0;
139             }
140         }
141         else {
142             update = 1;
143         }
144     }
145     free(devdata.dptr);
146     free(diddata.dptr);
147     if (!update) {
148         return 0;
149     }
150
151     /* Fix up the database. */
152     cnid_tdb_update(cdb, id, st, did, name, len);
153     return id;
154 }
155
156 #endif