]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cnid_update.c
fix LFS test for cross compilation, from Bolke de Bruin
[netatalk.git] / libatalk / cnid / cnid_update.c
1 /*
2  * $Id: cnid_update.c,v 1.20 2002-08-30 03:12:52 jmarcus Exp $
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif /* HAVE_CONFIG_H */
8
9 #ifdef CNID_DB
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/param.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 #include <atalk/logger.h>
16
17 #include <db.h>
18 #include <netatalk/endian.h>
19 #include <atalk/adouble.h>
20 #include <atalk/cnid.h>
21
22 #include "cnid_private.h"
23
24 #ifdef CNID_DB_CDB
25     #define tid    NULL
26 #endif /* CNID_DB_CDB */
27
28 /* cnid_update: takes the given cnid and updates the metadata.  To
29  * handle the did/name data, there are a bunch of functions to get
30  * and set the various fields. */
31 int cnid_update(void *CNID, const cnid_t id, const struct stat *st,
32                 const cnid_t did, const char *name, const int len
33                 /*, const char *info, const int infolen*/)
34 {
35     CNID_private *db;
36     DBT key, data, altdata;
37 #ifndef CNID_DB_CDB
38     DB_TXN *tid;
39 #endif /* CNID_DB_CDB */
40     int rc;
41
42     if (!(db = CNID) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
43         return -1;
44     }
45
46     memset(&key, 0, sizeof(key));
47     memset(&altdata, 0, sizeof(altdata));
48
49 #ifndef CNID_DB_CDB
50 retry:
51     if ((rc = txn_begin(db->dbenv, NULL, &tid, 0))) {
52         LOG(log_error, logtype_default, "cnid_update: Failed to begin transaction: %s", db_strerror(rc));
53         return rc;
54     }
55 #endif /* CNID_DB_CDB */
56
57     /* Get the old info. */
58     key.data = (cnid_t *)&id;
59     key.size = sizeof(id);
60     memset(&data, 0, sizeof(data));
61 #ifdef CNID_DB_CDB
62     if ((rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0))) {
63 #else  /* CNID_DB_CDB */
64     if ((rc = db->db_cnid->get(db->db_cnid, tid, &key, &data, DB_RMW))) {
65         txn_abort(tid);
66 #endif /* CNID_DB_CDB */
67         switch (rc) {
68 #ifndef CNID_DB_CDB
69         case DB_LOCK_DEADLOCK:
70             goto retry;
71 #endif /* CNID_DB_CDB */
72         case DB_NOTFOUND:
73             /* Silently fail here.  We're allowed to do this since this CNID
74              * might have been deleted out from under us, or someone has
75              * called cnid_lookup then cnid_update (which is redundant). */
76             return 0;
77         default:
78             goto update_err;
79         }
80     }
81
82     /* Delete the old dev/ino mapping. */
83     key.data = data.data;
84     key.size = CNID_DEVINO_LEN;
85     if ((rc = db->db_devino->del(db->db_devino, tid, &key, 0))) {
86         switch (rc) {
87 #ifndef CNID_DB_CDB
88         case DB_LOCK_DEADLOCK:
89             txn_abort(tid);
90             goto retry;
91 #endif /* CNID_DB_CDB */
92         case DB_NOTFOUND:
93             break;
94         default:
95 #ifndef CNID_DB_CDB
96             txn_abort(tid);
97 #endif /* CNID_DB_CDB */
98             goto update_err;
99         }
100     }
101
102     /* Delete the old did/name mapping. */
103     key.data = (char *) data.data + CNID_DEVINO_LEN;
104     key.size = data.size - CNID_DEVINO_LEN;
105     if ((rc = db->db_didname->del(db->db_didname, tid, &key, 0))) {
106         switch (rc) {
107 #ifndef CNID_DB_CDB
108         case DB_LOCK_DEADLOCK:
109             txn_abort(tid);
110             goto retry;
111 #endif /* CNID_DB_CDB */
112         case DB_NOTFOUND:
113             break;
114         default:
115 #ifndef CNID_DB_CDB
116             txn_abort(tid);
117 #endif /* CNID_DB_CDB */
118             goto update_err;
119         }
120     }
121
122     /* Make a new entry. */
123     data.data = make_cnid_data(st, did, name, len);
124     data.size = CNID_HEADER_LEN + len + 1;
125
126     /* Update the old CNID with the new info. */
127     key.data = (cnid_t *) &id;
128     key.size = sizeof(id);
129     if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
130 #ifndef CNID_DB_CDB
131         txn_abort(tid);
132 #endif /* CNID_DB_CDB */
133         switch (rc) {
134 #ifndef CNID_DB_CDB
135         case DB_LOCK_DEADLOCK:
136             goto retry;
137 #endif /* CNID_DB_CDB */
138         default:
139             goto update_err;
140         }
141     }
142
143     /* Put in a new dev/ino mapping. */
144     key.data = data.data;
145     key.size = CNID_DEVINO_LEN;
146     altdata.data = (cnid_t *) &id;
147     altdata.size = sizeof(id);
148     if ((rc = db->db_devino->put(db->db_devino, tid, &key, &altdata, 0))) {
149 #ifndef CNID_DB_CDB
150         txn_abort(tid);
151 #endif /* CNID_DB_CDB */
152         switch (rc) {
153 #ifndef CNID_DB_CDB
154         case DB_LOCK_DEADLOCK:
155             goto retry;
156 #endif /* CNID_DB_CDB */
157         default:
158             goto update_err;
159         }
160     }
161
162     /* put in a new did/name mapping. */
163     key.data = (char *) data.data + CNID_DEVINO_LEN;
164     key.size = data.size - CNID_DEVINO_LEN;
165     if ((rc = db->db_didname->put(db->db_didname, tid, &key, &altdata, 0))) {
166 #ifndef CNID_DB_CDB
167         txn_abort(tid);
168 #endif /* CNID_DB_CDB */
169         switch (rc) {
170 #ifndef CNID_DB_CDB
171         case DB_LOCK_DEADLOCK:
172             goto retry;
173 #endif /* CNID_DB_CDB */
174         default:
175             goto update_err;
176         }
177     }
178
179
180 #ifdef CNID_DB_CDB
181     return 0;
182 #else  /* CNID_DB_CDB */
183     return txn_commit(tid, 0);
184 #endif /* CNID_DB_CDB */
185
186 update_err:
187     LOG(log_error, logtype_default, "cnid_update: Unable to update CNID %u: %s",
188         ntohl(id), db_strerror(rc));
189     return -1;
190 }
191 #endif /* CNID_DB */