2 * Copyright (C) 1995-1997 Paul H. Hargrove
3 * This file may be distributed under the terms of the GNU Public License.
5 * This file contains the inode_operations and file_operations
6 * structures for HFS directories under the CAP scheme.
8 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
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.
16 * "XXX" in a comment is a note to myself to consider changing something.
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.
24 #include <linux/hfs_fs_sb.h>
25 #include <linux/hfs_fs_i.h>
26 #include <linux/hfs_fs.h>
28 /*================ Forward declarations ================*/
30 static int cap_lookup(struct inode
*, struct dentry
*);
31 static int cap_readdir(struct file
*, void *, filldir_t
);
33 /*================ Global variables ================*/
37 #define DOT_RESOURCE_LEN 9
38 #define DOT_FINDERINFO_LEN 11
39 #define DOT_ROOTINFO_LEN 9
41 const struct hfs_name hfs_cap_reserved1
[] = {
44 {DOT_RESOURCE_LEN
, ".resource"},
45 {DOT_FINDERINFO_LEN
, ".finderinfo"},
49 const struct hfs_name hfs_cap_reserved2
[] = {
50 {DOT_ROOTINFO_LEN
, ".rootinfo"},
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])
60 static struct file_operations hfs_cap_dir_operations
= {
61 NULL
, /* lseek - default */
62 hfs_dir_read
, /* read - invalid */
63 NULL
, /* write - bad */
64 cap_readdir
, /* readdir */
65 NULL
, /* select - default */
66 NULL
, /* ioctl - default */
67 NULL
, /* mmap - none */
68 NULL
, /* no special open code */
70 NULL
, /* no special release code */
71 file_fsync
, /* fsync - default */
72 NULL
, /* fasync - default */
73 NULL
, /* check_media_change - none */
74 NULL
/* revalidate - none */
77 struct inode_operations hfs_cap_ndir_inode_operations
= {
78 &hfs_cap_dir_operations
,/* default directory file-ops */
79 hfs_create
, /* create */
80 cap_lookup
, /* lookup */
82 hfs_unlink
, /* unlink */
84 hfs_mkdir
, /* mkdir */
85 hfs_rmdir
, /* rmdir */
86 hfs_mknod
, /* mknod */
87 hfs_rename
, /* rename */
89 NULL
, /* follow_link */
94 NULL
, /* permission */
98 struct inode_operations hfs_cap_fdir_inode_operations
= {
99 &hfs_cap_dir_operations
,/* default directory file-ops */
101 cap_lookup
, /* lookup */
110 NULL
, /* follow_link */
112 NULL
, /* writepage */
115 NULL
, /* permission */
119 struct inode_operations hfs_cap_rdir_inode_operations
= {
120 &hfs_cap_dir_operations
,/* default directory file-ops */
121 hfs_create
, /* create */
122 cap_lookup
, /* lookup */
131 NULL
, /* follow_link */
133 NULL
, /* writepage */
136 NULL
, /* permission */
140 /*================ File-local functions ================*/
145 * This is the lookup() entry in the inode_operations structure for
146 * HFS directories in the CAP scheme. The purpose is to generate the
147 * inode corresponding to an entry in a directory, given the inode for
148 * the directory and the name (and its length) of the entry.
150 static int cap_lookup(struct inode
* dir
, struct dentry
*dentry
)
153 struct hfs_name cname
;
154 struct hfs_cat_entry
*entry
;
155 struct hfs_cat_key key
;
156 struct inode
*inode
= NULL
;
158 if (!dir
|| !S_ISDIR(dir
->i_mode
)) {
162 dentry
->d_op
= &hfs_dentry_operations
;
163 entry
= HFS_I(dir
)->entry
;
164 dtype
= HFS_ITYPE(dir
->i_ino
);
166 /* Perform name-mangling */
167 hfs_nameout(dir
, &cname
, dentry
->d_name
.name
,
171 if (hfs_streq(&cname
, DOT
)) {
172 /* this little trick skips the iget and iput */
177 /* Check for "..". */
178 if (hfs_streq(&cname
, DOT_DOT
)) {
179 struct hfs_cat_entry
*parent
;
181 if (dtype
!= HFS_CAP_NDIR
) {
182 /* Case for ".." in ".finderinfo" or ".resource" */
184 ++entry
->count
; /* __hfs_iget() eats one */
186 /* Case for ".." in a normal directory */
187 parent
= hfs_cat_parent(entry
);
189 inode
= hfs_iget(parent
, HFS_CAP_NDIR
, dentry
);
193 /* Check for special directories if in a normal directory.
194 Note that cap_dupdir() does an iput(dir). */
195 if (dtype
==HFS_CAP_NDIR
) {
196 /* Check for ".resource", ".finderinfo" and ".rootinfo" */
197 if (hfs_streq(&cname
, DOT_RESOURCE
)) {
198 ++entry
->count
; /* __hfs_iget() eats one */
199 inode
= hfs_iget(entry
, HFS_CAP_RDIR
, dentry
);
201 } else if (hfs_streq(&cname
, DOT_FINDERINFO
)) {
202 ++entry
->count
; /* __hfs_iget() eats one */
203 inode
= hfs_iget(entry
, HFS_CAP_FDIR
, dentry
);
205 } else if ((entry
->cnid
== htonl(HFS_ROOT_CNID
)) &&
206 hfs_streq(&cname
, DOT_ROOTINFO
)) {
207 ++entry
->count
; /* __hfs_iget() eats one */
208 inode
= hfs_iget(entry
, HFS_CAP_FNDR
, dentry
);
213 /* Do an hfs_iget() on the mangled name. */
214 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
215 inode
= hfs_iget(hfs_cat_get(entry
->mdb
, &key
),
216 HFS_I(dir
)->file_type
, dentry
);
218 /* Don't return a resource fork for a directory */
219 if (inode
&& (dtype
== HFS_CAP_RDIR
) &&
220 (HFS_I(inode
)->entry
->type
== HFS_CDR_DIR
)) {
221 iput(inode
); /* this does an hfs_cat_put */
226 d_add(dentry
, inode
);
233 * This is the readdir() entry in the file_operations structure for
234 * HFS directories in the CAP scheme. The purpose is to enumerate the
235 * entries in a directory, given the inode of the directory and a
236 * (struct file *), the 'f_pos' field of which indicates the location
237 * in the directory. The (struct file *) is updated so that the next
238 * call with the same 'dir' and 'filp' arguments will produce the next
239 * directory entry. The entries are returned in 'dirent', which is
240 * "filled-in" by calling filldir(). This allows the same readdir()
241 * function be used for different dirent formats. We try to read in
242 * as many entries as we can before filldir() refuses to take any more.
244 * XXX: In the future it may be a good idea to consider not generating
245 * metadata files for covered directories since the data doesn't
246 * correspond to the mounted directory. However this requires an
247 * iget() for every directory which could be considered an excessive
248 * amount of overhead. Since the inode for a mount point is always
249 * in-core this is another argument for a call to get an inode if it
250 * is in-core or NULL if it is not.
252 static int cap_readdir(struct file
* filp
,
253 void * dirent
, filldir_t filldir
)
257 struct hfs_brec brec
;
258 struct hfs_cat_entry
*entry
;
259 struct inode
*dir
= filp
->f_dentry
->d_inode
;
261 if (!dir
|| !dir
->i_sb
|| !S_ISDIR(dir
->i_mode
)) {
265 entry
= HFS_I(dir
)->entry
;
266 type
= HFS_ITYPE(dir
->i_ino
);
267 skip_dirs
= (type
== HFS_CAP_RDIR
);
269 if (filp
->f_pos
== 0) {
270 /* Entry 0 is for "." */
271 if (filldir(dirent
, DOT
->Name
, DOT_LEN
, 0, dir
->i_ino
)) {
277 if (filp
->f_pos
== 1) {
278 /* Entry 1 is for ".." */
281 if (type
== HFS_CAP_NDIR
) {
282 cnid
= hfs_get_nl(entry
->key
.ParID
);
287 if (filldir(dirent
, DOT_DOT
->Name
,
288 DOT_DOT_LEN
, 1, ntohl(cnid
))) {
294 if (filp
->f_pos
< (dir
->i_size
- 3)) {
298 if (hfs_cat_open(entry
, &brec
) ||
299 hfs_cat_next(entry
, &brec
, filp
->f_pos
- 2, &cnid
, &type
)) {
302 while (filp
->f_pos
< (dir
->i_size
- 3)) {
303 if (hfs_cat_next(entry
, &brec
, 1, &cnid
, &type
)) {
306 if (!skip_dirs
|| (type
!= HFS_CDR_DIR
)) {
309 unsigned char tmp_name
[HFS_NAMEMAX
];
311 ino
= ntohl(cnid
) | HFS_I(dir
)->file_type
;
312 len
= hfs_namein(dir
, tmp_name
,
313 &((struct hfs_cat_key
*)brec
.key
)->CName
);
314 if (filldir(dirent
, tmp_name
, len
,
316 hfs_cat_close(entry
, &brec
);
322 hfs_cat_close(entry
, &brec
);
325 if (filp
->f_pos
== (dir
->i_size
- 3)) {
326 if ((entry
->cnid
== htonl(HFS_ROOT_CNID
)) &&
327 (type
== HFS_CAP_NDIR
)) {
328 /* In root dir last-2 entry is for ".rootinfo" */
329 if (filldir(dirent
, DOT_ROOTINFO
->Name
,
330 DOT_ROOTINFO_LEN
, filp
->f_pos
,
331 ntohl(entry
->cnid
) | HFS_CAP_FNDR
)) {
338 if (filp
->f_pos
== (dir
->i_size
- 2)) {
339 if (type
== HFS_CAP_NDIR
) {
340 /* In normal dirs last-1 entry is for ".finderinfo" */
341 if (filldir(dirent
, DOT_FINDERINFO
->Name
,
342 DOT_FINDERINFO_LEN
, filp
->f_pos
,
343 ntohl(entry
->cnid
) | HFS_CAP_FDIR
)) {
350 if (filp
->f_pos
== (dir
->i_size
- 1)) {
351 if (type
== HFS_CAP_NDIR
) {
352 /* In normal dirs last entry is for ".resource" */
353 if (filldir(dirent
, DOT_RESOURCE
->Name
,
354 DOT_RESOURCE_LEN
, filp
->f_pos
,
355 ntohl(entry
->cnid
) | HFS_CAP_RDIR
)) {
366 /* due to the dcache caching negative dentries for non-existent files,
367 * we need to drop those entries when a file silently gets created.
368 * as far as i can tell, the calls that need to do this are the file
369 * related calls (create, rename, and mknod). the directory calls
370 * should be immune. the relevant calls in dir.c call drop_dentry
371 * upon successful completion. */
372 void hfs_cap_drop_dentry(struct dentry
*dentry
, const ino_t type
)
374 if (type
== HFS_CAP_DATA
) { /* given name */
375 hfs_drop_special(DOT_FINDERINFO
, dentry
->d_parent
, dentry
);
376 hfs_drop_special(DOT_RESOURCE
, dentry
->d_parent
, dentry
);
381 if ((de
= hfs_lookup_dentry(dentry
->d_name
.name
,
383 dentry
->d_parent
->d_parent
))) {
390 case HFS_CAP_RSRC
: /* given .resource/name */
391 /* look for .finderinfo/name */
392 hfs_drop_special(DOT_FINDERINFO
, dentry
->d_parent
->d_parent
,
395 case HFS_CAP_FNDR
: /* given .finderinfo/name. i don't this
397 /* look for .resource/name */
398 hfs_drop_special(DOT_RESOURCE
, dentry
->d_parent
->d_parent
,