* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / fs / hfs / inode.c
blob8fde9117d83dcb20ebdc644599668825b2b6ec4b
1 /*
2 * linux/fs/hfs/inode.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 inode-related functions which do not depend on
8 * which 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.
19 #include "hfs.h"
20 #include <linux/hfs_fs_sb.h>
21 #include <linux/hfs_fs_i.h>
22 #include <linux/hfs_fs.h>
24 /*================ Variable-like macros ================*/
26 #define HFS_VALID_MODE_BITS (S_IFREG | S_IFDIR | S_IRWXUGO)
28 /*================ File-local functions ================*/
31 * init_file_inode()
33 * Given an HFS catalog entry initialize an inode for a file.
35 static void init_file_inode(struct inode *inode, hfs_u8 fork)
37 struct hfs_fork *fk;
38 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
40 if (!IS_NOEXEC(inode) && (fork == HFS_FK_DATA)) {
41 inode->i_mode = S_IRWXUGO | S_IFREG;
42 } else {
43 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
46 if (fork == HFS_FK_DATA) {
47 hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType);
49 fk = &entry->u.file.data_fork;
50 HFS_I(inode)->convert =
51 ((HFS_SB(inode->i_sb)->s_conv == 't') ||
52 ((HFS_SB(inode->i_sb)->s_conv == 'a') &&
53 ((type == htonl(0x54455854)) || /* "TEXT" */
54 (type == htonl(0x7474726f))))); /* "ttro" */
55 } else {
56 fk = &entry->u.file.rsrc_fork;
57 HFS_I(inode)->convert = 0;
59 HFS_I(inode)->fork = fk;
60 inode->i_size = fk->lsize;
61 inode->i_blocks = fk->psize;
62 inode->i_nlink = 1;
65 /*================ Global functions ================*/
68 * hfs_put_inode()
70 * This is the put_inode() entry in the super_operations for HFS
71 * filesystems. The purpose is to perform any filesystem-dependent
72 * cleanup necessary when the use-count of an inode falls to zero.
74 void hfs_put_inode(struct inode * inode)
76 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
78 hfs_cat_put(entry);
79 if (inode->i_count == 1) {
80 struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
82 if (tmp) {
83 HFS_I(inode)->layout = NULL;
84 HFS_DELETE(tmp);
90 * hfs_notify_change()
92 * Based very closely on fs/msdos/inode.c by Werner Almesberger
94 * This is the notify_change() field in the super_operations structure
95 * for HFS file systems. The purpose is to take that changes made to
96 * an inode and apply then in a filesystem-dependent manner. In this
97 * case the process has a few of tasks to do:
98 * 1) prevent changes to the i_uid and i_gid fields.
99 * 2) map file permissions to the closest allowable permissions
100 * 3) Since multiple Linux files can share the same on-disk inode under
101 * HFS (for instance the data and resource forks of a file) a change
102 * to permissions must be applied to all other in-core inodes which
103 * correspond to the same HFS file.
105 int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
107 struct inode *inode = dentry->d_inode;
108 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
109 struct dentry **de = entry->sys_entry;
110 struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
111 int error, i;
113 error = inode_change_ok(inode, attr); /* basic permission checks */
114 if (error) {
115 /* Let netatalk's afpd think chmod() always succeeds */
116 if (hsb->s_afpd &&
117 (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
118 return 0;
119 } else {
120 return error;
124 /* no uig/gid changes and limit which mode bits can be set */
125 if (((attr->ia_valid & ATTR_UID) &&
126 (attr->ia_uid != hsb->s_uid)) ||
127 ((attr->ia_valid & ATTR_GID) &&
128 (attr->ia_gid != hsb->s_gid)) ||
129 ((attr->ia_valid & ATTR_MODE) &&
130 (((entry->type == HFS_CDR_DIR) &&
131 (attr->ia_mode != inode->i_mode))||
132 (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
133 return hsb->s_quiet ? 0 : error;
136 if (entry->type == HFS_CDR_DIR) {
137 attr->ia_valid &= ~ATTR_MODE;
138 } else if (attr->ia_valid & ATTR_MODE) {
139 /* Only the 'w' bits can ever change and only all together. */
140 if (attr->ia_mode & S_IWUSR) {
141 attr->ia_mode = inode->i_mode | S_IWUGO;
142 } else {
143 attr->ia_mode = inode->i_mode & ~S_IWUGO;
145 attr->ia_mode &= ~hsb->s_umask;
147 inode_setattr(inode, attr);
149 /* We wouldn't want to mess with the sizes of the other fork */
150 attr->ia_valid &= ~ATTR_SIZE;
152 /* We must change all in-core inodes corresponding to this file. */
153 for (i = 0; i < 4; ++i) {
154 if (de[i] && (de[i] != dentry)) {
155 inode_setattr(de[i]->d_inode, attr);
159 /* Change the catalog entry if needed */
160 if (attr->ia_valid & ATTR_MTIME) {
161 entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
162 hfs_cat_mark_dirty(entry);
164 if (attr->ia_valid & ATTR_MODE) {
165 hfs_u8 new_flags;
167 if (inode->i_mode & S_IWUSR) {
168 new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
169 } else {
170 new_flags = entry->u.file.flags | HFS_FIL_LOCK;
173 if (new_flags != entry->u.file.flags) {
174 entry->u.file.flags = new_flags;
175 hfs_cat_mark_dirty(entry);
178 /* size changes handled in hfs_extent_adj() */
180 return 0;
184 * __hfs_iget()
186 * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
187 * the catalog B-tree and the 'type' of the desired file return the
188 * inode for that file/directory or NULL. Note that 'type' indicates
189 * whether we want the actual file or directory, or the corresponding
190 * metadata (AppleDouble header file or CAP metadata file).
192 * In an ideal world we could call iget() and would not need this
193 * function. However, since there is no way to even know the inode
194 * number until we've found the file/directory in the catalog B-tree
195 * that simply won't happen.
197 * The main idea here is to look in the catalog B-tree to get the
198 * vital info about the file or directory (including the file id which
199 * becomes the inode number) and then to call iget() and return the
200 * inode if it is complete. If it is not then we use the catalog
201 * entry to fill in the missing info, by calling the appropriate
202 * 'fillin' function. Note that these fillin functions are
203 * essentially hfs_*_read_inode() functions, but since there is no way
204 * to pass the catalog entry through iget() to such a read_inode()
205 * function, we have to call them after iget() returns an incomplete
206 * inode to us. This is pretty much the same problem faced in the NFS
207 * code, and pretty much the same solution. The SMB filesystem deals
208 * with this in a different way: by using the address of the
209 * kmalloc()'d space which holds the data as the inode number.
211 * XXX: Both this function and NFS's corresponding nfs_fhget() would
212 * benefit from a way to pass an additional (void *) through iget() to
213 * the VFS read_inode() function.
215 * this will hfs_cat_put() the entry if it fails.
217 struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
218 struct dentry *dentry)
220 struct dentry **sys_entry;
221 struct super_block *sb;
222 struct inode *inode;
224 if (!entry) {
225 return NULL;
228 /* If there are several processes all calling __iget() for
229 the same inode then they will all get the same one back.
230 The first one to return from __iget() will notice that the
231 i_mode field of the inode is blank and KNOW that it is
232 the first to return. Therefore, it will set the appropriate
233 'sys_entry' field in the entry and initialize the inode.
234 All the initialization must be done without sleeping,
235 or else other processes could end up using a partially
236 initialized inode. */
238 sb = entry->mdb->sys_mdb;
239 sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
241 if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
242 hfs_cat_put(entry);
243 return NULL;
246 if (inode->i_dev != sb->s_dev) {
247 iput(inode); /* automatically does an hfs_cat_put */
248 inode = NULL;
249 } else if (!inode->i_mode || (*sys_entry == NULL)) {
250 /* Initialize the inode */
251 struct hfs_sb_info *hsb = HFS_SB(sb);
253 inode->i_rdev = 0;
254 inode->i_ctime = inode->i_atime = inode->i_mtime =
255 hfs_m_to_utime(entry->modify_date);
256 inode->i_blksize = HFS_SECTOR_SIZE;
257 inode->i_uid = hsb->s_uid;
258 inode->i_gid = hsb->s_gid;
260 memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
261 HFS_I(inode)->magic = HFS_INO_MAGIC;
262 HFS_I(inode)->entry = entry;
263 HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
265 hsb->s_ifill(inode, type, hsb->s_version);
266 if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
267 (entry->u.file.flags & HFS_FIL_LOCK)) {
268 inode->i_mode &= ~S_IWUGO;
270 inode->i_mode &= ~hsb->s_umask;
272 if (!inode->i_mode) {
273 iput(inode); /* does an hfs_cat_put */
274 inode = NULL;
275 } else
276 *sys_entry = dentry; /* cache dentry */
280 return inode;
283 /*================ Scheme-specific functions ================*/
286 * hfs_cap_ifill()
288 * This function serves the same purpose as a read_inode() function does
289 * in other filesystems. It is called by __hfs_iget() to fill in
290 * the missing fields of an uninitialized inode under the CAP scheme.
292 void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
294 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
296 HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
297 if (type == HFS_CAP_FNDR) {
298 inode->i_size = sizeof(struct hfs_cap_info);
299 inode->i_blocks = 0;
300 inode->i_nlink = 1;
301 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
302 inode->i_op = &hfs_cap_info_inode_operations;
303 } else if (entry->type == HFS_CDR_FIL) {
304 init_file_inode(inode, (type == HFS_CAP_DATA) ?
305 HFS_FK_DATA : HFS_FK_RSRC);
306 inode->i_op = &hfs_file_inode_operations;
307 } else { /* Directory */
308 struct hfs_dir *hdir = &entry->u.dir;
310 inode->i_blocks = 0;
311 inode->i_size = hdir->files + hdir->dirs + 5;
312 HFS_I(inode)->dir_size = 1;
313 if (type == HFS_CAP_NDIR) {
314 inode->i_mode = S_IRWXUGO | S_IFDIR;
315 inode->i_nlink = hdir->dirs + 4;
316 inode->i_op = &hfs_cap_ndir_inode_operations;
317 HFS_I(inode)->file_type = HFS_CAP_NORM;
318 } else if (type == HFS_CAP_FDIR) {
319 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
320 inode->i_nlink = 2;
321 inode->i_op = &hfs_cap_fdir_inode_operations;
322 HFS_I(inode)->file_type = HFS_CAP_FNDR;
323 } else if (type == HFS_CAP_RDIR) {
324 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
325 inode->i_nlink = 2;
326 inode->i_op = &hfs_cap_rdir_inode_operations;
327 HFS_I(inode)->file_type = HFS_CAP_RSRC;
333 * hfs_dbl_ifill()
335 * This function serves the same purpose as a read_inode() function does
336 * in other filesystems. It is called by __hfs_iget() to fill in
337 * the missing fields of an uninitialized inode under the AppleDouble
338 * scheme.
340 void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
342 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
344 HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
345 if (type == HFS_DBL_HDR) {
346 if (entry->type == HFS_CDR_FIL) {
347 init_file_inode(inode, HFS_FK_RSRC);
348 inode->i_size += HFS_DBL_HDR_LEN;
349 HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
350 } else {
351 inode->i_size = HFS_DBL_HDR_LEN;
352 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
353 inode->i_nlink = 1;
354 HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
356 inode->i_op = &hfs_hdr_inode_operations;
357 } else if (entry->type == HFS_CDR_FIL) {
358 init_file_inode(inode, HFS_FK_DATA);
359 inode->i_op = &hfs_file_inode_operations;
360 } else { /* Directory */
361 struct hfs_dir *hdir = &entry->u.dir;
363 inode->i_blocks = 0;
364 inode->i_nlink = hdir->dirs + 2;
365 inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
366 inode->i_mode = S_IRWXUGO | S_IFDIR;
367 inode->i_op = &hfs_dbl_dir_inode_operations;
368 HFS_I(inode)->file_type = HFS_DBL_NORM;
369 HFS_I(inode)->dir_size = 2;
374 * hfs_nat_ifill()
376 * This function serves the same purpose as a read_inode() function does
377 * in other filesystems. It is called by __hfs_iget() to fill in
378 * the missing fields of an uninitialized inode under the Netatalk
379 * scheme.
381 void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
383 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
385 HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
386 if (type == HFS_NAT_HDR) {
387 if (entry->type == HFS_CDR_FIL) {
388 init_file_inode(inode, HFS_FK_RSRC);
389 inode->i_size += HFS_NAT_HDR_LEN;
390 } else {
391 inode->i_size = HFS_NAT_HDR_LEN;
392 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
393 inode->i_nlink = 1;
395 inode->i_op = &hfs_hdr_inode_operations;
396 HFS_I(inode)->default_layout = (version == 2) ?
397 &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
398 } else if (entry->type == HFS_CDR_FIL) {
399 init_file_inode(inode, HFS_FK_DATA);
400 inode->i_op = &hfs_file_inode_operations;
401 } else { /* Directory */
402 struct hfs_dir *hdir = &entry->u.dir;
404 inode->i_blocks = 0;
405 inode->i_size = hdir->files + hdir->dirs + 4;
406 inode->i_mode = S_IRWXUGO | S_IFDIR;
407 HFS_I(inode)->dir_size = 1;
408 if (type == HFS_NAT_NDIR) {
409 inode->i_nlink = hdir->dirs + 3;
410 inode->i_op = &hfs_nat_ndir_inode_operations;
411 HFS_I(inode)->file_type = HFS_NAT_NORM;
412 } else if (type == HFS_NAT_HDIR) {
413 inode->i_nlink = 2;
414 inode->i_op = &hfs_nat_hdir_inode_operations;
415 HFS_I(inode)->file_type = HFS_NAT_HDR;