]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/dbd_lookup.c
Change the dbd CNID backend to store dev/ino in 8 byte network order.
[netatalk.git] / etc / cnid_dbd / dbd_lookup.c
1 /*
2  * $Id: dbd_lookup.c,v 1.1.4.4 2003-11-25 00:41:31 lenneis Exp $
3  *
4  * Copyright (C) Joerg Lenneis 2003
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/param.h>
16 #include <errno.h>
17 #include <netatalk/endian.h>
18 #include <atalk/logger.h>
19 #include <atalk/cnid_dbd_private.h>
20
21 #include "pack.h"
22 #include "dbif.h"
23 #include "dbd.h"
24
25 /*
26  *  This returns the CNID corresponding to a particular file.  It will also fix
27  *  up the database if there's a problem.
28  */
29
30 int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
31 {
32     char *buf;
33     DBT key, devdata, diddata;
34     char dev[CNID_DEV_LEN];
35     char ino[CNID_INO_LEN];
36     int devino = 1, didname = 1; 
37     int rc;
38     cnid_t id_devino, id_didname;
39     u_int32_t type_devino  = (unsigned)-1;
40     u_int32_t type_didname = (unsigned)-1;
41     int update = 0;
42     
43     
44     memset(&key, 0, sizeof(key));
45     memset(&diddata, 0, sizeof(diddata));
46     memset(&devdata, 0, sizeof(devdata));
47
48     rply->namelen = 0;
49     rply->cnid = 0;
50     
51     buf = pack_cnid_data(rqst); 
52     memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
53     /* FIXME: ino is not needed later on, remove? */
54     memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
55
56     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
57        only get a match in one of them, that means a file has moved. */
58     key.data = buf +CNID_DEVINO_OFS;
59     key.size = CNID_DEVINO_LEN;
60
61     if ((rc = dbif_get(DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
62         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
63                 ntohl(rqst->did), rqst->name);
64         rply->result = CNID_DBD_RES_ERR_DB;
65         return -1;
66     }
67     if (rc == 0) {
68         devino = 0;
69     }
70     else {
71         memcpy(&id_devino, devdata.data, sizeof(rply->cnid));
72         memcpy(&type_devino, devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
73         type_devino = ntohl(type_devino);
74     }
75     
76     /* FIXME: This second call to pack_cnid_data() is redundant, any reason it is here? */
77     buf = pack_cnid_data(rqst); 
78     key.data = buf +CNID_DID_OFS;
79     key.size = CNID_DID_LEN + rqst->namelen + 1;
80
81     if ((rc = dbif_get(DBIF_IDX_DIDNAME, &key, &diddata, 0))  < 0) {
82         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
83                 ntohl(rqst->did), rqst->name);
84         rply->result = CNID_DBD_RES_ERR_DB;
85         return -1;
86     }
87     if (rc == 0) {
88         didname = 0;
89     }
90     else {
91         memcpy(&id_didname, diddata.data, sizeof(rply->cnid));
92         memcpy(&type_didname, diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
93         type_didname = ntohl(type_didname);
94     }
95     
96     if (!devino && !didname) {  
97         /* not found */
98         rply->result = CNID_DBD_RES_NOTFOUND;
99         return 1;
100     }
101
102     if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
103         /* the same */
104         rply->cnid = id_didname;
105         rply->result = CNID_DBD_RES_OK;
106         return 1;
107     }
108     
109     if (didname) {
110         rqst->cnid = id_didname;
111         /* we have a did:name 
112          * if it's the same dev or not the same type
113          * just delete it
114         */
115         if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
116                    type_didname != rqst->type) {
117             if (dbd_delete(rqst, rply) < 0) {
118                 return -1;
119             }
120         }
121         else {
122             update = 1;
123         }
124     }
125
126     if (devino) {
127         rqst->cnid = id_devino;
128         if (type_devino != rqst->type) {
129             /* same dev:inode but not same type one is a folder the other 
130              * is a file,it's an inode reused, delete the record
131             */
132             if (dbd_delete(rqst, rply) < 0) {
133                 return -1;
134             }
135         }
136         else {
137             update = 1;
138         }
139     }
140     if (!update) {
141         rply->result = CNID_DBD_RES_NOTFOUND;
142         return 1;
143     }
144     /* Fix up the database. assume it was a file move and rename */
145     rc = dbd_update(rqst, rply);
146     if (rc >0) {
147         rply->cnid = rqst->cnid;
148     }
149 #ifdef DEBUG
150     LOG(log_info, logtype_cnid, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", 
151     ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
152 #endif
153     return rc;
154 }