• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/netatalk-3.0.5/libatalk/cnid/cdb/
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/* ----------------------------- */
20static 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
71cleanup:
72    return CNID_INVALID;
73}
74
75cnid_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->_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->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
136cleanup:
137    return CNID_INVALID;
138}
139
140#endif /* CNID_BACKEND_CDB */
141