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

📄 file.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/affs/file.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 * *  affs regular file handling primitives */#include <asm/segment.h>#include <asm/system.h>#include <linux/sched.h>#include <linux/affs_fs.h>#include <linux/fcntl.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/locks.h>#include <linux/dirent.h>#include <linux/fs.h>#include <linux/amigaffs.h>#include <linux/mm.h>#include <linux/pagemap.h>#define MIN(a,b) (((a)<(b))?(a):(b))#define MAX(a,b) (((a)>(b))?(a):(b))static int affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, int count);static int affs_file_write(struct inode *inode, struct file *filp, const char *buf, int count);static int affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, int count);static void affs_release_file(struct inode *inode, struct file *filp);static struct file_operations affs_file_operations = {	NULL,			/* lseek - default */	generic_file_read,	/* read */	affs_file_write,	/* write */	NULL,			/* readdir - bad */	NULL,			/* select - default */	NULL,			/* ioctl - default */	generic_file_mmap,	/* mmap */	NULL,			/* no special open is needed */	affs_release_file,	/* release */	file_fsync		/* brute force, but works */};struct inode_operations affs_file_inode_operations = {	&affs_file_operations,	/* default file operations */	NULL,			/* create */	NULL,			/* lookup */	NULL,			/* link */	NULL,			/* unlink */	NULL,			/* symlink */	NULL,			/* mkdir */	NULL,			/* rmdir */	NULL,			/* mknod */	NULL,			/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	generic_readpage,	/* readpage */	NULL,			/* writepage */	affs_bmap,		/* bmap */	affs_truncate,		/* truncate */	NULL,			/* permission */	NULL			/* smap */};static struct file_operations affs_file_operations_ofs = {	NULL,			/* lseek - default */	affs_file_read_ofs,	/* read */	affs_file_write_ofs,	/* write */	NULL,			/* readdir - bad */	NULL,			/* select - default */	NULL,			/* ioctl - default */	NULL,			/* mmap */	NULL,			/* no special open is needed */	affs_release_file,	/* release */	file_fsync		/* brute force, but works */};struct inode_operations affs_file_inode_operations_ofs = {	&affs_file_operations_ofs,	/* default file operations */	NULL,			/* create */	NULL,			/* lookup */	NULL,			/* link */	NULL,			/* unlink */	NULL,			/* symlink */	NULL,			/* mkdir */	NULL,			/* rmdir */	NULL,			/* mknod */	NULL,			/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	NULL,			/* readpage */	NULL,			/* writepage */	NULL,			/* bmap */	affs_truncate,		/* truncate */	NULL,			/* permission */	NULL			/* smap */};intaffs_bmap(struct inode *inode, int block){	struct buffer_head	*bh;	int			 ext, key;	int			 ptype, stype;	pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block);	if (block < 0) {		printk("affs_bmap: block < 0\n");		return 0;	}	/* If this is a hard link, quietly exchange the inode with the original */	key = inode->u.affs_i.i_original ? inode->u.affs_i.i_original : inode->i_ino;	ext = block / AFFS_I2HSIZE(inode);	if (ext) {		if (ext > inode->u.affs_i.i_max_ext)			ext = inode->u.affs_i.i_max_ext;		if (ext)			key = inode->u.affs_i.i_ext[ext -  1];		block -= ext * AFFS_I2HSIZE(inode);	}	for (;;) {		bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));		if (!bh)			return 0;		if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) ||		    (ptype != T_SHORT && ptype != T_LIST) || stype != ST_FILE) {			affs_brelse(bh);			return 0;		}		if (block < AFFS_I2HSIZE(inode))			break;		block -= AFFS_I2HSIZE(inode);		key    = htonl(FILE_END(bh->b_data,inode)->extension);		affs_brelse(bh);		if (ext < EXT_CACHE_SIZE - 1) {			inode->u.affs_i.i_ext[ext] = key;			inode->u.affs_i.i_max_ext  = ++ext;		}	}	key = AFFS_GET_HASHENTRY(bh->b_data,(AFFS_I2HSIZE(inode) - 1) - block);	affs_brelse(bh);	return key;}struct buffer_head *affs_getblock(struct inode *inode, int block){	struct buffer_head	*bh;	struct buffer_head	*ebh;	int			 key;	int			 ext;	int			 cnt, j, pt;	pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block);	if (block < 0)		return NULL;	key = inode->i_ino;	pt  = T_SHORT;	ext = block / AFFS_I2HSIZE(inode);	if (ext) {		if (ext > inode->u.affs_i.i_max_ext)			ext = inode->u.affs_i.i_max_ext;		if (ext) {			key    = inode->u.affs_i.i_ext[ext - 1];			block -= ext * AFFS_I2HSIZE(inode);			pt     = T_LIST;		}	}	for (;;) {		bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));		if (!bh)			return NULL;		if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) ||		    cnt != pt || j != ST_FILE) {		    	printk("AFFS: getblock(): inode %d is not a valid %s\n",key,			       pt == T_SHORT ? "file header" : "extension block");			affs_brelse(bh);			return NULL;		}		j = htonl(((struct file_front *)bh->b_data)->block_count);		while (j < AFFS_I2HSIZE(inode) && j <= block) {			key = affs_new_data(inode);			if (!key)				break;			lock_super(inode->i_sb);			if (AFFS_BLOCK(bh->b_data,inode,j)) {				unlock_super(inode->i_sb);				printk("AFFS: getblock(): block already allocated\n");				affs_free_block(inode->i_sb,key);				j++;				continue;			}			unlock_super(inode->i_sb);			AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key);			j++;		}		if (pt == T_SHORT)			((struct file_front *)bh->b_data)->first_data =								AFFS_BLOCK(bh->b_data,inode,0);		((struct file_front *)bh->b_data)->block_count = ntohl(j);		affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);		mark_buffer_dirty(bh,1);		if (block < j)			break;		if (j < AFFS_I2HSIZE(inode)) {			affs_brelse(bh);			return NULL;		}		block -= AFFS_I2HSIZE(inode);		key    = htonl(FILE_END(bh->b_data,inode)->extension);		if (!key) {			key = affs_new_header(inode);			if (!key) {				affs_brelse(bh);				return NULL;			}			ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));			if (!ebh) {				affs_free_block(inode->i_sb,key);				return NULL;			}			((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST);			((struct file_front *)ebh->b_data)->own_key      = ntohl(key);			FILE_END(ebh->b_data,inode)->secondary_type      = ntohl(ST_FILE);			FILE_END(ebh->b_data,inode)->parent              = ntohl(inode->i_ino);			affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);			FILE_END(bh->b_data,inode)->extension = ntohl(key);			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);			mark_buffer_dirty(bh,1);			affs_brelse(bh);			bh = ebh;		}		affs_brelse(bh);		pt = T_LIST;		if (ext < EXT_CACHE_SIZE - 1) {			inode->u.affs_i.i_ext[ext] = key;			inode->u.affs_i.i_max_ext  = ++ext;		}	}	key = htonl(AFFS_BLOCK(bh->b_data,inode,block));	affs_brelse(bh);	if (!key)		return NULL;		return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));}struct buffer_head *affs_getblock_ofs(struct inode *inode, int block, int *blk_key){	struct buffer_head	*bh;	struct buffer_head	*pbh;	struct buffer_head	*ebh;	int			 key;	int			 ext;	int			 cnt, j, pt;	pr_debug("AFFS: getblock_ofs(%lu,%d)\n",inode->i_ino,block);	if (block < 0)		return NULL;	key = inode->i_ino;	pt  = T_SHORT;	ext = block / AFFS_I2HSIZE(inode);	if (ext) {		if (ext > inode->u.affs_i.i_max_ext)			ext = inode->u.affs_i.i_max_ext;		if (ext) {			key    = inode->u.affs_i.i_ext[ext - 1];			block -= ext * AFFS_I2HSIZE(inode);			pt     = T_LIST;		}	}	pbh = NULL;	for (;;) {		bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));		if (!bh)			return NULL;		if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) ||		    cnt != pt || j != ST_FILE) {		    	printk("AFFS: getblock(): inode %d is not a valid %s\n",key,			       pt == T_SHORT ? "file header" : "extension block");			affs_brelse(bh);			return NULL;		}		j = htonl(((struct file_front *)bh->b_data)->block_count);		while (j < AFFS_I2HSIZE(inode) && j <= block) {			if (!pbh && inode->u.affs_i.i_lastblock >= 0) {				if (j > 0)					pbh = affs_bread(inode->i_dev,ntohl(AFFS_BLOCK(bh->b_data,inode,j - 1)),							 AFFS_I2BSIZE(inode));				else					pbh = affs_getblock_ofs(inode,inode->u.affs_i.i_lastblock,&key);				if (!pbh) {					printk("AFFS: getblock(): cannot get last block in file\n");					break;				}			}			key = affs_new_data(inode);			if (!key)				break;			lock_super(inode->i_sb);			if (AFFS_BLOCK(bh->b_data,inode,j)) {				unlock_super(inode->i_sb);				printk("AFFS: getblock(): block already allocated\n");				affs_free_block(inode->i_sb,key);				j++;				continue;			}			AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key);			unlock_super(inode->i_sb);			ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));			if (!ebh) {				printk("AFFS: getblock(): cannot get block %d\n",key);				affs_free_block(inode->i_sb,key);				AFFS_BLOCK(bh->b_data,inode,j) = 0;				break;			}			inode->u.affs_i.i_lastblock++;			DATA_FRONT(ebh)->primary_type    = ntohl(T_DATA);			DATA_FRONT(ebh)->header_key      = ntohl(inode->i_ino);			DATA_FRONT(ebh)->sequence_number = ntohl(inode->u.affs_i.i_lastblock + 1);			if (pbh) {				DATA_FRONT(pbh)->data_size = ntohl(AFFS_I2BSIZE(inode) - 24);				DATA_FRONT(pbh)->next_data = ntohl(key);				affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5);				mark_buffer_dirty(pbh,0);				mark_buffer_dirty(ebh,0);				affs_brelse(pbh);			}			pbh = ebh;			j++;		}		if (pt == T_SHORT)			((struct file_front *)bh->b_data)->first_data =								AFFS_BLOCK(bh->b_data,inode,0);		((struct file_front *)bh->b_data)->block_count = ntohl(j);		affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);		mark_buffer_dirty(bh,1);		if (block < j) {			if (pbh)				affs_brelse(pbh);			break;		}		if (j < AFFS_I2HSIZE(inode)) {			affs_brelse(bh);			return NULL;		}		block -= AFFS_I2HSIZE(inode);		key    = htonl(FILE_END(bh->b_data,inode)->extension);		if (!key) {			key = affs_new_header(inode);			if (!key) {				affs_brelse(bh);				return NULL;			}			ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));			if (!ebh) {				affs_free_block(inode->i_sb,key);				return NULL;			}			((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST);			((struct file_front *)ebh->b_data)->own_key      = ntohl(key);			FILE_END(ebh->b_data,inode)->secondary_type      = ntohl(ST_FILE);			FILE_END(ebh->b_data,inode)->parent              = ntohl(inode->i_ino);			affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);			FILE_END(bh->b_data,inode)->extension = ntohl(key);			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);			mark_buffer_dirty(bh,1);			affs_brelse(bh);			bh = ebh;		}

⌨️ 快捷键说明

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