2 * $Id: dbd_add.c,v 1.8 2010-01-19 14:57:11 franklahm Exp $
4 * Copyright (C) Joerg Lenneis 2003
5 * All Rights Reserved. See COPYING.
10 #endif /* HAVE_CONFIG_H */
15 #endif /* HAVE_UNISTD_H */
18 #endif /* HAVE_FCNTL_H */
20 #ifdef HAVE_SYS_TIME_H
22 #endif /* HAVE_SYS_TIME_H */
24 #include <atalk/logger.h>
25 #include <atalk/cnid_dbd_private.h>
26 #include <atalk/cnid.h>
37 int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
42 memset(&key, 0, sizeof(key));
43 memset(&data, 0, sizeof(data));
45 key.data = &rply->cnid;
46 key.size = sizeof(rply->cnid);
48 data.data = pack_cnid_data(rqst);
49 data.size = CNID_HEADER_LEN + rqst->namelen + 1;
50 memcpy(data.data, &rply->cnid, sizeof(rply->cnid));
53 if ((rc = dbif_put(dbd, DBIF_CNID, &key, &data, DB_NOOVERWRITE))) {
54 /* This could indicate a database error or that the key already exists
55 (because of DB_NOOVERWRITE). In that case we still look at some sort of
56 database corruption since that is not supposed to happen. */
60 rply->result = CNID_DBD_RES_ERR_DUPLCNID;
63 /* FIXME: Should that not be logged for case 1:? */
64 LOG(log_error, logtype_cnid, "add_cnid: duplicate %x %s", rply->cnid
65 , (char *)data.data + CNID_NAME_OFS);
67 rqst->cnid = rply->cnid;
68 rc = dbd_update(dbd, rqst, rply);
70 rply->result = CNID_DBD_RES_ERR_DB;
83 /* ---------------------- */
84 int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
86 DBT rootinfo_key, rootinfo_data;
90 memset(&rootinfo_key, 0, sizeof(rootinfo_key));
91 memset(&rootinfo_data, 0, sizeof(rootinfo_data));
92 rootinfo_key.data = ROOTINFO_KEY;
93 rootinfo_key.size = ROOTINFO_KEYLEN;
95 if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) <= 0) {
96 rply->result = CNID_DBD_RES_ERR_DB;
99 memcpy(&hint, (char *)rootinfo_data.data +CNID_TYPE_OFS, sizeof(hint));
101 /* If we've hit the max CNID allowed, we return an error. CNID
102 * needs to be recycled before proceding. */
103 if (++id == CNID_INVALID) {
104 rply->result = CNID_DBD_RES_ERR_MAX;
109 memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
111 rootinfo_data.size = ROOTINFO_DATALEN;
113 memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint));
115 if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
116 rply->result = CNID_DBD_RES_ERR_DB;
125 int dbd_stamp(DBD *dbd)
127 DBT rootinfo_key, rootinfo_data;
129 char buf[ROOTINFO_DATALEN];
130 char stamp[CNID_DEV_LEN];
132 memset(&rootinfo_key, 0, sizeof(rootinfo_key));
133 memset(&rootinfo_data, 0, sizeof(rootinfo_data));
134 rootinfo_key.data = ROOTINFO_KEY;
135 rootinfo_key.size = ROOTINFO_KEYLEN;
137 switch (dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) {
139 hint = htonl(CNID_START);
140 memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
141 rootinfo_data.data = buf;
142 rootinfo_data.size = ROOTINFO_DATALEN;
143 if (dbif_stamp(dbd, stamp, CNID_DEV_LEN) < 0) {
146 memcpy((char *)rootinfo_data.data + CNID_TYPE_OFS, &hint, sizeof(hint));
147 memcpy((char *)rootinfo_data.data + CNID_DEV_OFS, stamp, sizeof(stamp));
148 if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
153 case 1: /* we already have one */
161 /* ------------------------ */
162 /* We need a nolookup version for `dbd` */
163 int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int nolookup)
167 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx) {start}",
168 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
170 /* See if we have an entry already and return it if yes */
172 if (dbd_lookup(dbd, rqst, rply, 0) < 0) {
173 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): error in dbd_lookup",
174 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
178 if (rply->result == CNID_DBD_RES_OK) {
179 /* Found it. rply->cnid is the correct CNID now. */
180 LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
185 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): {adding to database ...}",
186 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
189 if (get_cnid(dbd, rply) < 0) {
190 if (rply->result == CNID_DBD_RES_ERR_MAX) {
191 LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
192 /* This will cause an abort/rollback if transactions are used */
195 LOG(log_error, logtype_cnid, "dbd_add: Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
200 if (add_cnid(dbd, rqst, rply) < 0) {
201 if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
202 LOG(log_error, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Cannot add CNID: %u",
203 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
204 /* abort/rollback, see above */
207 LOG(log_error, logtype_cnid, "dbd_add: Failed to add CNID for %s to database", rqst->name);
211 LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): Added with CNID: %u",
212 ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
214 rply->result = CNID_DBD_RES_OK;