~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/hfs/inode.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/fs/hfs/inode.c
  3  *
  4  * Copyright (C) 1995-1997  Paul H. Hargrove
  5  * This file may be distributed under the terms of the GNU Public License.
  6  *
  7  * This file contains inode-related functions which do not depend on
  8  * which scheme is being used to represent forks.
  9  *
 10  * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
 11  *
 12  * "XXX" in a comment is a note to myself to consider changing something.
 13  *
 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.
 17  */
 18 
 19 #include "hfs.h"
 20 #include <linux/hfs_fs_sb.h>
 21 #include <linux/hfs_fs_i.h>
 22 #include <linux/hfs_fs.h>
 23 #include <linux/smp_lock.h>
 24 
 25 /*================ Variable-like macros ================*/
 26 
 27 #define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
 28 
 29 /*================ File-local functions ================*/
 30 
 31 /*
 32  * init_file_inode()
 33  *
 34  * Given an HFS catalog entry initialize an inode for a file.
 35  */
 36 static void init_file_inode(struct inode *inode, hfs_u8 fork)
 37 {
 38         struct hfs_fork *fk;
 39         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 40 
 41         if (!IS_NOEXEC(inode) && (fork == HFS_FK_DATA)) {
 42                 inode->i_mode = S_IRWXUGO | S_IFREG;
 43         } else {
 44                 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
 45         }
 46 
 47         if (fork == HFS_FK_DATA) {
 48 #if 0 /* XXX: disable crlf translations for now */
 49                 hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType);
 50 
 51                 HFS_I(inode)->convert =
 52                         ((HFS_SB(inode->i_sb)->s_conv == 't') ||
 53                          ((HFS_SB(inode->i_sb)->s_conv == 'a') &&
 54                           ((type == htonl(0x54455854)) ||   /* "TEXT" */
 55                            (type == htonl(0x7474726f)))));  /* "ttro" */
 56 #else
 57                 HFS_I(inode)->convert = 0;
 58 #endif
 59                 fk = &entry->u.file.data_fork;
 60         } else {
 61                 fk = &entry->u.file.rsrc_fork;
 62                 HFS_I(inode)->convert = 0;
 63         }
 64         HFS_I(inode)->fork = fk;
 65         inode->i_size = fk->lsize;
 66         inode->i_blocks = fk->psize;
 67         inode->i_nlink = 1;
 68 }
 69 
 70 /*================ Global functions ================*/
 71 
 72 /*
 73  * hfs_put_inode()
 74  *
 75  * This is the put_inode() entry in the super_operations for HFS
 76  * filesystems.  The purpose is to perform any filesystem-dependent 
 77  * cleanup necessary when the use-count of an inode falls to zero.
 78  */
 79 void hfs_put_inode(struct inode * inode)
 80 {
 81         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 82 
 83         lock_kernel();
 84         hfs_cat_put(entry);
 85         if (atomic_read(&inode->i_count) == 1) {
 86           struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
 87 
 88           if (tmp) {
 89                 HFS_I(inode)->layout = NULL;
 90                 HFS_DELETE(tmp);
 91           }
 92         }
 93         unlock_kernel();
 94 }
 95 
 96 /*
 97  * hfs_notify_change()
 98  *
 99  * Based very closely on fs/msdos/inode.c by Werner Almesberger
100  *
101  * This is the notify_change() field in the super_operations structure
102  * for HFS file systems.  The purpose is to take that changes made to
103  * an inode and apply then in a filesystem-dependent manner.  In this
104  * case the process has a few of tasks to do:
105  *  1) prevent changes to the i_uid and i_gid fields.
106  *  2) map file permissions to the closest allowable permissions
107  *  3) Since multiple Linux files can share the same on-disk inode under
108  *     HFS (for instance the data and resource forks of a file) a change
109  *     to permissions must be applied to all other in-core inodes which 
110  *     correspond to the same HFS file.
111  */
112 enum {HFS_NORM, HFS_HDR, HFS_CAP};
113 
114 static int __hfs_notify_change(struct dentry *dentry, struct iattr * attr, int kind)
115 {
116         struct inode *inode = dentry->d_inode;
117         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
118         struct dentry **de = entry->sys_entry;
119         struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
120         int error, i;
121 
122         error = inode_change_ok(inode, attr); /* basic permission checks */
123         if (error) {
124                 /* Let netatalk's afpd think chmod() always succeeds */
125                 if (hsb->s_afpd &&
126                     (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
127                         return 0;
128                 } else {
129                         return error;
130                 }
131         }
132 
133         /* no uig/gid changes and limit which mode bits can be set */
134         if (((attr->ia_valid & ATTR_UID) && 
135              (attr->ia_uid != hsb->s_uid)) ||
136             ((attr->ia_valid & ATTR_GID) && 
137              (attr->ia_gid != hsb->s_gid)) ||
138             ((attr->ia_valid & ATTR_MODE) &&
139              (((entry->type == HFS_CDR_DIR) &&
140                (attr->ia_mode != inode->i_mode))||
141               (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
142                 return hsb->s_quiet ? 0 : error;
143         }
144         
145         if (entry->type == HFS_CDR_DIR) {
146                 attr->ia_valid &= ~ATTR_MODE;
147         } else if (attr->ia_valid & ATTR_MODE) {
148                 /* Only the 'w' bits can ever change and only all together. */
149                 if (attr->ia_mode & S_IWUSR) {
150                         attr->ia_mode = inode->i_mode | S_IWUGO;
151                 } else {
152                         attr->ia_mode = inode->i_mode & ~S_IWUGO;
153                 }
154                 attr->ia_mode &= ~hsb->s_umask;
155         }
156         /*
157          * Normal files handle size change in normal way.
158          * Oddballs are served here.
159          */
160         if (attr->ia_valid & ATTR_SIZE) {
161                 if (kind == HFS_CAP) {
162                         inode->i_size = attr->ia_size;
163                         if (inode->i_size > HFS_FORK_MAX)
164                                 inode->i_size = HFS_FORK_MAX;
165                         mark_inode_dirty(inode);
166                         attr->ia_valid &= ~ATTR_SIZE;
167                 } else if (kind == HFS_HDR) {
168                         hdr_truncate(inode, attr->ia_size);
169                         attr->ia_valid &= ~ATTR_SIZE;
170                 }
171         }
172         inode_setattr(inode, attr);
173 
174         /* We wouldn't want to mess with the sizes of the other fork */
175         attr->ia_valid &= ~ATTR_SIZE;
176 
177         /* We must change all in-core inodes corresponding to this file. */
178         for (i = 0; i < 4; ++i) {
179           if (de[i] && (de[i] != dentry)) {
180                 inode_setattr(de[i]->d_inode, attr);
181           }
182         }
183 
184         /* Change the catalog entry if needed */
185         if (attr->ia_valid & ATTR_MTIME) {
186                 entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
187                 hfs_cat_mark_dirty(entry);
188         }
189         if (attr->ia_valid & ATTR_MODE) {
190                 hfs_u8 new_flags;
191 
192                 if (inode->i_mode & S_IWUSR) {
193                         new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
194                 } else {
195                         new_flags = entry->u.file.flags | HFS_FIL_LOCK;
196                 }
197 
198                 if (new_flags != entry->u.file.flags) {
199                         entry->u.file.flags = new_flags;
200                         hfs_cat_mark_dirty(entry);
201                 }
202         }
203         /* size changes handled in hfs_extent_adj() */
204 
205         return 0;
206 }
207 
208 int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
209 {
210         return __hfs_notify_change(dentry, attr, HFS_NORM);
211 }
212 
213 int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr)
214 {
215         return __hfs_notify_change(dentry, attr, HFS_CAP);
216 }
217 
218 int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
219 {
220         return __hfs_notify_change(dentry, attr, HFS_HDR);
221 }
222 
223 static int hfs_writepage(struct page *page)
224 {
225         return block_write_full_page(page,hfs_get_block);
226 }
227 static int hfs_readpage(struct file *file, struct page *page)
228 {
229         return block_read_full_page(page,hfs_get_block);
230 }
231 static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
232 {
233         return cont_prepare_write(page,from,to,hfs_get_block,
234                 &page->mapping->host->u.hfs_i.mmu_private);
235 }
236 static int hfs_bmap(struct address_space *mapping, long block)
237 {
238         return generic_block_bmap(mapping,block,hfs_get_block);
239 }
240 struct address_space_operations hfs_aops = {
241         readpage: hfs_readpage,
242         writepage: hfs_writepage,
243         sync_page: block_sync_page,
244         prepare_write: hfs_prepare_write,
245         commit_write: generic_commit_write,
246         bmap: hfs_bmap
247 };
248 
249 /*
250  * __hfs_iget()
251  *
252  * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
253  * the catalog B-tree and the 'type' of the desired file return the
254  * inode for that file/directory or NULL.  Note that 'type' indicates
255  * whether we want the actual file or directory, or the corresponding
256  * metadata (AppleDouble header file or CAP metadata file).
257  *
258  * In an ideal world we could call iget() and would not need this
259  * function.  However, since there is no way to even know the inode
260  * number until we've found the file/directory in the catalog B-tree
261  * that simply won't happen.
262  *
263  * The main idea here is to look in the catalog B-tree to get the
264  * vital info about the file or directory (including the file id which
265  * becomes the inode number) and then to call iget() and return the
266  * inode if it is complete.  If it is not then we use the catalog
267  * entry to fill in the missing info, by calling the appropriate
268  * 'fillin' function.  Note that these fillin functions are
269  * essentially hfs_*_read_inode() functions, but since there is no way
270  * to pass the catalog entry through iget() to such a read_inode()
271  * function, we have to call them after iget() returns an incomplete
272  * inode to us.  This is pretty much the same problem faced in the NFS
273  * code, and pretty much the same solution. The SMB filesystem deals
274  * with this in a different way: by using the address of the
275  * kmalloc()'d space which holds the data as the inode number.
276  *
277  * XXX: Both this function and NFS's corresponding nfs_fhget() would
278  * benefit from a way to pass an additional (void *) through iget() to
279  * the VFS read_inode() function.
280  *
281  * this will hfs_cat_put() the entry if it fails.
282  */
283 struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
284                        struct dentry *dentry)
285 {
286         struct dentry **sys_entry;
287         struct super_block *sb;
288         struct inode *inode;
289 
290         if (!entry) {
291                 return NULL;
292         }
293 
294         /* If there are several processes all calling __iget() for
295            the same inode then they will all get the same one back.
296            The first one to return from __iget() will notice that the
297            i_mode field of the inode is blank and KNOW that it is
298            the first to return.  Therefore, it will set the appropriate
299            'sys_entry' field in the entry and initialize the inode.
300            All the initialization must be done without sleeping,
301            or else other processes could end up using a partially
302            initialized inode.                           */
303 
304         sb = entry->mdb->sys_mdb;
305         sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
306 
307         if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
308                 hfs_cat_put(entry);
309                 return NULL;
310         }
311 
312         if (inode->i_dev != sb->s_dev) {
313                 iput(inode); /* automatically does an hfs_cat_put */
314                 inode = NULL;
315         } else if (!inode->i_mode || (*sys_entry == NULL)) {
316                 /* Initialize the inode */
317                 struct hfs_sb_info *hsb = HFS_SB(sb);
318 
319                 inode->i_rdev = 0;
320                 inode->i_ctime = inode->i_atime = inode->i_mtime =
321                                         hfs_m_to_utime(entry->modify_date);
322                 inode->i_blksize = HFS_SECTOR_SIZE;
323                 inode->i_uid = hsb->s_uid;
324                 inode->i_gid = hsb->s_gid;
325 
326                 memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
327                 HFS_I(inode)->magic = HFS_INO_MAGIC;
328                 HFS_I(inode)->entry = entry;
329                 HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
330 
331                 hsb->s_ifill(inode, type, hsb->s_version);
332                 if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
333                     (entry->u.file.flags & HFS_FIL_LOCK)) {
334                         inode->i_mode &= ~S_IWUGO;
335                 }
336                 inode->i_mode &= ~hsb->s_umask;
337 
338                 if (!inode->i_mode) {
339                         iput(inode); /* does an hfs_cat_put */
340                         inode = NULL;
341                 } else
342                         *sys_entry = dentry; /* cache dentry */
343 
344         }
345 
346         return inode;
347 }
348 
349 /*================ Scheme-specific functions ================*/
350 
351 /* 
352  * hfs_cap_ifill()
353  *
354  * This function serves the same purpose as a read_inode() function does
355  * in other filesystems.  It is called by __hfs_iget() to fill in
356  * the missing fields of an uninitialized inode under the CAP scheme.
357  */
358 void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
359 {
360         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
361 
362         HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
363         if (type == HFS_CAP_FNDR) {
364                 inode->i_size = sizeof(struct hfs_cap_info);
365                 inode->i_blocks = 0;
366                 inode->i_nlink = 1;
367                 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
368                 inode->i_op = &hfs_cap_info_inode_operations;
369                 inode->i_fop = &hfs_cap_info_operations;
370         } else if (entry->type == HFS_CDR_FIL) {
371                 init_file_inode(inode, (type == HFS_CAP_DATA) ?
372                                                 HFS_FK_DATA : HFS_FK_RSRC);
373                 inode->i_op = &hfs_file_inode_operations;
374                 inode->i_fop = &hfs_file_operations;
375                 inode->i_mapping->a_ops = &hfs_aops;
376                 inode->u.hfs_i.mmu_private = inode->i_size;
377         } else { /* Directory */
378                 struct hfs_dir *hdir = &entry->u.dir;
379 
380                 inode->i_blocks = 0;
381                 inode->i_size = hdir->files + hdir->dirs + 5;
382                 HFS_I(inode)->dir_size = 1;
383                 if (type == HFS_CAP_NDIR) {
384                         inode->i_mode = S_IRWXUGO | S_IFDIR;
385                         inode->i_nlink = hdir->dirs + 4;
386                         inode->i_op = &hfs_cap_ndir_inode_operations;
387                         inode->i_fop = &hfs_cap_dir_operations;
388                         HFS_I(inode)->file_type = HFS_CAP_NORM;
389                 } else if (type == HFS_CAP_FDIR) {
390                         inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
391                         inode->i_nlink = 2;
392                         inode->i_op = &hfs_cap_fdir_inode_operations;
393                         inode->i_fop = &hfs_cap_dir_operations;
394                         HFS_I(inode)->file_type = HFS_CAP_FNDR;
395                 } else if (type == HFS_CAP_RDIR) {
396                         inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
397                         inode->i_nlink = 2;
398                         inode->i_op = &hfs_cap_rdir_inode_operations;
399                         inode->i_fop = &hfs_cap_dir_operations;
400                         HFS_I(inode)->file_type = HFS_CAP_RSRC;
401                 }
402         }
403 }
404 
405 /* 
406  * hfs_dbl_ifill()
407  *
408  * This function serves the same purpose as a read_inode() function does
409  * in other filesystems.  It is called by __hfs_iget() to fill in
410  * the missing fields of an uninitialized inode under the AppleDouble
411  * scheme.
412  */
413 void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
414 {
415         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
416 
417         HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
418         if (type == HFS_DBL_HDR) {
419                 if (entry->type == HFS_CDR_FIL) {
420                         init_file_inode(inode, HFS_FK_RSRC);
421                         inode->i_size += HFS_DBL_HDR_LEN;
422                         HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
423                 } else {
424                         inode->i_size = HFS_DBL_HDR_LEN;
425                         inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
426                         inode->i_nlink = 1;
427                         HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
428                 }
429                 inode->i_op = &hfs_hdr_inode_operations;
430                 inode->i_fop = &hfs_hdr_operations;
431         } else if (entry->type == HFS_CDR_FIL) {
432                 init_file_inode(inode, HFS_FK_DATA);
433                 inode->i_op = &hfs_file_inode_operations;
434                 inode->i_fop = &hfs_file_operations;
435                 inode->i_mapping->a_ops = &hfs_aops;
436                 inode->u.hfs_i.mmu_private = inode->i_size;
437         } else { /* Directory */
438                 struct hfs_dir *hdir = &entry->u.dir;
439 
440                 inode->i_blocks = 0;
441                 inode->i_nlink = hdir->dirs + 2;
442                 inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
443                 inode->i_mode = S_IRWXUGO | S_IFDIR;
444                 inode->i_op = &hfs_dbl_dir_inode_operations;
445                 inode->i_fop = &hfs_dbl_dir_operations;
446                 HFS_I(inode)->file_type = HFS_DBL_NORM;
447                 HFS_I(inode)->dir_size = 2;
448         }
449 }
450 
451 /* 
452  * hfs_nat_ifill()
453  *
454  * This function serves the same purpose as a read_inode() function does
455  * in other filesystems.  It is called by __hfs_iget() to fill in
456  * the missing fields of an uninitialized inode under the Netatalk
457  * scheme.
458  */
459 void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
460 {
461         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
462 
463         HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
464         if (type == HFS_NAT_HDR) {
465                 if (entry->type == HFS_CDR_FIL) {
466                         init_file_inode(inode, HFS_FK_RSRC);
467                         inode->i_size += HFS_NAT_HDR_LEN;
468                 } else {
469                         inode->i_size = HFS_NAT_HDR_LEN;
470                         inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
471                         inode->i_nlink = 1;
472                 }
473                 inode->i_op = &hfs_hdr_inode_operations;
474                 inode->i_fop = &hfs_hdr_operations;
475                 HFS_I(inode)->default_layout = (version == 2) ?
476                         &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
477         } else if (entry->type == HFS_CDR_FIL) {
478                 init_file_inode(inode, HFS_FK_DATA);
479                 inode->i_op = &hfs_file_inode_operations;
480                 inode->i_fop = &hfs_file_operations;
481                 inode->i_mapping->a_ops = &hfs_aops;
482                 inode->u.hfs_i.mmu_private = inode->i_size;
483         } else { /* Directory */
484                 struct hfs_dir *hdir = &entry->u.dir;
485 
486                 inode->i_blocks = 0;
487                 inode->i_size = hdir->files + hdir->dirs + 4;
488                 inode->i_mode = S_IRWXUGO | S_IFDIR;
489                 HFS_I(inode)->dir_size = 1;
490                 if (type == HFS_NAT_NDIR) {
491                         inode->i_nlink = hdir->dirs + 3;
492                         inode->i_op = &hfs_nat_ndir_inode_operations;
493                         HFS_I(inode)->file_type = HFS_NAT_NORM;
494                 } else if (type == HFS_NAT_HDIR) {
495                         inode->i_nlink = 2;
496                         inode->i_op = &hfs_nat_hdir_inode_operations;
497                         HFS_I(inode)->file_type = HFS_NAT_HDR;
498                 }
499                 inode->i_fop = &hfs_nat_dir_operations;
500         }
501 }
502 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.