⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* *  linux/fs/affs/inode.c * *  (c) 1996  Hans-Joachim Widmaier - Rewritten * *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem. * *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem. * *  (C) 1991  Linus Torvalds - minix filesystem */#define DEBUG 0#include <asm/div64.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/malloc.h>#include <linux/stat.h>#include <linux/sched.h>#include <linux/affs_fs.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/genhd.h>#include <linux/amigaffs.h>#include <linux/major.h>#include <linux/blkdev.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <asm/system.h>#include <asm/uaccess.h>extern int *blk_size[];extern struct timezone sys_tz;extern struct inode_operations affs_symlink_inode_operations;#define MIN(a,b) (((a)<(b))?(a):(b))unsigned longaffs_parent_ino(struct inode *dir){	int root_ino = (dir->i_sb->u.affs_sb.s_root_block);	if (!S_ISDIR(dir->i_mode)) {		affs_error(dir->i_sb,"parent_ino","Trying to get parent of non-directory");		return root_ino;	}	if (dir->i_ino == root_ino)		return root_ino;	return dir->u.affs_i.i_parent;}voidaffs_read_inode(struct inode *inode){	struct buffer_head	*bh;	struct file_front	*file_front;	struct file_end		*file_end;	s32			 block;	unsigned long		 prot;	s32			 ptype, stype;	unsigned short		 id;	loff_t		tmp;	pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino);	block = inode->i_ino;	if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {		affs_error(inode->i_sb,"read_inode","Cannot read block %d",block);		return;	}	if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) {		affs_error(inode->i_sb,"read_inode",			   "Checksum or type (ptype=%d) error on inode %d",ptype,block);		affs_brelse(bh);		return;	}	file_front = (struct file_front *)bh->b_data;	file_end   = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));	prot       = (be32_to_cpu(file_end->protect) & ~0x10) ^ FIBF_OWNER;	inode->u.affs_i.i_protect      = prot;	inode->u.affs_i.i_parent       = be32_to_cpu(file_end->parent);	inode->u.affs_i.i_original     = 0;	inode->u.affs_i.i_zone         = 0;	inode->u.affs_i.i_hlink        = 0;	inode->u.affs_i.i_pa_cnt       = 0;	inode->u.affs_i.i_pa_next      = 0;	inode->u.affs_i.i_pa_last      = 0;	inode->u.affs_i.i_ec           = NULL;	inode->u.affs_i.i_lastblock    = -1;	inode->i_nlink                 = 1;	inode->i_mode                  = 0;	if (inode->i_sb->u.affs_sb.s_flags & SF_SETMODE)		inode->i_mode = inode->i_sb->u.affs_sb.s_mode;	else		inode->i_mode = prot_to_mode(prot);	if (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)		inode->i_uid = inode->i_sb->u.affs_sb.s_uid;	id = be16_to_cpu(file_end->owner_uid);	if (id == 0 || inode->i_sb->u.affs_sb.s_flags & SF_SETUID)		inode->i_uid = inode->i_sb->u.affs_sb.s_uid;	else if (id == 0xFFFF && inode->i_sb->u.affs_sb.s_flags & SF_MUFS)		inode->i_uid = 0;	else 		inode->i_uid = id;	id = be16_to_cpu(file_end->owner_gid);	if (id == 0 || inode->i_sb->u.affs_sb.s_flags & SF_SETGID)		inode->i_gid = inode->i_sb->u.affs_sb.s_gid;	else if (id == 0xFFFF && inode->i_sb->u.affs_sb.s_flags & SF_MUFS)		inode->i_gid = 0;	else		inode->i_gid = id;	switch (be32_to_cpu(file_end->secondary_type)) {		case ST_ROOT:			inode->i_uid   = inode->i_sb->u.affs_sb.s_uid;			inode->i_gid   = inode->i_sb->u.affs_sb.s_gid;		case ST_USERDIR:			if (be32_to_cpu(file_end->secondary_type) == ST_USERDIR ||			    inode->i_sb->u.affs_sb.s_flags & SF_SETMODE) {				if (inode->i_mode & S_IRUSR)					inode->i_mode |= S_IXUSR;				if (inode->i_mode & S_IRGRP)					inode->i_mode |= S_IXGRP;				if (inode->i_mode & S_IROTH)					inode->i_mode |= S_IXOTH;				inode->i_mode |= S_IFDIR;			} else				inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;			inode->i_size  = 0;			break;		case ST_LINKDIR:			affs_error(inode->i_sb,"read_inode","inode is LINKDIR");			affs_brelse(bh);			return;		case ST_LINKFILE:			affs_error(inode->i_sb,"read_inode","inode is LINKFILE");			affs_brelse(bh);			return;		case ST_FILE:			inode->i_mode |= S_IFREG;			inode->i_size  = be32_to_cpu(file_end->byte_size);			if (inode->i_sb->u.affs_sb.s_flags & SF_OFS)				block = AFFS_I2BSIZE(inode) - 24;			else				block = AFFS_I2BSIZE(inode);			tmp = inode->i_size + block -1;			do_div (tmp, block);			tmp--;			inode->u.affs_i.i_lastblock = tmp;			break;		case ST_SOFTLINK:			inode->i_mode |= S_IFLNK;			inode->i_size  = 0;			break;	}	inode->i_mtime = inode->i_atime = inode->i_ctime		       = (be32_to_cpu(file_end->created.ds_Days) * (24 * 60 * 60) +		         be32_to_cpu(file_end->created.ds_Minute) * 60 +			 be32_to_cpu(file_end->created.ds_Tick) / 50 +			 ((8 * 365 + 2) * 24 * 60 * 60)) +			 sys_tz.tz_minuteswest * 60;	affs_brelse(bh);	if (S_ISREG(inode->i_mode)) {		if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {			inode->i_op = &affs_file_inode_operations;			inode->i_fop = &affs_file_operations_ofs;			return;		}		inode->i_op = &affs_file_inode_operations;		inode->i_fop = &affs_file_operations;		inode->i_mapping->a_ops = &affs_aops;		inode->u.affs_i.mmu_private = inode->i_size;	} else if (S_ISDIR(inode->i_mode)) {		/* Maybe it should be controlled by mount parameter? */		inode->i_mode |= S_ISVTX;		inode->i_op = &affs_dir_inode_operations;		inode->i_fop = &affs_dir_operations;	}	else if (S_ISLNK(inode->i_mode)) {		inode->i_op = &affs_symlink_inode_operations;		inode->i_data.a_ops = &affs_symlink_aops;	}}voidaffs_write_inode(struct inode *inode, int unused){	struct buffer_head	*bh;	struct file_end		*file_end;	uid_t			 uid;	gid_t			 gid;	pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);	if (!inode->i_nlink)		return;	lock_kernel();	if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) {		affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino);		unlock_kernel();		return;	}	file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));	if (file_end->secondary_type == be32_to_cpu(ST_ROOT)) {		secs_to_datestamp(inode->i_mtime,&ROOT_END(bh->b_data,inode)->disk_altered);	} else {		file_end->protect   = cpu_to_be32(inode->u.affs_i.i_protect ^ FIBF_OWNER);		file_end->byte_size = cpu_to_be32(inode->i_size);		secs_to_datestamp(inode->i_mtime,&file_end->created);		if (!(inode->i_ino == inode->i_sb->u.affs_sb.s_root_block)) {			uid = inode->i_uid;			gid = inode->i_gid;			if (inode->i_sb->u.affs_sb.s_flags & SF_MUFS) {				if (inode->i_uid == 0 || inode->i_uid == 0xFFFF)					uid = inode->i_uid ^ ~0;				if (inode->i_gid == 0 || inode->i_gid == 0xFFFF)					gid = inode->i_gid ^ ~0;			}			if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETUID))				file_end->owner_uid = cpu_to_be16(uid);			if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETGID))				file_end->owner_gid = cpu_to_be16(gid);		}	}	affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);	mark_buffer_dirty(bh);	brelse(bh);	unlock_kernel();}intaffs_notify_change(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	int error;	pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);	error = inode_change_ok(inode,attr);	if (error)		goto out;	if (((attr->ia_valid & ATTR_UID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) ||	    ((attr->ia_valid & ATTR_GID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)) ||	    ((attr->ia_valid & ATTR_MODE) &&	     (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE)))) {		if (!(inode->i_sb->u.affs_sb.s_flags & SF_QUIET))			error = -EPERM;		goto out;	}	if (attr->ia_valid & ATTR_MODE)		inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode);	error = 0;	inode_setattr(inode, attr);out:	return error;}voidaffs_put_inode(struct inode *inode){	pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",		inode->i_ino,inode->i_nlink);	lock_kernel();	affs_free_prealloc(inode);	if (atomic_read(&inode->i_count) == 1) {		unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec;		if (cache_page) {			pr_debug("AFFS: freeing ext cache\n");			inode->u.affs_i.i_ec = NULL;			free_page(cache_page);		}	}	unlock_kernel();}voidaffs_delete_inode(struct inode *inode){	pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink);	lock_kernel();	inode->i_size = 0;	if (S_ISREG(inode->i_mode) && !inode->u.affs_i.i_hlink)		affs_truncate(inode);	affs_free_block(inode->i_sb,inode->i_ino);	unlock_kernel();	clear_inode(inode);}struct inode *affs_new_inode(const struct inode *dir){	struct inode		*inode;	struct super_block	*sb;	s32			 block;	if (!dir)		return NULL;	sb = dir->i_sb;	inode = new_inode(sb);	if (!inode)		return NULL;	if (!(block = affs_new_header((struct inode *)dir))) {		iput(inode);		return NULL;	}	inode->i_uid     = current->fsuid;	inode->i_gid     = current->fsgid;	inode->i_ino     = block;	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME;	inode->u.affs_i.i_original  = 0;	inode->u.affs_i.i_parent    = dir->i_ino;	inode->u.affs_i.i_zone      = 0;	inode->u.affs_i.i_hlink     = 0;	inode->u.affs_i.i_pa_cnt    = 0;	inode->u.affs_i.i_pa_next   = 0;	inode->u.affs_i.i_pa_last   = 0;	inode->u.affs_i.i_ec        = NULL;	inode->u.affs_i.i_lastblock = -1;	insert_inode_hash(inode);	mark_inode_dirty(inode);	return inode;}/* * Add an entry to a directory. Create the header block * and insert it into the hash table. */intaffs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,	       struct dentry *dentry, int type){	struct buffer_head	*dir_bh;	struct buffer_head	*inode_bh;	struct buffer_head	*link_bh;	int			 retval;	const unsigned char	*name = dentry->d_name.name;	int			 len  = dentry->d_name.len;	pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d)\n",dir->i_ino,inode->i_ino,		 len,name,type);	if ((retval = affs_check_name(name,len)))		return retval;	if (len > 30)		len = 30;	dir_bh   = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));	inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));	link_bh  = NULL;	retval   = -EIO;	if (!dir_bh || !inode_bh)		goto addentry_done;	if (link) {		link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link));		if (!link_bh)			goto addentry_done;	}	((struct dir_front *)inode_bh->b_data)->primary_type = cpu_to_be32(T_SHORT);	((struct dir_front *)inode_bh->b_data)->own_key      = cpu_to_be32(inode->i_ino);	DIR_END(inode_bh->b_data,inode)->dir_name[0]         = len;	strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len);	DIR_END(inode_bh->b_data,inode)->secondary_type = cpu_to_be32(type);	DIR_END(inode_bh->b_data,inode)->parent         = cpu_to_be32(dir->i_ino);	lock_super(inode->i_sb);	retval = affs_insert_hash(dir->i_ino,inode_bh,dir);	if (link_bh) {		LINK_END(inode_bh->b_data,inode)->original   = cpu_to_be32(link->i_ino);		LINK_END(inode_bh->b_data,inode)->link_chain =						FILE_END(link_bh->b_data,link)->link_chain;		FILE_END(link_bh->b_data,link)->link_chain   = cpu_to_be32(inode->i_ino);		affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);		link->i_version = ++event;		mark_inode_dirty(link);		mark_buffer_dirty(link_bh);	}	affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5);	affs_fix_checksum(AFFS_I2BSIZE(dir),dir_bh->b_data,5);	dir->i_version = ++event;	dir->i_mtime   = dir->i_atime = dir->i_ctime = CURRENT_TIME;	unlock_super(inode->i_sb);	mark_inode_dirty(dir);	mark_inode_dirty(inode);	mark_buffer_dirty(dir_bh);	mark_buffer_dirty(inode_bh);addentry_done:	affs_brelse(dir_bh);	affs_brelse(inode_bh);	affs_brelse(link_bh);	return retval;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -