• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/libatalk/cnid/tdb/
1/*
2 * $Id: cnid_tdb_lookup.c,v 1.6 2009-11-21 11:12:49 didg Exp $
3 */
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#ifdef CNID_BACKEND_TDB
10
11#include "cnid_tdb.h"
12#include <atalk/logger.h>
13
14cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, char *name, const size_t len)
15{
16    char *buf;
17    struct _cnid_tdb_private *db;
18    TDB_DATA key, devdata, diddata, cniddata;
19    int devino = 1, didname = 1;
20    char dev[CNID_DEV_LEN];
21    char ino[CNID_INO_LEN];
22    u_int32_t type_devino  = (unsigned)-1;
23    u_int32_t type_didname = (unsigned)-1;
24    u_int32_t type;
25    int update = 0;
26    cnid_t id_devino = 0, id_didname = 0,id = 0;
27
28    if (!cdb || !(db = cdb->_private) || !st || !name) {
29        return 0;
30    }
31
32    if ((buf = make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
33        LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
34        return 0;
35    }
36    memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
37    type = ntohl(type);
38
39    memset(&key, 0, sizeof(key));
40    memset(&devdata, 0, sizeof(devdata));
41    memset(&diddata, 0, sizeof(diddata));
42    memset(&cniddata, 0, sizeof(cniddata));
43
44    /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
45    * only get a match in one of them, that means a file has moved. */
46    memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
47    memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
48
49    key.dptr = buf +CNID_DEVINO_OFS;
50    key.dsize  = CNID_DEVINO_LEN;
51    cniddata = tdb_fetch(db->tdb_devino, key);
52    if (!cniddata.dptr) {
53         devino = 0;
54    }
55    else {
56
57        key.dptr = cniddata.dptr;
58        key.dsize = sizeof(id);
59
60        devdata = tdb_fetch(db->tdb_cnid, key);
61        free(cniddata.dptr);
62        if (devdata.dptr) {
63            memcpy(&id_devino, devdata.dptr, sizeof(cnid_t));
64            memcpy(&type_devino, (char *)devdata.dptr +CNID_TYPE_OFS, sizeof(type_devino));
65            type_devino = ntohl(type_devino);
66        }
67        else {
68             devino = 0;
69        }
70    }
71
72    /* did/name now */
73    key.dptr = buf + CNID_DID_OFS;
74    key.dsize = CNID_DID_LEN + len + 1;
75    cniddata = tdb_fetch(db->tdb_didname, key);
76    if (!cniddata.dptr) {
77        didname = 0;
78    }
79    else {
80
81        key.dptr = cniddata.dptr;
82        key.dsize = sizeof(id);
83
84        diddata = tdb_fetch(db->tdb_cnid, key);
85        free(cniddata.dptr);
86        if (diddata.dptr) {
87            memcpy(&id_didname, diddata.dptr, sizeof(cnid_t));
88            memcpy(&type_didname, (char *)diddata.dptr +CNID_TYPE_OFS, sizeof(type_didname));
89            type_didname = ntohl(type_didname);
90        }
91        else {
92             didname = 0;
93        }
94    }
95    /* Set id.  Honor did/name over dev/ino as dev/ino isn't necessarily
96     * 1-1. */
97    if (!devino && !didname) {
98        free(devdata.dptr);
99        free(diddata.dptr);
100        return 0;
101    }
102
103    if (devino && didname && id_devino == id_didname && type_devino == type) {
104        /* the same */
105        free(devdata.dptr);
106        free(diddata.dptr);
107        return id_didname;
108    }
109
110    if (didname) {
111        id = id_didname;
112        /* we have a did:name
113         * if it's the same dev or not the same type
114         * just delete it
115        */
116        if (!memcmp(dev, (char *)diddata.dptr + CNID_DEV_OFS, CNID_DEV_LEN) ||
117                   type_didname != type) {
118            if (cnid_tdb_delete(cdb, id) < 0) {
119                free(devdata.dptr);
120                free(diddata.dptr);
121                return 0;
122            }
123        }
124        else {
125            update = 1;
126        }
127    }
128
129    if (devino) {
130        id = id_devino;
131        if (type_devino != type) {
132            /* same dev:inode but not same type one is a folder the other
133             * is a file,it's an inode reused, delete the record
134            */
135            if (cnid_tdb_delete(cdb, id) < 0) {
136                free(devdata.dptr);
137                free(diddata.dptr);
138                return 0;
139            }
140        }
141        else {
142            update = 1;
143        }
144    }
145    free(devdata.dptr);
146    free(diddata.dptr);
147    if (!update) {
148        return 0;
149    }
150
151    /* Fix up the database. */
152    cnid_tdb_update(cdb, id, st, did, name, len);
153    return id;
154}
155
156#endif
157