]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/dbd_lookup.c
Some fixes to logging statements
[netatalk.git] / etc / cnid_dbd / dbd_lookup.c
1 /*
2  * $Id: dbd_lookup.c,v 1.8 2009-05-28 10:22:07 franklahm Exp $
3  *
4  * Copyright (C) Joerg Lenneis 2003
5  * All Rights Reserved.  See COPYING.
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(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
31 {
32     unsigned char *buf;
33     DBT key, devdata, diddata;
34     char dev[CNID_DEV_LEN];
35     int devino = 1, didname = 1; 
36     int rc;
37     cnid_t id_devino, id_didname;
38     u_int32_t type_devino  = (unsigned)-1;
39     u_int32_t type_didname = (unsigned)-1;
40     int update = 0;
41     
42     
43     memset(&key, 0, sizeof(key));
44     memset(&diddata, 0, sizeof(diddata));
45     memset(&devdata, 0, sizeof(devdata));
46
47     rply->namelen = 0;
48     rply->cnid = 0;
49     
50     buf = pack_cnid_data(rqst); 
51     memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
52
53     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
54        only get a match in one of them, that means a file has moved. */
55     key.data = buf + CNID_DEVINO_OFS;
56     key.size = CNID_DEVINO_LEN;
57
58     if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
59         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
60                 ntohl(rqst->did), rqst->name);
61         rply->result = CNID_DBD_RES_ERR_DB;
62         return -1;
63     }
64     if (rc == 0) {
65         devino = 0;
66     }
67     else {
68         memcpy(&id_devino, devdata.data, sizeof(rply->cnid));
69         memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
70         type_devino = ntohl(type_devino);
71     }
72
73     key.data = buf + CNID_DID_OFS;
74     key.size = CNID_DID_LEN + rqst->namelen + 1;
75
76     if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0))  < 0) {
77         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
78                 ntohl(rqst->did), rqst->name);
79         rply->result = CNID_DBD_RES_ERR_DB;
80         return -1;
81     }
82     if (rc == 0) {
83         didname = 0;
84     }
85     else {
86         memcpy(&id_didname, diddata.data, sizeof(rply->cnid));
87         memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
88         type_didname = ntohl(type_didname);
89     }
90     
91     if (!devino && !didname) {  
92         /* not found */
93
94         LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino 0x%llx/0x%llx did %u name %s neither in devino nor didname", 
95             (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name);
96
97         rply->result = CNID_DBD_RES_NOTFOUND;
98         return 1;
99     }
100
101     if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
102         /* the same */
103
104         LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u", 
105             (unsigned long long )rqst->dev, (unsigned long long )rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname));
106
107         rply->cnid = id_didname;
108         rply->result = CNID_DBD_RES_OK;
109         return 1;
110     }
111     
112     if (didname) {
113         LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: changed dev/ino for '%s'", rqst->name);
114         rqst->cnid = id_didname;
115         /* we have a did:name 
116          * if it's the same dev or not the same type
117          * just delete it
118         */
119         if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
120                    type_didname != rqst->type) {
121             if (dbd_delete(dbd, rqst, rply) < 0) {
122                 return -1;
123             }
124         }
125         else {
126             update = 1;
127         }
128     }
129
130     if (devino) {
131         LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: server side rename oder reused inode for '%s'", rqst->name);
132         rqst->cnid = id_devino;
133         if (type_devino != rqst->type) {
134             /* same dev:inode but not same type one is a folder the other 
135              * is a file,it's an inode reused, delete the record
136             */
137             if (dbd_delete(dbd, rqst, rply) < 0) {
138                 return -1;
139             }
140         }
141         else {
142             update = 1;
143         }
144     }
145     if (!update) {
146         rply->result = CNID_DBD_RES_NOTFOUND;
147         return 1;
148     }
149     /* Fix up the database. assume it was a file move and rename */
150     rc = dbd_update(dbd, rqst, rply);
151     if (rc >0) {
152         rply->cnid = rqst->cnid;
153     }
154
155     LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u (needed update)", 
156         (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
157
158     return rc;
159 }