2 * linux/fs/hfs/dir_dbl.c
4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU Public License.
7 * This file contains the inode_operations and file_operations
8 * structures for HFS directories.
10 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
12 * "XXX" in a comment is a note to myself to consider changing something.
14 * In function preconditions the term "valid" applied to a pointer to
15 * a structure means that the pointer is non-NULL and the structure it
16 * points to has all fields initialized to consistent values.
20 #include <linux/hfs_fs_sb.h>
21 #include <linux/hfs_fs_i.h>
22 #include <linux/hfs_fs.h>
24 /*================ Forward declarations ================*/
26 static int dbl_lookup(struct inode
*, struct dentry
*);
27 static int dbl_readdir(struct file
*, void *, filldir_t
);
28 static int dbl_create(struct inode
*, struct dentry
*, int);
29 static int dbl_mkdir(struct inode
*, struct dentry
*, int);
30 static int dbl_mknod(struct inode
*, struct dentry
*, int, int);
31 static int dbl_unlink(struct inode
*, struct dentry
*);
32 static int dbl_rmdir(struct inode
*, struct dentry
*);
33 static int dbl_rename(struct inode
*, struct dentry
*,
34 struct inode
*, struct dentry
*);
36 /*================ Global variables ================*/
40 #define ROOTINFO_LEN 8
41 #define PCNT_ROOTINFO_LEN 9
43 const struct hfs_name hfs_dbl_reserved1
[] = {
49 const struct hfs_name hfs_dbl_reserved2
[] = {
50 {ROOTINFO_LEN
, "RootInfo"},
51 {PCNT_ROOTINFO_LEN
, "%RootInfo"},
55 #define DOT (&hfs_dbl_reserved1[0])
56 #define DOT_DOT (&hfs_dbl_reserved1[1])
57 #define ROOTINFO (&hfs_dbl_reserved2[0])
58 #define PCNT_ROOTINFO (&hfs_dbl_reserved2[1])
60 static struct file_operations hfs_dbl_dir_operations
= {
61 NULL
, /* lseek - default */
62 hfs_dir_read
, /* read - invalid */
63 NULL
, /* write - bad */
64 dbl_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_dbl_dir_inode_operations
= {
78 &hfs_dbl_dir_operations
,/* default directory file-ops */
79 dbl_create
, /* create */
80 dbl_lookup
, /* lookup */
82 dbl_unlink
, /* unlink */
84 dbl_mkdir
, /* mkdir */
85 dbl_rmdir
, /* rmdir */
86 dbl_mknod
, /* mknod */
87 dbl_rename
, /* rename */
89 NULL
, /* follow_link */
94 NULL
, /* permission */
99 /*================ File-local functions ================*/
104 static int is_hdr(struct inode
*dir
, const char *name
, int len
)
108 if (name
[0] == '%') {
109 struct hfs_cat_entry
*entry
= HFS_I(dir
)->entry
;
110 struct hfs_cat_entry
*victim
;
111 struct hfs_name cname
;
112 struct hfs_cat_key key
;
114 hfs_nameout(dir
, &cname
, name
+1, len
-1);
115 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
116 if ((victim
= hfs_cat_get(entry
->mdb
, &key
))) {
127 * This is the lookup() entry in the inode_operations structure for
128 * HFS directories in the AppleDouble scheme. The purpose is to
129 * generate the inode corresponding to an entry in a directory, given
130 * the inode for the directory and the name (and its length) of the
133 static int dbl_lookup(struct inode
* dir
, struct dentry
*dentry
)
135 struct hfs_name cname
;
136 struct hfs_cat_entry
*entry
;
137 struct hfs_cat_key key
;
138 struct inode
*inode
= NULL
;
140 if (!dir
|| !S_ISDIR(dir
->i_mode
)) {
144 dentry
->d_op
= &hfs_dentry_operations
;
145 entry
= HFS_I(dir
)->entry
;
147 /* Perform name-mangling */
148 hfs_nameout(dir
, &cname
, dentry
->d_name
.name
, dentry
->d_name
.len
);
151 if (hfs_streq(&cname
, DOT
)) {
152 /* this little trick skips the iget and iput */
157 /* Check for "..". */
158 if (hfs_streq(&cname
, DOT_DOT
)) {
159 inode
= hfs_iget(hfs_cat_parent(entry
), HFS_DBL_DIR
, dentry
);
163 /* Check for "%RootInfo" if in the root directory. */
164 if ((entry
->cnid
== htonl(HFS_ROOT_CNID
)) &&
165 hfs_streq(&cname
, PCNT_ROOTINFO
)) {
166 ++entry
->count
; /* __hfs_iget() eats one */
167 inode
= hfs_iget(entry
, HFS_DBL_HDR
, dentry
);
171 /* Do an hfs_iget() on the mangled name. */
172 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
173 inode
= hfs_iget(hfs_cat_get(entry
->mdb
, &key
), HFS_DBL_NORM
, dentry
);
175 /* Try as a header if not found and first character is '%' */
176 if (!inode
&& (dentry
->d_name
.name
[0] == '%')) {
177 hfs_nameout(dir
, &cname
, dentry
->d_name
.name
+1,
178 dentry
->d_name
.len
-1);
179 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
180 inode
= hfs_iget(hfs_cat_get(entry
->mdb
, &key
),
181 HFS_DBL_HDR
, dentry
);
185 d_add(dentry
, inode
);
192 * This is the readdir() entry in the file_operations structure for
193 * HFS directories in the AppleDouble scheme. The purpose is to
194 * enumerate the entries in a directory, given the inode of the
195 * directory and a (struct file *), the 'f_pos' field of which
196 * indicates the location in the directory. The (struct file *) is
197 * updated so that the next call with the same 'dir' and 'filp'
198 * arguments will produce the next directory entry. The entries are
199 * returned in 'dirent', which is "filled-in" by calling filldir().
200 * This allows the same readdir() function be used for different
201 * formats. We try to read in as many entries as we can before
202 * filldir() refuses to take any more.
204 * XXX: In the future it may be a good idea to consider not generating
205 * metadata files for covered directories since the data doesn't
206 * correspond to the mounted directory. However this requires an
207 * iget() for every directory which could be considered an excessive
208 * amount of overhead. Since the inode for a mount point is always
209 * in-core this is another argument for a call to get an inode if it
210 * is in-core or NULL if it is not.
212 static int dbl_readdir(struct file
* filp
,
213 void * dirent
, filldir_t filldir
)
215 struct hfs_brec brec
;
216 struct hfs_cat_entry
*entry
;
217 struct inode
*dir
= filp
->f_dentry
->d_inode
;
219 if (!dir
|| !dir
->i_sb
|| !S_ISDIR(dir
->i_mode
)) {
223 entry
= HFS_I(dir
)->entry
;
225 if (filp
->f_pos
== 0) {
226 /* Entry 0 is for "." */
227 if (filldir(dirent
, DOT
->Name
, DOT_LEN
, 0, dir
->i_ino
)) {
233 if (filp
->f_pos
== 1) {
234 /* Entry 1 is for ".." */
235 if (filldir(dirent
, DOT_DOT
->Name
, DOT_DOT_LEN
, 1,
236 hfs_get_hl(entry
->key
.ParID
))) {
242 if (filp
->f_pos
< (dir
->i_size
- 1)) {
246 if (hfs_cat_open(entry
, &brec
) ||
247 hfs_cat_next(entry
, &brec
, (filp
->f_pos
- 1) >> 1,
252 while (filp
->f_pos
< (dir
->i_size
- 1)) {
253 unsigned char tmp_name
[HFS_NAMEMAX
+ 1];
255 int is_hdr
= (filp
->f_pos
& 1);
259 ino
= ntohl(cnid
) | HFS_DBL_HDR
;
261 len
= 1 + hfs_namein(dir
, tmp_name
+ 1,
262 &((struct hfs_cat_key
*)brec
.key
)->CName
);
264 if (hfs_cat_next(entry
, &brec
, 1,
269 len
= hfs_namein(dir
, tmp_name
,
270 &((struct hfs_cat_key
*)brec
.key
)->CName
);
273 if (filldir(dirent
, tmp_name
, len
, filp
->f_pos
, ino
)) {
274 hfs_cat_close(entry
, &brec
);
279 hfs_cat_close(entry
, &brec
);
282 if (filp
->f_pos
== (dir
->i_size
- 1)) {
283 if (entry
->cnid
== htonl(HFS_ROOT_CNID
)) {
284 /* In root dir last entry is for "%RootInfo" */
285 if (filldir(dirent
, PCNT_ROOTINFO
->Name
,
286 PCNT_ROOTINFO_LEN
, filp
->f_pos
,
287 ntohl(entry
->cnid
) | HFS_DBL_HDR
)) {
300 * This is the create() entry in the inode_operations structure for
301 * AppleDouble directories. The purpose is to create a new file in
302 * a directory and return a corresponding inode, given the inode for
303 * the directory and the name (and its length) of the new file.
305 static int dbl_create(struct inode
* dir
, struct dentry
*dentry
,
310 if (is_hdr(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
)) {
313 error
= hfs_create(dir
, dentry
, mode
);
321 * This is the mkdir() entry in the inode_operations structure for
322 * AppleDouble directories. The purpose is to create a new directory
323 * in a directory, given the inode for the parent directory and the
324 * name (and its length) of the new directory.
326 static int dbl_mkdir(struct inode
* parent
, struct dentry
*dentry
,
331 if (is_hdr(parent
, dentry
->d_name
.name
, dentry
->d_name
.len
)) {
334 error
= hfs_mkdir(parent
, dentry
, mode
);
342 * This is the mknod() entry in the inode_operations structure for
343 * regular HFS directories. The purpose is to create a new entry
344 * in a directory, given the inode for the parent directory and the
345 * name (and its length) and the mode of the new entry (and the device
346 * number if the entry is to be a device special file).
348 static int dbl_mknod(struct inode
*dir
, struct dentry
*dentry
,
353 if (is_hdr(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
)) {
356 error
= hfs_mknod(dir
, dentry
, mode
, rdev
);
364 * This is the unlink() entry in the inode_operations structure for
365 * AppleDouble directories. The purpose is to delete an existing
366 * file, given the inode for the parent directory and the name
367 * (and its length) of the existing file.
369 static int dbl_unlink(struct inode
* dir
, struct dentry
*dentry
)
373 error
= hfs_unlink(dir
, dentry
);
374 if ((error
== -ENOENT
) && is_hdr(dir
, dentry
->d_name
.name
,
375 dentry
->d_name
.len
)) {
384 * This is the rmdir() entry in the inode_operations structure for
385 * AppleDouble directories. The purpose is to delete an existing
386 * directory, given the inode for the parent directory and the name
387 * (and its length) of the existing directory.
389 static int dbl_rmdir(struct inode
* parent
, struct dentry
*dentry
)
393 error
= hfs_rmdir(parent
, dentry
);
394 if ((error
== -ENOENT
) && is_hdr(parent
, dentry
->d_name
.name
,
395 dentry
->d_name
.len
)) {
404 * This is the rename() entry in the inode_operations structure for
405 * AppleDouble directories. The purpose is to rename an existing
406 * file or directory, given the inode for the current directory and
407 * the name (and its length) of the existing file/directory and the
408 * inode for the new directory and the name (and its length) of the
409 * new file/directory.
411 * XXX: how do we handle must_be_dir?
413 static int dbl_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
414 struct inode
*new_dir
, struct dentry
*new_dentry
)
418 if (is_hdr(new_dir
, new_dentry
->d_name
.name
,
419 new_dentry
->d_name
.len
)) {
422 error
= hfs_rename(old_dir
, old_dentry
,
423 new_dir
, new_dentry
);
424 if ((error
== -ENOENT
) /*&& !must_be_dir*/ &&
425 is_hdr(old_dir
, old_dentry
->d_name
.name
,
426 old_dentry
->d_name
.len
)) {
434 /* due to the dcache caching negative dentries for non-existent files,
435 * we need to drop those entries when a file silently gets created.
436 * as far as i can tell, the calls that need to do this are the file
437 * related calls (create, rename, and mknod). the directory calls
438 * should be immune. the relevant calls in dir.c call drop_dentry
439 * upon successful completion. */
440 void hfs_dbl_drop_dentry(struct dentry
*dentry
, const ino_t type
)
442 unsigned char tmp_name
[HFS_NAMEMAX
+ 1];
443 struct dentry
*de
= NULL
;
447 /* given %name, look for name. i don't think this happens. */
448 de
= hfs_lookup_dentry(dentry
->d_name
.name
+ 1, dentry
->d_name
.len
- 1,
452 /* given name, look for %name */
454 strncpy(tmp_name
+ 1, dentry
->d_name
.name
, HFS_NAMELEN
- 1);
455 de
= hfs_lookup_dentry(tmp_name
, dentry
->d_name
.len
+ 1,