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