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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Set defaults, but the inode is still incomplete!	 * Note: get_new_inode() sets the following on a new inode:	 *      i_sb = sb	 *      i_no = ino	 *      i_flags = sb->s_flags	 *      i_state = 0	 * clean_inode(): zero fills and sets	 *      i_count = 1	 *      i_nlink = 1	 *      i_op = NULL;	 */	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);	if (!bh) {		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",		       inode->i_ino);		make_bad_inode(inode);		return;	}	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&	    ident != TAG_IDENT_USE) {		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",		       inode->i_ino, ident);		brelse(bh);		make_bad_inode(inode);		return;	}	fe = (struct fileEntry *)bh->b_data;	if (le16_to_cpu(fe->icbTag.strategyType) == 4096) {		struct buffer_head *ibh = NULL, *nbh = NULL;		struct indirectEntry *ie;		ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident);		if (ident == TAG_IDENT_IE) {			if (ibh) {				kernel_lb_addr loc;				ie = (struct indirectEntry *)ibh->b_data;				loc = lelb_to_cpu(ie->indirectICB.extLocation);				if (ie->indirectICB.extLength &&				    (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident))) {					if (ident == TAG_IDENT_FE ||					    ident == TAG_IDENT_EFE) {						memcpy(&UDF_I_LOCATION(inode), &loc,						       sizeof(kernel_lb_addr));						brelse(bh);						brelse(ibh);						brelse(nbh);						__udf_read_inode(inode);						return;					} else {						brelse(nbh);						brelse(ibh);					}				} else {					brelse(ibh);				}			}		} else {			brelse(ibh);		}	} else if (le16_to_cpu(fe->icbTag.strategyType) != 4) {		printk(KERN_ERR "udf: unsupported strategy type: %d\n",		       le16_to_cpu(fe->icbTag.strategyType));		brelse(bh);		make_bad_inode(inode);		return;	}	udf_fill_inode(inode, bh);	brelse(bh);}static void udf_fill_inode(struct inode *inode, struct buffer_head *bh){	struct fileEntry *fe;	struct extendedFileEntry *efe;	time_t convtime;	long convtime_usec;	int offset;	fe = (struct fileEntry *)bh->b_data;	efe = (struct extendedFileEntry *)bh->b_data;	if (le16_to_cpu(fe->icbTag.strategyType) == 4)		UDF_I_STRAT4096(inode) = 0;	else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */		UDF_I_STRAT4096(inode) = 1;	UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK;	UDF_I_UNIQUE(inode) = 0;	UDF_I_LENEATTR(inode) = 0;	UDF_I_LENEXTENTS(inode) = 0;	UDF_I_LENALLOC(inode) = 0;	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE) {		UDF_I_EFE(inode) = 1;		UDF_I_USE(inode) = 0;		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry))) {			make_bad_inode(inode);			return;		}		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry),		       inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));	} else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) {		UDF_I_EFE(inode) = 0;		UDF_I_USE(inode) = 0;		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry))) {			make_bad_inode(inode);			return;		}		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry),		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));	} else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) {		UDF_I_EFE(inode) = 0;		UDF_I_USE(inode) = 1;		UDF_I_LENALLOC(inode) =		    le32_to_cpu(((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry))) {			make_bad_inode(inode);			return;		}		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry),		       inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));		return;	}	inode->i_uid = le32_to_cpu(fe->uid);	if (inode->i_uid == -1 ||	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;	inode->i_gid = le32_to_cpu(fe->gid);	if (inode->i_gid == -1 ||	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) ||	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);	if (!inode->i_nlink)		inode->i_nlink = 1;	inode->i_size = le64_to_cpu(fe->informationLength);	UDF_I_LENEXTENTS(inode) = inode->i_size;	inode->i_mode = udf_convert_permissions(fe);	inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;	if (UDF_I_EFE(inode) == 0) {		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<			(inode->i_sb->s_blocksize_bits - 9);		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(fe->accessTime))) {			inode->i_atime.tv_sec = convtime;			inode->i_atime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);		}		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(fe->modificationTime))) {			inode->i_mtime.tv_sec = convtime;			inode->i_mtime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);		}		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(fe->attrTime))) {			inode->i_ctime.tv_sec = convtime;			inode->i_ctime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);		}		UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);		UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);		UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);		offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);	} else {		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<		    (inode->i_sb->s_blocksize_bits - 9);		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(efe->accessTime))) {			inode->i_atime.tv_sec = convtime;			inode->i_atime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);		}		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(efe->modificationTime))) {			inode->i_mtime.tv_sec = convtime;			inode->i_mtime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);		}		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(efe->createTime))) {			UDF_I_CRTIME(inode).tv_sec = convtime;			UDF_I_CRTIME(inode).tv_nsec = convtime_usec * 1000;		} else {			UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb);		}		if (udf_stamp_to_time(&convtime, &convtime_usec,				      lets_to_cpu(efe->attrTime))) {			inode->i_ctime.tv_sec = convtime;			inode->i_ctime.tv_nsec = convtime_usec * 1000;		} else {			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);		}		UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);		UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);		UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);		offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);	}	switch (fe->icbTag.fileType) {	case ICBTAG_FILE_TYPE_DIRECTORY:		inode->i_op = &udf_dir_inode_operations;		inode->i_fop = &udf_dir_operations;		inode->i_mode |= S_IFDIR;		inc_nlink(inode);		break;	case ICBTAG_FILE_TYPE_REALTIME:	case ICBTAG_FILE_TYPE_REGULAR:	case ICBTAG_FILE_TYPE_UNDEF:		if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)			inode->i_data.a_ops = &udf_adinicb_aops;		else			inode->i_data.a_ops = &udf_aops;		inode->i_op = &udf_file_inode_operations;		inode->i_fop = &udf_file_operations;		inode->i_mode |= S_IFREG;		break;	case ICBTAG_FILE_TYPE_BLOCK:		inode->i_mode |= S_IFBLK;		break;	case ICBTAG_FILE_TYPE_CHAR:		inode->i_mode |= S_IFCHR;		break;	case ICBTAG_FILE_TYPE_FIFO:		init_special_inode(inode, inode->i_mode | S_IFIFO, 0);		break;	case ICBTAG_FILE_TYPE_SOCKET:		init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);		break;	case ICBTAG_FILE_TYPE_SYMLINK:		inode->i_data.a_ops = &udf_symlink_aops;		inode->i_op = &page_symlink_inode_operations;		inode->i_mode = S_IFLNK | S_IRWXUGO;		break;	default:		printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n",		       inode->i_ino, fe->icbTag.fileType);		make_bad_inode(inode);		return;	}	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {		struct deviceSpec *dsea = (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);		if (dsea) {			init_special_inode(inode, inode->i_mode,					   MKDEV(le32_to_cpu(dsea->majorDeviceIdent),						 le32_to_cpu(dsea->minorDeviceIdent)));			/* Developer ID ??? */		} else {			make_bad_inode(inode);		}	}}static int udf_alloc_i_data(struct inode *inode, size_t size){	UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);	if (!UDF_I_DATA(inode)) {		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n",		       inode->i_ino);		return -ENOMEM;	}	return 0;}static mode_t udf_convert_permissions(struct fileEntry *fe){	mode_t mode;	uint32_t permissions;	uint32_t flags;	permissions = le32_to_cpu(fe->permissions);	flags = le16_to_cpu(fe->icbTag.flags);	mode =	(( permissions      ) & S_IRWXO) |		(( permissions >> 2 ) & S_IRWXG) |		(( permissions >> 4 ) & S_IRWXU) |		(( flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) |		(( flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) |		(( flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0);	return mode;}/* * udf_write_inode * * PURPOSE *	Write out the specified inode. * * DESCRIPTION *	This routine is called whenever an inode is synced. *	Currently this routine is just a placeholder. * * HISTORY *	July 1, 1997 - Andrew E. Mileski *	Written, tested, and released. */int udf_write_inode(struct inode *inode, int sync){	int ret;	lock_kernel();	ret = udf_update_inode(inode, sync);	unlock_kernel();	return ret;}int udf_sync_inode(struct inode *inode){	return udf_update_inode(inode, 1);}static int udf_update_inode(struct inode *inode, int do_sync){	struct buffer_head *bh = NULL;	struct fileEntry *fe;	struct extendedFileEntry *efe;	uint32_t udfperms;	uint16_t icbflags;	uint16_t crclen;	int i;	kernel_timestamp cpu_time;	int err = 0;	bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));	if (!bh) {		udf_debug("bread failure\n");		return -EIO;	}	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);	fe = (struct fileEntry *)bh->b_data;	efe = (struct extendedFileEntry *)bh->b_data;	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) {		struct unallocSpaceEntry *use =			(struct unallocSpaceEntry *)bh->b_data;		use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode),		       inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));		crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) - sizeof(tag);		use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);		use->descTag.descCRCLength = cpu_to_le16(crclen);		use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));		use->descTag.tagChecksum = 0;		for (i = 0; i < 16; i++) {			if (i != 4)				use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i];		}		mark_buffer_dirty(bh);		brelse(bh);		return err;	}	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))		fe->uid = cpu_to_le32(-1);	else		fe->uid = cpu_to_le32(inode->i_uid);	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))		fe->gid = cpu_to_le32(-1);	else		fe->gid = cpu_to_le32(inode->i_gid);	udfperms =	((inode->i_mode & S_IRWXO)     ) |			((inode->i_mode & S_IRWXG) << 2) |			((inode->i_mode & S_IRWXU) << 4);	udfperms |=	(le32_to_cpu(fe->permissions) &			(FE_PERM_O_DELETE | FE_PERM_O_CHATTR |			 FE_PERM_G_DELETE | FE_PERM_G_CHATTR |			 FE_PERM_U_DELETE | FE_PERM_U_CHATTR));	fe->permissions = cpu_to_le32(udfperms);	if (S_ISDIR(inode->i_mode))		fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);	else		fe->fileLinkCount = cpu_to_le16(inode->i_nlink);	fe->informationLength = cpu_to_le64(inode->i_size);	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {		regid *eid;		struct deviceSpec *dsea =			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);		if (!dsea) {			dsea = (struct deviceSpec *)				udf_add_extendedattr(inode,						     sizeof(struct deviceSpec) +						     sizeof(regid), 12, 0x3);			dsea->attrType = cpu_to_le32(12);			dsea->attrSubtype = 1;			dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) +						       sizeof(regid));			dsea->impUseLength = cpu_to_le32(sizeof(regid));		}		eid = (regid *)dsea->impUse;		memset(eid, 0, sizeof(regid));		strcpy(eid->ident, UDF_ID_DEVELOPER);		eid->identSuffix[0] = UDF_OS_CLASS_UNIX;		eid->identSuffix[1] = UDF_OS_ID_LINUX;		dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));		dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));	}	if (UDF_I_EFE(inode) == 0) {		memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode),		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));		fe->logicalBlocksRecorded = cpu_to_le64(			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>			(inode->i_sb->s_blocksize_bits - 9));		if (udf_time_to_stamp(&cpu_time, inode->i_atime))			fe->accessTime = cpu_to_lets(cpu_time);		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))			fe->modificationTime = cpu_to_lets(cpu_time);		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))			fe->attrTime = cpu_to_lets(cpu_time);		memset(&(fe->impIdent), 0, sizeof(regid));		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;		fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));		fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));		fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);		crclen = sizeof(struct fileEntry);	} else {		memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode),		       inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));		efe->objectSize = cpu_to_le64(inode->i_size);		efe->logicalBlocksRecorded = cpu_to_le64(			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>			(inode->i_sb->s_blocksize_bits - 9));		if (UDF_I_CRTIME(inode).tv_sec > inode->i_atime.tv_sec ||		    (UDF_I_CRTIME(inode).tv_sec == inode->i_atime.tv_sec &&		     UDF_I_CRTIME(inode).tv_nsec > inode->i_atime.tv_nsec)) {			UDF_I_CRTIME(inode) = inode->i_atime;		}		if (UDF_I_CRTIME(inode).tv_sec > inode->i_mtime.tv_sec ||		    (UDF_I_CRTIME(inode).tv_sec == inode->i_mtime.tv_sec &&		     UDF_I_CRTIME(inode).tv_nsec > inode->i_mtime.tv_nsec)) {			UDF_I_CRTIME(inode) = inode->i_mtime;		}		if (UDF_I_CRTIME(inode).tv_sec > inode->i_ctime.tv_sec ||		    (UDF_I_CRTIME(inode).tv_sec == inode->i_ctime.tv_sec &&		     UDF_I_CRTIME(inode).tv_nsec > inode->i_ctime.tv_nsec)) {			UDF_I_CRTIME(inode) = inode->i_ctime;		}		if (udf_time_to_stamp(&cpu_time, inode->i_atime))			efe->accessTime = cpu_to_lets(cpu_time);		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))			efe->modificationTime = cpu_to_lets(cpu_time);		if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode)))			efe->createTime = cpu_to_lets(cpu_time);		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))			efe->attrTime = cpu_to_lets(cpu_time);		memset(&(efe->impIdent), 0, sizeof(regid));

⌨️ 快捷键说明

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