~ubuntu-branches/debian/lenny/netatalk/lenny

« back to all changes in this revision

Viewing changes to libatalk/cnid/tdb/cnid_tdb_add.c

  • Committer: Bazaar Package Importer
  • Author(s): Ante Karamatic
  • Date: 2005-10-07 13:46:11 UTC
  • mfrom: (1.1.2 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051007134611-r07qa2g67xwkp2if
Tags: 2.0.3-1ubuntu1
* debian/netatalk.init
  - run cnid_metad if CNID_METAD_RUN=yes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: cnid_tdb_add.c,v 1.1.2.1.2.2 2005/01/31 17:01:16 didg Exp $
 
3
 *
 
4
 * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
 
5
 * All Rights Reserved. See COPYRIGHT.
 
6
 *
 
7
 */
 
8
 
 
9
#ifdef HAVE_CONFIG_H
 
10
#include "config.h"
 
11
#endif
 
12
 
 
13
#ifdef CNID_BACKEND_TDB
 
14
#include "cnid_tdb.h"
 
15
#include <atalk/util.h>
 
16
#include <sys/param.h>
 
17
#include <sys/types.h>
 
18
#include <sys/stat.h>
 
19
#include <unistd.h>
 
20
#include <atalk/logger.h>
 
21
 
 
22
/* add an entry to the CNID databases. we do this as a transaction
 
23
 * to prevent messiness. */
 
24
 
 
25
static int add_cnid (struct _cnid_tdb_private *db, TDB_DATA *key, TDB_DATA *data) {
 
26
    TDB_DATA altkey, altdata;
 
27
 
 
28
    memset(&altkey, 0, sizeof(altkey));
 
29
    memset(&altdata, 0, sizeof(altdata));
 
30
 
 
31
 
 
32
    /* main database */
 
33
    if (tdb_store(db->tdb_cnid, *key, *data, TDB_REPLACE)) {
 
34
        goto abort;
 
35
    }
 
36
 
 
37
    /* dev/ino database */
 
38
    altkey.dptr = data->dptr;
 
39
    altkey.dsize = TDB_DEVINO_LEN;
 
40
    altdata.dptr = key->dptr;
 
41
    altdata.dsize = key->dsize;
 
42
    if (tdb_store(db->tdb_devino, altkey, altdata, TDB_REPLACE)) {
 
43
        goto abort;
 
44
    }
 
45
 
 
46
    /* did/name database */
 
47
    altkey.dptr = (char *) data->dptr + TDB_DEVINO_LEN;
 
48
    altkey.dsize = data->dsize - TDB_DEVINO_LEN;
 
49
    if (tdb_store(db->tdb_didname, altkey, altdata, TDB_REPLACE)) {
 
50
        goto abort;
 
51
    }
 
52
    return 0;
 
53
 
 
54
abort:
 
55
    return -1;
 
56
}
 
57
 
 
58
/* ----------------------- */
 
59
static cnid_t get_cnid(struct _cnid_tdb_private *db)
 
60
{
 
61
    TDB_DATA rootinfo_key, data;
 
62
    cnid_t hint,id;
 
63
    
 
64
    memset(&rootinfo_key, 0, sizeof(rootinfo_key));
 
65
    memset(&data, 0, sizeof(data));
 
66
    rootinfo_key.dptr = ROOTINFO_KEY;
 
67
    rootinfo_key.dsize = ROOTINFO_KEYLEN;
 
68
    
 
69
    tdb_chainlock(db->tdb_didname, rootinfo_key);  
 
70
    data = tdb_fetch(db->tdb_didname, rootinfo_key);
 
71
    if (data.dptr)
 
72
    {
 
73
        memcpy(&hint, data.dptr, sizeof(cnid_t));
 
74
        free(data.dptr);
 
75
        id = ntohl(hint);
 
76
        /* If we've hit the max CNID allowed, we return a fatal error.  CNID
 
77
         * needs to be recycled before proceding. */
 
78
        if (++id == CNID_INVALID) {
 
79
            LOG(log_error, logtype_default, "cnid_add: FATAL: CNID database has reached its limit.");
 
80
            errno = CNID_ERR_MAX;
 
81
            goto cleanup;
 
82
        }
 
83
        hint = htonl(id);
 
84
    }
 
85
    else {
 
86
        hint = htonl(TDB_START);
 
87
    }
 
88
    
 
89
    memset(&data, 0, sizeof(data));
 
90
    data.dptr = (char *)&hint;
 
91
    data.dsize = sizeof(hint);
 
92
    if (tdb_store(db->tdb_didname, rootinfo_key, data, TDB_REPLACE)) {
 
93
        goto cleanup;
 
94
    }
 
95
 
 
96
    tdb_chainunlock(db->tdb_didname, rootinfo_key );  
 
97
    return hint;
 
98
cleanup:
 
99
    tdb_chainunlock(db->tdb_didname, rootinfo_key);  
 
100
    return CNID_INVALID;
 
101
}
 
102
 
 
103
 
 
104
/* ------------------------ */
 
105
cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
 
106
                     const cnid_t did, char *name, const int len, cnid_t hint)
 
107
{
 
108
    const struct stat *lstp;
 
109
    cnid_t id;
 
110
    struct _cnid_tdb_private *priv;
 
111
    TDB_DATA key, data; 
 
112
    int rc;      
 
113
    
 
114
    if (!cdb || !(priv = cdb->_private) || !st || !name) {
 
115
        errno = CNID_ERR_PARAM;
 
116
        return CNID_INVALID;
 
117
    }
 
118
    /* Do a lookup. */
 
119
    id = cnid_tdb_lookup(cdb, st, did, name, len);
 
120
    /* ... Return id if it is valid, or if Rootinfo is read-only. */
 
121
    if (id || (priv->flags & TDBFLAG_DB_RO)) {
 
122
        return id;
 
123
    }
 
124
 
 
125
#if 0
 
126
    struct stat lst;
 
127
    lstp = lstat(name, &lst) < 0 ? st : &lst;
 
128
#endif
 
129
    lstp = st;
 
130
 
 
131
    /* Initialize our DBT data structures. */
 
132
    memset(&key, 0, sizeof(key));
 
133
    memset(&data, 0, sizeof(data));
 
134
 
 
135
    key.dptr = (char *)&hint;
 
136
    key.dsize = sizeof(cnid_t);
 
137
    if ((data.dptr = make_tdb_data(lstp, did, name, len)) == NULL) {
 
138
        LOG(log_error, logtype_default, "tdb_add: Path name is too long");
 
139
        errno = CNID_ERR_PATH;
 
140
        return CNID_INVALID;
 
141
    }
 
142
    data.dsize = TDB_HEADER_LEN + len + 1;
 
143
    hint = get_cnid(priv);
 
144
    if (hint == 0) {
 
145
        errno = CNID_ERR_DB;
 
146
        return CNID_INVALID;
 
147
    }
 
148
    
 
149
    /* Now we need to add the CNID data to the databases. */
 
150
    rc = add_cnid(priv, &key, &data);
 
151
    if (rc) {
 
152
        LOG(log_error, logtype_default, "tdb_add: Failed to add CNID for %s to database using hint %u", name, ntohl(hint));
 
153
        errno = CNID_ERR_DB;
 
154
        return CNID_INVALID;
 
155
    }
 
156
 
 
157
    return hint;
 
158
}
 
159
 
 
160
#endif