2 * $Id: dbd_add.c,v 1.1.4.7 2004-02-07 19:46:08 didg 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 /* cnid - dev - inode - type - did - name */
38 #define ROOTINFO_DATA "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0RootInfo"
39 #define ROOTINFO_DATALEN (3*4 +2*8 +9)
40 #define CNID_START 17 /* 0x80000000L */
42 static int add_cnid(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
47 memset(&key, 0, sizeof(key));
48 memset(&data, 0, sizeof(data));
50 key.data = &rply->cnid;
51 key.size = sizeof(rply->cnid);
53 data.data = pack_cnid_data(rqst);
54 data.size = CNID_HEADER_LEN + rqst->namelen + 1;
55 memcpy(data.data, &rply->cnid, sizeof(rply->cnid));
58 if ((rc = dbif_put(DBIF_IDX_CNID, &key, &data, DB_NOOVERWRITE))) {
59 /* This could indicate a database error or that the key already exists
60 (because of DB_NOOVERWRITE). In that case we still look at some sort of
61 database corruption since that is not supposed to happen. */
65 rply->result = CNID_DBD_RES_ERR_DUPLCNID;
68 /* FIXME: Should that not be logged for case 1:? */
69 LOG(log_error, logtype_cnid, "add_cnid: duplicate %x %s", rply->cnid
70 , (char *)data.data + CNID_NAME_OFS);
72 rqst->cnid = rply->cnid;
73 rc = dbd_update(rqst, rply);
75 rply->result = CNID_DBD_RES_ERR_DB;
88 /* ---------------------- */
89 static int get_cnid(struct cnid_dbd_rply *rply)
91 DBT rootinfo_key, rootinfo_data;
95 memset(&rootinfo_key, 0, sizeof(rootinfo_key));
96 memset(&rootinfo_data, 0, sizeof(rootinfo_data));
97 rootinfo_key.data = ROOTINFO_KEY;
98 rootinfo_key.size = ROOTINFO_KEYLEN;
100 if ((rc = dbif_get(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0)) <= 0) {
101 rply->result = CNID_DBD_RES_ERR_DB;
104 memcpy(&hint, (char *)rootinfo_data.data +CNID_TYPE_OFS, sizeof(hint));
106 /* If we've hit the max CNID allowed, we return an error. CNID
107 * needs to be recycled before proceding. */
108 if (++id == CNID_INVALID) {
109 rply->result = CNID_DBD_RES_ERR_MAX;
114 memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
116 rootinfo_data.size = ROOTINFO_DATALEN;
118 memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint));
120 if (dbif_put(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
121 rply->result = CNID_DBD_RES_ERR_DB;
132 DBT rootinfo_key, rootinfo_data;
134 char buf[ROOTINFO_DATALEN];
135 char stamp[CNID_DEV_LEN];
137 memset(&rootinfo_key, 0, sizeof(rootinfo_key));
138 memset(&rootinfo_data, 0, sizeof(rootinfo_data));
139 rootinfo_key.data = ROOTINFO_KEY;
140 rootinfo_key.size = ROOTINFO_KEYLEN;
142 switch (dbif_get(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0)) {
144 hint = htonl(CNID_START);
145 memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
146 rootinfo_data.data = buf;
147 rootinfo_data.size = ROOTINFO_DATALEN;
148 if (dbif_stamp(stamp, CNID_DEV_LEN) < 0) {
151 memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint));
152 memcpy((char *)rootinfo_data.data +CNID_DEV_OFS, stamp, sizeof(stamp));
153 if (dbif_put(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
158 case 1: /* we already have one */
166 /* ------------------------ */
167 int dbd_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
171 /* See if we have an entry already and return it if yes */
172 if (dbd_lookup(rqst, rply) < 0)
175 if (rply->result == CNID_DBD_RES_OK) {
176 /* Found it. rply->cnid is the correct CNID now. */
178 LOG(log_info, logtype_cnid, "dbd_add: dbd_lookup success, cnid %u", ntohl(rply->cnid));
183 if (get_cnid(rply) < 0) {
184 if (rply->result == CNID_DBD_RES_ERR_MAX) {
185 LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
186 /* This will cause an abort/rollback if transactions are used */
189 LOG(log_error, logtype_cnid, "dbd_add: Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
194 if (add_cnid(rqst, rply) < 0) {
195 if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
196 LOG(log_error, logtype_cnid, "dbd_add: Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
197 /* abort/rollback, see above */
200 LOG(log_error, logtype_cnid, "dbd_add: Failed to add CNID for %s to database", rqst->name);
205 LOG(log_info, logtype_cnid, "dbd_add: Added dev/ino %s did %u name %s cnid %u",
206 stringify_devino(rqst->dev, rqst->ino),
207 ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
209 rply->result = CNID_DBD_RES_OK;