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

📄 namei.c

📁 Linux 1.0 内核C源代码 Linux最早版本代码 由Linus Torvalds亲自书写的
💻 C
📖 第 1 页 / 共 2 页
字号:
}


static int msdos_empty(struct inode *dir)
{
	off_t pos;
	struct buffer_head *bh;
	struct msdos_dir_entry *de;

	if (dir->i_count > 1)
		return -EBUSY;
	if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
		pos = 0;
		bh = NULL;
		while (msdos_get_entry(dir,&pos,&bh,&de) > -1)
			if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
			    MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
			    MSDOS_NAME)) {
				brelse(bh);
				return -ENOTEMPTY;
			}
		if (bh)
			brelse(bh);
	}
	return 0;
}


int msdos_rmdir(struct inode *dir,const char *name,int len)
{
	int res,ino;
	struct buffer_head *bh;
	struct msdos_dir_entry *de;
	struct inode *inode;

	bh = NULL;
	inode = NULL;
	res = -EPERM;
	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
		goto rmdir_done;
	if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
	res = -ENOENT;
	if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
	res = -ENOTDIR;
	if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
	res = -EBUSY;
	if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done;
	res = msdos_empty(inode);
	if (res)
		goto rmdir_done;
	inode->i_nlink = 0;
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	dir->i_nlink--;
	inode->i_dirt = dir->i_dirt = 1;
	de->name[0] = DELETED_FLAG;
	bh->b_dirt = 1;
	res = 0;
rmdir_done:
	brelse(bh);
	iput(dir);
	iput(inode);
	return res;
}


int msdos_unlink(struct inode *dir,const char *name,int len)
{
	int res,ino;
	struct buffer_head *bh;
	struct msdos_dir_entry *de;
	struct inode *inode;

	bh = NULL;
	inode = NULL;
	if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
		goto unlink_done;
	if (!(inode = iget(dir->i_sb,ino))) {
		res = -ENOENT;
		goto unlink_done;
	}
	if (!S_ISREG(inode->i_mode)) {
		res = -EPERM;
		goto unlink_done;
	}
	inode->i_nlink = 0;
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	MSDOS_I(inode)->i_busy = 1;
	inode->i_dirt = dir->i_dirt = 1;
	de->name[0] = DELETED_FLAG;
	bh->b_dirt = 1;
unlink_done:
	brelse(bh);
	iput(inode);
	iput(dir);
	return res;
}


static int rename_same_dir(struct inode *old_dir,char *old_name,
    struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
    struct msdos_dir_entry *old_de,int old_ino)
{
	struct buffer_head *new_bh;
	struct msdos_dir_entry *new_de;
	struct inode *new_inode,*old_inode;
	int new_ino,exists,error;

	if (!strncmp(old_name,new_name,MSDOS_NAME)) return 0;
	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
	if (*(unsigned char *) old_de->name == DELETED_FLAG) {
		if (exists) brelse(new_bh);
		return -ENOENT;
	}
	if (exists) {
		if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
			brelse(new_bh);
			return -EIO;
		}
		error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
		    msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
		    ? -EPERM : 0;
		if (error) {
			iput(new_inode);
			brelse(new_bh);
			return error;
		}
		if (S_ISDIR(new_inode->i_mode)) {
			new_dir->i_nlink--;
			new_dir->i_dirt = 1;
		}
		new_inode->i_nlink = 0;
		MSDOS_I(new_inode)->i_busy = 1;
		new_inode->i_dirt = 1;
		new_de->name[0] = DELETED_FLAG;
		new_bh->b_dirt = 1;
		iput(new_inode);
		brelse(new_bh);
	}
	memcpy(old_de->name,new_name,MSDOS_NAME);
	old_bh->b_dirt = 1;
	if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
		if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
			msdos_read_inode(old_inode);
			iput(old_inode);
		}
	return 0;
}


static int rename_diff_dir(struct inode *old_dir,char *old_name,
    struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
    struct msdos_dir_entry *old_de,int old_ino)
{
	struct buffer_head *new_bh,*free_bh,*dotdot_bh;
	struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
	struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
	int new_ino,free_ino,dotdot_ino;
	int error,exists,ino;

	if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
	if (old_ino == new_dir->i_ino) return -EINVAL;
	if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
	while (walk->i_ino != MSDOS_ROOT_INO) {
		ino = msdos_parent_ino(walk,1);
		iput(walk);
		if (ino < 0) return ino;
		if (ino == old_ino) return -EINVAL;
		if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
	}
	iput(walk);
	while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) <
	     0) {
		if (error != -ENOENT) return error;
		error = msdos_add_cluster(new_dir);
		if (error) return error;
	}
	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
	if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
		brelse(free_bh);
		if (exists) brelse(new_bh);
		return -EIO;
	}
	if (*(unsigned char *) old_de->name == DELETED_FLAG) {
		iput(old_inode);
		brelse(free_bh);
		if (exists) brelse(new_bh);
		return -ENOENT;
	}
	new_inode = NULL; /* to make GCC happy */
	if (exists) {
		if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
			iput(old_inode);
			brelse(new_bh);
			return -EIO;
		}
		error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
		    msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
		    ? -EPERM : 0;
		if (error) {
			iput(new_inode);
			iput(old_inode);
			brelse(new_bh);
			return error;
		}
		new_inode->i_nlink = 0;
		MSDOS_I(new_inode)->i_busy = 1;
		new_inode->i_dirt = 1;
		new_de->name[0] = DELETED_FLAG;
		new_bh->b_dirt = 1;
	}
	memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
	memcpy(free_de->name,new_name,MSDOS_NAME);
	if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
		free_de->name[0] = DELETED_FLAG;
/*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
		brelse(free_bh);
		if (exists) {
			iput(new_inode);
			brelse(new_bh);
		}
		return -EIO;
	}
	if (exists && S_ISDIR(new_inode->i_mode)) {
		new_dir->i_nlink--;
		new_dir->i_dirt = 1;
	}
	msdos_read_inode(free_inode);
	MSDOS_I(old_inode)->i_busy = 1;
	cache_inval_inode(old_inode);
	old_inode->i_dirt = 1;
	old_de->name[0] = DELETED_FLAG;
	old_bh->b_dirt = 1;
	free_bh->b_dirt = 1;
	if (!exists) iput(free_inode);
	else {
		MSDOS_I(new_inode)->i_depend = free_inode;
		MSDOS_I(free_inode)->i_old = new_inode;
		/* free_inode is put when putting new_inode */
		iput(new_inode);
		brelse(new_bh);
	}
	if (S_ISDIR(old_inode->i_mode)) {
		if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
		    &dotdot_de,&dotdot_ino)) < 0) goto rename_done;
		if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
			brelse(dotdot_bh);
			error = -EIO;
			goto rename_done;
		}
		dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
		    MSDOS_I(new_dir)->i_start;
		dotdot_inode->i_dirt = 1;
		dotdot_bh->b_dirt = 1;
		old_dir->i_nlink--;
		new_dir->i_nlink++;
		/* no need to mark them dirty */
		dotdot_inode->i_nlink = new_dir->i_nlink;
		iput(dotdot_inode);
		brelse(dotdot_bh);
	}
	error = 0;
rename_done:
	brelse(free_bh);
	iput(old_inode);
	return error;
}


int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
	struct inode *new_dir,const char *new_name,int new_len)
{
	char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
	struct buffer_head *old_bh;
	struct msdos_dir_entry *old_de;
	int old_ino,error;

	if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
	    old_name,old_len,old_msdos_name,1)) < 0) goto rename_done;
	if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
	    new_name,new_len,new_msdos_name,0)) < 0) goto rename_done;
	if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
	    &old_ino)) < 0) goto rename_done;
	lock_creation();
	if (old_dir == new_dir)
		error = rename_same_dir(old_dir,old_msdos_name,new_dir,
		    new_msdos_name,old_bh,old_de,old_ino);
	else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
		    new_msdos_name,old_bh,old_de,old_ino);
	unlock_creation();
	brelse(old_bh);
rename_done:
	iput(old_dir);
	iput(new_dir);
	return error;
}

⌨️ 快捷键说明

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