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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;			if (poffset >= lfi) {				nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);			} else {				nameptr = fname;				memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);				memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);			}		}		if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {			if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen) {				brelse(epos.bh);				cfi->descTag.tagSerialNum = cpu_to_le16(1);				cfi->fileVersionNum = cpu_to_le16(1);				cfi->fileCharacteristics = 0;				cfi->lengthFileIdent = namelen;				cfi->lengthOfImpUse = cpu_to_le16(0);				if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {					return fi;				} else {					*err = -EIO;					return NULL;				}			}		}		if (!lfi || !dentry)			continue;		if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&		    udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name)) {			if (fibh->sbh != fibh->ebh)				brelse(fibh->ebh);			brelse(fibh->sbh);			brelse(epos.bh);			*err = -EEXIST;			return NULL;		}	}add:	f_pos += nfidlen;	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&	    sb->s_blocksize - fibh->eoffset < nfidlen) {		brelse(epos.bh);		epos.bh = NULL;		fibh->soffset -= udf_ext0_offset(dir);		fibh->eoffset -= udf_ext0_offset(dir);		f_pos -= (udf_ext0_offset(dir) >> 2);		if (fibh->sbh != fibh->ebh)			brelse(fibh->ebh);		brelse(fibh->sbh);		if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))			return NULL;		epos.block = UDF_I_LOCATION(dir);		eloc.logicalBlockNum = block;		eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;		elen = dir->i_sb->s_blocksize;		epos.offset = udf_file_entry_alloc_offset(dir);		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)			epos.offset += sizeof(short_ad);		else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)			epos.offset += sizeof(long_ad);	}	if (sb->s_blocksize - fibh->eoffset >= nfidlen) {		fibh->soffset = fibh->eoffset;		fibh->eoffset += nfidlen;		if (fibh->sbh != fibh->ebh) {			brelse(fibh->sbh);			fibh->sbh = fibh->ebh;		}		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) {			brelse(fibh->sbh);			fibh->sbh = fibh->ebh;		}		block = eloc.logicalBlockNum + ((elen - 1) >>						dir->i_sb->s_blocksize_bits);		fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err);		if (!fibh->ebh) {			brelse(epos.bh);			brelse(fibh->sbh);			return NULL;		}		if (!fibh->soffset) {			if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==			    (EXT_RECORDED_ALLOCATED >> 30)) {				block = eloc.logicalBlockNum + ((elen - 1) >>					dir->i_sb->s_blocksize_bits);			} else {				block++;			}			brelse(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)) {		brelse(epos.bh);		dir->i_size += nfidlen;		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)			UDF_I_LENALLOC(dir) += nfidlen;		mark_inode_dirty(dir);		return fi;	} else {		brelse(epos.bh);		if (fibh->sbh != fibh->ebh)			brelse(fibh->ebh);		brelse(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);}static int udf_create(struct inode *dir, struct dentry *dentry, int mode,		      struct nameidata *nd){	struct udf_fileident_bh fibh;	struct inode *inode;	struct fileIdentDesc cfi, *fi;	int err;	lock_kernel();	inode = udf_new_inode(dir, mode, &err);	if (!inode) {		unlock_kernel();		return err;	}	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 = mode;	mark_inode_dirty(inode);	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {		inode->i_nlink--;		mark_inode_dirty(inode);		iput(inode);		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));	*(__le32 *)((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 (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	unlock_kernel();	d_instantiate(dentry, inode);	return 0;}static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,		     dev_t rdev){	struct inode *inode;	struct udf_fileident_bh fibh;	struct fileIdentDesc cfi, *fi;	int err;	if (!old_valid_dev(rdev))		return -EINVAL;	lock_kernel();	err = -EIO;	inode = udf_new_inode(dir, mode, &err);	if (!inode)		goto out;	inode->i_uid = current->fsuid;	init_special_inode(inode, mode, rdev);	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {		inode->i_nlink--;		mark_inode_dirty(inode);		iput(inode);		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));	*(__le32 *)((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);	}	mark_inode_dirty(inode);	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	d_instantiate(dentry, inode);	err = 0;out:	unlock_kernel();	return err;}static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode){	struct inode *inode;	struct udf_fileident_bh fibh;	struct fileIdentDesc cfi, *fi;	int err;	lock_kernel();	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;	inode->i_fop = &udf_dir_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));	*(__le32 *)((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);	brelse(fibh.sbh);	inode->i_mode = S_IFDIR | mode;	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));	*(__le32 *)((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);	inc_nlink(dir);	mark_inode_dirty(dir);	d_instantiate(dentry, inode);	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	err = 0;out:	unlock_kernel();	return err;}static int empty_dir(struct inode *dir){	struct fileIdentDesc *fi, cfi;	struct udf_fileident_bh fibh;	loff_t f_pos;	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;	int block;	kernel_lb_addr eloc;	uint32_t elen;	sector_t offset;	struct extent_position epos = {};	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),			      &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {		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)				epos.offset -= sizeof(short_ad);			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)				epos.offset -= sizeof(long_ad);		} else {			offset = 0;		}		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {			brelse(epos.bh);			return 0;		}	} else {		brelse(epos.bh);		return 0;	}	while ((f_pos < size)) {		fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,					&elen, &offset);		if (!fi) {			if (fibh.sbh != fibh.ebh)				brelse(fibh.ebh);			brelse(fibh.sbh);			brelse(epos.bh);			return 0;		}		if (cfi.lengthFileIdent &&		    (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {			if (fibh.sbh != fibh.ebh)				brelse(fibh.ebh);			brelse(fibh.sbh);			brelse(epos.bh);			return 0;		}	}	if (fibh.sbh != fibh.ebh)		brelse(fibh.ebh);	brelse(fibh.sbh);	brelse(epos.bh);	return 1;}static 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;	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_rmdir;	retval = -ENOTEMPTY;	if (!empty_dir(inode))		goto end_rmdir;	retval = udf_delete_entry(dir, fi, &fibh, &cfi);	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);	clear_nlink(inode);	inode->i_size = 0;	inode_dec_link_count(dir);

⌨️ 快捷键说明

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