• 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/cdb/
1/*
2 * $Id: cnid_cdb_lookup.c,v 1.6 2009-11-20 17:22:11 didg Exp $
3 */
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif /* HAVE_CONFIG_H */
8
9#ifdef CNID_BACKEND_CDB
10#include "cnid_cdb_private.h"
11
12#define LOGFILEMAX    100  /* kbytes */
13#define CHECKTIMEMAX   30  /* minutes */
14
15/* This returns the CNID corresponding to a particular file.  It will
16 * also fix up the various databases if there's a problem. */
17cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
18                   char *name, const size_t len)
19{
20    unsigned char *buf;
21    CNID_private *db;
22    DBT key, devdata, diddata;
23    char dev[CNID_DEV_LEN];
24    char ino[CNID_INO_LEN];
25    int devino = 1, didname = 1;
26    u_int32_t type_devino  = (unsigned)-1;
27    u_int32_t type_didname = (unsigned)-1;
28    u_int32_t type;
29    int update = 0;
30    cnid_t id_devino, id_didname,id = 0;
31    int rc;
32
33    if (!cdb || !(db = cdb->_private) || !st || !name) {
34        return 0;
35    }
36
37    if ((buf = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
38        LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
39        return 0;
40    }
41
42    memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
43    type = ntohl(type);
44
45    memset(&key, 0, sizeof(key));
46    memset(&diddata, 0, sizeof(diddata));
47    memset(&devdata, 0, sizeof(devdata));
48
49    /* Look for a CNID for our did/name */
50    key.data = buf +CNID_DEVINO_OFS;
51    key.size = CNID_DEVINO_LEN;
52
53    memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
54    memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
55
56    if (0 != (rc = db->db_didname->get(db->db_devino, NULL, &key, &devdata, 0 )) ) {
57        if (rc != DB_NOTFOUND) {
58            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
59               did, name, db_strerror(rc));
60            return 0;
61        }
62        devino = 0;
63    }
64    else {
65        memcpy(&id_devino, devdata.data, sizeof(cnid_t));
66        memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
67        type_devino = ntohl(type_devino);
68    }
69
70    buf = make_cnid_data(cdb->flags, st, did, name, len);
71    key.data = buf +CNID_DID_OFS;
72    key.size = CNID_DID_LEN + len + 1;
73
74    if (0 != (rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0 ) ) ) {
75        if (rc != DB_NOTFOUND) {
76            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
77               did, name, db_strerror(rc));
78            return 0;
79        }
80        didname = 0;
81    }
82    else {
83        memcpy(&id_didname, diddata.data, sizeof(cnid_t));
84        memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
85        type_didname = ntohl(type_didname);
86    }
87
88    if (!devino && !didname) {
89        return 0;
90    }
91
92    if (devino && didname && id_devino == id_didname && type_devino == type) {
93        /* the same */
94        return id_didname;
95    }
96
97    if (didname) {
98        id = id_didname;
99        /* we have a did:name
100         * if it's the same dev or not the same type
101         * just delete it
102        */
103        if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
104                   type_didname != type) {
105            if (cnid_cdb_delete(cdb, id) < 0) {
106                return 0;
107            }
108        }
109        else {
110            update = 1;
111        }
112    }
113
114    if (devino) {
115        id = id_devino;
116        if (type_devino != type) {
117            /* same dev:inode but not same type one is a folder the other
118             * is a file,it's an inode reused, delete the record
119            */
120            if (cnid_cdb_delete(cdb, id) < 0) {
121                return 0;
122            }
123        }
124        else {
125            update = 1;
126        }
127    }
128    if (!update) {
129        return 0;
130    }
131    /* Fix up the database. assume it was a file move and rename */
132    cnid_cdb_update(cdb, id, st, did, name, len);
133
134#ifdef DEBUG
135    LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));
136#endif
137    return id;
138}
139
140#endif /* CNID_BACKEND_CDB */
141