2 * Copyright (C) Joerg Lenneis 2003
3 * Copyright (C) Frank Lahm 2010
4 * All Rights Reserved. See COPYING.
9 #endif /* HAVE_CONFIG_H */
17 #include <atalk/logger.h>
18 #include <atalk/cnid_bdb_private.h>
19 #include <atalk/cnid.h>
26 int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
31 memset(&key, 0, sizeof(key));
32 memset(&data, 0, sizeof(data));
34 key.data = &rply->cnid;
35 key.size = sizeof(rply->cnid);
37 data.data = pack_cnid_data(rqst);
38 data.size = CNID_HEADER_LEN + rqst->namelen + 1;
39 memcpy(data.data, &rply->cnid, sizeof(rply->cnid));
42 if ((rc = dbif_put(dbd, DBIF_CNID, &key, &data, DB_NOOVERWRITE))) {
43 /* This could indicate a database error or that the key already exists
44 (because of DB_NOOVERWRITE). In that case we still look at some sort of
45 database corruption since that is not supposed to happen. */
49 rply->result = CNID_DBD_RES_ERR_DUPLCNID;
52 /* FIXME: Should that not be logged for case 1:? */
53 LOG(log_error, logtype_cnid, "add_cnid: duplicate %x %s", rply->cnid
54 , (char *)data.data + CNID_NAME_OFS);
56 rqst->cnid = rply->cnid;
57 rc = dbd_update(dbd, rqst, rply);
59 rply->result = CNID_DBD_RES_ERR_DB;
72 /* ---------------------- */
73 int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
76 static char buf[ROOTINFO_DATALEN];
77 DBT rootinfo_key, rootinfo_data, key, data;
81 memset(&rootinfo_key, 0, sizeof(rootinfo_key));
82 memset(&rootinfo_data, 0, sizeof(rootinfo_data));
83 rootinfo_key.data = ROOTINFO_KEY;
84 rootinfo_key.size = ROOTINFO_KEYLEN;
86 memset(&key, 0, sizeof(key));
87 memset(&data, 0, sizeof(data));
90 if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) != 1) {
91 rply->result = CNID_DBD_RES_ERR_DB;
94 memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
95 memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint));
97 if (id < CNID_START - 1)
104 if (rply->cnid != CNID_INVALID) {
105 trycnid = ntohl(rply->cnid);
106 rply->cnid = CNID_INVALID;
108 if (++id == CNID_INVALID)
112 tmp = htonl(trycnid);
114 key.size = sizeof(cnid_t);
115 rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0);
118 } else if (rc == -1) {
119 rply->result = CNID_DBD_RES_ERR_DB;
125 rootinfo_data.data = buf;
126 rootinfo_data.size = ROOTINFO_DATALEN;
128 memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
130 if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
131 rply->result = CNID_DBD_RES_ERR_DB;
136 rply->cnid = htonl(trycnid);
140 /* ------------------------ */
141 /* We need a nolookup version for `dbd` */
142 int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
146 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx) {start}",
147 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
149 /* See if we have an entry already and return it if yes */
150 if (dbd_lookup(dbd, rqst, rply) < 0) {
151 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): error in dbd_lookup",
152 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
156 if (rply->result == CNID_DBD_RES_OK) {
157 /* Found it. rply->cnid is the correct CNID now. */
158 LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
162 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): {adding to database ...}",
163 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
166 /* rqst->cnid is the cnid "hint"/backup from the adouble file */
167 rply->cnid = rqst->cnid;
169 if (get_cnid(dbd, rply) < 0) {
170 if (rply->result == CNID_DBD_RES_ERR_MAX) {
171 LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
172 /* This will cause an abort/rollback if transactions are used */
175 LOG(log_error, logtype_cnid, "dbd_add: Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
180 if (add_cnid(dbd, rqst, rply) < 0) {
181 if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
182 LOG(log_error, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Cannot add CNID: %u",
183 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
184 /* abort/rollback, see above */
187 LOG(log_error, logtype_cnid, "dbd_add: Failed to add CNID for %s to database", rqst->name);
191 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): Added with CNID: %u",
192 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
194 rply->result = CNID_DBD_RES_OK;