예제 #1
0
파일: namei.c 프로젝트: dmgerman/original
static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

	inode = dentry->d_inode;
	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
	retval = -ENOENT;
	if (!bh || de->inode != inode->i_ino)
		goto end_rmdir;

	if (!empty_dir(inode)) {
		retval = -ENOTEMPTY;
		goto end_rmdir;
	}
	if (inode->i_nlink != 2)
		printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink);
	de->inode = 0;
	mark_buffer_dirty(bh);
	inode->i_nlink=0;
	dir->i_nlink--;
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(inode);
	mark_inode_dirty(dir);
	retval = 0;
end_rmdir:
	brelse(bh);
	return retval;
}
예제 #2
0
파일: namei.c 프로젝트: dmgerman/original
static int sysv_unlink(struct inode * dir, struct dentry * dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

	retval = -ENOENT;
	inode = dentry->d_inode;
	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
	if (!bh || de->inode != inode->i_ino)
		goto end_unlink;
	if (!inode->i_nlink) {
		printk("Deleting nonexistent file (%s:%lu), %d\n",
		        kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
		inode->i_nlink=1;
	}
	de->inode = 0;
	mark_buffer_dirty(bh);
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(dir);
	inode->i_nlink--;
	inode->i_ctime = dir->i_ctime;
	mark_inode_dirty(inode);
	retval = 0;
end_unlink:
	brelse(bh);
	return retval;
}
예제 #3
0
int sysv_link(struct dentry * old_dentry, struct inode * dir, 
	      struct dentry * dentry)
{
	struct inode *oldinode = old_dentry->d_inode;
	int error;
	struct sysv_dir_entry * de;
	struct buffer_head * bh;

	if (S_ISDIR(oldinode->i_mode)) {
		return -EPERM;
	}
	if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) {
		return -EMLINK;
	}
	bh = sysv_find_entry(dir, dentry->d_name.name,
                             dentry->d_name.len, &de);
	if (bh) {
		brelse(bh);
		return -EEXIST;
	}
	error = sysv_add_entry(dir, dentry->d_name.name,
                               dentry->d_name.len, &bh, &de);
	if (error) {
		brelse(bh);
		return error;
	}
	de->inode = oldinode->i_ino;
	mark_buffer_dirty(bh, 1);
	brelse(bh);
	oldinode->i_nlink++;
	oldinode->i_ctime = CURRENT_TIME;
	mark_inode_dirty(oldinode);
        d_instantiate(dentry, oldinode);
	return 0;
}
예제 #4
0
파일: namei.c 프로젝트: dmgerman/original
static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
{
	int error;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

	bh = sysv_find_entry(dir, dentry->d_name.name,
			     dentry->d_name.len, &de);
	if (bh) {
		brelse(bh);
		return -EEXIST;
	}
	inode = sysv_new_inode(dir);
	if (!inode)
		return -ENOSPC;
	inode->i_uid = current->fsuid;
	init_special_inode(inode, mode, rdev);
	mark_inode_dirty(inode);
	error = sysv_add_entry(dir, dentry->d_name.name, 
			       dentry->d_name.len, &bh, &de);
	if (error) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		return error;
	}
	de->inode = inode->i_ino;
	mark_buffer_dirty(bh);
	brelse(bh);
	d_instantiate(dentry, inode);
	return 0;
}
예제 #5
0
int sysv_symlink(struct inode * dir, struct dentry * dentry, 
		 const char * symname)
{
	struct sysv_dir_entry * de;
	struct inode * inode;
	struct buffer_head * name_block;
	char * name_block_data;
	struct super_block * sb;
	int i;
	char c;
	struct buffer_head * bh;

	if (!(inode = sysv_new_inode(dir)))
		return -ENOSPC;

	inode->i_mode = S_IFLNK | 0777;
	inode->i_op = &sysv_symlink_inode_operations;
	name_block = sysv_file_bread(inode, 0, 1);
	if (!name_block) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		return -ENOSPC;
	}
	sb = inode->i_sb;
	name_block_data = name_block->b_data;
	i = 0;
	while (i < sb->sv_block_size_1 && (c = *(symname++)))
		name_block_data[i++] = c;
	name_block_data[i] = 0;
	mark_buffer_dirty(name_block, 1);
	brelse(name_block);
	inode->i_size = i;
	mark_inode_dirty(inode);
	bh = sysv_find_entry(dir, dentry->d_name.name,
                             dentry->d_name.len, &de);
	if (bh) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		brelse(bh);
		return -EEXIST;
	}
	i = sysv_add_entry(dir, dentry->d_name.name,
                           dentry->d_name.len, &bh, &de);
	if (i) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		return i;
	}
	de->inode = inode->i_ino;
	mark_buffer_dirty(bh, 1);
	brelse(bh);
        d_instantiate(dentry, inode);
	return 0;
}
예제 #6
0
int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode)
{
	int error;
	struct inode * inode;
	struct buffer_head * bh, *dir_block;
	struct sysv_dir_entry * de;

	if (!dir)
		return -EINVAL;
	bh = sysv_find_entry(dir, dentry->d_name.name,
                              dentry->d_name.len, &de);
	if (bh) {
		brelse(bh);
		return -EEXIST;
	}
	if (dir->i_nlink >= dir->i_sb->sv_link_max) 
		return -EMLINK;
	inode = sysv_new_inode(dir);
	if (!inode)
		return -ENOSPC;
	inode->i_op = &sysv_dir_inode_operations;
	inode->i_size = 2 * SYSV_DIRSIZE;
	dir_block = sysv_file_bread(inode,0,1);
	if (!dir_block) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		return -ENOSPC;
	}
	de = (struct sysv_dir_entry *) (dir_block->b_data + 0*SYSV_DIRSIZE);
	de->inode = inode->i_ino;
	strcpy(de->name,"."); /* rest of de->name is zero, see sysv_new_block */
	de = (struct sysv_dir_entry *) (dir_block->b_data + 1*SYSV_DIRSIZE);
	de->inode = dir->i_ino;
	strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
	inode->i_nlink = 2;
	mark_buffer_dirty(dir_block, 1);
	brelse(dir_block);
	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
	if (dir->i_mode & S_ISGID)
		inode->i_mode |= S_ISGID;
	mark_inode_dirty(inode);
	error = sysv_add_entry(dir, dentry->d_name.name,
                               dentry->d_name.len, &bh, &de);
 	if (error) {
		inode->i_nlink=0;
		iput(inode);
		return error;
	}
	de->inode = inode->i_ino;
	mark_buffer_dirty(bh, 1);
	dir->i_nlink++;
	mark_inode_dirty(dir);
	brelse(bh);
        d_instantiate(dentry, inode);
 	return 0;
}
예제 #7
0
ino_t sysv_inode_by_name(struct dentry *dentry)
{
	struct page *page;
	struct sysv_dir_entry *de = sysv_find_entry (dentry, &page);
	ino_t res = 0;
	
	if (de) {
		res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
		dir_put_page(page);
	}
	return res;
}
예제 #8
0
int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
{
	int error;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

	if (!dir)
		return -ENOENT;
	bh = sysv_find_entry(dir, dentry->d_name.name,
			     dentry->d_name.len, &de);
	if (bh) {
		brelse(bh);
		return -EEXIST;
	}
	inode = sysv_new_inode(dir);
	if (!inode)
		return -ENOSPC;
	inode->i_uid = current->fsuid;
	inode->i_mode = mode;
	inode->i_op = NULL;
	if (S_ISREG(inode->i_mode))
		inode->i_op = &sysv_file_inode_operations;
	else if (S_ISCHR(inode->i_mode))
		inode->i_op = &chrdev_inode_operations;
	else if (S_ISBLK(inode->i_mode))
		inode->i_op = &blkdev_inode_operations;
	else if (S_ISFIFO(inode->i_mode))
		init_fifo(inode);
	if (S_ISBLK(mode) || S_ISCHR(mode))
		inode->i_rdev = to_kdev_t(rdev);
	mark_inode_dirty(inode);
	error = sysv_add_entry(dir, dentry->d_name.name, 
			       dentry->d_name.len, &bh, &de);
	if (error) {
		inode->i_nlink--;
		mark_inode_dirty(inode);
		iput(inode);
		return error;
	}
	de->inode = inode->i_ino;
	mark_buffer_dirty(bh, 1);
	brelse(bh);
	d_instantiate(dentry, inode);
	return 0;
}
예제 #9
0
int sysv_unlink(struct inode * dir, struct dentry * dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

repeat:
	retval = -ENOENT;
	inode = NULL;
	bh = sysv_find_entry(dir, dentry->d_name.name,
                             dentry->d_name.len, &de);
	if (!bh)
		goto end_unlink;
	inode = dentry->d_inode;

	retval = -EPERM;
	if (de->inode != inode->i_ino) {
		brelse(bh);
		current->counter = 0;
		schedule();
		goto repeat;
	}
	if (de->inode != inode->i_ino) {
		retval = -ENOENT;
		goto end_unlink;
	}
	if (!inode->i_nlink) {
		printk("Deleting nonexistent file (%s:%lu), %d\n",
		        kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
		inode->i_nlink=1;
	}
	de->inode = 0;
	mark_buffer_dirty(bh, 1);
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(dir);
	inode->i_nlink--;
	inode->i_ctime = dir->i_ctime;
	mark_inode_dirty(inode);
	d_delete(dentry);
	retval = 0;
end_unlink:
	brelse(bh);
	return retval;
}
예제 #10
0
파일: namei.c 프로젝트: dmgerman/original
static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry)
{
	struct inode * inode = NULL;
	struct sysv_dir_entry * de;
	struct buffer_head * bh;

	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);

	if (bh) {
		int ino = de->inode;
		brelse(bh);
		inode = iget(dir->i_sb, ino);
	
		if (!inode) 
			return ERR_PTR(-EACCES);
	}
	d_add(dentry, inode);
	return NULL;
}
예제 #11
0
static int sysv_unlink(struct inode * dir, struct dentry * dentry)
{
    struct inode * inode = dentry->d_inode;
    struct page * page;
    struct sysv_dir_entry * de;
    int err = -ENOENT;

    de = sysv_find_entry(dentry, &page);
    if (!de)
        goto out;

    err = sysv_delete_entry (de, page);
    if (err)
        goto out;

    inode->i_ctime = dir->i_ctime;
    inode_dec_link_count(inode);
out:
    return err;
}
예제 #12
0
int sysv_lookup(struct inode * dir, struct dentry * dentry)
{
	struct inode * inode = NULL;
	struct sysv_dir_entry * de;
	struct buffer_head * bh;

	if (!dir)
		return -ENOENT;
	if (!S_ISDIR(dir->i_mode)) {
		return -ENOENT;
	}
	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);

	if (bh) {
		int ino = de->inode;
		brelse(bh);
		inode = iget(dir->i_sb, ino);
	
		if (!inode) 
			return -EACCES;
	}
	d_add(dentry, inode);
	return 0;
}
예제 #13
0
static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
                       struct inode * new_dir, struct dentry * new_dentry)
{
    struct inode * old_inode = old_dentry->d_inode;
    struct inode * new_inode = new_dentry->d_inode;
    struct page * dir_page = NULL;
    struct sysv_dir_entry * dir_de = NULL;
    struct page * old_page;
    struct sysv_dir_entry * old_de;
    int err = -ENOENT;

    old_de = sysv_find_entry(old_dentry, &old_page);
    if (!old_de)
        goto out;

    if (S_ISDIR(old_inode->i_mode)) {
        err = -EIO;
        dir_de = sysv_dotdot(old_inode, &dir_page);
        if (!dir_de)
            goto out_old;
    }

    if (new_inode) {
        struct page * new_page;
        struct sysv_dir_entry * new_de;

        err = -ENOTEMPTY;
        if (dir_de && !sysv_empty_dir(new_inode))
            goto out_dir;

        err = -ENOENT;
        new_de = sysv_find_entry(new_dentry, &new_page);
        if (!new_de)
            goto out_dir;
        inode_inc_link_count(old_inode);
        sysv_set_link(new_de, new_page, old_inode);
        new_inode->i_ctime = CURRENT_TIME_SEC;
        if (dir_de)
            drop_nlink(new_inode);
        inode_dec_link_count(new_inode);
    } else {
        if (dir_de) {
            err = -EMLINK;
            if (new_dir->i_nlink >= SYSV_SB(new_dir->i_sb)->s_link_max)
                goto out_dir;
        }
        inode_inc_link_count(old_inode);
        err = sysv_add_link(new_dentry, old_inode);
        if (err) {
            inode_dec_link_count(old_inode);
            goto out_dir;
        }
        if (dir_de)
            inode_inc_link_count(new_dir);
    }

    sysv_delete_entry(old_de, old_page);
    inode_dec_link_count(old_inode);

    if (dir_de) {
        sysv_set_link(dir_de, dir_page, new_dir);
        inode_dec_link_count(old_dir);
    }
    return 0;

out_dir:
    if (dir_de) {
        kunmap(dir_page);
        page_cache_release(dir_page);
    }
out_old:
    kunmap(old_page);
    page_cache_release(old_page);
out:
    return err;
}
예제 #14
0
파일: namei.c 프로젝트: dmgerman/original
/*
 * Anybody can rename anything with this: the permission checks are left to the
 * higher-level routines.
 */
static int sysv_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 sysv_dir_entry * old_de, * new_de;
	int retval;

	old_inode = old_dentry->d_inode;
	new_inode = new_dentry->d_inode;
	new_bh = dir_bh = NULL;
	old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name,
				old_dentry->d_name.len, &old_de);
	retval = -ENOENT;
	if (!old_bh || old_de->inode != old_inode->i_ino)
		goto end_rename;
	retval = -EPERM;
	new_bh = sysv_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;
		}
	}
	if (S_ISDIR(old_inode->i_mode)) {
		if (new_inode) {
			retval = -ENOTEMPTY;
			if (!empty_dir(new_inode))
				goto end_rename;
		}
		retval = -EIO;
		dir_bh = sysv_file_bread(old_inode, 0, 0);
		if (!dir_bh)
			goto end_rename;
		if (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 >= new_dir->i_sb->sv_link_max)
			goto end_rename;
	}
	if (!new_bh) {
		retval = sysv_add_entry(new_dir, new_dentry->d_name.name,
					new_dentry->d_name.len, &new_bh, &new_de);
		if (retval)
			goto end_rename;
	}
	new_de->inode = old_inode->i_ino;
	old_de->inode = 0;
	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(old_dir);
	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(new_dir);
	if (new_inode) {
		new_inode->i_nlink--;
		new_inode->i_ctime = CURRENT_TIME;
		mark_inode_dirty(new_inode);
	}
	mark_buffer_dirty(old_bh);
	mark_buffer_dirty(new_bh);
	if (dir_bh) {
		PARENT_INO(dir_bh->b_data) = 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);
		}
	}
	retval = 0;
end_rename:
	brelse(dir_bh);
	brelse(old_bh);
	brelse(new_bh);
	return retval;
}
예제 #15
0
/*
 * rename uses retrying to avoid race-conditions: at least they should be minimal.
 * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
 * checks fail, it tries to restart itself again. Very practical - no changes
 * are done until we know everything works ok.. and then all the changes can be
 * done in one fell swoop when we have claimed all the buffers needed.
 *
 * Anybody can rename anything with this: the permission checks are left to the
 * higher-level routines.
 */
static int do_sysv_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 sysv_dir_entry * old_de, * new_de;
	int retval;

	goto start_up;
try_again:
	brelse(old_bh);
	brelse(new_bh);
	brelse(dir_bh);
	current->counter = 0;
	schedule();
start_up:
	old_inode = new_inode = NULL;
	old_bh = new_bh = dir_bh = NULL;
	old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name,
				old_dentry->d_name.len, &old_de);
	retval = -ENOENT;
	if (!old_bh)
		goto end_rename;
	old_inode = old_dentry->d_inode;	/* don't cross mnt-points */
	retval = -EPERM;
	new_inode = new_dentry->d_inode;
	new_bh = sysv_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;
		}
	}
	if (new_inode == old_inode) {
		retval = 0;
		goto end_rename;
	}
	if (S_ISDIR(old_inode->i_mode)) {
		retval = -EINVAL;
		if (is_subdir(new_dentry, old_dentry))
			goto end_rename;
		if (new_inode) {
			if (new_dentry->d_count > 1)
				shrink_dcache_parent(new_dentry);
			retval = -EBUSY;
			if (new_dentry->d_count > 1)
				goto end_rename;
			retval = -ENOTEMPTY;
			if (!empty_dir(new_inode))
				goto end_rename;
		}
		retval = -EIO;
		dir_bh = sysv_file_bread(old_inode, 0, 0);
		if (!dir_bh)
			goto end_rename;
		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
			goto end_rename;
		retval = -EMLINK;
		if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
			goto end_rename;
	}
	if (!new_bh) {
		retval = sysv_add_entry(new_dir, new_dentry->d_name.name,
					new_dentry->d_name.len, &new_bh, &new_de);
		if (retval)
			goto end_rename;
	}
/* sanity checking before doing the rename - avoid races */
	if (new_inode && (new_de->inode != new_inode->i_ino))
		goto try_again;
	if (new_de->inode && !new_inode)
		goto try_again;
	if (old_de->inode != old_inode->i_ino)
		goto try_again;
/* ok, that's it */
	old_de->inode = 0;
	new_de->inode = old_inode->i_ino;
	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(old_dir);
	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(new_dir);
	if (new_inode) {
		new_inode->i_nlink--;
		new_inode->i_ctime = CURRENT_TIME;
		mark_inode_dirty(new_inode);
	}
	mark_buffer_dirty(old_bh, 1);
	mark_buffer_dirty(new_bh, 1);
	if (dir_bh) {
		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
		mark_buffer_dirty(dir_bh, 1);
		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);
		}
	}
	d_move(old_dentry, new_dentry);
	retval = 0;
end_rename:
	brelse(dir_bh);
	brelse(old_bh);
	brelse(new_bh);
	return retval;
}