• 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/last/
1
2/*
3 * $Id: cnid_last.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $
4 *
5 * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
6 * All Rights Reserved. See COPYRIGHT.
7 *
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif /* HAVE_CONFIG_H */
13
14#ifdef CNID_BACKEND_LAST
15#include <stdlib.h>
16#include "cnid_last.h"
17#include <atalk/util.h>
18#include <atalk/logger.h>
19
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <unistd.h>
23
24/* ------------------------ */
25cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st,
26                     const cnid_t did _U_, char *name _U_, const size_t len _U_, cnid_t hint _U_)
27{
28
29    /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */
30    /* Propably we should look through DID tree. */
31
32    /*
33     * First thing:  DID and FNUMs are
34     * in the same space for purposes of enumerate (and several
35     * other wierd places).  While we consider this Apple's bug,
36     * this is the work-around:  In order to maintain constant and
37     * unique DIDs and FNUMs, we monotonically generate the DIDs
38     * during the session, and derive the FNUMs from the filesystem.
39     * Since the DIDs are small, we insure that the FNUMs are fairly
40     * large by setting thier high bits to the device number.
41     *
42     * AFS already does something very similar to this for the
43     * inode number, so we don't repeat the procedure.
44     *
45     * new algorithm:
46     * due to complaints over did's being non-persistent,
47     * here's the current hack to provide semi-persistent
48     * did's:
49     *      1) we reserve the first bit for file ids.
50     *      2) the next 7 bits are for the device.
51     *      3) the remaining 24 bits are for the inode.
52     *
53     * both the inode and device information are actually hashes
54     * that are then truncated to the requisite bit length.
55     *
56     * it should be okay to use lstat to deal with symlinks.
57     */
58
59    struct _cnid_last_private *priv;
60
61    if (!cdb || !(cdb->_private))
62        return CNID_INVALID;
63
64    priv = (struct _cnid_last_private *) (cdb->_private);
65
66    if (S_ISDIR(st->st_mode))
67        return htonl(priv->last_did++);
68    else
69        return htonl((st->st_dev << 16) | (st->st_ino & 0x0000ffff));
70}
71
72
73
74void cnid_last_close(struct _cnid_db *cdb)
75{
76    free(cdb->volpath);
77    free(cdb->_private);
78    free(cdb);
79}
80
81
82
83int cnid_last_delete(struct _cnid_db *cdb _U_, const cnid_t id _U_)
84{
85    return CNID_INVALID;
86}
87
88
89
90/* Return CNID for a given did/name. */
91cnid_t cnid_last_get(struct _cnid_db *cdb _U_, const cnid_t did _U_, char *name _U_, const size_t len _U_)
92{
93    /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */
94    /* Propably we should look through DID tree. */
95    return CNID_INVALID;
96}
97
98
99
100/* */
101cnid_t cnid_last_lookup(struct _cnid_db *cdb _U_, const struct stat *st _U_, const cnid_t did _U_,
102    char *name _U_, const size_t len _U_)
103{
104    /* FIXME: this function doesn't work in [last] scheme ! */
105    /* Should be never called or CNID should be somewhat refactored again. */
106    return CNID_INVALID;
107}
108
109
110static struct _cnid_db *cnid_last_new(const char *volpath)
111{
112    struct _cnid_db *cdb;
113    struct _cnid_last_private *priv;
114
115    if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL)
116        return NULL;
117
118    if ((cdb->volpath = strdup(volpath)) == NULL) {
119        free(cdb);
120        return NULL;
121    }
122
123    if ((cdb->_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) {
124        free(cdb->volpath);
125        free(cdb);
126        return NULL;
127    }
128
129    /* Set up private state */
130    priv = (struct _cnid_last_private *) (cdb->_private);
131    priv->last_did = 17;
132
133    /* Set up standard fields */
134    cdb->flags = 0;
135    cdb->cnid_add = cnid_last_add;
136    cdb->cnid_delete = cnid_last_delete;
137    cdb->cnid_get = cnid_last_get;
138    cdb->cnid_lookup = cnid_last_lookup;
139    cdb->cnid_nextid = NULL;    /* cnid_last_nextid; */
140    cdb->cnid_resolve = cnid_last_resolve;
141    cdb->cnid_update = cnid_last_update;
142    cdb->cnid_close = cnid_last_close;
143
144    return cdb;
145}
146
147struct _cnid_db *cnid_last_open(struct cnid_open_args *args)
148{
149    struct _cnid_db *cdb;
150
151    if (!args->dir) {
152        return NULL;
153    }
154
155    if ((cdb = cnid_last_new(args->dir)) == NULL) {
156        LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
157        return NULL;
158    }
159
160    return cdb;
161}
162
163struct _cnid_module cnid_last_module = {
164    "last",
165    {NULL, NULL},
166    cnid_last_open,
167    0
168};
169
170/* Return the did/name pair corresponding to a CNID. */
171char *cnid_last_resolve(struct _cnid_db *cdb _U_, cnid_t * id _U_, void *buffer _U_, size_t len _U_)
172{
173    /* FIXME: frankly, it does not work. As get, add and other functions. */
174    return NULL;
175}
176
177
178int cnid_last_update(struct _cnid_db *cdb _U_, const cnid_t id _U_, const struct stat *st _U_,
179                     const cnid_t did  _U_, char *name  _U_, const size_t len _U_)
180{
181    return 0;
182}
183
184
185#endif /* CNID_BACKEND_LAST */
186