]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cdb/cnid_cdb_lookup.c
0eebb9f96bca47a70c9eabd6fd66fbf05ea462d8
[netatalk.git] / libatalk / cnid / cdb / cnid_cdb_lookup.c
1 /*
2  * $Id: cnid_cdb_lookup.c,v 1.3 2005-05-03 14:55:13 didg Exp $
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif /* HAVE_CONFIG_H */
8
9 #ifdef CNID_BACKEND_CDB
10 #include "cnid_cdb_private.h"
11
12 #define LOGFILEMAX    100  /* kbytes */
13 #define CHECKTIMEMAX   30  /* minutes */
14
15 /* This returns the CNID corresponding to a particular file.  It will
16  * also fix up the various databases if there's a problem. */
17 cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
18                    char *name, const size_t len)
19 {
20     unsigned char *buf;
21     CNID_private *db;
22     DBT key, devdata, diddata;
23     char dev[CNID_DEV_LEN];
24     char ino[CNID_INO_LEN];  
25     int devino = 1, didname = 1; 
26     u_int32_t type_devino  = (unsigned)-1;
27     u_int32_t type_didname = (unsigned)-1;
28     u_int32_t type;
29     int update = 0;
30     cnid_t id_devino, id_didname,id = 0;
31     int rc;
32
33     if (!cdb || !(db = cdb->_private) || !st || !name) {
34         return 0;
35     }
36     
37     if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
38         LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
39         return 0;
40     }
41
42     memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
43     type = ntohl(type);
44
45     memset(&key, 0, sizeof(key));
46     memset(&diddata, 0, sizeof(diddata));
47     memset(&devdata, 0, sizeof(devdata));
48
49     /* Look for a CNID for our did/name */
50     key.data = buf +CNID_DEVINO_OFS;
51     key.size = CNID_DEVINO_LEN;
52
53     memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
54     memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
55     
56     if (0 != (rc = db->db_didname->get(db->db_devino, NULL, &key, &devdata, 0 )) ) {
57         if (rc != DB_NOTFOUND) {
58             LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
59                did, name, db_strerror(rc));
60             return 0;
61         }
62         devino = 0;
63     }
64     else {
65         memcpy(&id_devino, devdata.data, sizeof(cnid_t));
66         memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
67         type_devino = ntohl(type_devino);
68     }
69
70     buf = make_cnid_data(st, did, name, len);
71     key.data = buf +CNID_DID_OFS;
72     key.size = CNID_DID_LEN + len + 1;
73     
74     if (0 != (rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0 ) ) ) {
75         if (rc != DB_NOTFOUND) {
76             LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
77                did, name, db_strerror(rc));
78             return 0;
79         }
80         didname = 0;
81     }
82     else {
83         memcpy(&id_didname, diddata.data, sizeof(cnid_t));
84         memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
85         type_didname = ntohl(type_didname);
86     }
87
88     if (!devino && !didname) {  
89         return 0;
90     }
91
92     if (devino && didname && id_devino == id_didname && type_devino == type) {
93         /* the same */
94         return id_didname;
95     }
96  
97     if (didname) {
98         id = id_didname;
99         /* we have a did:name 
100          * if it's the same dev or not the same type
101          * just delete it
102         */
103         if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
104                    type_didname != type) {
105             if (cnid_cdb_delete(cdb, id) < 0) {
106                 return 0;
107             }
108         }
109         else {
110             update = 1;
111         }
112     }
113
114     if (devino) {
115         id = id_devino;
116         if (type_devino != type) {
117             /* same dev:inode but not same type one is a folder the other 
118              * is a file,it's an inode reused, delete the record
119             */
120             if (cnid_cdb_delete(cdb, id) < 0) {
121                 return 0;
122             }
123         }
124         else {
125             update = 1;
126         }
127     }
128     if (!update) {
129         return 0;
130     }
131     /* Fix up the database. assume it was a file move and rename */
132     cnid_cdb_update(cdb, id, st, did, name, len);
133
134 #ifdef DEBUG
135     LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));
136 #endif
137     return id;
138 }
139
140 #endif /* CNID_BACKEND_CDB */