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 directory-related functions independent of which
8 * scheme is being used to represent forks.
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 /*================ File-local functions ================*/
29 * Build a key for a file by the given name in the given directory.
30 * If the name matches one of the reserved names returns 1 otherwise 0.
32 static int build_key(struct hfs_cat_key
*key
, struct inode
*dir
,
33 const char *name
, int len
)
35 struct hfs_name cname
;
36 const struct hfs_name
*reserved
;
39 hfs_nameout(dir
, &cname
, name
, len
);
41 /* check against reserved names */
42 reserved
= HFS_SB(dir
->i_sb
)->s_reserved1
;
43 while (reserved
->Len
) {
44 if (hfs_streq(reserved
->Name
, reserved
->Len
,
45 cname
.Name
, cname
.Len
)) {
51 /* check against the names reserved only in the root directory */
52 if (HFS_I(dir
)->entry
->cnid
== htonl(HFS_ROOT_CNID
)) {
53 reserved
= HFS_SB(dir
->i_sb
)->s_reserved2
;
54 while (reserved
->Len
) {
55 if (hfs_streq(reserved
->Name
, reserved
->Len
,
56 cname
.Name
, cname
.Len
)) {
64 hfs_cat_build_key(HFS_I(dir
)->entry
->cnid
, &cname
, key
);
72 * Update the fields 'i_size', 'i_nlink', 'i_ctime', 'i_mtime' and
73 * 'i_version' of the inodes associated with a directory that has
74 * had a file ('is_dir'==0) or directory ('is_dir'!=0) added to it.
76 static inline void update_dirs_plus(struct hfs_cat_entry
*dir
, int is_dir
)
80 for (i
= 0; i
< 4; ++i
) {
81 struct dentry
*de
= dir
->sys_entry
[i
];
83 struct inode
*tmp
= de
->d_inode
;
84 if (S_ISDIR(tmp
->i_mode
)) {
86 (i
== HFS_ITYPE_TO_INT(HFS_ITYPE_NORM
))) {
87 /* In "normal" directory only */
90 tmp
->i_size
+= HFS_I(tmp
)->dir_size
;
91 tmp
->i_version
= ++event
;
93 tmp
->i_ctime
= tmp
->i_mtime
= CURRENT_TIME
;
94 mark_inode_dirty(tmp
);
100 * update_dirs_minus()
102 * Update the fields 'i_size', 'i_nlink', 'i_ctime', 'i_mtime' and
103 * 'i_version' of the inodes associated with a directory that has
104 * had a file ('is_dir'==0) or directory ('is_dir'!=0) removed.
106 static inline void update_dirs_minus(struct hfs_cat_entry
*dir
, int is_dir
)
110 for (i
= 0; i
< 4; ++i
) {
111 struct dentry
*de
= dir
->sys_entry
[i
];
113 struct inode
*tmp
= de
->d_inode
;
114 if (S_ISDIR(tmp
->i_mode
)) {
116 (i
== HFS_ITYPE_TO_INT(HFS_ITYPE_NORM
))) {
117 /* In "normal" directory only */
120 tmp
->i_size
-= HFS_I(tmp
)->dir_size
;
121 tmp
->i_version
= ++event
;
123 tmp
->i_ctime
= tmp
->i_mtime
= CURRENT_TIME
;
124 mark_inode_dirty(tmp
);
130 * mark_inodes_deleted()
132 * Update inodes associated with a deleted entry to reflect its deletion.
133 * Well, we really just drop the dentry.
135 * XXX: we should be using delete_inode for some of this stuff.
137 static inline void mark_inodes_deleted(struct hfs_cat_entry
*entry
,
138 struct dentry
*dentry
)
144 for (i
= 0; i
< 4; ++i
) {
145 if ((de
= entry
->sys_entry
[i
]) && (dentry
!= de
)) {
149 tmp
->i_ctime
= CURRENT_TIME
;
150 mark_inode_dirty(tmp
);
157 /*================ Global functions ================*/
162 * This is the read() entry in the file_operations structure for HFS
163 * directories. It simply returns an error code, since reading is not
166 hfs_rwret_t
hfs_dir_read(struct file
* filp
, char *buf
,
167 hfs_rwarg_t count
, loff_t
*ppos
)
175 * This is the create() entry in the inode_operations structure for
176 * regular HFS directories. The purpose is to create a new file in
177 * a directory and return a corresponding inode, given the inode for
178 * the directory and the name (and its length) of the new file.
180 int hfs_create(struct inode
* dir
, struct dentry
*dentry
, int mode
)
182 struct hfs_cat_entry
*entry
= HFS_I(dir
)->entry
;
183 struct hfs_cat_entry
*new;
184 struct hfs_cat_key key
;
188 /* build the key, checking against reserved names */
189 if (build_key(&key
, dir
, dentry
->d_name
.name
, dentry
->d_name
.len
))
192 if ((error
= hfs_cat_create(entry
, &key
,
193 (mode
& S_IWUSR
) ? 0 : HFS_FIL_LOCK
,
194 HFS_SB(dir
->i_sb
)->s_type
,
195 HFS_SB(dir
->i_sb
)->s_creator
, &new)))
198 /* create an inode for the new file. back out if we run
200 new->count
++; /* hfs_iget() eats one */
201 if (!(inode
= hfs_iget(new, HFS_I(dir
)->file_type
, dentry
))) {
202 hfs_cat_delete(entry
, new, 1);
208 update_dirs_plus(entry
, 0);
209 /* toss any relevant negative dentries */
210 if (HFS_I(dir
)->d_drop_op
)
211 HFS_I(dir
)->d_drop_op(dentry
, HFS_I(dir
)->file_type
);
212 mark_inode_dirty(inode
);
213 d_instantiate(dentry
, inode
);
220 * This is the mkdir() entry in the inode_operations structure for
221 * regular HFS directories. The purpose is to create a new directory
222 * in a directory, given the inode for the parent directory and the
223 * name (and its length) of the new directory.
225 int hfs_mkdir(struct inode
* parent
, struct dentry
*dentry
, int mode
)
227 struct hfs_cat_entry
*entry
= HFS_I(parent
)->entry
;
228 struct hfs_cat_entry
*new;
229 struct hfs_cat_key key
;
233 /* build the key, checking against reserved names */
234 if (build_key(&key
, parent
, dentry
->d_name
.name
,
238 /* try to create the directory */
239 if ((error
= hfs_cat_mkdir(entry
, &key
, &new)))
242 /* back out if we run into trouble */
243 new->count
++; /* hfs_iget eats one */
244 if (!(inode
= hfs_iget(new, HFS_I(parent
)->file_type
, dentry
))) {
245 hfs_cat_delete(entry
, new, 1);
251 update_dirs_plus(entry
, 1);
252 mark_inode_dirty(inode
);
253 d_instantiate(dentry
, inode
);
260 * This is the unlink() entry in the inode_operations structure for
261 * regular HFS directories. The purpose is to delete an existing
262 * file, given the inode for the parent directory and the name
263 * (and its length) of the existing file.
265 int hfs_unlink(struct inode
* dir
, struct dentry
*dentry
)
267 struct hfs_cat_entry
*entry
= HFS_I(dir
)->entry
;
268 struct hfs_cat_entry
*victim
= NULL
;
269 struct hfs_cat_key key
;
272 if (build_key(&key
, dir
, dentry
->d_name
.name
,
276 if (!(victim
= hfs_cat_get(entry
->mdb
, &key
)))
280 if (victim
->type
!= HFS_CDR_FIL
)
283 if (!(error
= hfs_cat_delete(entry
, victim
, 1))) {
284 struct inode
*inode
= dentry
->d_inode
;
286 mark_inodes_deleted(victim
, dentry
);
288 inode
->i_ctime
= CURRENT_TIME
;
289 mark_inode_dirty(inode
);
291 update_dirs_minus(entry
, 0);
295 hfs_cat_put(victim
); /* Note that hfs_cat_put(NULL) is safe. */
302 * This is the rmdir() entry in the inode_operations structure for
303 * regular HFS directories. The purpose is to delete an existing
304 * directory, given the inode for the parent directory and the name
305 * (and its length) of the existing directory.
307 int hfs_rmdir(struct inode
* parent
, struct dentry
*dentry
)
309 struct hfs_cat_entry
*entry
= HFS_I(parent
)->entry
;
310 struct hfs_cat_entry
*victim
= NULL
;
311 struct inode
*inode
= dentry
->d_inode
;
312 struct hfs_cat_key key
;
315 if (build_key(&key
, parent
, dentry
->d_name
.name
,
319 if (!(victim
= hfs_cat_get(entry
->mdb
, &key
)))
323 if (victim
->type
!= HFS_CDR_DIR
)
327 if (!list_empty(&dentry
->d_hash
))
330 if (/* we only have to worry about 2 and 3 for mount points */
331 (victim
->sys_entry
[2] &&
332 (victim
->sys_entry
[2]->d_mounts
!=
333 victim
->sys_entry
[2]->d_covers
)) ||
334 (victim
->sys_entry
[3] &&
335 (victim
->sys_entry
[3]->d_mounts
!=
336 victim
->sys_entry
[3]->d_covers
))
341 if ((error
= hfs_cat_delete(entry
, victim
, 1)))
344 mark_inodes_deleted(victim
, dentry
);
346 inode
->i_ctime
= CURRENT_TIME
;
347 mark_inode_dirty(inode
);
349 update_dirs_minus(entry
, 1);
352 hfs_cat_put(victim
); /* Note that hfs_cat_put(NULL) is safe. */
359 * This is the rename() entry in the inode_operations structure for
360 * regular HFS directories. The purpose is to rename an existing
361 * file or directory, given the inode for the current directory and
362 * the name (and its length) of the existing file/directory and the
363 * inode for the new directory and the name (and its length) of the
364 * new file/directory.
365 * XXX: how do you handle must_be dir?
367 int hfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
368 struct inode
*new_dir
, struct dentry
*new_dentry
)
370 struct hfs_cat_entry
*old_parent
= HFS_I(old_dir
)->entry
;
371 struct hfs_cat_entry
*new_parent
= HFS_I(new_dir
)->entry
;
372 struct hfs_cat_entry
*victim
= NULL
;
373 struct hfs_cat_entry
*deleted
;
374 struct hfs_cat_key key
;
377 if (build_key(&key
, old_dir
, old_dentry
->d_name
.name
,
378 old_dentry
->d_name
.len
) ||
379 (HFS_ITYPE(old_dir
->i_ino
) != HFS_ITYPE(new_dir
->i_ino
)))
382 if (!(victim
= hfs_cat_get(old_parent
->mdb
, &key
)))
386 if (build_key(&key
, new_dir
, new_dentry
->d_name
.name
,
387 new_dentry
->d_name
.len
))
390 if (!(error
= hfs_cat_move(old_parent
, new_parent
,
391 victim
, &key
, &deleted
))) {
392 int is_dir
= (victim
->type
== HFS_CDR_DIR
);
394 /* drop the old dentries */
395 mark_inodes_deleted(victim
, old_dentry
);
396 update_dirs_minus(old_parent
, is_dir
);
398 mark_inodes_deleted(deleted
, new_dentry
);
399 hfs_cat_put(deleted
);
401 /* no existing inodes. just drop negative dentries */
402 if (HFS_I(new_dir
)->d_drop_op
)
403 HFS_I(new_dir
)->d_drop_op(new_dentry
,
404 HFS_I(new_dir
)->file_type
);
405 update_dirs_plus(new_parent
, is_dir
);
411 hfs_cat_put(victim
); /* Note that hfs_cat_put(NULL) is safe. */