The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/hfs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 General 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 (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         error = inode_setattr(inode, attr);
  173         if (error)
  174                 return error;
  175 
  176         /* We wouldn't want to mess with the sizes of the other fork */
  177         attr->ia_valid &= ~ATTR_SIZE;
  178 
  179         /* We must change all in-core inodes corresponding to this file. */
  180         for (i = 0; i < 4; ++i) {
  181           if (de[i] && (de[i] != dentry)) {
  182                 inode_setattr(de[i]->d_inode, attr);
  183           }
  184         }
  185 
  186         /* Change the catalog entry if needed */
  187         if (attr->ia_valid & ATTR_MTIME) {
  188                 entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
  189                 hfs_cat_mark_dirty(entry);
  190         }
  191         if (attr->ia_valid & ATTR_MODE) {
  192                 hfs_u8 new_flags;
  193 
  194                 if (inode->i_mode & S_IWUSR) {
  195                         new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
  196                 } else {
  197                         new_flags = entry->u.file.flags | HFS_FIL_LOCK;
  198                 }
  199 
  200                 if (new_flags != entry->u.file.flags) {
  201                         entry->u.file.flags = new_flags;
  202                         hfs_cat_mark_dirty(entry);
  203                 }
  204         }
  205         /* size changes handled in hfs_extent_adj() */
  206 
  207         return 0;
  208 }
  209 
  210 int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
  211 {
  212         return __hfs_notify_change(dentry, attr, HFS_NORM);
  213 }
  214 
  215 int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr)
  216 {
  217         return __hfs_notify_change(dentry, attr, HFS_CAP);
  218 }
  219 
  220 int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
  221 {
  222         return __hfs_notify_change(dentry, attr, HFS_HDR);
  223 }
  224 
  225 static int hfs_writepage(struct page *page)
  226 {
  227         return block_write_full_page(page,hfs_get_block);
  228 }
  229 static int hfs_readpage(struct file *file, struct page *page)
  230 {
  231         return block_read_full_page(page,hfs_get_block);
  232 }
  233 static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  234 {
  235         return cont_prepare_write(page,from,to,hfs_get_block,
  236                 &page->mapping->host->u.hfs_i.mmu_private);
  237 }
  238 static int hfs_bmap(struct address_space *mapping, long block)
  239 {
  240         return generic_block_bmap(mapping,block,hfs_get_block);
  241 }
  242 struct address_space_operations hfs_aops = {
  243         readpage: hfs_readpage,
  244         writepage: hfs_writepage,
  245         sync_page: block_sync_page,
  246         prepare_write: hfs_prepare_write,
  247         commit_write: generic_commit_write,
  248         bmap: hfs_bmap
  249 };
  250 
  251 /*
  252  * __hfs_iget()
  253  *
  254  * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
  255  * the catalog B-tree and the 'type' of the desired file return the
  256  * inode for that file/directory or NULL.  Note that 'type' indicates
  257  * whether we want the actual file or directory, or the corresponding
  258  * metadata (AppleDouble header file or CAP metadata file).
  259  *
  260  * In an ideal world we could call iget() and would not need this
  261  * function.  However, since there is no way to even know the inode
  262  * number until we've found the file/directory in the catalog B-tree
  263  * that simply won't happen.
  264  *
  265  * The main idea here is to look in the catalog B-tree to get the
  266  * vital info about the file or directory (including the file id which
  267  * becomes the inode number) and then to call iget() and return the
  268  * inode if it is complete.  If it is not then we use the catalog
  269  * entry to fill in the missing info, by calling the appropriate
  270  * 'fillin' function.  Note that these fillin functions are
  271  * essentially hfs_*_read_inode() functions, but since there is no way
  272  * to pass the catalog entry through iget() to such a read_inode()
  273  * function, we have to call them after iget() returns an incomplete
  274  * inode to us.  This is pretty much the same problem faced in the NFS
  275  * code, and pretty much the same solution. The SMB filesystem deals
  276  * with this in a different way: by using the address of the
  277  * kmalloc()'d space which holds the data as the inode number.
  278  *
  279  * XXX: Both this function and NFS's corresponding nfs_fhget() would
  280  * benefit from a way to pass an additional (void *) through iget() to
  281  * the VFS read_inode() function.
  282  *
  283  * this will hfs_cat_put() the entry if it fails.
  284  */
  285 struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
  286                        struct dentry *dentry)
  287 {
  288         struct dentry **sys_entry;
  289         struct super_block *sb;
  290         struct inode *inode;
  291 
  292         if (!entry) {
  293                 return NULL;
  294         }
  295 
  296         /* If there are several processes all calling __iget() for
  297            the same inode then they will all get the same one back.
  298            The first one to return from __iget() will notice that the
  299            i_mode field of the inode is blank and KNOW that it is
  300            the first to return.  Therefore, it will set the appropriate
  301            'sys_entry' field in the entry and initialize the inode.
  302            All the initialization must be done without sleeping,
  303            or else other processes could end up using a partially
  304            initialized inode.                           */
  305 
  306         sb = entry->mdb->sys_mdb;
  307         sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
  308 
  309         if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
  310                 hfs_cat_put(entry);
  311                 return NULL;
  312         }
  313 
  314         if (inode->i_dev != sb->s_dev) {
  315                 iput(inode); /* automatically does an hfs_cat_put */
  316                 inode = NULL;
  317         } else if (!inode->i_mode || (*sys_entry == NULL)) {
  318                 /* Initialize the inode */
  319                 struct hfs_sb_info *hsb = HFS_SB(sb);
  320 
  321                 inode->i_rdev = 0;
  322                 inode->i_ctime = inode->i_atime = inode->i_mtime =
  323                                         hfs_m_to_utime(entry->modify_date);
  324                 inode->i_blksize = HFS_SECTOR_SIZE;
  325                 inode->i_uid = hsb->s_uid;
  326                 inode->i_gid = hsb->s_gid;
  327 
  328                 memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
  329                 HFS_I(inode)->magic = HFS_INO_MAGIC;
  330                 HFS_I(inode)->entry = entry;
  331                 HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
  332 
  333                 hsb->s_ifill(inode, type, hsb->s_version);
  334                 if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
  335                     (entry->u.file.flags & HFS_FIL_LOCK)) {
  336                         inode->i_mode &= ~S_IWUGO;
  337                 }
  338                 inode->i_mode &= ~hsb->s_umask;
  339 
  340                 if (!inode->i_mode) {
  341                         iput(inode); /* does an hfs_cat_put */
  342                         inode = NULL;
  343                 } else
  344                         *sys_entry = dentry; /* cache dentry */
  345 
  346         }
  347 
  348         return inode;
  349 }
  350 
  351 /*================ Scheme-specific functions ================*/
  352 
  353 /* 
  354  * hfs_cap_ifill()
  355  *
  356  * This function serves the same purpose as a read_inode() function does
  357  * in other filesystems.  It is called by __hfs_iget() to fill in
  358  * the missing fields of an uninitialized inode under the CAP scheme.
  359  */
  360 void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
  361 {
  362         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  363 
  364         HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
  365         if (type == HFS_CAP_FNDR) {
  366                 inode->i_size = sizeof(struct hfs_cap_info);
  367                 inode->i_blocks = 0;
  368                 inode->i_nlink = 1;
  369                 inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
  370                 inode->i_op = &hfs_cap_info_inode_operations;
  371                 inode->i_fop = &hfs_cap_info_operations;
  372         } else if (entry->type == HFS_CDR_FIL) {
  373                 init_file_inode(inode, (type == HFS_CAP_DATA) ?
  374                                                 HFS_FK_DATA : HFS_FK_RSRC);
  375                 inode->i_op = &hfs_file_inode_operations;
  376                 inode->i_fop = &hfs_file_operations;
  377                 inode->i_mapping->a_ops = &hfs_aops;
  378                 inode->u.hfs_i.mmu_private = inode->i_size;
  379         } else { /* Directory */
  380                 struct hfs_dir *hdir = &entry->u.dir;
  381 
  382                 inode->i_blocks = 0;
  383                 inode->i_size = hdir->files + hdir->dirs + 5;
  384                 HFS_I(inode)->dir_size = 1;
  385                 if (type == HFS_CAP_NDIR) {
  386                         inode->i_mode = S_IRWXUGO | S_IFDIR;
  387                         inode->i_nlink = hdir->dirs + 4;
  388                         inode->i_op = &hfs_cap_ndir_inode_operations;
  389                         inode->i_fop = &hfs_cap_dir_operations;
  390                         HFS_I(inode)->file_type = HFS_CAP_NORM;
  391                 } else if (type == HFS_CAP_FDIR) {
  392                         inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
  393                         inode->i_nlink = 2;
  394                         inode->i_op = &hfs_cap_fdir_inode_operations;
  395                         inode->i_fop = &hfs_cap_dir_operations;
  396                         HFS_I(inode)->file_type = HFS_CAP_FNDR;
  397                 } else if (type == HFS_CAP_RDIR) {
  398                         inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
  399                         inode->i_nlink = 2;
  400                         inode->i_op = &hfs_cap_rdir_inode_operations;
  401                         inode->i_fop = &hfs_cap_dir_operations;
  402                         HFS_I(inode)->file_type = HFS_CAP_RSRC;
  403                 }
  404         }
  405 }
  406 
  407 /* 
  408  * hfs_dbl_ifill()
  409  *
  410  * This function serves the same purpose as a read_inode() function does
  411  * in other filesystems.  It is called by __hfs_iget() to fill in
  412  * the missing fields of an uninitialized inode under the AppleDouble
  413  * scheme.
  414  */
  415 void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
  416 {
  417         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  418 
  419         HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
  420         if (type == HFS_DBL_HDR) {
  421                 if (entry->type == HFS_CDR_FIL) {
  422                         init_file_inode(inode, HFS_FK_RSRC);
  423                         inode->i_size += HFS_DBL_HDR_LEN;
  424                         HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
  425                 } else {
  426                         inode->i_size = HFS_DBL_HDR_LEN;
  427                         inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
  428                         inode->i_nlink = 1;
  429                         HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
  430                 }
  431                 inode->i_op = &hfs_hdr_inode_operations;
  432                 inode->i_fop = &hfs_hdr_operations;
  433         } else if (entry->type == HFS_CDR_FIL) {
  434                 init_file_inode(inode, HFS_FK_DATA);
  435                 inode->i_op = &hfs_file_inode_operations;
  436                 inode->i_fop = &hfs_file_operations;
  437                 inode->i_mapping->a_ops = &hfs_aops;
  438                 inode->u.hfs_i.mmu_private = inode->i_size;
  439         } else { /* Directory */
  440                 struct hfs_dir *hdir = &entry->u.dir;
  441 
  442                 inode->i_blocks = 0;
  443                 inode->i_nlink = hdir->dirs + 2;
  444                 inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
  445                 inode->i_mode = S_IRWXUGO | S_IFDIR;
  446                 inode->i_op = &hfs_dbl_dir_inode_operations;
  447                 inode->i_fop = &hfs_dbl_dir_operations;
  448                 HFS_I(inode)->file_type = HFS_DBL_NORM;
  449                 HFS_I(inode)->dir_size = 2;
  450         }
  451 }
  452 
  453 /* 
  454  * hfs_nat_ifill()
  455  *
  456  * This function serves the same purpose as a read_inode() function does
  457  * in other filesystems.  It is called by __hfs_iget() to fill in
  458  * the missing fields of an uninitialized inode under the Netatalk
  459  * scheme.
  460  */
  461 void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
  462 {
  463         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  464 
  465         HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
  466         if (type == HFS_NAT_HDR) {
  467                 if (entry->type == HFS_CDR_FIL) {
  468                         init_file_inode(inode, HFS_FK_RSRC);
  469                         inode->i_size += HFS_NAT_HDR_LEN;
  470                 } else {
  471                         inode->i_size = HFS_NAT_HDR_LEN;
  472                         inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
  473                         inode->i_nlink = 1;
  474                 }
  475                 inode->i_op = &hfs_hdr_inode_operations;
  476                 inode->i_fop = &hfs_hdr_operations;
  477                 HFS_I(inode)->default_layout = (version == 2) ?
  478                         &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
  479         } else if (entry->type == HFS_CDR_FIL) {
  480                 init_file_inode(inode, HFS_FK_DATA);
  481                 inode->i_op = &hfs_file_inode_operations;
  482                 inode->i_fop = &hfs_file_operations;
  483                 inode->i_mapping->a_ops = &hfs_aops;
  484                 inode->u.hfs_i.mmu_private = inode->i_size;
  485         } else { /* Directory */
  486                 struct hfs_dir *hdir = &entry->u.dir;
  487 
  488                 inode->i_blocks = 0;
  489                 inode->i_size = hdir->files + hdir->dirs + 4;
  490                 inode->i_mode = S_IRWXUGO | S_IFDIR;
  491                 HFS_I(inode)->dir_size = 1;
  492                 if (type == HFS_NAT_NDIR) {
  493                         inode->i_nlink = hdir->dirs + 3;
  494                         inode->i_op = &hfs_nat_ndir_inode_operations;
  495                         HFS_I(inode)->file_type = HFS_NAT_NORM;
  496                 } else if (type == HFS_NAT_HDIR) {
  497                         inode->i_nlink = 2;
  498                         inode->i_op = &hfs_nat_hdir_inode_operations;
  499                         HFS_I(inode)->file_type = HFS_NAT_HDR;
  500                 }
  501                 inode->i_fop = &hfs_nat_dir_operations;
  502         }
  503 }

Cache object: 4fdc0eb5c4204c4ad9ad584a5cfe1f5c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.