📄 inode.c
字号:
* * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in * the catalog B-tree and the 'type' of the desired file return the * inode for that file/directory or NULL. Note that 'type' indicates * whether we want the actual file or directory, or the corresponding * metadata (AppleDouble header file or CAP metadata file). * * In an ideal world we could call iget() and would not need this * function. However, since there is no way to even know the inode * number until we've found the file/directory in the catalog B-tree * that simply won't happen. * * The main idea here is to look in the catalog B-tree to get the * vital info about the file or directory (including the file id which * becomes the inode number) and then to call iget() and return the * inode if it is complete. If it is not then we use the catalog * entry to fill in the missing info, by calling the appropriate * 'fillin' function. Note that these fillin functions are * essentially hfs_*_read_inode() functions, but since there is no way * to pass the catalog entry through iget() to such a read_inode() * function, we have to call them after iget() returns an incomplete * inode to us. This is pretty much the same problem faced in the NFS * code, and pretty much the same solution. The SMB filesystem deals * with this in a different way: by using the address of the * kmalloc()'d space which holds the data as the inode number. * * XXX: Both this function and NFS's corresponding nfs_fhget() would * benefit from a way to pass an additional (void *) through iget() to * the VFS read_inode() function. * * this will hfs_cat_put() the entry if it fails. */struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type, struct dentry *dentry){ struct dentry **sys_entry; struct super_block *sb; struct inode *inode; if (!entry) { return NULL; } /* If there are several processes all calling __iget() for the same inode then they will all get the same one back. The first one to return from __iget() will notice that the i_mode field of the inode is blank and KNOW that it is the first to return. Therefore, it will set the appropriate 'sys_entry' field in the entry and initialize the inode. All the initialization must be done without sleeping, or else other processes could end up using a partially initialized inode. */ sb = entry->mdb->sys_mdb; sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)]; if (!(inode = iget(sb, ntohl(entry->cnid) | type))) { hfs_cat_put(entry); return NULL; } if (inode->i_dev != sb->s_dev) { iput(inode); /* automatically does an hfs_cat_put */ inode = NULL; } else if (!inode->i_mode || (*sys_entry == NULL)) { /* Initialize the inode */ struct hfs_sb_info *hsb = HFS_SB(sb); inode->i_rdev = 0; inode->i_ctime = inode->i_atime = inode->i_mtime = hfs_m_to_utime(entry->modify_date); inode->i_blksize = HFS_SECTOR_SIZE; inode->i_uid = hsb->s_uid; inode->i_gid = hsb->s_gid; memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info)); HFS_I(inode)->magic = HFS_INO_MAGIC; HFS_I(inode)->entry = entry; HFS_I(inode)->tz_secondswest = hfs_to_utc(0); hsb->s_ifill(inode, type, hsb->s_version); if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) && (entry->u.file.flags & HFS_FIL_LOCK)) { inode->i_mode &= ~S_IWUGO; } inode->i_mode &= ~hsb->s_umask; if (!inode->i_mode) { iput(inode); /* does an hfs_cat_put */ inode = NULL; } else *sys_entry = dentry; /* cache dentry */ } return inode;}/*================ Scheme-specific functions ================*//* * hfs_cap_ifill() * * This function serves the same purpose as a read_inode() function does * in other filesystems. It is called by __hfs_iget() to fill in * the missing fields of an uninitialized inode under the CAP scheme. */void hfs_cap_ifill(struct inode * inode, ino_t type, const int version){ struct hfs_cat_entry *entry = HFS_I(inode)->entry; HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry; if (type == HFS_CAP_FNDR) { inode->i_size = sizeof(struct hfs_cap_info); inode->i_blocks = 0; inode->i_nlink = 1; inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG; inode->i_op = &hfs_cap_info_inode_operations; inode->i_fop = &hfs_cap_info_operations; } else if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, (type == HFS_CAP_DATA) ? HFS_FK_DATA : HFS_FK_RSRC); inode->i_op = &hfs_file_inode_operations; inode->i_fop = &hfs_file_operations; inode->i_mapping->a_ops = &hfs_aops; inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; inode->i_blocks = 0; inode->i_size = hdir->files + hdir->dirs + 5; HFS_I(inode)->dir_size = 1; if (type == HFS_CAP_NDIR) { inode->i_mode = S_IRWXUGO | S_IFDIR; inode->i_nlink = hdir->dirs + 4; inode->i_op = &hfs_cap_ndir_inode_operations; inode->i_fop = &hfs_cap_dir_operations; HFS_I(inode)->file_type = HFS_CAP_NORM; } else if (type == HFS_CAP_FDIR) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 2; inode->i_op = &hfs_cap_fdir_inode_operations; inode->i_fop = &hfs_cap_dir_operations; HFS_I(inode)->file_type = HFS_CAP_FNDR; } else if (type == HFS_CAP_RDIR) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 2; inode->i_op = &hfs_cap_rdir_inode_operations; inode->i_fop = &hfs_cap_dir_operations; HFS_I(inode)->file_type = HFS_CAP_RSRC; } }}/* * hfs_dbl_ifill() * * This function serves the same purpose as a read_inode() function does * in other filesystems. It is called by __hfs_iget() to fill in * the missing fields of an uninitialized inode under the AppleDouble * scheme. */void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version){ struct hfs_cat_entry *entry = HFS_I(inode)->entry; HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry; if (type == HFS_DBL_HDR) { if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_RSRC); inode->i_size += HFS_DBL_HDR_LEN; HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout; } else { inode->i_size = HFS_DBL_HDR_LEN; inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG; inode->i_nlink = 1; HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout; } inode->i_op = &hfs_hdr_inode_operations; inode->i_fop = &hfs_hdr_operations; } else if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_DATA); inode->i_op = &hfs_file_inode_operations; inode->i_fop = &hfs_file_operations; inode->i_mapping->a_ops = &hfs_aops; inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; inode->i_blocks = 0; inode->i_nlink = hdir->dirs + 2; inode->i_size = 3 + 2 * (hdir->dirs + hdir->files); inode->i_mode = S_IRWXUGO | S_IFDIR; inode->i_op = &hfs_dbl_dir_inode_operations; inode->i_fop = &hfs_dbl_dir_operations; HFS_I(inode)->file_type = HFS_DBL_NORM; HFS_I(inode)->dir_size = 2; }}/* * hfs_nat_ifill() * * This function serves the same purpose as a read_inode() function does * in other filesystems. It is called by __hfs_iget() to fill in * the missing fields of an uninitialized inode under the Netatalk * scheme. */void hfs_nat_ifill(struct inode * inode, ino_t type, const int version){ struct hfs_cat_entry *entry = HFS_I(inode)->entry; HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry; if (type == HFS_NAT_HDR) { if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_RSRC); inode->i_size += HFS_NAT_HDR_LEN; } else { inode->i_size = HFS_NAT_HDR_LEN; inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG; inode->i_nlink = 1; } inode->i_op = &hfs_hdr_inode_operations; inode->i_fop = &hfs_hdr_operations; HFS_I(inode)->default_layout = (version == 2) ? &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout; } else if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_DATA); inode->i_op = &hfs_file_inode_operations; inode->i_fop = &hfs_file_operations; inode->i_mapping->a_ops = &hfs_aops; inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; inode->i_blocks = 0; inode->i_size = hdir->files + hdir->dirs + 4; inode->i_mode = S_IRWXUGO | S_IFDIR; HFS_I(inode)->dir_size = 1; if (type == HFS_NAT_NDIR) { inode->i_nlink = hdir->dirs + 3; inode->i_op = &hfs_nat_ndir_inode_operations; HFS_I(inode)->file_type = HFS_NAT_NORM; } else if (type == HFS_NAT_HDIR) { inode->i_nlink = 2; inode->i_op = &hfs_nat_hdir_inode_operations; HFS_I(inode)->file_type = HFS_NAT_HDR; } inode->i_fop = &hfs_nat_dir_operations; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -