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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);	mark_inode_dirty(dir);end_rmdir:	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);out:	unlock_kernel();	return retval;}static 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;	kernel_lb_addr tloc;	retval = -ENOENT;	lock_kernel();	fi = udf_find_entry(dir, dentry, &fibh, &cfi);	if (!fi)		goto out;	retval = -EIO;	tloc = lelb_to_cpu(cfi.icb.extLocation);	if (udf_get_lb_pblock(dir->i_sb, tloc, 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_fs_time(dir->i_sb);	mark_inode_dirty(dir);	inode_dec_link_count(inode);	inode->i_ctime = dir->i_ctime;	retval = 0;end_unlink:	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);out:	unlock_kernel();	return retval;}static 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 extent_position epos = {};	int eoffset, elen = 0;	struct fileIdentDesc *fi;	struct fileIdentDesc cfi;	char *ea;	int err;	int block;	char name[UDF_NAME_LEN];	int namelen;	lock_kernel();	if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))		goto out;	inode->i_mode = S_IFLNK | S_IRWXUGO;	inode->i_data.a_ops = &udf_symlink_aops;	inode->i_op = &page_symlink_inode_operations;	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB) {		kernel_lb_addr eloc;		uint32_t elen;		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;		epos.block = UDF_I_LOCATION(inode);		epos.offset = udf_file_entry_alloc_offset(inode);		epos.bh = NULL;		eloc.logicalBlockNum = block;		eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;		elen = inode->i_sb->s_blocksize;		UDF_I_LENEXTENTS(inode) = elen;		udf_add_aext(inode, &epos, eloc, elen, 0);		brelse(epos.bh);		block = udf_get_pblock(inode->i_sb, block,				       UDF_I_LOCATION(inode).partitionReferenceNum, 0);		epos.bh = udf_tread(inode->i_sb, block);		lock_buffer(epos.bh);		memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);		set_buffer_uptodate(epos.bh);		unlock_buffer(epos.bh);		mark_buffer_dirty_inode(epos.bh, inode);		ea = epos.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 == '/') {		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) {			namelen = udf_put_filename(inode->i_sb, compstart, name,						   symname - compstart);			if (!namelen)				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 == '/');		}	}	brelse(epos.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);		*(__le32 *)((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));	}	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {		mark_inode_dirty(dir);	}	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	d_instantiate(dentry, inode);	err = 0;out:	unlock_kernel();	return err;out_no_entry:	inode_dec_link_count(inode);	iput(inode);	goto out;}static 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;	struct fileIdentDesc cfi, *fi;	int err;	lock_kernel();	if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {		unlock_kernel();		return -EMLINK;	}	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {		unlock_kernel();		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);		*(__le32 *)((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));	}	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {		mark_inode_dirty(dir);	}	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	inc_nlink(inode);	inode->i_ctime = current_fs_time(inode->i_sb);	mark_inode_dirty(inode);	atomic_inc(&inode->i_count);	d_instantiate(dentry, inode);	unlock_kernel();	return 0;}/* Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,		      struct inode *new_dir, struct dentry *new_dentry){	struct inode *old_inode = old_dentry->d_inode;	struct inode *new_inode = new_dentry->d_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;	kernel_lb_addr tloc;	lock_kernel();	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) {		if (ofibh.sbh != ofibh.ebh)			brelse(ofibh.ebh);		brelse(ofibh.sbh);	}	tloc = lelb_to_cpu(ocfi.icb.extLocation);	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0)	    != old_inode->i_ino)		goto end_rename;	nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);	if (nfi) {		if (!new_inode) {			if (nfibh.sbh != nfibh.ebh)				brelse(nfibh.ebh);			brelse(nfibh.sbh);			nfi = NULL;		}	}	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;		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;		tloc = lelb_to_cpu(dir_fi->icb.extLocation);		if (udf_get_lb_pblock(old_inode->i_sb, tloc, 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;	}	/*	 * Like most other Unix systems, set the ctime for inodes on a	 * rename.	 */	old_inode->i_ctime = current_fs_time(old_inode->i_sb);	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_dir, ofi, &ofibh, &ocfi);	if (new_inode) {		new_inode->i_ctime = current_fs_time(new_inode->i_sb);		inode_dec_link_count(new_inode);	}	old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);	mark_inode_dirty(old_dir);	if (dir_fi) {		dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir));		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +						le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) {			mark_inode_dirty(old_inode);		} else {			mark_buffer_dirty_inode(dir_bh, old_inode);		}		inode_dec_link_count(old_dir);		if (new_inode) {			inode_dec_link_count(new_inode);		} else {			inc_nlink(new_dir);			mark_inode_dirty(new_dir);		}	}	if (ofi) {		if (ofibh.sbh != ofibh.ebh)			brelse(ofibh.ebh);		brelse(ofibh.sbh);	}	retval = 0;end_rename:	brelse(dir_bh);	if (nfi) {		if (nfibh.sbh != nfibh.ebh)			brelse(nfibh.ebh);		brelse(nfibh.sbh);	}	unlock_kernel();	return retval;}const struct inode_operations udf_dir_inode_operations = {	.lookup				= udf_lookup,	.create				= udf_create,	.link				= udf_link,	.unlink				= udf_unlink,	.symlink			= udf_symlink,	.mkdir				= udf_mkdir,	.rmdir				= udf_rmdir,	.mknod				= udf_mknod,	.rename				= udf_rename,};

⌨️ 快捷键说明

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