• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/libatalk/cnid/cdb/
1/*
2 * $Id: cnid_cdb_rebuild_add.c,v 1.6 2009-11-20 17:22:11 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/* ----------------------------- */
21static 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
72cleanup:
73    return CNID_INVALID;
74}
75
76/* ------------------------ */
77cnid_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_debug9, 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(cdb->flags, 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_debug9, 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
139cleanup:
140    return CNID_INVALID;
141}
142
143#endif /* CNID_BACKEND_CDB */
144