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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (r == 1)		goto bail2;	if (r == -1) {		err = -EEXIST;		goto bail2;	}	fnode->len = len;	memcpy(fnode->name, name, len > 15 ? 15 : len);	fnode->up = dir->i_ino;	hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));	mark_buffer_dirty(bh);	brelse(bh);	insert_inode_hash(result);	hpfs_write_inode_nolock(result);	d_instantiate(dentry, result);	mutex_unlock(&hpfs_i(dir)->i_mutex);	unlock_kernel();	return 0;bail2:	mutex_unlock(&hpfs_i(dir)->i_mutex);	iput(result);bail1:	brelse(bh);	hpfs_free_sectors(dir->i_sb, fno, 1);bail:	unlock_kernel();	return err;}static int hpfs_unlink(struct inode *dir, struct dentry *dentry){	const char *name = dentry->d_name.name;	unsigned len = dentry->d_name.len;	struct quad_buffer_head qbh;	struct hpfs_dirent *de;	struct inode *inode = dentry->d_inode;	dnode_secno dno;	fnode_secno fno;	int r;	int rep = 0;	int err;	lock_kernel();	hpfs_adjust_length((char *)name, &len);again:	mutex_lock(&hpfs_i(inode)->i_parent_mutex);	mutex_lock(&hpfs_i(dir)->i_mutex);	err = -ENOENT;	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);	if (!de)		goto out;	err = -EPERM;	if (de->first)		goto out1;	err = -EISDIR;	if (de->directory)		goto out1;	fno = de->fnode;	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);	switch (r) {	case 1:		hpfs_error(dir->i_sb, "there was error when removing dirent");		err = -EFSERROR;		break;	case 2:		/* no space for deleting, try to truncate file */		err = -ENOSPC;		if (rep++)			break;		mutex_unlock(&hpfs_i(dir)->i_mutex);		mutex_unlock(&hpfs_i(inode)->i_parent_mutex);		d_drop(dentry);		spin_lock(&dentry->d_lock);		if (atomic_read(&dentry->d_count) > 1 ||		    permission(inode, MAY_WRITE, NULL) ||		    !S_ISREG(inode->i_mode) ||		    get_write_access(inode)) {			spin_unlock(&dentry->d_lock);			d_rehash(dentry);		} else {			struct iattr newattrs;			spin_unlock(&dentry->d_lock);			/*printk("HPFS: truncating file before delete.\n");*/			newattrs.ia_size = 0;			newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;			err = notify_change(dentry, &newattrs);			put_write_access(inode);			if (!err)				goto again;		}		unlock_kernel();		return -ENOSPC;	default:		drop_nlink(inode);		err = 0;	}	goto out;out1:	hpfs_brelse4(&qbh);out:	mutex_unlock(&hpfs_i(dir)->i_mutex);	mutex_unlock(&hpfs_i(inode)->i_parent_mutex);	unlock_kernel();	return err;}static int hpfs_rmdir(struct inode *dir, struct dentry *dentry){	const char *name = dentry->d_name.name;	unsigned len = dentry->d_name.len;	struct quad_buffer_head qbh;	struct hpfs_dirent *de;	struct inode *inode = dentry->d_inode;	dnode_secno dno;	fnode_secno fno;	int n_items = 0;	int err;	int r;	hpfs_adjust_length((char *)name, &len);	lock_kernel();	mutex_lock(&hpfs_i(inode)->i_parent_mutex);	mutex_lock(&hpfs_i(dir)->i_mutex);	err = -ENOENT;	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);	if (!de)		goto out;	err = -EPERM;	if (de->first)		goto out1;	err = -ENOTDIR;	if (!de->directory)		goto out1;	hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items);	err = -ENOTEMPTY;	if (n_items)		goto out1;	fno = de->fnode;	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);	switch (r) {	case 1:		hpfs_error(dir->i_sb, "there was error when removing dirent");		err = -EFSERROR;		break;	case 2:		err = -ENOSPC;		break;	default:		drop_nlink(dir);		clear_nlink(inode);		err = 0;	}	goto out;out1:	hpfs_brelse4(&qbh);out:	mutex_unlock(&hpfs_i(dir)->i_mutex);	mutex_unlock(&hpfs_i(inode)->i_parent_mutex);	unlock_kernel();	return err;}static int hpfs_symlink_readpage(struct file *file, struct page *page){	char *link = kmap(page);	struct inode *i = page->mapping->host;	struct fnode *fnode;	struct buffer_head *bh;	int err;	err = -EIO;	lock_kernel();	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))		goto fail;	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);	brelse(bh);	if (err)		goto fail;	unlock_kernel();	SetPageUptodate(page);	kunmap(page);	unlock_page(page);	return 0;fail:	unlock_kernel();	SetPageError(page);	kunmap(page);	unlock_page(page);	return err;}const struct address_space_operations hpfs_symlink_aops = {	.readpage	= hpfs_symlink_readpage};	static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,		struct inode *new_dir, struct dentry *new_dentry){	char *old_name = (char *)old_dentry->d_name.name;	int old_len = old_dentry->d_name.len;	char *new_name = (char *)new_dentry->d_name.name;	int new_len = new_dentry->d_name.len;	struct inode *i = old_dentry->d_inode;	struct inode *new_inode = new_dentry->d_inode;	struct quad_buffer_head qbh, qbh1;	struct hpfs_dirent *dep, *nde;	struct hpfs_dirent de;	dnode_secno dno;	int r;	struct buffer_head *bh;	struct fnode *fnode;	int err;	if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;	err = 0;	hpfs_adjust_length((char *)old_name, &old_len);	lock_kernel();	/* order doesn't matter, due to VFS exclusion */	mutex_lock(&hpfs_i(i)->i_parent_mutex);	if (new_inode)		mutex_lock(&hpfs_i(new_inode)->i_parent_mutex);	mutex_lock(&hpfs_i(old_dir)->i_mutex);	if (new_dir != old_dir)		mutex_lock(&hpfs_i(new_dir)->i_mutex);		/* Erm? Moving over the empty non-busy directory is perfectly legal */	if (new_inode && S_ISDIR(new_inode->i_mode)) {		err = -EINVAL;		goto end1;	}	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");		err = -ENOENT;		goto end1;	}	copy_de(&de, dep);	de.hidden = new_name[0] == '.';	if (new_inode) {		int r;		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, (char *)new_name, new_len, NULL, &qbh1))) {				clear_nlink(new_inode);				copy_de(nde, &de);				memcpy(nde->name, new_name, new_len);				hpfs_mark_4buffers_dirty(&qbh1);				hpfs_brelse4(&qbh1);				goto end;			}			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");			err = -EFSERROR;			goto end1;		}		err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;		goto end1;	}	if (new_dir == old_dir) hpfs_brelse4(&qbh);	hpfs_lock_creation(i->i_sb);	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {		hpfs_unlock_creation(i->i_sb);		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");		err = r == 1 ? -ENOSPC : -EFSERROR;		if (new_dir != old_dir) hpfs_brelse4(&qbh);		goto end1;	}		if (new_dir == old_dir)		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {			hpfs_unlock_creation(i->i_sb);			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");			err = -ENOENT;			goto end1;		}	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {		hpfs_unlock_creation(i->i_sb);		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");		err = r == 2 ? -ENOSPC : -EFSERROR;		goto end1;	}	hpfs_unlock_creation(i->i_sb);		end:	hpfs_i(i)->i_parent_dir = new_dir->i_ino;	if (S_ISDIR(i->i_mode)) {		inc_nlink(new_dir);		drop_nlink(old_dir);	}	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {		fnode->up = new_dir->i_ino;		fnode->len = new_len;		memcpy(fnode->name, new_name, new_len>15?15:new_len);		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);		mark_buffer_dirty(bh);		brelse(bh);	}	hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;	hpfs_decide_conv(i, (char *)new_name, new_len);end1:	if (old_dir != new_dir)		mutex_unlock(&hpfs_i(new_dir)->i_mutex);	mutex_unlock(&hpfs_i(old_dir)->i_mutex);	mutex_unlock(&hpfs_i(i)->i_parent_mutex);	if (new_inode)		mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex);	unlock_kernel();	return err;}const struct inode_operations hpfs_dir_iops ={	.create		= hpfs_create,	.lookup		= hpfs_lookup,	.unlink		= hpfs_unlink,	.symlink	= hpfs_symlink,	.mkdir		= hpfs_mkdir,	.rmdir		= hpfs_rmdir,	.mknod		= hpfs_mknod,	.rename		= hpfs_rename,	.setattr	= hpfs_notify_change,};

⌨️ 快捷键说明

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