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

📄 namei.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct buffer_head * dir_block;	struct ext2_dir_entry_2 * de;	int err;	if (dir->i_nlink >= EXT2_LINK_MAX)		return -EMLINK;	inode = ext2_new_inode (dir, S_IFDIR);	err = PTR_ERR(inode);	if (IS_ERR(inode))		return err;	inode->i_op = &ext2_dir_inode_operations;	inode->i_fop = &ext2_dir_operations;	inode->i_size = inode->i_sb->s_blocksize;	inode->i_blocks = 0;		dir_block = ext2_bread (inode, 0, 1, &err);	if (!dir_block) {		inode->i_nlink--; /* is this nlink == 0? */		mark_inode_dirty(inode);		iput (inode);		return err;	}	de = (struct ext2_dir_entry_2 *) dir_block->b_data;	de->inode = cpu_to_le32(inode->i_ino);	de->name_len = 1;	de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));	strcpy (de->name, ".");	ext2_set_de_type(dir->i_sb, de, S_IFDIR);	de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));	de->inode = cpu_to_le32(dir->i_ino);	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));	de->name_len = 2;	strcpy (de->name, "..");	ext2_set_de_type(dir->i_sb, de, S_IFDIR);	inode->i_nlink = 2;	mark_buffer_dirty_inode(dir_block, dir);	brelse (dir_block);	inode->i_mode = S_IFDIR | mode;	if (dir->i_mode & S_ISGID)		inode->i_mode |= S_ISGID;	mark_inode_dirty(inode);	err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, 			     inode);	if (err)		goto out_no_entry;	dir->i_nlink++;	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;	mark_inode_dirty(dir);	d_instantiate(dentry, inode);	return 0;out_no_entry:	inode->i_nlink = 0;	mark_inode_dirty(inode);	iput (inode);	return err;}/* * routine to check that the specified directory is empty (for rmdir) */static int empty_dir (struct inode * inode){	unsigned long offset;	struct buffer_head * bh;	struct ext2_dir_entry_2 * de, * de1;	struct super_block * sb;	int err;	sb = inode->i_sb;	if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||	    !(bh = ext2_bread (inode, 0, 0, &err))) {	    	ext2_warning (inode->i_sb, "empty_dir",			      "bad directory (dir #%lu) - no data block",			      inode->i_ino);		return 1;	}	de = (struct ext2_dir_entry_2 *) bh->b_data;	de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));	if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || 	    strcmp (".", de->name) || strcmp ("..", de1->name)) {	    	ext2_warning (inode->i_sb, "empty_dir",			      "bad directory (dir #%lu) - no `.' or `..'",			      inode->i_ino);		brelse (bh);		return 1;	}	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);	de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));	while (offset < inode->i_size ) {		if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {			brelse (bh);			bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err);			if (!bh) {#if 0				ext2_error (sb, "empty_dir",					    "directory #%lu contains a hole at offset %lu",					    inode->i_ino, offset);#endif				offset += sb->s_blocksize;				continue;			}			de = (struct ext2_dir_entry_2 *) bh->b_data;		}		if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,					   offset)) {			brelse (bh);			return 1;		}		if (le32_to_cpu(de->inode)) {			brelse (bh);			return 0;		}		offset += le16_to_cpu(de->rec_len);		de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));	}	brelse (bh);	return 1;}static int ext2_rmdir (struct inode * dir, struct dentry *dentry){	int retval;	struct inode * inode;	struct buffer_head * bh;	struct ext2_dir_entry_2 * de;	retval = -ENOENT;	bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);	if (!bh)		goto end_rmdir;	inode = dentry->d_inode;	DQUOT_INIT(inode);	retval = -EIO;	if (le32_to_cpu(de->inode) != inode->i_ino)		goto end_rmdir;	retval = -ENOTEMPTY;	if (!empty_dir (inode))		goto end_rmdir;	retval = ext2_delete_entry(dir, de, bh);	if (retval)		goto end_rmdir;	if (inode->i_nlink != 2)		ext2_warning (inode->i_sb, "ext2_rmdir",			      "empty directory has nlink!=2 (%d)",			      inode->i_nlink);	inode->i_version = ++event;	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;	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;	mark_inode_dirty(dir);end_rmdir:	brelse (bh);	return retval;}static int ext2_unlink(struct inode * dir, struct dentry *dentry){	int retval;	struct inode * inode;	struct buffer_head * bh;	struct ext2_dir_entry_2 * de;	retval = -ENOENT;	bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);	if (!bh)		goto end_unlink;	inode = dentry->d_inode;	DQUOT_INIT(inode);	retval = -EIO;	if (le32_to_cpu(de->inode) != inode->i_ino)		goto end_unlink;		if (!inode->i_nlink) {		ext2_warning (inode->i_sb, "ext2_unlink",			      "Deleting nonexistent file (%lu), %d",			      inode->i_ino, inode->i_nlink);		inode->i_nlink = 1;	}	retval = ext2_delete_entry(dir, de, bh);	if (retval)		goto end_unlink;	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;	mark_inode_dirty(dir);	inode->i_nlink--;	mark_inode_dirty(inode);	inode->i_ctime = dir->i_ctime;	retval = 0;end_unlink:	brelse (bh);	return retval;}static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname){	struct inode * inode;	int l, err;	l = strlen(symname)+1;	if (l > dir->i_sb->s_blocksize)		return -ENAMETOOLONG;	inode = ext2_new_inode (dir, S_IFLNK);	err = PTR_ERR(inode);	if (IS_ERR(inode))		return err;	inode->i_mode = S_IFLNK | S_IRWXUGO;	if (l > sizeof (inode->u.ext2_i.i_data)) {		inode->i_op = &page_symlink_inode_operations;		inode->i_mapping->a_ops = &ext2_aops;		err = block_symlink(inode, symname, l);		if (err)			goto out_no_entry;	} else {		inode->i_op = &ext2_fast_symlink_inode_operations;		memcpy((char*)&inode->u.ext2_i.i_data,symname,l);		inode->i_size = l-1;	}	mark_inode_dirty(inode);	err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, 			     inode);	if (err)		goto out_no_entry;	d_instantiate(dentry, inode);	return 0;out_no_entry:	inode->i_nlink--;	mark_inode_dirty(inode);	iput (inode);	return err;}static int ext2_link (struct dentry * old_dentry,		struct inode * dir, struct dentry *dentry){	struct inode *inode = old_dentry->d_inode;	int err;	if (S_ISDIR(inode->i_mode))		return -EPERM;	if (inode->i_nlink >= EXT2_LINK_MAX)		return -EMLINK;		err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, 			     inode);	if (err)		return err;	inode->i_nlink++;	inode->i_ctime = CURRENT_TIME;	mark_inode_dirty(inode);	atomic_inc(&inode->i_count);	d_instantiate(dentry, inode);	return 0;}#define PARENT_INO(buffer) \	((struct ext2_dir_entry_2 *) ((char *) buffer + \	le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode/* * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,			   struct inode * new_dir,struct dentry *new_dentry){	struct inode * old_inode, * new_inode;	struct buffer_head * old_bh, * new_bh, * dir_bh;	struct ext2_dir_entry_2 * old_de, * new_de;	int retval;	old_bh = new_bh = dir_bh = NULL;	old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);	/*	 *  Check for inode number is _not_ due to possible IO errors.	 *  We might rmdir the source, keep it as pwd of some process	 *  and merrily kill the link to whatever was created under the	 *  same name. Goodbye sticky bit ;-<	 */	old_inode = old_dentry->d_inode;	retval = -ENOENT;	if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)		goto end_rename;	new_inode = new_dentry->d_inode;	new_bh = ext2_find_entry (new_dir, new_dentry->d_name.name,				new_dentry->d_name.len, &new_de);	if (new_bh) {		if (!new_inode) {			brelse (new_bh);			new_bh = NULL;		} else {			DQUOT_INIT(new_inode);		}	}	if (S_ISDIR(old_inode->i_mode)) {		if (new_inode) {			retval = -ENOTEMPTY;			if (!empty_dir (new_inode))				goto end_rename;		}		retval = -EIO;		dir_bh = ext2_bread (old_inode, 0, 0, &retval);		if (!dir_bh)			goto end_rename;		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)			goto end_rename;		retval = -EMLINK;		if (!new_inode && new_dir!=old_dir &&				new_dir->i_nlink >= EXT2_LINK_MAX)			goto end_rename;	}	if (!new_bh) {		retval = ext2_add_entry (new_dir, new_dentry->d_name.name,					 new_dentry->d_name.len,					 old_inode);		if (retval)			goto end_rename;	} else {		new_de->inode = le32_to_cpu(old_inode->i_ino);		if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb,					      EXT2_FEATURE_INCOMPAT_FILETYPE))			new_de->file_type = old_de->file_type;		new_dir->i_version = ++event;		mark_buffer_dirty_inode(new_bh, new_dir);		if (IS_SYNC(new_dir)) {			ll_rw_block (WRITE, 1, &new_bh);			wait_on_buffer (new_bh);		}		brelse(new_bh);		new_bh = NULL;	}		/*	 * Like most other Unix systems, set the ctime for inodes on a	 * rename.	 */	old_inode->i_ctime = CURRENT_TIME;	mark_inode_dirty(old_inode);	/*	 * ok, that's it	 */	ext2_delete_entry(old_dir, old_de, old_bh);	if (new_inode) {		new_inode->i_nlink--;		new_inode->i_ctime = CURRENT_TIME;		mark_inode_dirty(new_inode);	}	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;	old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;	mark_inode_dirty(old_dir);	if (dir_bh) {		PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);		mark_buffer_dirty_inode(dir_bh, old_inode);		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++;			new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;			mark_inode_dirty(new_dir);		}	}	retval = 0;end_rename:	brelse (dir_bh);	brelse (old_bh);	brelse (new_bh);	return retval;}/* * directories can handle most operations... */struct inode_operations ext2_dir_inode_operations = {	create:		ext2_create,	lookup:		ext2_lookup,	link:		ext2_link,	unlink:		ext2_unlink,	symlink:	ext2_symlink,	mkdir:		ext2_mkdir,	rmdir:		ext2_rmdir,	mknod:		ext2_mknod,	rename:		ext2_rename,};

⌨️ 快捷键说明

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