OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [hfs/] [dir_cap.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (C) 1995-1997  Paul H. Hargrove
3
 * This file may be distributed under the terms of the GNU General Public License.
4
 *
5
 * This file contains the inode_operations and file_operations
6
 * structures for HFS directories under the CAP scheme.
7
 *
8
 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
9
 *
10
 * The source code distribution of the Columbia AppleTalk Package for
11
 * UNIX, version 6.0, (CAP) was used as a specification of the
12
 * location and format of files used by CAP's Aufs.  No code from CAP
13
 * appears in hfs_fs.  hfs_fs is not a work ``derived'' from CAP in
14
 * the sense of intellectual property law.
15
 *
16
 * "XXX" in a comment is a note to myself to consider changing something.
17
 *
18
 * In function preconditions the term "valid" applied to a pointer to
19
 * a structure means that the pointer is non-NULL and the structure it
20
 * points to has all fields initialized to consistent values.
21
 */
22
 
23
#include "hfs.h"
24
#include <linux/hfs_fs_sb.h>
25
#include <linux/hfs_fs_i.h>
26
#include <linux/hfs_fs.h>
27
 
28
/*================ Forward declarations ================*/
29
 
30
static struct dentry *cap_lookup(struct inode *, struct dentry *);
31
static int cap_readdir(struct file *, void *, filldir_t);
32
 
33
/*================ Global variables ================*/
34
 
35
#define DOT_LEN                 1
36
#define DOT_DOT_LEN             2
37
#define DOT_RESOURCE_LEN        9
38
#define DOT_FINDERINFO_LEN      11
39
#define DOT_ROOTINFO_LEN        9
40
 
41
const struct hfs_name hfs_cap_reserved1[] = {
42
        {DOT_LEN,               "."},
43
        {DOT_DOT_LEN,           ".."},
44
        {DOT_RESOURCE_LEN,      ".resource"},
45
        {DOT_FINDERINFO_LEN,    ".finderinfo"},
46
        {0,                      ""},
47
};
48
 
49
const struct hfs_name hfs_cap_reserved2[] = {
50
        {DOT_ROOTINFO_LEN,      ".rootinfo"},
51
        {0,                      ""},
52
};
53
 
54
#define DOT             (&hfs_cap_reserved1[0])
55
#define DOT_DOT         (&hfs_cap_reserved1[1])
56
#define DOT_RESOURCE    (&hfs_cap_reserved1[2])
57
#define DOT_FINDERINFO  (&hfs_cap_reserved1[3])
58
#define DOT_ROOTINFO    (&hfs_cap_reserved2[0])
59
 
60
struct file_operations hfs_cap_dir_operations = {
61
        read:           generic_read_dir,
62
        readdir:        cap_readdir,
63
        fsync:          file_fsync,
64
};
65
 
66
struct inode_operations hfs_cap_ndir_inode_operations = {
67
        create:         hfs_create,
68
        lookup:         cap_lookup,
69
        unlink:         hfs_unlink,
70
        mkdir:          hfs_mkdir,
71
        rmdir:          hfs_rmdir,
72
        rename:         hfs_rename,
73
        setattr:        hfs_notify_change,
74
};
75
 
76
struct inode_operations hfs_cap_fdir_inode_operations = {
77
        lookup:         cap_lookup,
78
        setattr:        hfs_notify_change,
79
};
80
 
81
struct inode_operations hfs_cap_rdir_inode_operations = {
82
        create:         hfs_create,
83
        lookup:         cap_lookup,
84
        setattr:        hfs_notify_change,
85
};
86
 
87
/*================ File-local functions ================*/
88
 
89
/*
90
 * cap_lookup()
91
 *
92
 * This is the lookup() entry in the inode_operations structure for
93
 * HFS directories in the CAP scheme.  The purpose is to generate the
94
 * inode corresponding to an entry in a directory, given the inode for
95
 * the directory and the name (and its length) of the entry.
96
 */
97
static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry)
98
{
99
        ino_t dtype;
100
        struct hfs_name cname;
101
        struct hfs_cat_entry *entry;
102
        struct hfs_cat_key key;
103
        struct inode *inode = NULL;
104
 
105
        dentry->d_op = &hfs_dentry_operations;
106
        entry = HFS_I(dir)->entry;
107
        dtype = HFS_ITYPE(dir->i_ino);
108
 
109
        /* Perform name-mangling */
110
        hfs_nameout(dir, &cname, dentry->d_name.name,
111
                    dentry->d_name.len);
112
 
113
        /* no need to check for "."  or ".." */
114
 
115
        /* Check for special directories if in a normal directory.
116
           Note that cap_dupdir() does an iput(dir). */
117
        if (dtype==HFS_CAP_NDIR) {
118
                /* Check for ".resource", ".finderinfo" and ".rootinfo" */
119
                if (hfs_streq(cname.Name, cname.Len,
120
                              DOT_RESOURCE->Name, DOT_RESOURCE_LEN)) {
121
                        ++entry->count; /* __hfs_iget() eats one */
122
                        inode = hfs_iget(entry, HFS_CAP_RDIR, dentry);
123
                        goto done;
124
                } else if (hfs_streq(cname.Name, cname.Len,
125
                                     DOT_FINDERINFO->Name,
126
                                     DOT_FINDERINFO_LEN)) {
127
                        ++entry->count; /* __hfs_iget() eats one */
128
                        inode = hfs_iget(entry, HFS_CAP_FDIR, dentry);
129
                        goto done;
130
                } else if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
131
                           hfs_streq(cname.Name, cname.Len,
132
                                     DOT_ROOTINFO->Name, DOT_ROOTINFO_LEN)) {
133
                        ++entry->count; /* __hfs_iget() eats one */
134
                        inode = hfs_iget(entry, HFS_CAP_FNDR, dentry);
135
                        goto done;
136
                }
137
        }
138
 
139
        /* Do an hfs_iget() on the mangled name. */
140
        hfs_cat_build_key(entry->cnid, &cname, &key);
141
        inode = hfs_iget(hfs_cat_get(entry->mdb, &key),
142
                         HFS_I(dir)->file_type, dentry);
143
 
144
        /* Don't return a resource fork for a directory */
145
        if (inode && (dtype == HFS_CAP_RDIR) &&
146
            (HFS_I(inode)->entry->type == HFS_CDR_DIR)) {
147
                iput(inode); /* this does an hfs_cat_put */
148
                inode = NULL;
149
        }
150
 
151
done:
152
        d_add(dentry, inode);
153
        return NULL;
154
}
155
 
156
/*
157
 * cap_readdir()
158
 *
159
 * This is the readdir() entry in the file_operations structure for
160
 * HFS directories in the CAP scheme.  The purpose is to enumerate the
161
 * entries in a directory, given the inode of the directory and a
162
 * (struct file *), the 'f_pos' field of which indicates the location
163
 * in the directory.  The (struct file *) is updated so that the next
164
 * call with the same 'dir' and 'filp' arguments will produce the next
165
 * directory entry.  The entries are returned in 'dirent', which is
166
 * "filled-in" by calling filldir().  This allows the same readdir()
167
 * function be used for different dirent formats.  We try to read in
168
 * as many entries as we can before filldir() refuses to take any more.
169
 *
170
 * XXX: In the future it may be a good idea to consider not generating
171
 * metadata files for covered directories since the data doesn't
172
 * correspond to the mounted directory.  However this requires an
173
 * iget() for every directory which could be considered an excessive
174
 * amount of overhead.  Since the inode for a mount point is always
175
 * in-core this is another argument for a call to get an inode if it
176
 * is in-core or NULL if it is not.
177
 */
178
static int cap_readdir(struct file * filp,
179
                       void * dirent, filldir_t filldir)
180
{
181
        ino_t type;
182
        int skip_dirs;
183
        struct hfs_brec brec;
184
        struct hfs_cat_entry *entry;
185
        struct inode *dir = filp->f_dentry->d_inode;
186
 
187
        entry = HFS_I(dir)->entry;
188
        type = HFS_ITYPE(dir->i_ino);
189
        skip_dirs = (type == HFS_CAP_RDIR);
190
 
191
        if (filp->f_pos == 0) {
192
                /* Entry 0 is for "." */
193
                if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino, DT_DIR)) {
194
                        return 0;
195
                }
196
                filp->f_pos = 1;
197
        }
198
 
199
        if (filp->f_pos == 1) {
200
                /* Entry 1 is for ".." */
201
                hfs_u32 cnid;
202
 
203
                if (type == HFS_CAP_NDIR) {
204
                        cnid = hfs_get_nl(entry->key.ParID);
205
                } else {
206
                        cnid = entry->cnid;
207
                }
208
 
209
                if (filldir(dirent, DOT_DOT->Name,
210
                            DOT_DOT_LEN, 1, ntohl(cnid), DT_DIR)) {
211
                        return 0;
212
                }
213
                filp->f_pos = 2;
214
        }
215
 
216
        if (filp->f_pos < (dir->i_size - 3)) {
217
                hfs_u32 cnid;
218
                hfs_u8 type;
219
 
220
                if (hfs_cat_open(entry, &brec) ||
221
                    hfs_cat_next(entry, &brec, filp->f_pos - 2, &cnid, &type)) {
222
                        return 0;
223
                }
224
                while (filp->f_pos < (dir->i_size - 3)) {
225
                        if (hfs_cat_next(entry, &brec, 1, &cnid, &type)) {
226
                                return 0;
227
                        }
228
                        if (!skip_dirs || (type != HFS_CDR_DIR)) {
229
                                ino_t ino;
230
                                unsigned int len;
231
                                unsigned char tmp_name[HFS_NAMEMAX];
232
 
233
                                ino = ntohl(cnid) | HFS_I(dir)->file_type;
234
                                len = hfs_namein(dir, tmp_name,
235
                                    &((struct hfs_cat_key *)brec.key)->CName);
236
                                if (filldir(dirent, tmp_name, len,
237
                                            filp->f_pos, ino, DT_UNKNOWN)) {
238
                                        hfs_cat_close(entry, &brec);
239
                                        return 0;
240
                                }
241
                        }
242
                        ++filp->f_pos;
243
                }
244
                hfs_cat_close(entry, &brec);
245
        }
246
 
247
        if (filp->f_pos == (dir->i_size - 3)) {
248
                if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
249
                    (type == HFS_CAP_NDIR)) {
250
                        /* In root dir last-2 entry is for ".rootinfo" */
251
                        if (filldir(dirent, DOT_ROOTINFO->Name,
252
                                    DOT_ROOTINFO_LEN, filp->f_pos,
253
                                    ntohl(entry->cnid) | HFS_CAP_FNDR,
254
                                    DT_UNKNOWN)) {
255
                                return 0;
256
                        }
257
                }
258
                ++filp->f_pos;
259
        }
260
 
261
        if (filp->f_pos == (dir->i_size - 2)) {
262
                if (type == HFS_CAP_NDIR) {
263
                        /* In normal dirs last-1 entry is for ".finderinfo" */
264
                        if (filldir(dirent, DOT_FINDERINFO->Name,
265
                                    DOT_FINDERINFO_LEN, filp->f_pos,
266
                                    ntohl(entry->cnid) | HFS_CAP_FDIR,
267
                                    DT_UNKNOWN)) {
268
                                return 0;
269
                        }
270
                }
271
                ++filp->f_pos;
272
        }
273
 
274
        if (filp->f_pos == (dir->i_size - 1)) {
275
                if (type == HFS_CAP_NDIR) {
276
                        /* In normal dirs last entry is for ".resource" */
277
                        if (filldir(dirent, DOT_RESOURCE->Name,
278
                                    DOT_RESOURCE_LEN, filp->f_pos,
279
                                    ntohl(entry->cnid) | HFS_CAP_RDIR,
280
                                    DT_UNKNOWN)) {
281
                                return 0;
282
                        }
283
                }
284
                ++filp->f_pos;
285
        }
286
 
287
        return 0;
288
}
289
 
290
 
291
/* due to the dcache caching negative dentries for non-existent files,
292
 * we need to drop those entries when a file silently gets created.
293
 * as far as i can tell, the calls that need to do this are the file
294
 * related calls (create, rename, and mknod). the directory calls
295
 * should be immune. the relevant calls in dir.c call drop_dentry
296
 * upon successful completion. */
297
void hfs_cap_drop_dentry(struct dentry *dentry, const ino_t type)
298
{
299
  if (type == HFS_CAP_DATA) { /* given name */
300
    hfs_drop_special(dentry->d_parent, DOT_FINDERINFO, dentry);
301
    hfs_drop_special(dentry->d_parent, DOT_RESOURCE, dentry);
302
  } else {
303
    struct dentry *de;
304
 
305
    /* given {.resource,.finderinfo}/name, look for name */
306
    if ((de = hfs_lookup_dentry(dentry->d_parent->d_parent,
307
                                dentry->d_name.name, dentry->d_name.len))) {
308
      if (!de->d_inode)
309
        d_drop(de);
310
      dput(de);
311
    }
312
 
313
    switch (type) {
314
    case HFS_CAP_RSRC: /* given .resource/name */
315
       /* look for .finderinfo/name */
316
      hfs_drop_special(dentry->d_parent->d_parent, DOT_FINDERINFO,
317
                       dentry);
318
      break;
319
    case HFS_CAP_FNDR: /* given .finderinfo/name. i don't this
320
                        * happens. */
321
      /* look for .resource/name */
322
      hfs_drop_special(dentry->d_parent->d_parent, DOT_RESOURCE,
323
                       dentry);
324
      break;
325
    }
326
  }
327
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.