]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cnid_update.c
6652b597a034ea3d5c4b258a9b2e7e72e03bb3c8
[netatalk.git] / libatalk / cnid / cnid_update.c
1 /*
2  * $Id: cnid_update.c,v 1.4 2001-08-15 02:16:25 srittau 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, const 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   
35   if (!(db = CNID) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO))
36     return -1;
37
38   memset(&key, 0, sizeof(key));
39   memset(&data, 0, sizeof(data));
40   memset(&altdata, 0, sizeof(altdata));
41
42   /* begin a transaction */
43 retry:
44   if ((errno = txn_begin(db->dbenv, NULL, &tid, 0))) {
45     return errno;
46   }
47
48   /* get the old info */
49   key.data = (cnid_t *) &id;
50   key.size = sizeof(id);
51   if ((errno = db->db_cnid->get(db->db_cnid, tid, &key, &data, 0))) {
52     txn_abort(tid);
53     if (errno == EAGAIN)
54       goto retry;
55     goto update_err;
56   }
57
58   /* delete the old dev/ino mapping */
59   key.data = data.data;
60   key.size = CNID_DEVINO_LEN;
61   if ((errno = db->db_devino->del(db->db_devino, tid, &key, 0))) {
62     if (errno == EAGAIN) {
63       txn_abort(tid);
64       goto retry;
65     }
66
67     /* silently fail on a non-existent entry */
68     if (errno != DB_NOTFOUND) {
69       txn_abort(tid);
70       goto update_err;
71     }
72   }
73
74   /* delete the old did/name mapping */
75   key.data = (char *) data.data + CNID_DEVINO_LEN;
76   key.size = data.size - CNID_DEVINO_LEN;
77   if ((errno = db->db_didname->del(db->db_didname, tid, &key, 0))) {
78     if (errno == EAGAIN) {
79       txn_abort(tid);
80       goto retry;
81     }
82
83     /* silently fail on a non-existent entry */
84     if (errno != DB_NOTFOUND) {
85       txn_abort(tid);
86       goto update_err;
87     }
88   }
89
90   /* delete the old aliases if necessary */
91
92
93   /* make a new entry */
94   data.data = make_cnid_data(st, did, name, len);
95   data.size = CNID_HEADER_LEN + len + 1;
96
97   /* put a new dev/ino mapping in */
98   key.data = data.data;
99   key.size = CNID_DEVINO_LEN;
100   altdata.data = (cnid_t *) &id;
101   altdata.size = sizeof(id);
102   if ((errno = db->db_devino->put(db->db_devino, tid, &key, &altdata, 0))) {
103     txn_abort(tid);
104     if (errno == EAGAIN) {
105       goto retry;
106     }
107     goto update_err;
108   }
109
110   /* put a new did/name mapping in */
111   key.data = (char *) data.data + CNID_DEVINO_LEN;
112   key.size = data.size - CNID_DEVINO_LEN;
113   if ((errno = db->db_didname->put(db->db_didname, tid, &key, &altdata, 0))) {
114     txn_abort(tid);
115     if (errno == EAGAIN) {
116       goto retry;
117     }
118     goto update_err;
119   }
120
121   /* update the old CNID with the new info */
122   key.data = (cnid_t *) &id;
123   key.size = sizeof(id);
124   if ((errno = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
125     txn_abort(tid);
126     if (errno == EAGAIN) {
127       goto retry;
128     }
129     goto update_err;
130   }
131
132   /* end transaction */
133   return txn_commit(tid, 0);
134
135 update_err:
136   syslog(LOG_ERR, "cnid_update: can't update CNID(%x)", id);
137   return -1;
138 }