📄 inode.c
字号:
/* * linux/fs/hfs/inode.c * * Copyright (C) 1995-1997 Paul H. Hargrove * This file may be distributed under the terms of the GNU General Public License. * * This file contains inode-related functions which do not depend on * which scheme is being used to represent forks. * * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds * * "XXX" in a comment is a note to myself to consider changing something. * * In function preconditions the term "valid" applied to a pointer to * a structure means that the pointer is non-NULL and the structure it * points to has all fields initialized to consistent values. */#include "hfs.h"#include <linux/hfs_fs_sb.h>#include <linux/hfs_fs_i.h>#include <linux/hfs_fs.h>#include <linux/smp_lock.h>/*================ Variable-like macros ================*/#define HFS_VALID_MODE_BITS (S_IFREG | S_IFDIR | S_IRWXUGO)/*================ File-local functions ================*//* * init_file_inode() * * Given an HFS catalog entry initialize an inode for a file. */static void init_file_inode(struct inode *inode, hfs_u8 fork){ struct hfs_fork *fk; struct hfs_cat_entry *entry = HFS_I(inode)->entry; if (fork == HFS_FK_DATA) { inode->i_mode = S_IRWXUGO | S_IFREG; } else { inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG; } if (fork == HFS_FK_DATA) {#if 0 /* XXX: disable crlf translations for now */ hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType); HFS_I(inode)->convert = ((HFS_SB(inode->i_sb)->s_conv == 't') || ((HFS_SB(inode->i_sb)->s_conv == 'a') && ((type == htonl(0x54455854)) || /* "TEXT" */ (type == htonl(0x7474726f))))); /* "ttro" */#else HFS_I(inode)->convert = 0;#endif fk = &entry->u.file.data_fork; } else { fk = &entry->u.file.rsrc_fork; HFS_I(inode)->convert = 0; } HFS_I(inode)->fork = fk; inode->i_size = fk->lsize; inode->i_blocks = fk->psize; inode->i_nlink = 1;}/*================ Global functions ================*//* * hfs_put_inode() * * This is the put_inode() entry in the super_operations for HFS * filesystems. The purpose is to perform any filesystem-dependent * cleanup necessary when the use-count of an inode falls to zero. */void hfs_put_inode(struct inode * inode){ struct hfs_cat_entry *entry = HFS_I(inode)->entry; lock_kernel(); hfs_cat_put(entry); if (atomic_read(&inode->i_count) == 1) { struct hfs_hdr_layout *tmp = HFS_I(inode)->layout; if (tmp) { HFS_I(inode)->layout = NULL; HFS_DELETE(tmp); } } unlock_kernel();}/* * hfs_notify_change() * * Based very closely on fs/msdos/inode.c by Werner Almesberger * * This is the notify_change() field in the super_operations structure * for HFS file systems. The purpose is to take that changes made to * an inode and apply then in a filesystem-dependent manner. In this * case the process has a few of tasks to do: * 1) prevent changes to the i_uid and i_gid fields. * 2) map file permissions to the closest allowable permissions * 3) Since multiple Linux files can share the same on-disk inode under * HFS (for instance the data and resource forks of a file) a change * to permissions must be applied to all other in-core inodes which * correspond to the same HFS file. */enum {HFS_NORM, HFS_HDR, HFS_CAP};static int __hfs_notify_change(struct dentry *dentry, struct iattr * attr, int kind){ struct inode *inode = dentry->d_inode; struct hfs_cat_entry *entry = HFS_I(inode)->entry; struct dentry **de = entry->sys_entry; struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); int error, i; error = inode_change_ok(inode, attr); /* basic permission checks */ if (error) { /* Let netatalk's afpd think chmod() always succeeds */ if (hsb->s_afpd && (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) { return 0; } else { return error; } } /* no uig/gid changes and limit which mode bits can be set */ if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != hsb->s_uid)) || ((attr->ia_valid & ATTR_GID) && (attr->ia_gid != hsb->s_gid)) || ((attr->ia_valid & ATTR_MODE) && (((entry->type == HFS_CDR_DIR) && (attr->ia_mode != inode->i_mode))|| (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) { return hsb->s_quiet ? 0 : error; } if (entry->type == HFS_CDR_DIR) { attr->ia_valid &= ~ATTR_MODE; } else if (attr->ia_valid & ATTR_MODE) { /* Only the 'w' bits can ever change and only all together. */ if (attr->ia_mode & S_IWUSR) { attr->ia_mode = inode->i_mode | S_IWUGO; } else { attr->ia_mode = inode->i_mode & ~S_IWUGO; } attr->ia_mode &= ~hsb->s_umask; } /* * Normal files handle size change in normal way. * Oddballs are served here. */ if (attr->ia_valid & ATTR_SIZE) { if (kind == HFS_CAP) { inode->i_size = attr->ia_size; if (inode->i_size > HFS_FORK_MAX) inode->i_size = HFS_FORK_MAX; mark_inode_dirty(inode); attr->ia_valid &= ~ATTR_SIZE; } else if (kind == HFS_HDR) { hdr_truncate(inode, attr->ia_size); attr->ia_valid &= ~ATTR_SIZE; } } error = inode_setattr(inode, attr); if (error) return error; /* We wouldn't want to mess with the sizes of the other fork */ attr->ia_valid &= ~ATTR_SIZE; /* We must change all in-core inodes corresponding to this file. */ for (i = 0; i < 4; ++i) { if (de[i] && (de[i] != dentry)) { inode_setattr(de[i]->d_inode, attr); } } /* Change the catalog entry if needed */ if (attr->ia_valid & ATTR_MTIME) { entry->modify_date = hfs_u_to_mtime(inode->i_mtime); hfs_cat_mark_dirty(entry); } if (attr->ia_valid & ATTR_MODE) { hfs_u8 new_flags; if (inode->i_mode & S_IWUSR) { new_flags = entry->u.file.flags & ~HFS_FIL_LOCK; } else { new_flags = entry->u.file.flags | HFS_FIL_LOCK; } if (new_flags != entry->u.file.flags) { entry->u.file.flags = new_flags; hfs_cat_mark_dirty(entry); } } /* size changes handled in hfs_extent_adj() */ return 0;}int hfs_notify_change(struct dentry *dentry, struct iattr * attr){ return __hfs_notify_change(dentry, attr, HFS_NORM);}int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr){ return __hfs_notify_change(dentry, attr, HFS_CAP);}int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr){ return __hfs_notify_change(dentry, attr, HFS_HDR);}static int hfs_writepage(struct page *page){ return block_write_full_page(page,hfs_get_block);}static int hfs_readpage(struct file *file, struct page *page){ return block_read_full_page(page,hfs_get_block);}static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){ return cont_prepare_write(page,from,to,hfs_get_block, &page->mapping->host->u.hfs_i.mmu_private);}static int hfs_bmap(struct address_space *mapping, long block){ return generic_block_bmap(mapping,block,hfs_get_block);}struct address_space_operations hfs_aops = { readpage: hfs_readpage, writepage: hfs_writepage, sync_page: block_sync_page, prepare_write: hfs_prepare_write, commit_write: generic_commit_write, bmap: hfs_bmap};/* * __hfs_iget()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -