]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cdb/cnid_cdb_rebuild_add.c
f8ac3405738513bd42bee6d845007bd895b03c91
[netatalk.git] / libatalk / cnid / cdb / cnid_cdb_rebuild_add.c
1 /*
2  * $Id: cnid_cdb_rebuild_add.c,v 1.3 2005-05-03 14:55:13 didg Exp $
3  *
4  * All Rights Reserved. See COPYRIGHT.
5  *
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #ifdef CNID_BACKEND_CDB
13 #include "cnid_cdb_private.h"
14
15 #define tid    NULL
16 #define DEBUG 1
17
18 #include "cnid_cdb.h"
19
20 /* ----------------------------- */
21 static cnid_t set_max_cnid(CNID_private *db, cnid_t hint)
22 {
23     DBT rootinfo_key, rootinfo_data;
24     int rc;
25     char buf[ROOTINFO_DATALEN];
26     cnid_t id, id1;
27     time_t t;
28     
29     memset(&rootinfo_key, 0, sizeof(rootinfo_key));
30     memset(&rootinfo_data, 0, sizeof(rootinfo_data));
31     
32     rootinfo_key.data = ROOTINFO_KEY;
33     rootinfo_key.size = ROOTINFO_KEYLEN;
34
35     switch ((rc = db->db_cnid->get(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) {
36     case 0:
37         memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
38         break;
39     case DB_NOTFOUND:
40         /* FIXME: This duplicates stuff from cnid_cdb_add.c. 
41            We also implicitely assume that sizeof(time_t) <= CNID_DEV_LEN */
42         memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
43         t = time(NULL);
44         memset(buf + CNID_DEV_OFS, 0, CNID_DEV_LEN);
45         memcpy(buf + CNID_DEV_OFS, &t, sizeof(time_t));
46         id = htonl(CNID_START);
47         memcpy(buf + CNID_TYPE_OFS, &id, sizeof(id));
48         break;
49     default:
50         LOG(log_error, logtype_default, "set_max_cnid: Unable to read rootinfo: %s", db_strerror(rc));
51         errno = CNID_ERR_DB; 
52         goto cleanup;
53     }
54
55     memcpy(&id, buf + CNID_TYPE_OFS, sizeof(id));
56     id = ntohl(id);
57     id1 = ntohl(hint);
58
59     if (id1 > id) {
60         memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
61         rootinfo_data.data = buf;
62         rootinfo_data.size = ROOTINFO_DATALEN;
63         if ((rc = db->db_cnid->put(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) {
64             LOG(log_error, logtype_default, "set_max_cnid: Unable to write rootinfo: %s", db_strerror(rc));
65             errno = CNID_ERR_DB; 
66             goto cleanup;
67         }
68     }
69
70     return hint;
71
72 cleanup:
73     return CNID_INVALID;
74 }
75
76 /* ------------------------ */
77 cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
78                 const cnid_t did, char *name, const size_t len, 
79                 cnid_t hint)
80 {
81     CNID_private *db;
82     DBT key, data;
83     int rc;
84
85     if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
86         errno = CNID_ERR_PARAM;
87         return CNID_INVALID;
88     }
89
90 #if 0
91     /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */
92     /* Do a lookup. */
93     id = cnid_cdb_lookup(cdb, st, did, name, len);
94     /* ... Return id if it is valid, or if Rootinfo is read-only. */
95     if (id || (db->flags & CNIDFLAG_DB_RO)) {
96 #ifdef DEBUG
97         LOG(log_info, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
98 #endif
99         return id;
100     }
101 #endif
102
103     /* Initialize our DBT data structures. */
104     memset(&key, 0, sizeof(key));
105     memset(&data, 0, sizeof(data));
106
107     if ((data.data = make_cnid_data(st, did, name, len)) == NULL) {
108         LOG(log_error, logtype_default, "cnid_add: Path name is too long");
109         errno = CNID_ERR_PATH;
110         return CNID_INVALID;
111     }
112     data.size = CNID_HEADER_LEN + len + 1;
113     
114     memcpy(data.data, &hint, sizeof(hint));
115     
116     key.data = &hint;
117     key.size = sizeof(hint);
118
119     /* Now we need to add the CNID data to the databases. */
120     if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
121             LOG(log_error, logtype_default
122                    , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 
123                    name, ntohl(hint), db_strerror(rc));  
124             errno = CNID_ERR_DB;
125             goto cleanup;
126     }
127
128     if (set_max_cnid(db, hint) == CNID_INVALID) {
129             errno = CNID_ERR_DB;
130             goto cleanup;
131     }
132
133 #ifdef DEBUG
134     LOG(log_info, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
135 #endif
136
137     return hint;
138
139 cleanup:
140     return CNID_INVALID;
141 }
142
143 #endif /* CNID_BACKEND_CDB */