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 struct dentry
*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_unlink(struct inode
*, struct dentry
*);
31 static int dbl_rmdir(struct inode
*, struct dentry
*);
32 static int dbl_rename(struct inode
*, struct dentry
*,
33 struct inode
*, struct dentry
*);
35 /*================ Global variables ================*/
39 #define ROOTINFO_LEN 8
40 #define PCNT_ROOTINFO_LEN 9
42 const struct hfs_name hfs_dbl_reserved1
[] = {
48 const struct hfs_name hfs_dbl_reserved2
[] = {
49 {ROOTINFO_LEN
, "RootInfo"},
50 {PCNT_ROOTINFO_LEN
, "%RootInfo"},
54 #define DOT (&hfs_dbl_reserved1[0])
55 #define DOT_DOT (&hfs_dbl_reserved1[1])
56 #define ROOTINFO (&hfs_dbl_reserved2[0])
57 #define PCNT_ROOTINFO (&hfs_dbl_reserved2[1])
59 static struct file_operations hfs_dbl_dir_operations
= {
60 NULL
, /* lseek - default */
61 hfs_dir_read
, /* read - invalid */
62 NULL
, /* write - bad */
63 dbl_readdir
, /* readdir */
64 NULL
, /* select - default */
65 NULL
, /* ioctl - default */
66 NULL
, /* mmap - none */
67 NULL
, /* no special open code */
69 NULL
, /* no special release code */
70 file_fsync
, /* fsync - default */
71 NULL
, /* fasync - default */
72 NULL
, /* check_media_change - none */
73 NULL
/* revalidate - none */
76 struct inode_operations hfs_dbl_dir_inode_operations
= {
77 &hfs_dbl_dir_operations
,/* default directory file-ops */
78 dbl_create
, /* create */
79 dbl_lookup
, /* lookup */
81 dbl_unlink
, /* unlink */
83 dbl_mkdir
, /* mkdir */
84 dbl_rmdir
, /* rmdir */
86 dbl_rename
, /* rename */
88 NULL
, /* follow_link */
94 NULL
, /* permission */
100 /*================ File-local functions ================*/
105 static int is_hdr(struct inode
*dir
, const char *name
, int len
)
109 if (name
[0] == '%') {
110 struct hfs_cat_entry
*entry
= HFS_I(dir
)->entry
;
111 struct hfs_cat_entry
*victim
;
112 struct hfs_name cname
;
113 struct hfs_cat_key key
;
115 hfs_nameout(dir
, &cname
, name
+1, len
-1);
116 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
117 if ((victim
= hfs_cat_get(entry
->mdb
, &key
))) {
128 * This is the lookup() entry in the inode_operations structure for
129 * HFS directories in the AppleDouble scheme. The purpose is to
130 * generate the inode corresponding to an entry in a directory, given
131 * the inode for the directory and the name (and its length) of the
134 static struct dentry
*dbl_lookup(struct inode
* dir
, struct dentry
*dentry
)
136 struct hfs_name cname
;
137 struct hfs_cat_entry
*entry
;
138 struct hfs_cat_key key
;
139 struct inode
*inode
= NULL
;
141 dentry
->d_op
= &hfs_dentry_operations
;
142 entry
= HFS_I(dir
)->entry
;
144 /* Perform name-mangling */
145 hfs_nameout(dir
, &cname
, dentry
->d_name
.name
, dentry
->d_name
.len
);
147 /* no need to check for "." or ".." */
149 /* Check for "%RootInfo" if in the root directory. */
150 if ((entry
->cnid
== htonl(HFS_ROOT_CNID
)) &&
151 hfs_streq(cname
.Name
, cname
.Len
,
152 PCNT_ROOTINFO
->Name
, PCNT_ROOTINFO_LEN
)) {
153 ++entry
->count
; /* __hfs_iget() eats one */
154 inode
= hfs_iget(entry
, HFS_DBL_HDR
, dentry
);
158 /* Do an hfs_iget() on the mangled name. */
159 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
160 inode
= hfs_iget(hfs_cat_get(entry
->mdb
, &key
), HFS_DBL_NORM
, dentry
);
162 /* Try as a header if not found and first character is '%' */
163 if (!inode
&& (dentry
->d_name
.name
[0] == '%')) {
164 hfs_nameout(dir
, &cname
, dentry
->d_name
.name
+1,
165 dentry
->d_name
.len
-1);
166 hfs_cat_build_key(entry
->cnid
, &cname
, &key
);
167 inode
= hfs_iget(hfs_cat_get(entry
->mdb
, &key
),
168 HFS_DBL_HDR
, dentry
);
172 d_add(dentry
, inode
);
179 * This is the readdir() entry in the file_operations structure for
180 * HFS directories in the AppleDouble scheme. The purpose is to
181 * enumerate the entries in a directory, given the inode of the
182 * directory and a (struct file *), the 'f_pos' field of which
183 * indicates the location in the directory. The (struct file *) is
184 * updated so that the next call with the same 'dir' and 'filp'
185 * arguments will produce the next directory entry. The entries are
186 * returned in 'dirent', which is "filled-in" by calling filldir().
187 * This allows the same readdir() function be used for different
188 * formats. We try to read in as many entries as we can before
189 * filldir() refuses to take any more.
191 * XXX: In the future it may be a good idea to consider not generating
192 * metadata files for covered directories since the data doesn't
193 * correspond to the mounted directory. However this requires an
194 * iget() for every directory which could be considered an excessive
195 * amount of overhead. Since the inode for a mount point is always
196 * in-core this is another argument for a call to get an inode if it
197 * is in-core or NULL if it is not.
199 static int dbl_readdir(struct file
* filp
,
200 void * dirent
, filldir_t filldir
)
202 struct hfs_brec brec
;
203 struct hfs_cat_entry
*entry
;
204 struct inode
*dir
= filp
->f_dentry
->d_inode
;
206 entry
= HFS_I(dir
)->entry
;
208 if (filp
->f_pos
== 0) {
209 /* Entry 0 is for "." */
210 if (filldir(dirent
, DOT
->Name
, DOT_LEN
, 0, dir
->i_ino
)) {
216 if (filp
->f_pos
== 1) {
217 /* Entry 1 is for ".." */
218 if (filldir(dirent
, DOT_DOT
->Name
, DOT_DOT_LEN
, 1,
219 hfs_get_hl(entry
->key
.ParID
))) {
225 if (filp
->f_pos
< (dir
->i_size
- 1)) {
229 if (hfs_cat_open(entry
, &brec
) ||
230 hfs_cat_next(entry
, &brec
, (filp
->f_pos
- 1) >> 1,
235 while (filp
->f_pos
< (dir
->i_size
- 1)) {
236 unsigned char tmp_name
[HFS_NAMEMAX
+ 1];
238 int is_hdr
= (filp
->f_pos
& 1);
242 ino
= ntohl(cnid
) | HFS_DBL_HDR
;
244 len
= 1 + hfs_namein(dir
, tmp_name
+ 1,
245 &((struct hfs_cat_key
*)brec
.key
)->CName
);
247 if (hfs_cat_next(entry
, &brec
, 1,
252 len
= hfs_namein(dir
, tmp_name
,
253 &((struct hfs_cat_key
*)brec
.key
)->CName
);
256 if (filldir(dirent
, tmp_name
, len
, filp
->f_pos
, ino
)) {
257 hfs_cat_close(entry
, &brec
);
262 hfs_cat_close(entry
, &brec
);
265 if (filp
->f_pos
== (dir
->i_size
- 1)) {
266 if (entry
->cnid
== htonl(HFS_ROOT_CNID
)) {
267 /* In root dir last entry is for "%RootInfo" */
268 if (filldir(dirent
, PCNT_ROOTINFO
->Name
,
269 PCNT_ROOTINFO_LEN
, filp
->f_pos
,
270 ntohl(entry
->cnid
) | HFS_DBL_HDR
)) {
283 * This is the create() entry in the inode_operations structure for
284 * AppleDouble directories. The purpose is to create a new file in
285 * a directory and return a corresponding inode, given the inode for
286 * the directory and the name (and its length) of the new file.
288 static int dbl_create(struct inode
* dir
, struct dentry
*dentry
,
293 if (is_hdr(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
)) {
296 error
= hfs_create(dir
, dentry
, mode
);
304 * This is the mkdir() entry in the inode_operations structure for
305 * AppleDouble directories. The purpose is to create a new directory
306 * in a directory, given the inode for the parent directory and the
307 * name (and its length) of the new directory.
309 static int dbl_mkdir(struct inode
* parent
, struct dentry
*dentry
,
314 if (is_hdr(parent
, dentry
->d_name
.name
, dentry
->d_name
.len
)) {
317 error
= hfs_mkdir(parent
, dentry
, mode
);
325 * This is the unlink() entry in the inode_operations structure for
326 * AppleDouble directories. The purpose is to delete an existing
327 * file, given the inode for the parent directory and the name
328 * (and its length) of the existing file.
330 static int dbl_unlink(struct inode
* dir
, struct dentry
*dentry
)
334 error
= hfs_unlink(dir
, dentry
);
335 if ((error
== -ENOENT
) && is_hdr(dir
, dentry
->d_name
.name
,
336 dentry
->d_name
.len
)) {
345 * This is the rmdir() entry in the inode_operations structure for
346 * AppleDouble directories. The purpose is to delete an existing
347 * directory, given the inode for the parent directory and the name
348 * (and its length) of the existing directory.
350 static int dbl_rmdir(struct inode
* parent
, struct dentry
*dentry
)
354 error
= hfs_rmdir(parent
, dentry
);
355 if ((error
== -ENOENT
) && is_hdr(parent
, dentry
->d_name
.name
,
356 dentry
->d_name
.len
)) {
365 * This is the rename() entry in the inode_operations structure for
366 * AppleDouble directories. The purpose is to rename an existing
367 * file or directory, given the inode for the current directory and
368 * the name (and its length) of the existing file/directory and the
369 * inode for the new directory and the name (and its length) of the
370 * new file/directory.
372 * XXX: how do we handle must_be_dir?
374 static int dbl_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
375 struct inode
*new_dir
, struct dentry
*new_dentry
)
379 if (is_hdr(new_dir
, new_dentry
->d_name
.name
,
380 new_dentry
->d_name
.len
)) {
383 error
= hfs_rename(old_dir
, old_dentry
,
384 new_dir
, new_dentry
);
385 if ((error
== -ENOENT
) /*&& !must_be_dir*/ &&
386 is_hdr(old_dir
, old_dentry
->d_name
.name
,
387 old_dentry
->d_name
.len
)) {
395 /* due to the dcache caching negative dentries for non-existent files,
396 * we need to drop those entries when a file silently gets created.
397 * as far as i can tell, the calls that need to do this are the file
398 * related calls (create, rename, and mknod). the directory calls
399 * should be immune. the relevant calls in dir.c call drop_dentry
400 * upon successful completion. */
401 void hfs_dbl_drop_dentry(struct dentry
*dentry
, const ino_t type
)
403 unsigned char tmp_name
[HFS_NAMEMAX
+ 1];
404 struct dentry
*de
= NULL
;
408 /* given %name, look for name. i don't think this happens. */
409 de
= hfs_lookup_dentry(dentry
->d_parent
,
410 dentry
->d_name
.name
+ 1, dentry
->d_name
.len
- 1);
413 /* given name, look for %name */
415 strncpy(tmp_name
+ 1, dentry
->d_name
.name
, HFS_NAMELEN
- 1);
416 de
= hfs_lookup_dentry(dentry
->d_parent
,
417 tmp_name
, dentry
->d_name
.len
+ 1);