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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		err = fat_flush_inodes(inode->i_sb, dir, inode);	return err;}/***** Make a directory */static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode){	struct super_block *sb = dir->i_sb;	struct fat_slot_info sinfo;	struct inode *inode;	unsigned char msdos_name[MSDOS_NAME];	struct timespec ts;	int err, is_hid, cluster;	lock_kernel();	err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,				msdos_name, &MSDOS_SB(sb)->options);	if (err)		goto out;	is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');	/* foo vs .foo situation */	if (!fat_scan(dir, msdos_name, &sinfo)) {		brelse(sinfo.bh);		err = -EINVAL;		goto out;	}	ts = CURRENT_TIME_SEC;	cluster = fat_alloc_new_dir(dir, &ts);	if (cluster < 0) {		err = cluster;		goto out;	}	err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);	if (err)		goto out_free;	inc_nlink(dir);	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);	brelse(sinfo.bh);	if (IS_ERR(inode)) {		err = PTR_ERR(inode);		/* the directory was completed, just return a error */		goto out;	}	inode->i_nlink = 2;	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;	/* timestamp is already written, so mark_inode_dirty() is unneeded. */	d_instantiate(dentry, inode);	unlock_kernel();	fat_flush_inodes(sb, dir, inode);	return 0;out_free:	fat_free_clusters(dir, cluster);out:	unlock_kernel();	return err;}/***** Unlink a file */static int msdos_unlink(struct inode *dir, struct dentry *dentry){	struct inode *inode = dentry->d_inode;	struct fat_slot_info sinfo;	int err;	lock_kernel();	err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);	if (err)		goto out;	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */	if (err)		goto out;	clear_nlink(inode);	inode->i_ctime = CURRENT_TIME_SEC;	fat_detach(inode);out:	unlock_kernel();	if (!err)		err = fat_flush_inodes(inode->i_sb, dir, inode);	return err;}static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,			   struct dentry *old_dentry,			   struct inode *new_dir, unsigned char *new_name,			   struct dentry *new_dentry, int is_hid){	struct buffer_head *dotdot_bh;	struct msdos_dir_entry *dotdot_de;	struct inode *old_inode, *new_inode;	struct fat_slot_info old_sinfo, sinfo;	struct timespec ts;	loff_t dotdot_i_pos, new_i_pos;	int err, old_attrs, is_dir, update_dotdot, corrupt = 0;	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;	old_inode = old_dentry->d_inode;	new_inode = new_dentry->d_inode;	err = fat_scan(old_dir, old_name, &old_sinfo);	if (err) {		err = -EIO;		goto out;	}	is_dir = S_ISDIR(old_inode->i_mode);	update_dotdot = (is_dir && old_dir != new_dir);	if (update_dotdot) {		if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,					 &dotdot_i_pos) < 0) {			err = -EIO;			goto out;		}	}	old_attrs = MSDOS_I(old_inode)->i_attrs;	err = fat_scan(new_dir, new_name, &sinfo);	if (!err) {		if (!new_inode) {			/* "foo" -> ".foo" case. just change the ATTR_HIDDEN */			if (sinfo.de != old_sinfo.de) {				err = -EINVAL;				goto out;			}			if (is_hid)				MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;			else				MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;			if (IS_DIRSYNC(old_dir)) {				err = fat_sync_inode(old_inode);				if (err) {					MSDOS_I(old_inode)->i_attrs = old_attrs;					goto out;				}			} else				mark_inode_dirty(old_inode);			old_dir->i_version++;			old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;			if (IS_DIRSYNC(old_dir))				(void)fat_sync_inode(old_dir);			else				mark_inode_dirty(old_dir);			goto out;		}	}	ts = CURRENT_TIME_SEC;	if (new_inode) {		if (err)			goto out;		if (is_dir) {			err = fat_dir_empty(new_inode);			if (err)				goto out;		}		new_i_pos = MSDOS_I(new_inode)->i_pos;		fat_detach(new_inode);	} else {		err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,				      &ts, &sinfo);		if (err)			goto out;		new_i_pos = sinfo.i_pos;	}	new_dir->i_version++;	fat_detach(old_inode);	fat_attach(old_inode, new_i_pos);	if (is_hid)		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;	else		MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;	if (IS_DIRSYNC(new_dir)) {		err = fat_sync_inode(old_inode);		if (err)			goto error_inode;	} else		mark_inode_dirty(old_inode);	if (update_dotdot) {		int start = MSDOS_I(new_dir)->i_logstart;		dotdot_de->start = cpu_to_le16(start);		dotdot_de->starthi = cpu_to_le16(start >> 16);		mark_buffer_dirty(dotdot_bh);		if (IS_DIRSYNC(new_dir)) {			err = sync_dirty_buffer(dotdot_bh);			if (err)				goto error_dotdot;		}		drop_nlink(old_dir);		if (!new_inode)			inc_nlink(new_dir);	}	err = fat_remove_entries(old_dir, &old_sinfo);	/* and releases bh */	old_sinfo.bh = NULL;	if (err)		goto error_dotdot;	old_dir->i_version++;	old_dir->i_ctime = old_dir->i_mtime = ts;	if (IS_DIRSYNC(old_dir))		(void)fat_sync_inode(old_dir);	else		mark_inode_dirty(old_dir);	if (new_inode) {		drop_nlink(new_inode);		if (is_dir)			drop_nlink(new_inode);		new_inode->i_ctime = ts;	}out:	brelse(sinfo.bh);	brelse(dotdot_bh);	brelse(old_sinfo.bh);	return err;error_dotdot:	/* data cluster is shared, serious corruption */	corrupt = 1;	if (update_dotdot) {		int start = MSDOS_I(old_dir)->i_logstart;		dotdot_de->start = cpu_to_le16(start);		dotdot_de->starthi = cpu_to_le16(start >> 16);		mark_buffer_dirty(dotdot_bh);		corrupt |= sync_dirty_buffer(dotdot_bh);	}error_inode:	fat_detach(old_inode);	fat_attach(old_inode, old_sinfo.i_pos);	MSDOS_I(old_inode)->i_attrs = old_attrs;	if (new_inode) {		fat_attach(new_inode, new_i_pos);		if (corrupt)			corrupt |= fat_sync_inode(new_inode);	} else {		/*		 * If new entry was not sharing the data cluster, it		 * shouldn't be serious corruption.		 */		int err2 = fat_remove_entries(new_dir, &sinfo);		if (corrupt)			corrupt |= err2;		sinfo.bh = NULL;	}	if (corrupt < 0) {		fat_fs_panic(new_dir->i_sb,			     "%s: Filesystem corrupted (i_pos %lld)",			     __FUNCTION__, sinfo.i_pos);	}	goto out;}/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,			struct inode *new_dir, struct dentry *new_dentry){	unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];	int err, is_hid;	lock_kernel();	err = msdos_format_name(old_dentry->d_name.name,				old_dentry->d_name.len, old_msdos_name,				&MSDOS_SB(old_dir->i_sb)->options);	if (err)		goto out;	err = msdos_format_name(new_dentry->d_name.name,				new_dentry->d_name.len, new_msdos_name,				&MSDOS_SB(new_dir->i_sb)->options);	if (err)		goto out;	is_hid =	     (new_dentry->d_name.name[0] == '.') && (new_msdos_name[0] != '.');	err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,			      new_dir, new_msdos_name, new_dentry, is_hid);out:	unlock_kernel();	if (!err)		err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir);	return err;}static const struct inode_operations msdos_dir_inode_operations = {	.create		= msdos_create,	.lookup		= msdos_lookup,	.unlink		= msdos_unlink,	.mkdir		= msdos_mkdir,	.rmdir		= msdos_rmdir,	.rename		= msdos_rename,	.setattr	= fat_notify_change,	.getattr	= fat_getattr,};static int msdos_fill_super(struct super_block *sb, void *data, int silent){	int res;	res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);	if (res)		return res;	sb->s_flags |= MS_NOATIME;	sb->s_root->d_op = &msdos_dentry_operations;	return 0;}static int msdos_get_sb(struct file_system_type *fs_type,			int flags, const char *dev_name,			void *data, struct vfsmount *mnt){	return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super,			   mnt);}static struct file_system_type msdos_fs_type = {	.owner		= THIS_MODULE,	.name		= "msdos",	.get_sb		= msdos_get_sb,	.kill_sb	= kill_block_super,	.fs_flags	= FS_REQUIRES_DEV,};static int __init init_msdos_fs(void){	return register_filesystem(&msdos_fs_type);}static void __exit exit_msdos_fs(void){	unregister_filesystem(&msdos_fs_type);}MODULE_LICENSE("GPL");MODULE_AUTHOR("Werner Almesberger");MODULE_DESCRIPTION("MS-DOS filesystem support");module_init(init_msdos_fs)module_exit(exit_msdos_fs)

⌨️ 快捷键说明

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