]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cnid_update.c
massive commenting/autoconf changes
[netatalk.git] / libatalk / cnid / cnid_update.c
1 /*
2  * $Id: cnid_update.c,v 1.2 2001-06-29 14:14:46 rufustfirefly Exp $
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif /* HAVE_CONFIG_H */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/param.h>
12 #include <sys/stat.h>
13 #include <errno.h>
14 #include <syslog.h>
15
16 #include <db.h>
17 #include <netatalk/endian.h>
18 #include <atalk/adouble.h>
19 #include <atalk/cnid.h>
20
21 #include "cnid_private.h"
22
23
24 /* cnid_update: takes the given cnid and updates the metadata. to
25    handle the did/name data, there are a bunch of functions to get
26    and set the various fields. */
27 int cnid_update(void *CNID, cnid_t id, const struct stat *st, 
28                 const cnid_t did, const char *name, const int len,
29                 const char *info, const int infolen)
30 {
31   CNID_private *db;
32   DBT key, data, altdata;
33   DB_TXN *tid;
34   DB_TXNMGR *txnp;
35   
36   if (!(db = CNID) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO))
37     return -1;
38
39   memset(&key, 0, sizeof(key));
40   memset(&data, 0, sizeof(data));
41   memset(&altdata, 0, sizeof(altdata));
42   txnp = db->dbenv.tx_info;
43
44   /* begin a transaction */
45 retry:
46   if (errno = txn_begin(txnp, NULL, &tid)) {
47     return errno;
48   }
49
50   /* get the old info */
51   key.data = &id;
52   key.size = sizeof(id);
53   if (errno = db->db_cnid->get(db->db_cnid, tid, &key, &data, 0)) {
54     txn_abort(tid);
55     if (errno == EAGAIN)
56       goto retry;
57     goto update_err;
58   }
59
60   /* delete the old dev/ino mapping */
61   key.data = data.data;
62   key.size = CNID_DEVINO_LEN;
63   if (errno = db->db_devino->del(db->db_devino, tid, &key, 0)) {
64     if (errno == EAGAIN) {
65       txn_abort(tid);
66       goto retry;
67     }
68       
69     /* silently fail on a non-existent entry */
70     if (errno != DB_NOTFOUND) {
71       txn_abort(tid);
72       goto update_err;
73     }
74   }
75
76   /* delete the old did/name mapping */
77   key.data = data.data + CNID_DEVINO_LEN;
78   key.size = data.size - CNID_DEVINO_LEN;
79   if (errno = db->db_didname->del(db->db_didname, tid, &key, 0)) {
80     if (errno == EAGAIN) {
81       txn_abort(tid);
82       goto retry;
83     }
84
85     /* silently fail on a non-existent entry */
86     if (errno != DB_NOTFOUND) {
87       txn_abort(tid);
88       goto update_err;
89     }
90   }
91   
92   /* delete the old aliases if necessary */
93
94
95   /* make a new entry */
96   data.data = make_cnid_data(st, did, name, len);
97   data.size = CNID_HEADER_LEN + len + 1;
98   
99   /* put a new dev/ino mapping in */
100   key.data = data.data;
101   key.size = CNID_DEVINO_LEN;
102   altdata.data = &id;
103   altdata.size = sizeof(id);
104   if (errno = db->db_devino->put(db->db_devino, tid, &key, &altdata, 0)) {
105     txn_abort(tid);
106     if (errno == EAGAIN) {
107       goto retry;
108     }
109     goto update_err;
110   }
111   
112   /* put a new did/name mapping in */
113   key.data = data.data + CNID_DEVINO_LEN;
114   key.size = data.size - CNID_DEVINO_LEN;
115   if (errno = db->db_didname->put(db->db_didname, tid, &key, &altdata, 0)) {
116     txn_abort(tid);
117     if (errno == EAGAIN) {
118       goto retry;
119     }
120     goto update_err;
121   }
122   
123   /* update the old CNID with the new info */
124   key.data = &id;
125   key.size = sizeof(id);
126   if (errno = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0)) {
127     txn_abort(tid);
128     if (errno == EAGAIN) {
129       goto retry;
130     }
131     goto update_err;
132   }
133   
134   /* end transaction */
135   return txn_commit(tid);
136
137 update_err:
138   syslog(LOG_ERR, "cnid_update: can't update CNID(%x)", id);
139   return -1;
140 }