]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/cdb/cnid_cdb_rebuild_add.c
- merge branch-netatalk-afp-3x-dev, HEAD was tagged before
[netatalk.git] / libatalk / cnid / cdb / cnid_cdb_rebuild_add.c
1 /*
2  * $Id: cnid_cdb_rebuild_add.c,v 1.2 2005-04-28 20:49:59 bfernhomberg 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 #ifdef ATACC
21 /* FIXME: Enhance for 8 byte dev/inode */
22 char *make_cnid_data(const struct stat *st,const cnid_t did,
23                      const char *name, const int len)
24 {
25     static char start[CNID_HEADER_LEN + MAXPATHLEN + 1];
26     char *buf = start  +CNID_LEN;
27     u_int32_t i;
28
29     if (len > MAXPATHLEN)
30         return NULL;
31
32     memcpy(buf, &st->st_dev, sizeof(st->st_dev));
33     buf += sizeof(st->st_dev);
34
35     i = htonl(st->st_ino);
36     memcpy(buf , &st->st_ino, sizeof(st->st_ino));
37     buf += sizeof(st->st_ino);
38
39     i = S_ISDIR(st->st_mode)?1:0;
40     i = htonl(i);
41     memcpy(buf, &i, sizeof(i));
42     buf += sizeof(i);
43     
44     /* did is already in network byte order */
45     memcpy(buf, &did, sizeof(did));
46     buf += sizeof(did);
47
48     memcpy(buf, name, len);
49     *(buf + len) = '\0';
50
51     return start;
52 }    
53 #endif
54
55
56 /* ----------------------------- */
57 static cnid_t set_max_cnid(CNID_private *db, cnid_t hint)
58 {
59     DBT rootinfo_key, rootinfo_data;
60     int rc;
61     char buf[ROOTINFO_DATALEN];
62     cnid_t id, id1;
63     time_t t;
64     
65     memset(&rootinfo_key, 0, sizeof(rootinfo_key));
66     memset(&rootinfo_data, 0, sizeof(rootinfo_data));
67     
68     rootinfo_key.data = ROOTINFO_KEY;
69     rootinfo_key.size = ROOTINFO_KEYLEN;
70
71     switch ((rc = db->db_cnid->get(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) {
72     case 0:
73         memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
74         break;
75     case DB_NOTFOUND:
76         /* FIXME: This duplicates stuff from cnid_cdb_add.c. 
77            We also implicitely assume that sizeof(time_t) <= CNID_DEV_LEN */
78         memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
79         t = time(NULL);
80         memset(buf + CNID_DEV_OFS, 0, CNID_DEV_LEN);
81         memcpy(buf + CNID_DEV_OFS, &t, sizeof(time_t));
82         id = htonl(CNID_START);
83         memcpy(buf + CNID_TYPE_OFS, &id, sizeof(id));
84         break;
85     default:
86         LOG(log_error, logtype_default, "set_max_cnid: Unable to read rootinfo: %s", db_strerror(rc));
87         errno = CNID_ERR_DB; 
88         goto cleanup;
89     }
90
91     memcpy(&id, buf + CNID_TYPE_OFS, sizeof(id));
92     id = ntohl(id);
93     id1 = ntohl(hint);
94
95     if (id1 > id) {
96         memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
97         rootinfo_data.data = buf;
98         rootinfo_data.size = ROOTINFO_DATALEN;
99         if ((rc = db->db_cnid->put(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) {
100             LOG(log_error, logtype_default, "set_max_cnid: Unable to write rootinfo: %s", db_strerror(rc));
101             errno = CNID_ERR_DB; 
102             goto cleanup;
103         }
104     }
105
106     return hint;
107
108 cleanup:
109     return CNID_INVALID;
110 }
111
112 /* ------------------------ */
113 cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
114                 const cnid_t did, const char *name, const int len, 
115                 cnid_t hint)
116 {
117     CNID_private *db;
118     DBT key, data;
119     int rc;
120
121     if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
122         errno = CNID_ERR_PARAM;
123         return CNID_INVALID;
124     }
125
126 #if 0
127     /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */
128     /* Do a lookup. */
129     id = cnid_cdb_lookup(cdb, st, did, name, len);
130     /* ... Return id if it is valid, or if Rootinfo is read-only. */
131     if (id || (db->flags & CNIDFLAG_DB_RO)) {
132 #ifdef DEBUG
133         LOG(log_info, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
134 #endif
135         return id;
136     }
137 #endif
138
139     /* Initialize our DBT data structures. */
140     memset(&key, 0, sizeof(key));
141     memset(&data, 0, sizeof(data));
142
143     if ((data.data = make_cnid_data(st, did, name, len)) == NULL) {
144         LOG(log_error, logtype_default, "cnid_add: Path name is too long");
145         errno = CNID_ERR_PATH;
146         return CNID_INVALID;
147     }
148     data.size = CNID_HEADER_LEN + len + 1;
149     
150     memcpy(data.data, &hint, sizeof(hint));
151     
152     key.data = &hint;
153     key.size = sizeof(hint);
154
155     /* Now we need to add the CNID data to the databases. */
156     if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
157             LOG(log_error, logtype_default
158                    , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 
159                    name, ntohl(hint), db_strerror(rc));  
160             errno = CNID_ERR_DB;
161             goto cleanup;
162     }
163
164     if (set_max_cnid(db, hint) == CNID_INVALID) {
165             errno = CNID_ERR_DB;
166             goto cleanup;
167     }
168
169 #ifdef DEBUG
170     LOG(log_info, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
171 #endif
172
173     return hint;
174
175 cleanup:
176     return CNID_INVALID;
177 }
178
179 #endif /* CNID_BACKEND_CDB */