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

📄 namei.c

📁 这是Linux系统下的对UDF文件系统新增的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	{		do		{			symname++;		} while (*symname == '/');		pc->componentType = 1;		pc->lengthComponentIdent = 0;		pc->componentFileVersionNum = 0;		pc += sizeof(struct pathComponent);		elen += sizeof(struct pathComponent);	}	err = -ENAMETOOLONG;	while (*symname)	{		if (elen + sizeof(struct pathComponent) > eoffset)			goto out_no_entry;		pc = (struct pathComponent *)(ea + elen);		compstart = (char *)symname;		do		{			symname++;		} while (*symname && *symname != '/');		pc->componentType = 5;		pc->lengthComponentIdent = 0;		pc->componentFileVersionNum = 0;		if (compstart[0] == '.')		{			if ((symname-compstart) == 1)				pc->componentType = 4;			else if ((symname-compstart) == 2 && compstart[1] == '.')				pc->componentType = 3;		}		if (pc->componentType == 5)		{			if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))				goto out_no_entry;			if (elen + sizeof(struct pathComponent) + namelen > eoffset)				goto out_no_entry;			else				pc->lengthComponentIdent = namelen;			memcpy(pc->componentIdent, name, namelen);		}		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;		if (*symname)		{			do			{				symname++;			} while (*symname == '/');		}	}	udf_release_data(bh);	inode->i_size = elen;	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)		UDF_I_LENALLOC(inode) = inode->i_size;	mark_inode_dirty(inode);	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))		goto out_no_entry;	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));	if (UDF_SB_LVIDBH(inode->i_sb))	{		struct logicalVolHeaderDesc *lvhd;		uint64_t uniqueID;		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);		uniqueID = le64_to_cpu(lvhd->uniqueID);		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);		if (!(++uniqueID & 0x00000000FFFFFFFFUL))			uniqueID += 16;		lvhd->uniqueID = cpu_to_le64(uniqueID);		mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);	}	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);	err = 0;out:	return err;out_no_entry:	inode->i_nlink--;	mark_inode_dirty(inode);	iput(inode);	goto out;}int udf_link(struct dentry * old_dentry, struct inode * dir,	 struct dentry *dentry){	struct inode *inode = old_dentry->d_inode;	struct udf_fileident_bh fibh;	int err;	struct fileIdentDesc cfi, *fi;	if (S_ISDIR(inode->i_mode))		return -EPERM;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))		return -EPERM;#endif	if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)		return -EMLINK;	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))		return err;	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));	if (UDF_SB_LVIDBH(inode->i_sb))	{		struct logicalVolHeaderDesc *lvhd;		uint64_t uniqueID;		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);		uniqueID = le64_to_cpu(lvhd->uniqueID);		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);		if (!(++uniqueID & 0x00000000FFFFFFFFUL))			uniqueID += 16;		lvhd->uniqueID = cpu_to_le64(uniqueID);		mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);	}	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);	inode->i_nlink ++;	inode->i_ctime = CURRENT_TIME;	UDF_I_UCTIME(inode) = CURRENT_UTIME;	mark_inode_dirty(inode);	inode->i_count ++;	d_instantiate(dentry, inode);	return 0;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)/* * rename uses retrying to avoid race-conditions: at least they should be * minimal. * it tries to allocate all the blocks, then sanity-checks, and if the sanity- * checks fail, it tries to restart itself again. Very practical - no changes * are done until we know everything works ok.. and then all the changes can be * done in one fell swoop when we have claimed all the buffers needed. * * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */static int do_udf_rename(struct inode *old_dir, struct dentry *old_dentry,	struct inode *new_dir, struct dentry *new_dentry){	struct inode * old_inode, * new_inode;	struct udf_fileident_bh ofibh, nfibh;	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;	struct buffer_head *dir_bh = NULL;	int retval = -ENOENT;	if (old_dentry->d_name.len > UDF_NAME_LEN)		goto end_rename;	old_inode = old_dentry->d_inode;	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))	{		if (ofibh.sbh != ofibh.ebh)			udf_release_data(ofibh.ebh);		udf_release_data(ofibh.sbh);	}	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, lelb_to_cpu(ocfi.icb.extLocation), 0) !=		old_inode->i_ino)	{		goto end_rename;	}	new_inode = new_dentry->d_inode;	nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);	if (nfi)	{		if (!new_inode)		{			if (nfibh.sbh != nfibh.ebh)				udf_release_data(nfibh.ebh);			udf_release_data(nfibh.sbh);			nfi = NULL;		}		else		{			DQUOT_INIT(new_inode);		}	}	retval = 0;	if (new_inode == old_inode)		goto end_rename;	if (S_ISDIR(old_inode->i_mode))	{		uint32_t offset = udf_ext0_offset(old_inode);		retval = -EINVAL;		if (is_subdir(new_dentry, old_dentry))			goto end_rename;		if (new_inode)		{			/* Prune any children before testing for busy */			if (new_dentry->d_count > 1)				shrink_dcache_parent(new_dentry);				retval = -EBUSY;				if (new_dentry->d_count > 1)					goto end_rename;			retval = -ENOTEMPTY;			if (!empty_dir(new_inode))				goto end_rename;		}		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)		{			dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -				(UDF_I_EFE(old_inode) ?					sizeof(struct extendedFileEntry) :					sizeof(struct fileEntry)),				old_inode->i_sb->s_blocksize, &offset);		}		else		{			dir_bh = udf_bread(old_inode, 0, 0, &retval);			if (!dir_bh)				goto end_rename;			dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);		}		if (!dir_fi)			goto end_rename;		if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=			old_dir->i_ino)		{			goto end_rename;		}		retval = -EMLINK;		if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)			goto end_rename;	}	if (!nfi)	{		nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);		if (!nfi)			goto end_rename;	}	new_dir->i_version = ++event;	/*	 * Like most other Unix systems, set the ctime for inodes on a	 * rename.	 */	old_inode->i_ctime = CURRENT_TIME;	UDF_I_UCTIME(old_inode) = CURRENT_UTIME;	mark_inode_dirty(old_inode);	/*	 * ok, that's it	 */	ncfi.fileVersionNum = ocfi.fileVersionNum;	ncfi.fileCharacteristics = ocfi.fileCharacteristics;	memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));	udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);	/* The old fid may have moved - find it again */	ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);	udf_delete_entry(old_inode, ofi, &ofibh, &ocfi);	old_dir->i_version = ++event;	if (new_inode)	{		new_inode->i_nlink--;		new_inode->i_ctime = CURRENT_TIME;		UDF_I_UCTIME(new_inode) = CURRENT_UTIME;		mark_inode_dirty(new_inode);	}	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;	UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;	mark_inode_dirty(old_dir);	if (dir_fi)	{		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +			cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3);		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)		{			mark_inode_dirty(old_inode);			old_inode->i_version = ++event;		}		else			mark_buffer_dirty(dir_bh, 1);		old_dir->i_nlink --;		mark_inode_dirty(old_dir);		if (new_inode)		{			new_inode->i_nlink --;			mark_inode_dirty(new_inode);		}		else		{			new_dir->i_nlink ++;			mark_inode_dirty(new_dir);		}	}	/* Update the dcache */	d_move(old_dentry, new_dentry);	if (ofi)	{		if (ofibh.sbh != ofibh.ebh)			udf_release_data(ofibh.ebh);		udf_release_data(ofibh.sbh);	}	retval = 0;end_rename:	udf_release_data(dir_bh);	if (nfi)	{		if (nfibh.sbh != nfibh.ebh)			udf_release_data(nfibh.ebh);		udf_release_data(nfibh.sbh);	}	return retval;}/* Ok, rename also locks out other renames, as they can change the parent of * a directory, and we don't want any races. Other races are checked for by * "do_rename()", which restarts if there are inconsistencies. * * Note that there is no race between different filesystems: it's only within * the same device that races occur: many renames can happen at once, as long * as they are on different partitions. * * In the udf file system, we use a lock flag stored in the memory * super-block.  This way, we really lock other renames only if they occur * on the same file system */int udf_rename(struct inode *old_dir, struct dentry *old_dentry,	struct inode *new_dir, struct dentry *new_dentry){	int result;	while (UDF_SB_RENAME_LOCK(old_dir->i_sb))		sleep_on(&UDF_SB_RENAME_WAIT(old_dir->i_sb));	UDF_SB_RENAME_LOCK(old_dir->i_sb) = 1;	result = do_udf_rename(old_dir, old_dentry, new_dir, new_dentry);	UDF_SB_RENAME_LOCK(old_dir->i_sb) = 0;	wake_up(&UDF_SB_RENAME_WAIT(old_dir->i_sb));	return result;}#else/* Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */int udf_rename (struct inode * old_dir, struct dentry * old_dentry,	struct inode * new_dir, struct dentry * new_dentry){	struct inode * old_inode, * new_inode;	struct udf_fileident_bh ofibh, nfibh;	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;	struct buffer_head *dir_bh = NULL;	int retval = -ENOENT;	old_inode = old_dentry->d_inode;	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))	{		if (ofibh.sbh != ofibh.ebh)				udf_release_data(ofibh.ebh);		udf_release_data(ofibh.sbh);	}	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, lelb_to_cpu(ocfi.icb.extLocation), 0) !=		old_inode->i_ino)	{		goto end_rename;	}	new_inode = new_dentry->d_inode;	nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);	if (nfi)	{		if (!new_inode)		{			if (nfibh.sbh != nfibh.ebh)				udf_release_data(nfibh.ebh);			udf_release_data(nfibh.sbh);			nfi = NULL;		}		else		{			DQUOT_INIT(new_inode);		}	}	if (S_ISDIR(old_inode->i_mode))	{		uint32_t offset = udf_ext0_offset(old_inode);		if (new_inode)		{			retval = -ENOTEMPTY;			if (!empty_dir(new_inode))				goto end_rename;		}		retval = -EIO;		dir_bh = udf_bread(old_inode, 0, 0, &retval);		if (!dir_bh)			goto end_rename;		dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);		if (!dir_fi)			goto end_rename;		if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=			old_dir->i_ino)		{			goto end_rename;		}		retval = -EMLINK;		if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)			goto end_rename;	}	if (!nfi)	{		nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);		if (!nfi)			goto end_rename;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)	new_dir->i_version = ++event;#else	new_dir->i_version = ++global_event;#endif	/*	 * ok, that's it	 */	ncfi.fileVersionNum = ocfi.fileVersionNum;	ncfi.fileCharacteristics = ocfi.fileCharacteristics;	memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));	udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);	/* The old fid may have moved - find it again */	ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);	udf_delete_entry(old_inode, ofi, &ofibh, &ocfi);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)	old_dir->i_version = ++event;#else	old_dir->i_version = ++global_event;#endif	if (new_inode)	{		new_inode->i_nlink--;		new_inode->i_ctime = CURRENT_TIME;		UDF_I_UCTIME(new_inode) = CURRENT_UTIME;		mark_inode_dirty(new_inode);	}	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;	UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;	mark_inode_dirty(old_dir);	if (dir_bh)	{		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +			cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3);		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)		{			mark_inode_dirty(old_inode);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)			old_inode->i_version = ++event;#else			old_inode->i_version = ++global_event;#endif		}		else			mark_buffer_dirty(dir_bh, 1);		old_dir->i_nlink --;		mark_inode_dirty(old_dir);		if (new_inode)		{			new_inode->i_nlink --;			mark_inode_dirty(new_inode);		}		else		{			new_dir->i_nlink ++;			mark_inode_dirty(new_dir);		}	}	if (ofi)	{		if (ofibh.sbh != ofibh.ebh)			udf_release_data(ofibh.ebh);		udf_release_data(ofibh.sbh);	}	retval = 0;end_rename:	udf_release_data(dir_bh);	if (nfi)	{		if (nfibh.sbh != nfibh.ebh)			udf_release_data(nfibh.ebh);		udf_release_data(nfibh.sbh);	}	return retval;}#endif

⌨️ 快捷键说明

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