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

📄 namei.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct super_block * sb;	struct inode * inode;	struct buffer_head * bh, * dir_block;	struct ufs_dir_entry * de;	int err;	unsigned flags, swab;		sb = dir->i_sb;	flags = sb->u.ufs_sb.s_flags;	swab = sb->u.ufs_sb.s_swab;	err = -EMLINK;	if (dir->i_nlink >= UFS_LINK_MAX)		goto out;	err = -EIO;	inode = ufs_new_inode (dir, S_IFDIR, &err);	if (!inode)		goto out;	inode->i_op = &ufs_dir_inode_operations;	inode->i_fop = &ufs_dir_operations;	inode->i_size = UFS_SECTOR_SIZE;	dir_block = ufs_bread (inode, 0, 1, &err);	if (!dir_block) {		inode->i_nlink--; /* is this nlink == 0? */		mark_inode_dirty(inode);		iput (inode);		return err;	}	inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;	de = (struct ufs_dir_entry *) dir_block->b_data;	de->d_ino = SWAB32(inode->i_ino);	ufs_set_de_type (de, inode->i_mode);	ufs_set_de_namlen(de,1);	de->d_reclen = SWAB16(UFS_DIR_REC_LEN(1));	strcpy (de->d_name, ".");	de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));	de->d_ino = SWAB32(dir->i_ino);	ufs_set_de_type (de, dir->i_mode);	de->d_reclen = SWAB16(UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));	ufs_set_de_namlen(de,2);	strcpy (de->d_name, "..");	inode->i_nlink = 2;	mark_buffer_dirty(dir_block);	brelse (dir_block);	inode->i_mode = S_IFDIR | mode;	if (dir->i_mode & S_ISGID)		inode->i_mode |= S_ISGID;	mark_inode_dirty(inode);	bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);	if (!bh)		goto out_no_entry;	de->d_ino = SWAB32(inode->i_ino);	ufs_set_de_type (de, inode->i_mode);	dir->i_version = ++event;	mark_buffer_dirty(bh);	if (IS_SYNC(dir)) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	dir->i_nlink++;	mark_inode_dirty(dir);	d_instantiate(dentry, inode);	brelse (bh);	err = 0;out:	return err;out_no_entry:	inode->i_nlink = 0;	mark_inode_dirty(inode);	iput (inode);	goto out;}/* * routine to check that the specified directory is empty (for rmdir) */static int ufs_empty_dir (struct inode * inode){	struct super_block * sb;	unsigned long offset;	struct buffer_head * bh;	struct ufs_dir_entry * de, * de1;	int err;	unsigned swab;			sb = inode->i_sb;	swab = sb->u.ufs_sb.s_swab;	if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||	    !(bh = ufs_bread (inode, 0, 0, &err))) {	    	ufs_warning (inode->i_sb, "empty_dir",			      "bad directory (dir #%lu) - no data block",			      inode->i_ino);		return 1;	}	de = (struct ufs_dir_entry *) bh->b_data;	de1 = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));	if (SWAB32(de->d_ino) != inode->i_ino || !SWAB32(de1->d_ino) || 	    strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {	    	ufs_warning (inode->i_sb, "empty_dir",			      "bad directory (dir #%lu) - no `.' or `..'",			      inode->i_ino);		return 1;	}	offset = SWAB16(de->d_reclen) + SWAB16(de1->d_reclen);	de = (struct ufs_dir_entry *) ((char *) de1 + SWAB16(de1->d_reclen));	while (offset < inode->i_size ) {		if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {			brelse (bh);			bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);	 		if (!bh) {				ufs_error (sb, "empty_dir",					    "directory #%lu contains a hole at offset %lu",					    inode->i_ino, offset);				offset += sb->s_blocksize;				continue;			}			de = (struct ufs_dir_entry *) bh->b_data;		}		if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {			brelse (bh);			return 1;		}		if (SWAB32(de->d_ino)) {			brelse (bh);			return 0;		}		offset += SWAB16(de->d_reclen);		de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));	}	brelse (bh);	return 1;}static int ufs_rmdir (struct inode * dir, struct dentry *dentry){	struct super_block *sb;	int retval;	struct inode * inode;	struct buffer_head * bh;	struct ufs_dir_entry * de;	unsigned swab;		sb = dir->i_sb;	swab = sb->u.ufs_sb.s_swab;			UFSD(("ENTER\n"))	retval = -ENOENT;	bh = ufs_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 (SWAB32(de->d_ino) != inode->i_ino)		goto end_rmdir;	retval = -ENOTEMPTY;	if (!ufs_empty_dir (inode))		goto end_rmdir;	retval = ufs_delete_entry (dir, de, bh);	dir->i_version = ++event;	if (retval)		goto end_rmdir;	mark_buffer_dirty(bh);	if (IS_SYNC(dir)) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	if (inode->i_nlink != 2)		ufs_warning (inode->i_sb, "ufs_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;	mark_inode_dirty(dir);end_rmdir:	brelse (bh);	UFSD(("EXIT\n"))		return retval;}static int ufs_unlink(struct inode * dir, struct dentry *dentry){	struct super_block * sb;	int retval;	struct inode * inode;	struct buffer_head * bh;	struct ufs_dir_entry * de;	unsigned flags, swab;	sb = dir->i_sb;	flags = sb->u.ufs_sb.s_flags;	swab = sb->u.ufs_sb.s_swab;	retval = -ENOENT;	bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);	UFSD(("de: ino %u, reclen %u, namelen %u, name %s\n", SWAB32(de->d_ino),		SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name))	if (!bh)		goto end_unlink;	inode = dentry->d_inode;	DQUOT_INIT(inode);	retval = -EIO;	if (SWAB32(de->d_ino) != inode->i_ino)		goto end_unlink;		if (!inode->i_nlink) {		ufs_warning (inode->i_sb, "ufs_unlink",			      "Deleting nonexistent file (%lu), %d",			      inode->i_ino, inode->i_nlink);		inode->i_nlink = 1;	}	retval = ufs_delete_entry (dir, de, bh);	if (retval)		goto end_unlink;	dir->i_version = ++event;	mark_buffer_dirty(bh);	if (IS_SYNC(dir)) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	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;}/* * Create symbolic link. We use only slow symlinks at this time. */static int ufs_symlink (struct inode * dir, struct dentry * dentry,	const char * symname){	struct super_block * sb = dir->i_sb;	struct ufs_dir_entry * de;	struct inode * inode;	struct buffer_head * bh = NULL;	unsigned l;	int err;	unsigned swab = sb->u.ufs_sb.s_swab;		UFSD(("ENTER\n"))		err = -ENAMETOOLONG;	l = strlen(symname)+1;	if (l > sb->s_blocksize)		goto out;	err = -EIO;		if (!(inode = ufs_new_inode (dir, S_IFLNK, &err))) {		return err;	}	inode->i_mode = S_IFLNK | S_IRWXUGO;	if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) {		/* slow symlink */		inode->i_op = &page_symlink_inode_operations;		inode->i_mapping->a_ops = &ufs_aops;		err = block_symlink(inode, symname, l);		if (err)			goto out_no_entry;	} else {		/* fast symlink */		inode->i_op = &ufs_fast_symlink_inode_operations;		memcpy((char*)&inode->u.ufs_i.i_u1.i_data,symname,l);		inode->i_size = l-1;	}	mark_inode_dirty(inode);	bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);	if (!bh)		goto out_no_entry;	de->d_ino = SWAB32(inode->i_ino);	dir->i_version = ++event;	mark_buffer_dirty(bh);	if (IS_SYNC(dir)) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	brelse (bh);	d_instantiate(dentry, inode);	err = 0;out:	return err;out_no_entry:	inode->i_nlink--;	mark_inode_dirty(inode);	iput (inode);	goto out;}static int ufs_link (struct dentry * old_dentry, struct inode * dir,	struct dentry *dentry){	struct inode *inode = old_dentry->d_inode;	struct super_block * sb = inode->i_sb;	struct ufs_dir_entry * de;	struct buffer_head * bh;	int err;	unsigned swab = sb->u.ufs_sb.s_swab;		if (S_ISDIR(inode->i_mode))		return -EPERM;	if (inode->i_nlink >= UFS_LINK_MAX)		return -EMLINK;	bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);	if (!bh)		return err;	de->d_ino = SWAB32(inode->i_ino);	dir->i_version = ++event;	mark_buffer_dirty(bh);	if (IS_SYNC(dir)) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	brelse (bh);	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 ufs_dir_entry *) ((char *) buffer + \	SWAB16(((struct ufs_dir_entry *) buffer)->d_reclen)))->d_ino/* * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,	struct inode * new_dir,	struct dentry * new_dentry ){	struct super_block * sb;	struct inode * old_inode, * new_inode;	struct buffer_head * old_bh, * new_bh, * dir_bh;	struct ufs_dir_entry * old_de, * new_de;	int retval;	unsigned flags, swab;		sb = old_dir->i_sb;	flags = sb->u.ufs_sb.s_flags;	swab = sb->u.ufs_sb.s_swab;	UFSD(("ENTER\n"))		old_inode = new_inode = NULL;	old_bh = new_bh = dir_bh = NULL;	new_de = NULL;	old_bh = ufs_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 ;-<	 */	retval = -ENOENT;	old_inode = old_dentry->d_inode;	if (!old_bh || SWAB32(old_de->d_ino) != old_inode->i_ino)		goto end_rename;	new_inode = new_dentry->d_inode;	new_bh = ufs_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 (!ufs_empty_dir (new_inode))				goto end_rename;		}		retval = -EIO;		dir_bh = ufs_bread (old_inode, 0, 0, &retval);		if (!dir_bh)			goto end_rename;		if (SWAB32(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)			goto end_rename;		retval = -EMLINK;		if (!new_inode && new_dir->i_nlink >= UFS_LINK_MAX)			goto end_rename;	}	if (!new_bh)		new_bh = ufs_add_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de,					 &retval);	if (!new_bh)		goto end_rename;	new_dir->i_version = ++event;	/*	 * ok, that's it	 */	new_de->d_ino = SWAB32(old_inode->i_ino);	ufs_delete_entry (old_dir, old_de, old_bh);	old_dir->i_version = ++event;	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;	mark_inode_dirty(old_dir);	if (dir_bh) {		PARENT_INO(dir_bh->b_data) = SWAB32(new_dir->i_ino);		mark_buffer_dirty(dir_bh);		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);		}	}	mark_buffer_dirty(old_bh);	if (IS_SYNC(old_dir)) {		ll_rw_block (WRITE, 1, &old_bh);		wait_on_buffer (old_bh);	}		mark_buffer_dirty(new_bh);	if (IS_SYNC(new_dir)) {		ll_rw_block (WRITE, 1, &new_bh);		wait_on_buffer (new_bh);	}	retval = 0;end_rename:	brelse (dir_bh);	brelse (old_bh);	brelse (new_bh);		UFSD(("EXIT\n"))		return retval;}struct inode_operations ufs_dir_inode_operations = {	create:		ufs_create,	lookup:		ufs_lookup,	link:		ufs_link,	unlink:		ufs_unlink,	symlink:	ufs_symlink,	mkdir:		ufs_mkdir,	rmdir:		ufs_rmdir,	mknod:		ufs_mknod,	rename:		ufs_rename,};

⌨️ 快捷键说明

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