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

📄 namei.c

📁 这是Linux系统下的对UDF文件系统新增的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)		{			block = UDF_I_LOCATION(dir).logicalBlockNum;			fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));		}		else		{			block = eloc.logicalBlockNum + ((elen - 1) >>				dir->i_sb->s_blocksize_bits);			fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);		}	}	else	{		fibh->soffset = fibh->eoffset - sb->s_blocksize;		fibh->eoffset += nfidlen - sb->s_blocksize;		if (fibh->sbh != fibh->ebh)		{			udf_release_data(fibh->sbh);			fibh->sbh = fibh->ebh;		}		block = eloc.logicalBlockNum + ((elen - 1) >>			dir->i_sb->s_blocksize_bits);		if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))		{			udf_release_data(bh);			udf_release_data(fibh->sbh);			return NULL;		}		if (!(fibh->soffset))		{			if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==				(EXT_RECORDED_ALLOCATED >> 30))			{				block = eloc.logicalBlockNum + ((elen - 1) >>					dir->i_sb->s_blocksize_bits);			}			else				block ++;			udf_release_data(fibh->sbh);			fibh->sbh = fibh->ebh;			fi = (struct fileIdentDesc *)(fibh->sbh->b_data);		}		else		{			fi = (struct fileIdentDesc *)				(fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);		}	}	memset(cfi, 0, sizeof(struct fileIdentDesc));	if (UDF_SB_UDFREV(sb) >= 0x0200)		udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, sizeof(tag));	else		udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, sizeof(tag));	cfi->fileVersionNum = cpu_to_le16(1);	cfi->lengthFileIdent = namelen;	cfi->lengthOfImpUse = cpu_to_le16(0);	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))	{		udf_release_data(bh);		dir->i_size += nfidlen;		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)			UDF_I_LENALLOC(dir) += nfidlen;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)		dir->i_version = ++event;#else		dir->i_version = ++global_event;#endif		mark_inode_dirty(dir);		return fi;	}	else	{		udf_release_data(bh);		if (fibh->sbh != fibh->ebh)			udf_release_data(fibh->ebh);		udf_release_data(fibh->sbh);		*err = -EIO;		return NULL;	}}static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,	struct udf_fileident_bh *fibh, struct fileIdentDesc *cfi){	cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))		memset(&(cfi->icb), 0x00, sizeof(long_ad));	return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);}int udf_create(struct inode *dir, struct dentry *dentry, int mode){	struct udf_fileident_bh fibh;	struct inode *inode;	struct fileIdentDesc cfi, *fi;	int err;	inode = udf_new_inode(dir, mode, &err);	if (!inode)		return err;	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)		inode->i_op = &udf_file_inode_operations_adinicb;	else		inode->i_op = &udf_file_inode_operations;	inode->i_mode = mode;	mark_inode_dirty(inode);	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))	{		inode->i_nlink --;		mark_inode_dirty(inode);		iput(inode);		return err;	}	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)	{		mark_inode_dirty(dir);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)		dir->i_version = ++event;#else		dir->i_version = ++global_event;#endif	}	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);	d_instantiate(dentry, inode);	return 0;}int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev){	struct inode * inode;	struct udf_fileident_bh fibh;	int err;	struct fileIdentDesc cfi, *fi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	err = -ENAMETOOLONG;	if (dentry->d_name.len >= UDF_NAME_LEN)		goto out;#endif	err = -EIO;	inode = udf_new_inode(dir, mode, &err);	if (!inode)		goto out;	inode->i_uid = current->fsuid;	inode->i_mode = mode;	inode->i_op = NULL;	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))	{		inode->i_nlink --;		mark_inode_dirty(inode);		iput(inode);		return err;	}	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)	{		mark_inode_dirty(dir);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)		dir->i_version = ++event;#else		dir->i_version = ++global_event;#endif	}	if (S_ISREG(inode->i_mode))	{		if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)			inode->i_op = &udf_file_inode_operations_adinicb;		else			inode->i_op = &udf_file_inode_operations;	}	else if (S_ISCHR(inode->i_mode))	{		inode->i_op = &chrdev_inode_operations;	} 	else if (S_ISBLK(inode->i_mode))	{		inode->i_op = &blkdev_inode_operations;	}	else if (S_ISFIFO(inode->i_mode))	{		init_fifo(inode);	}	if (S_ISBLK(mode) || S_ISCHR(mode))		inode->i_rdev = to_kdev_t(rdev);	mark_inode_dirty(inode);	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);	d_instantiate(dentry, inode);	err = 0;out:	return err;}int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode){	struct inode * inode;	struct udf_fileident_bh fibh;	int err;	struct fileIdentDesc cfi, *fi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	err = -ENAMETOOLONG;	if (dentry->d_name.len >= UDF_NAME_LEN)		goto out;#endif	err = -EMLINK;	if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1)		goto out;	err = -EIO;	inode = udf_new_inode(dir, S_IFDIR, &err);	if (!inode)		goto out;	inode->i_op = &udf_dir_inode_operations;	if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err)))	{		inode->i_nlink--;		mark_inode_dirty(inode);		iput(inode);		goto out;	}	inode->i_nlink = 2;	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =		cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);	cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;	udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);	udf_release_data(fibh.sbh);	inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);	if (dir->i_mode & S_ISGID)		inode->i_mode |= S_ISGID;	mark_inode_dirty(inode);	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))	{		inode->i_nlink = 0;		mark_inode_dirty(inode);		iput(inode);		goto out;	}	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);	cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)	dir->i_version = ++event;#else	dir->i_version = ++global_event;#endif	dir->i_nlink++;	mark_inode_dirty(dir);	d_instantiate(dentry, inode);	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);	err = 0;out:	return err;}static int empty_dir(struct inode *dir){	struct fileIdentDesc *fi, cfi;	struct udf_fileident_bh fibh;	loff_t f_pos;	int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;	int block;	lb_addr bloc, eloc;	uint32_t extoffset, elen, offset;	struct buffer_head *bh = NULL;	f_pos = (udf_ext0_offset(dir) >> 2);	fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)		fibh.sbh = fibh.ebh = NULL;	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))	{		offset >>= dir->i_sb->s_blocksize_bits;		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)		{			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)				extoffset -= sizeof(short_ad);			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)				extoffset -= sizeof(long_ad);		}		else			offset = 0;		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))		{			udf_release_data(bh);			return 0;		}	}	else	{		udf_release_data(bh);		return 0;	}	while ( (f_pos < size) )	{		fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);		if (!fi)		{			if (fibh.sbh != fibh.ebh)				udf_release_data(fibh.ebh);			udf_release_data(fibh.sbh);			udf_release_data(bh);			return 0;		}		if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)		{			if (fibh.sbh != fibh.ebh)				udf_release_data(fibh.ebh);			udf_release_data(fibh.sbh);			udf_release_data(bh);			return 0;		}	}	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);	udf_release_data(bh);	return 1;}int udf_rmdir(struct inode * dir, struct dentry * dentry){	int retval;	struct inode * inode = dentry->d_inode;	struct udf_fileident_bh fibh;	struct fileIdentDesc *fi, cfi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	retval = -ENAMETOOLONG;	if (dentry->d_name.len >= UDF_NAME_LEN)		goto out;#endif	retval = -ENOENT;	fi = udf_find_entry(dir, dentry, &fibh, &cfi);	if (!fi)		goto out;	DQUOT_INIT(inode);	retval = -EIO;	if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino)		goto end_rmdir;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	if (!empty_dir(inode))		retval = -ENOTEMPTY;	else if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=		inode->i_ino)	{		retval = -ENOENT;	}	else	{		retval = udf_delete_entry(dir, fi, &fibh, &cfi);		dir->i_version = ++event;	}#else	retval = -ENOTEMPTY;	if (!empty_dir(inode))		goto end_rmdir;	retval = udf_delete_entry(dir, fi, &fibh, &cfi);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)	dir->i_version = ++event;#else	dir->i_version = ++global_event;#endif#endif	if (retval)		goto end_rmdir;	if (inode->i_nlink != 2)		udf_warning(inode->i_sb, "udf_rmdir",			"empty directory has nlink != 2 (%d)",			inode->i_nlink);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)	inode->i_version = ++event;#else	inode->i_version = ++global_event;#endif	inode->i_nlink = 0;	inode->i_size = 0;	mark_inode_dirty(inode);	dir->i_nlink --;	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;	UDF_I_UCTIME(inode) = UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME;	mark_inode_dirty(dir);	d_delete(dentry);end_rmdir:	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);out:	return retval;}int udf_unlink(struct inode * dir, struct dentry * dentry){	int retval;	struct inode * inode = dentry->d_inode;	struct udf_fileident_bh fibh;	struct fileIdentDesc *fi;	struct fileIdentDesc cfi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	retval = -ENAMETOOLONG;	if (dentry->d_name.len >= UDF_NAME_LEN)		goto out;#endif	retval = -ENOENT;	fi = udf_find_entry(dir, dentry, &fibh, &cfi);	if (!fi)		goto out;	DQUOT_INIT(inode);	retval = -EIO;	if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=		inode->i_ino)	{		goto end_unlink;	}	if (!inode->i_nlink)	{		udf_debug("Deleting nonexistent file (%lu), %d\n",			inode->i_ino, inode->i_nlink);		inode->i_nlink = 1;	}	retval = udf_delete_entry(dir, fi, &fibh, &cfi);	if (retval)		goto end_unlink;	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME;	mark_inode_dirty(dir);	inode->i_nlink--;	mark_inode_dirty(inode);	inode->i_ctime = dir->i_ctime;	retval = 0;	d_delete(dentry);	/* This also frees the inode */end_unlink:	if (fibh.sbh != fibh.ebh)		udf_release_data(fibh.ebh);	udf_release_data(fibh.sbh);out:	return retval;}int udf_symlink(struct inode * dir, struct dentry * dentry, const char * symname){	struct inode * inode;	struct pathComponent *pc;	char *compstart;	struct udf_fileident_bh fibh;	struct buffer_head *bh = NULL;	int eoffset, elen = 0;	struct fileIdentDesc *fi;	struct fileIdentDesc cfi;	char *ea;	int err;	int block;	char name[UDF_NAME_LEN];	int namelen;	if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))		goto out;	inode->i_mode = S_IFLNK | S_IRWXUGO;	inode->i_op = &udf_symlink_inode_operations;	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)	{		struct buffer_head *bh = NULL;		lb_addr bloc, eloc;		uint32_t elen, extoffset;		block = udf_new_block(inode->i_sb, inode,			UDF_I_LOCATION(inode).partitionReferenceNum,			UDF_I_LOCATION(inode).logicalBlockNum, &err);		if (!block)			goto out_no_entry;		bloc = UDF_I_LOCATION(inode);		eloc.logicalBlockNum = block;		eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;		elen = inode->i_sb->s_blocksize;		UDF_I_LENEXTENTS(inode) = elen;		extoffset = udf_file_entry_alloc_offset(inode);		udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);		udf_release_data(bh);		inode->i_blocks = inode->i_sb->s_blocksize / 512;		block = udf_get_pblock(inode->i_sb, block,			UDF_I_LOCATION(inode).partitionReferenceNum, 0);		bh = udf_tread(inode->i_sb, block);		ea = bh->b_data + udf_ext0_offset(inode);	}	else		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);	eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);	pc = (struct pathComponent *)ea;	if (*symname == '/')

⌨️ 快捷键说明

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