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

📄 inode.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 3 页
字号:
					goto abort;				ninode = iget(inode->i_sb, nextino);				if (!ninode)					goto abort;				firstext  = ninode->u.isofs_i.i_first_extent;				sect_size = ninode->u.isofs_i.i_section_size;				nextino   = ninode->u.isofs_i.i_next_section_ino;				iput(ninode);								if (++section > 100) {					printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");					printk("isofs_get_blocks: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",					       inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);					goto abort;				}			}		}				if ( *bh_result ) {			(*bh_result)->b_dev      = inode->i_dev;			(*bh_result)->b_blocknr  = firstext + b_off - offset;			(*bh_result)->b_state   |= (1UL << BH_Mapped);		} else {			*bh_result = sb_getblk(inode->i_sb, firstext+b_off-offset);			if ( !*bh_result )				goto abort;		}		bh_result++;	/* Next buffer head */		b_off++;	/* Next buffer offset */		nblocks--;		rv++;	}abort:	unlock_kernel();	return rv;}/* * Used by the standard interfaces. */static int isofs_get_block(struct inode *inode, long iblock,		    struct buffer_head *bh_result, int create){	if ( create ) {		printk("isofs_get_block: Kernel tries to allocate a block\n");		return -EROFS;	}	return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;}static int isofs_bmap(struct inode *inode, int block){	struct buffer_head dummy;	int error;	dummy.b_state = 0;	dummy.b_blocknr = -1000;	error = isofs_get_block(inode, block, &dummy, 0);	if (!error)		return dummy.b_blocknr;	return 0;}struct buffer_head *isofs_bread(struct inode *inode, unsigned int block){	unsigned int blknr = isofs_bmap(inode, block);	if (!blknr)		return NULL;	return sb_bread(inode->i_sb, blknr);}static int isofs_readpage(struct file *file, struct page *page){	return block_read_full_page(page,isofs_get_block);}static int _isofs_bmap(struct address_space *mapping, long block){	return generic_block_bmap(mapping,block,isofs_get_block);}static struct address_space_operations isofs_aops = {	readpage: isofs_readpage,	sync_page: block_sync_page,	bmap: _isofs_bmap};static inline void test_and_set_uid(uid_t *p, uid_t value){	if(value) {		*p = value;	}}static inline void test_and_set_gid(gid_t *p, gid_t value){        if(value) {                *p = value;        }}static int isofs_read_level3_size(struct inode * inode){	unsigned long f_pos = inode->i_ino;	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);	int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;	struct buffer_head * bh = NULL;	unsigned long block, offset;	int i = 0;	int more_entries = 0;	struct iso_directory_record * tmpde = NULL;	inode->i_size = 0;	inode->u.isofs_i.i_next_section_ino = 0;	block = f_pos >> ISOFS_BUFFER_BITS(inode);	offset = f_pos & (bufsize-1);	do {		struct iso_directory_record * de;		unsigned int de_len;		if (!bh) {			bh = sb_bread(inode->i_sb, block);			if (!bh)				goto out_noread;		}		de = (struct iso_directory_record *) (bh->b_data + offset);		de_len = *(unsigned char *) de;		if (de_len == 0) {			brelse(bh);			bh = NULL;			f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);			block = f_pos >> ISOFS_BUFFER_BITS(inode);			offset = 0;			continue;		}		offset += de_len;		/* Make sure we have a full directory entry */		if (offset >= bufsize) {			int slop = bufsize - offset + de_len;			if (!tmpde) {				tmpde = kmalloc(256, GFP_KERNEL);				if (!tmpde)					goto out_nomem;			}			memcpy(tmpde, de, slop);			offset &= bufsize - 1;			block++;			brelse(bh);			bh = NULL;			if (offset) {				bh = sb_bread(inode->i_sb, block);				if (!bh)					goto out_noread;				memcpy((void *) tmpde + slop, bh->b_data, offset);			}			de = tmpde;		}		inode->i_size += isonum_733(de->size);		if (i == 1)			inode->u.isofs_i.i_next_section_ino = f_pos;		more_entries = de->flags[-high_sierra] & 0x80;		f_pos += de_len;		i++;		if(i > 100)			goto out_toomany;	} while(more_entries);out:	if (tmpde)		kfree(tmpde);	if (bh)		brelse(bh);	return 0;out_nomem:	if (bh)		brelse(bh);	return -ENOMEM;out_noread:	printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);	if (tmpde)		kfree(tmpde);	return -EIO;out_toomany:	printk(KERN_INFO "isofs_read_level3_size: "		"More than 100 file sections ?!?, aborting...\n"	  	"isofs_read_level3_size: inode=%lu ino=%lu\n",		inode->i_ino, f_pos);	goto out;}static void isofs_read_inode(struct inode * inode){	struct super_block *sb = inode->i_sb;	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);	int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);	int high_sierra = sb->u.isofs_sb.s_high_sierra;	struct buffer_head * bh = NULL;	struct iso_directory_record * de;	struct iso_directory_record * tmpde = NULL;	unsigned int de_len;	unsigned long offset;	int volume_seq_no, i;	bh = sb_bread(inode->i_sb, block);	if (!bh)		goto out_badread;	offset = (inode->i_ino & (bufsize - 1));	de = (struct iso_directory_record *) (bh->b_data + offset);	de_len = *(unsigned char *) de;	if (offset + de_len > bufsize) {		int frag1 = bufsize - offset;		tmpde = kmalloc(de_len, GFP_KERNEL);		if (tmpde == NULL) {			printk(KERN_INFO "isofs_read_inode: out of memory\n");			goto fail;		}		memcpy(tmpde, bh->b_data + offset, frag1);		brelse(bh);		bh = sb_bread(inode->i_sb, ++block);		if (!bh)			goto out_badread;		memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);		de = tmpde;	}	/* Assume it is a normal-format file unless told otherwise */	inode->u.isofs_i.i_file_format = isofs_file_normal;	if (de->flags[-high_sierra] & 2) {		inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;		inode->i_nlink = 1; /* Set to 1.  We know there are 2, but				       the find utility tries to optimize				       if it is 2, and it screws up.  It is				       easier to give 1 which tells find to				       do it the hard way. */	} else { 		/* Everybody gets to read the file. */		inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;		inode->i_nlink = 1;	        inode->i_mode |= S_IFREG;		/* If there are no periods in the name,		 * then set the execute permission bit		 */		for(i=0; i< de->name_len[0]; i++)			if(de->name[i]=='.' || de->name[i]==';')				break;		if(i == de->name_len[0] || de->name[i] == ';')			inode->i_mode |= S_IXUGO; /* execute permission */	}	inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;	inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;	inode->i_blocks = inode->i_blksize = 0;	inode->u.isofs_i.i_section_size = isonum_733 (de->size);	if(de->flags[-high_sierra] & 0x80) {		if(isofs_read_level3_size(inode)) goto fail;	} else {		inode->i_size = isonum_733 (de->size);	}	/*	 * The ISO-9660 filesystem only stores 32 bits for file size.	 * mkisofs handles files up to 2GB-2 = 2147483646 = 0x7FFFFFFE bytes	 * in size. This is according to the large file summit paper from 1996.	 * WARNING: ISO-9660 filesystems > 1 GB and even > 2 GB are fully	 *	    legal. Do not prevent to use DVD's schilling@fokus.gmd.de	 */	if ((inode->i_size < 0 || inode->i_size > 0x7FFFFFFE) &&	    inode->i_sb->u.isofs_sb.s_cruft == 'n') {		printk(KERN_WARNING "Warning: defective CD-ROM.  "		       "Enabling \"cruft\" mount option.\n");		inode->i_sb->u.isofs_sb.s_cruft = 'y';	}	/*	 * Some dipshit decided to store some other bit of information	 * in the high byte of the file length.  Catch this and holler.	 * WARNING: this will make it impossible for a file to be > 16MB	 * on the CDROM.	 */	if (inode->i_sb->u.isofs_sb.s_cruft == 'y' &&	    inode->i_size & 0xff000000) {		inode->i_size &= 0x00ffffff;	}	if (de->interleave[0]) {		printk("Interleaved files not (yet) supported.\n");		inode->i_size = 0;	}	/* I have no idea what file_unit_size is used for, so	   we will flag it for now */	if (de->file_unit_size[0] != 0) {		printk("File unit size != 0 for ISO file (%ld).\n",		       inode->i_ino);	}	/* I have no idea what other flag bits are used for, so	   we will flag it for now */#ifdef DEBUG	if((de->flags[-high_sierra] & ~2)!= 0){		printk("Unusual flag settings for ISO file (%ld %x).\n",		       inode->i_ino, de->flags[-high_sierra]);	}#endif	inode->i_mtime = inode->i_atime = inode->i_ctime =		iso_date(de->date, high_sierra);	inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +					   isonum_711 (de->ext_attr_length));	/* Set the number of blocks for stat() - should be done before RR */	inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */	inode->i_blocks  = (inode->i_size + 511) >> 9;	/*	 * Now test for possible Rock Ridge extensions which will override	 * some of these numbers in the inode structure.	 */	if (!high_sierra) {		parse_rock_ridge_inode(de, inode);		/* if we want uid/gid set, override the rock ridge setting */		test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);		test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);	}	/* get the volume sequence number */	volume_seq_no = isonum_723 (de->volume_sequence_number) ;	/*	 * Disable checking if we see any volume number other than 0 or 1.	 * We could use the cruft option, but that has multiple purposes, one	 * of which is limiting the file size to 16Mb.  Thus we silently allow	 * volume numbers of 0 to go through without complaining.	 */	if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&	    (volume_seq_no != 0) && (volume_seq_no != 1)) {		printk(KERN_WARNING "Warning: defective CD-ROM "		       "(volume sequence number %d). "		       "Enabling \"cruft\" mount option.\n", volume_seq_no);		inode->i_sb->u.isofs_sb.s_cruft = 'y';	}	/* Install the inode operations vector */#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS	if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&	    (volume_seq_no != 0) && (volume_seq_no != 1)) {		printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n");	} else#endif /*IGNORE_WRONG_MULTI_VOLUME_SPECS */	{		if (S_ISREG(inode->i_mode)) {			inode->i_fop = &generic_ro_fops;			switch ( inode->u.isofs_i.i_file_format ) {#ifdef CONFIG_ZISOFS			case isofs_file_compressed:				inode->i_data.a_ops = &zisofs_aops;				break;#endif			default:				inode->i_data.a_ops = &isofs_aops;				break;			}		} else if (S_ISDIR(inode->i_mode)) {			inode->i_op = &isofs_dir_inode_operations;			inode->i_fop = &isofs_dir_operations;		} else if (S_ISLNK(inode->i_mode)) {			inode->i_op = &page_symlink_inode_operations;			inode->i_data.a_ops = &isofs_symlink_aops;		} else			/* XXX - parse_rock_ridge_inode() had already set i_rdev. */			init_special_inode(inode, inode->i_mode,					   kdev_t_to_nr(inode->i_rdev));	} out:	if (tmpde)		kfree(tmpde);	if (bh)		brelse(bh);	return; out_badread:	printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); fail:	make_bad_inode(inode);	goto out;}#ifdef LEAK_CHECK#undef malloc#undef free_s#undef sb_bread#undef brelsevoid * leak_check_malloc(unsigned int size){  void * tmp;  check_malloc++;  tmp = kmalloc(size, GFP_KERNEL);  return tmp;}void leak_check_free_s(void * obj, int size){  check_malloc--;  return kfree(obj);}struct buffer_head * leak_check_bread(struct super_block *sb, int block){  check_bread++;  return sb_bread(sb, block);}void leak_check_brelse(struct buffer_head * bh){  check_bread--;  return brelse(bh);}#endifstatic DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);static int __init init_iso9660_fs(void){#ifdef CONFIG_ZISOFS	int err;	err = zisofs_init();	if ( err )		return err;#endif        return register_filesystem(&iso9660_fs_type);}static void __exit exit_iso9660_fs(void){        unregister_filesystem(&iso9660_fs_type);#ifdef CONFIG_ZISOFS	zisofs_cleanup();#endif}EXPORT_NO_SYMBOLS;module_init(init_iso9660_fs)module_exit(exit_iso9660_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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