Beispiel #1
0
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;
}
Beispiel #2
0
int minix_rmdir(register struct inode *dir, char *name, size_t len)
{
    int retval;
    register struct inode *inode;
    struct buffer_head *bh;
    struct minix_dir_entry *de;

    inode = NULL;
    bh = minix_find_entry(dir, name, len, &de);
    retval = -ENOENT;
    if (!bh)
	goto end_rmdir;
    retval = -EPERM;
    if (!(inode = iget(dir->i_sb, (ino_t) de->inode)))
	goto end_rmdir;
    if ((dir->i_mode & S_ISVTX) && !suser() &&
	current->euid != inode->i_uid && current->euid != dir->i_uid)
	goto end_rmdir;
    if (inode->i_dev != dir->i_dev)
	goto end_rmdir;
    if (inode == dir)		/* we may not delete ".", but "../dir" is ok */
	goto end_rmdir;
    if (!S_ISDIR(inode->i_mode)) {
	retval = -ENOTDIR;
	goto end_rmdir;
    }
    if (!empty_dir(inode)) {
	retval = -ENOTEMPTY;
	goto end_rmdir;
    }
    if (de->inode != inode->i_ino) {
	retval = -ENOENT;
	goto end_rmdir;
    }
    if (inode->i_count > 1) {
	retval = -EBUSY;
	goto end_rmdir;
    }
    if (inode->i_nlink != 2)
	printk("empty directory has nlink!=2 (%u)\n", inode->i_nlink);
    de->inode = 0;

#ifdef BLOAT_FS
    dir->i_version = ++event;
#endif

    mark_buffer_dirty(bh, 1);
    inode->i_nlink = 0;
    inode->i_dirt = 1;
    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
    dir->i_nlink--;
    dir->i_dirt = 1;
    retval = 0;

  end_rmdir:
    iput(dir);
    iput(inode);
    unmap_brelse(bh);
    return retval;
}
Beispiel #3
0
//handling symlink request
void symlink_handler(Msg *msg, int sender_pid)
{

    char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN];
    memset(oldname,'\0',MAXPATHNAMELEN);
    memset(newname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1);
    CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1);

    int dir_len=msg->num3;
    char *dir_newname=newname+msg->num3;
    while((*dir_newname)!='/'&&dir_newname!=newname){
        dir_len--;
        dir_newname--;
    }

    if((*dir_newname)=='/'){
        dir_len++;
        dir_newname++;
    }
    int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); 
    int sym_inum=alloc_inode(INODE_SYMLINK,parent_inum);
    if(sym_inum<=0){
        msg->type=-1;
        return;
    }

    inode_cache *parent_inode=read_inode(parent_inum);
    inode_cache *sym_inode=read_inode(sym_inum);
    int sym_bnum=alloc_block();
    block_cache *sym_block=read_block(sym_bnum);

    struct dir_entry *sym_dir_entry=search_dir_entry(parent_inum,dir_newname);
    if(sym_dir_entry!=NULL){
        msg->type=-1;
        return;
    }
    if((sym_dir_entry=empty_dir(msg->num1))==NULL){
        msg->type=-1;
        return;
    }

    sym_dir_entry->inum=sym_inum;
    memcpy(sym_dir_entry->name,dir_newname,msg->num3-dir_len);


    sym_inode->data.size=msg->num2;
    sym_inode->data.nlink=1;
    sym_inode->data.direct[0]=sym_bnum;

    sym_block->dirty=1;
    memcpy(sym_block->data,oldname,msg->num2);
    parent_inode->data.size+=sizeof(struct dir_entry);
    parent_inode->dirty=1;

}
Beispiel #4
0
//handling mkdir request
void mkdir_handler(Msg *msg, int sender_pid)
{
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1);
    char* dir_name = pathname+msg->num1;
    int direct_len = msg->num1;
    while ((*dir_name)!='/' && dir_name!=pathname) {
        dir_name--;
        direct_len--;
    }
    if ((*dir_name)=='/') {
        direct_len++;
        dir_name++;
    }
    if (strlen(dir_name)==0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }
    int direct_inum = path_to_inum(pathname,direct_len,msg->num2,0);
    if (direct_inum<=0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }
    int new_inum = check_dir(direct_inum,dir_name);
    if (new_inum<0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }

    //exist same file name in the directory
    else if (new_inum>0) {
        perror("exist a directory with same name");
        msg->type = ERROR;
        return;
    }
    else if (new_inum==0) {
        new_inum = alloc_inode(INODE_DIRECTORY,direct_inum);
        struct dir_entry *d = empty_dir(direct_inum);
        if (d==NULL) {
            perror("no empty space for new directory");
            msg->type = ERROR;
            return;
        }
        d->inum = new_inum;
        memcpy(d->name,dir_name,strlen(dir_name));
        inode_cache *n = read_inode(direct_inum);
        n->data.nlink++;
        n->data.size+=sizeof(struct dir_entry);
        n->dirty = 1;
        msg->num1 = 0;
    }
}
Beispiel #5
0
/*
 *   Empty a local directory 
 */
static void empty_dir(VMG_ const char *dir)
{
    /* open the directory search */
    osdirhdl_t dirhdl;
    if (os_open_dir(dir, &dirhdl))
    {
        err_try
        {
            /* keep going until we're out of files */
            char fname[OSFNMAX];
            while (os_read_dir(dirhdl, fname, sizeof(fname)))
            {
                /* get the full path */
                char path[OSFNMAX];
                os_build_full_path(path, sizeof(path), dir, fname);

                /* get the mode */
                unsigned long fmode;
                unsigned long fattr;
                if (osfmode(path, FALSE, &fmode, &fattr))
                {
                    /* check whether it's a directory or an ordinary file */
                    if ((fmode & OSFMODE_DIR) != 0)
                    {
                        /* 
                         *   directory - skip the special '.' and '..' links,
                         *   since they'd get us stuck in a loop 
                         */
                        os_specfile_t st = os_is_special_file(fname);
                        if (st != OS_SPECFILE_SELF && st != OS_SPECFILE_PARENT)
                        {
                            /* recursively empty the directory */
                            empty_dir(vmg_ path);
                            
                            /* remove this directory */
                            if (!os_rmdir(path))
                                err_throw(VMERR_DELETE_FILE);
                        }
                    }
                    else
                    {
                        /* ordinary file - delete it */
                        if (osfdel(path))
                            err_throw(VMERR_DELETE_FILE);
                    }
                }
            }
        }
        err_finally
        {
            /* close the directory search handle */
            os_close_dir(dirhdl);
        }
        err_end;
    }
Beispiel #6
0
int xiafs_rmdir(struct inode * dir, const char * name, int len)
{
    int retval;
    struct inode * inode;
    struct buffer_head * bh;
    struct xiafs_direct * de, * de_pre;

    inode = NULL;
    bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
    retval = -ENOENT;
    if (!bh)
        goto end_rmdir;
    retval = -EPERM;
    if (!(inode = iget(dir->i_sb, de->d_ino)))
        goto end_rmdir;
    if ((dir->i_mode & S_ISVTX) && !fsuser() &&
            current->fsuid != inode->i_uid &&
            current->fsuid != dir->i_uid)
        goto end_rmdir;
    if (inode->i_dev != dir->i_dev)
        goto end_rmdir;
    if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
        goto end_rmdir;
    if (!S_ISDIR(inode->i_mode)) {
        retval = -ENOTDIR;
	goto end_rmdir;
    }
    if (!empty_dir(inode)) {
        retval = -ENOTEMPTY;
	goto end_rmdir;
    }
    if (inode->i_count > 1) {
        retval = -EBUSY;
	goto end_rmdir;
    }
    if (inode->i_nlink != 2)
        printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
    xiafs_rm_entry(de, de_pre);
    mark_buffer_dirty(bh, 1);
    inode->i_nlink=0;
    inode->i_dirt=1;
    dir->i_nlink--;
    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
    dir->i_dirt=1;
    retval = 0;
end_rmdir:
    iput(dir);
    iput(inode);
    brelse(bh);
    return retval;
}
Beispiel #7
0
int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct buffer_head *bh;
	struct qnx4_inode_entry *de;
	struct inode *inode;
	int retval;
	int ino;

	QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
	lock_kernel();
	bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
			     &de, &ino);
	if (bh == NULL) {
		unlock_kernel();
		return -ENOENT;
	}
	inode = dentry->d_inode;
	if (inode->i_ino != ino) {
		retval = -EIO;
		goto end_rmdir;
	}
#if 0
	if (!empty_dir(inode)) {
		retval = -ENOTEMPTY;
		goto end_rmdir;
	}
#endif
	if (inode->i_nlink != 2) {
		QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
	}
	QNX4DEBUG(("qnx4: deleting directory\n"));
	de->di_status = 0;
	memset(de->di_fname, 0, sizeof de->di_fname);
	de->di_mode = 0;
	mark_buffer_dirty(bh);
	inode->i_nlink = 0;
	mark_inode_dirty(inode);
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
	dir->i_nlink--;
	mark_inode_dirty(dir);
	retval = 0;

      end_rmdir:
	brelse(bh);

	unlock_kernel();
	return retval;
}
Beispiel #8
0
int minix_rmdir(struct inode * dir, struct dentry *dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct minix_dir_entry * de;

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

	if (!empty_dir(inode)) {
		retval = -ENOTEMPTY;
		goto end_rmdir;
	}
	if (de->inode != inode->i_ino) {
		retval = -ENOENT;
		goto end_rmdir;
	}
	if (!list_empty(&dentry->d_hash)) {
		retval = -EBUSY;
		goto end_rmdir;
	}
	if (inode->i_nlink != 2)
		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
	de->inode = 0;
	dir->i_version = ++event;
	mark_buffer_dirty(bh, 1);
	inode->i_nlink=0;
	mark_inode_dirty(inode);
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	dir->i_nlink--;
	mark_inode_dirty(dir);
	d_delete(dentry);
	retval = 0;
end_rmdir:
	brelse(bh);
	return retval;
}
Beispiel #9
0
int
affs_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct inode		*inode = dentry->d_inode;
	int			 retval;
	unsigned long		 ino;
	struct buffer_head	*bh;

	pr_debug("AFFS: rmdir(dir=%lu,\"%.*s\")\n",dir->i_ino,
		 (int)dentry->d_name.len,dentry->d_name.name);

	retval = -ENOENT;
	if (!(bh = affs_find_entry(dir,dentry,&ino)))
		goto rmdir_done;

	/*
	 * Make sure the directory is empty and the dentry isn't busy.
	 */
	retval = -ENOTEMPTY;
	if (!empty_dir(bh,AFFS_I2HSIZE(inode)))
		goto rmdir_done;
	retval = -EBUSY;
	if (!list_empty(&dentry->d_hash))
		goto rmdir_done;

	if ((retval = affs_remove_header(bh,inode)) < 0)
		goto rmdir_done;
	
	inode->i_nlink = retval;
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	retval         = 0;
	dir->i_version = ++event;
	mark_inode_dirty(dir);
	mark_inode_dirty(inode);
	d_delete(dentry);

rmdir_done:
	affs_brelse(bh);
	return retval;
}
Beispiel #10
0
int mario_rmdir(struct inode *dir, char *name, int len)
{
	int ino, ret = 0;
	struct inode *inode;

	down(&dir->i_sem);
	if (!(ino = mario_find_entry(dir, name, len))) {
		ret = -ENOENT;
		goto tail;
	}
	inode = iget(dir->i_sb, ino);
	if (!S_ISDIR(inode->i_mode)) {
		ret = -ENOTDIR;
		goto tail;
	}
	/*
	 * We can not remove the root directory
	 */
	if (inode->i_rdev == MARIO_ROOT) {
		ret = -EBUSY;
		goto tail;
	}

	if (inode->i_count > 1) {
		ret = -EBUSY;
		goto tail;
	}
	if (!empty_dir(inode)) {
		ret = -ENOTEMPTY;
		goto tail;
	}
	mario_del_entry(inode, 1);
	iput(inode);	/* This inode would not be got any more */
tail:
	up(&dir->i_sem);
	iput(dir);
	return ret;
}
Beispiel #11
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_minix_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 minix_dir_entry * old_de, * new_de;
	struct minix_sb_info * info;
	int retval;

	info = &old_dir->i_sb->u.minix_sb;
	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 = minix_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;
	retval = -EPERM;
	new_inode = new_dentry->d_inode;
	new_bh = minix_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) {
			/* Prune any children before testing for busy */
			if (new_dentry->d_count > 1)
				shrink_dcache_parent(new_dentry);
			retval = -EBUSY;
			if (new_dentry->d_count > 1)
			retval = -ENOTEMPTY;
			if (!empty_dir(new_inode))
				goto end_rename;
			retval = -EBUSY;
		}
		retval = -EIO;
		dir_bh = minix_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 >= info->s_link_max)
			goto end_rename;
	}
	if (!new_bh) {
		retval = minix_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);
	old_dir->i_version = ++event;
	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(new_dir);
	new_dir->i_version = ++event;
	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);
		}
	}
	/* Update the dcache */
	d_move(old_dentry, new_dentry);
	retval = 0;
end_rename:
	brelse(dir_bh);
	brelse(old_bh);
	brelse(new_bh);
	return retval;
}
Beispiel #12
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;
}
Beispiel #13
0
int
affs_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 buffer_head	*old_bh;
	struct buffer_head	*new_bh;
	unsigned long		 old_ino;
	unsigned long		 new_ino;
	int			 retval;

	pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n",
		 old_dir->i_ino,old_dentry->d_name.len,old_dentry->d_name.name,old_inode,
		 new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode);
	
	if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len)))
		goto out;

	new_bh = NULL;
	retval = -ENOENT;
	old_bh = affs_find_entry(old_dir,old_dentry,&old_ino);
	if (!old_bh)
		goto end_rename;

	new_bh = affs_find_entry(new_dir,new_dentry,&new_ino);
	if (new_bh && !new_inode) {
		affs_error(old_inode->i_sb,"affs_rename",
			   "No inode for entry found (key=%lu)\n",new_ino);
		goto end_rename;
	}
	if (S_ISDIR(old_inode->i_mode)) {
		if (new_inode) {
			retval = -ENOTEMPTY;
			if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
				goto end_rename;
		}

		retval = -ENOENT;
		if (affs_parent_ino(old_inode) != old_dir->i_ino)
			goto end_rename;
	}
	/* Unlink destination if it already exists */
	if (new_inode) {
		if ((retval = affs_remove_header(new_bh,new_dir)) < 0)
			goto end_rename;
		new_inode->i_nlink = retval;
		mark_inode_dirty(new_inode);
		if (new_inode->i_ino == new_ino)
			new_inode->i_nlink = 0;
	}
	/* Remove header from its parent directory. */
	if ((retval = affs_remove_hash(old_bh,old_dir)))
		goto end_rename;
	/* And insert it into the new directory with the new name. */
	affs_copy_name(FILE_END(old_bh->b_data,old_inode)->file_name,new_dentry->d_name.name);
	if ((retval = affs_insert_hash(new_dir->i_ino,old_bh,new_dir)))
		goto end_rename;
	affs_fix_checksum(AFFS_I2BSIZE(new_dir),old_bh->b_data,5);

	new_dir->i_ctime   = new_dir->i_mtime = old_dir->i_ctime
			   = old_dir->i_mtime = CURRENT_TIME;
	new_dir->i_version = ++event;
	old_dir->i_version = ++event;
	retval             = 0;
	mark_inode_dirty(new_dir);
	mark_inode_dirty(old_dir);
	mark_buffer_dirty(old_bh,1);
	
end_rename:
	affs_brelse(old_bh);
	affs_brelse(new_bh);
out:
	return retval;
}
Beispiel #14
0
/*
 * 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;
}
Beispiel #15
0
//handling link request
void link_handler(Msg *msg, int sender_pid)
{

    char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN];

    if(path_to_inum(newname,msg->num3,msg->num1,0)>0){
        /*newname exists*/
        msg->type=-1;
        return;
    }

    memset(oldname,'\0',MAXPATHNAMELEN);
    memset(newname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1);
    CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1);
    int dir_len=msg->num3;
    char *dir_newname=newname+msg->num3;
    while((*dir_newname)!='/'&&dir_newname!=newname){
        dir_len--;
        dir_newname--;
    }

    if((*dir_newname)=='/'){
        dir_len++;
        dir_newname++;
    }
    int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); 
    
    int dir_len_old=msg->num2;
    char *dir_oldname=oldname+msg->num2;
    while((*dir_oldname)!='/'&&dir_oldname!=oldname){
        dir_len_old--;
        dir_oldname--;
    }

    if((*dir_oldname)=='/'){
        dir_len_old++;
        dir_oldname++;
    }

    int parent_old_inum=path_to_inum(oldname,dir_len_old,msg->num1,0);
    int old_inum=check_dir(parent_old_inum,dir_oldname);

    if(old_inum<=0){
        msg->type=-1;
        return;
    }

    inode_cache *old_inode=read_inode(old_inum);
    if(old_inode->data.type==INODE_DIRECTORY){
        msg->type=-1;
        return;
    }

    struct dir_entry *newlink=search_dir_entry(parent_inum,dir_newname);
    if(newlink!=NULL){
        msg->type=-1;
        return;
    }
    if((newlink=empty_dir(parent_inum))==NULL){
        msg->type=-1;
        return;
    }
 
    inode_cache *parent_inode=read_inode(parent_inum);
    parent_inode->data.size+=sizeof(struct dir_entry);
    parent_inode->dirty=1;
    newlink->inum=old_inum;
    memcpy(newlink->name,dir_newname,msg->num3-dir_len);
    old_inode->data.nlink++;
    old_inode->dirty=1;

}
Beispiel #16
0
static 
int do_mario_rename(struct inode *old_dir, char *old_name, int old_len,
	struct inode *new_dir, char *new_name, int new_len)
{
	int ino, error = 0;
	struct inode *old_inode, *new_inode;
	struct mario_dir_entry entry;

	if (old_len > MARIO_NAME_LEN - 1 || new_len > MARIO_NAME_LEN - 1)
		return -ENAMETOOLONG;
	if (!(ino = mario_find_entry(old_dir, old_name, old_len)))
		return -ENOENT;
	old_inode = iget(old_dir->i_sb, ino);

	if (!(ino = mario_find_entry(new_dir, new_name, new_len)))
		goto next_1;
	new_inode = iget(new_dir->i_sb, ino);

	if (new_inode == old_inode) {
		iput(new_inode);
		iput(old_inode);
		return 0;
	}
	/* do some check */
	if (S_ISDIR(new_inode->i_mode)) {
		if (!S_ISDIR(old_inode->i_mode))
			return -EISDIR;
		if (!empty_dir(new_inode))
			return -ENOTEMPTY;
	} else {
		if (S_ISDIR(old_inode->i_mode))
			return -ENOTDIR;
	}
	/* delete new_inode */
	down(&new_dir->i_sem);
	if (new_inode->i_count > 1) {
		error = -EBUSY;
		goto next_2;
	}
	mario_del_entry(new_inode, 1);
next_2:
	iput(new_inode);
	up(&new_dir->i_sem);
	if (error) {
		iput(old_inode);
		return error;
	}
next_1:
	/* delete old_inode but not free blocks occupied */
	down(&old_dir->i_sem);
	if (old_inode->i_count > 1) {
		error = -EBUSY;
		goto next_3;
	}
	mario_del_entry(old_inode, 0);
	/* add old_inode to new_dir */
	entry.data = old_inode->i_rdev;
	entry.mode = old_inode->i_mode;
	entry.size = old_inode->i_size;
	entry.blocks = old_inode->i_nr_block;
	strncpy(entry.name, new_name, new_len);
	entry.name[new_len] = '\0';
	/*
	 * If old_inode is a directory we need to change its parent
	 */
	if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) {
		struct buffer_head *bh;
		struct mario_dir_entry *tmp;

		bh = bread(old_inode->i_dev, old_inode->i_rdev);
		if (!bh) {
			error = -EIO;
			goto next_3;
		}
		tmp = (struct mario_dir_entry *)bh->b_data;
		tmp[1].data = new_dir->i_rdev;	/* .. */
		set_dirty(bh);
		brelse(bh);
	}
	mario_add_entry(new_dir, &entry, NULL);
next_3:
	iput(old_inode);
	up(&old_dir->i_sem);
	return error;
}
Beispiel #17
0
int syscall_rename(const char *a_oldpath, const char *a_newpath)
{
	int ohandle, nhandle;
	int drive1, drive2;
	char dir_path1[512], dir_path2[512];
	char name_comp1[13], name_comp2[13], conv_name1[11], conv_name2[11];
	char oldpath[512], newpath[512];
	struct dir_entry dent1, dent2;
	int exist1, exist2;
	struct DIR_FILE *dirf;
	int len1, len2;
	int i,t;

	len1 = strlen(a_oldpath);
	len2 = strlen(a_newpath);

	if (len1 > 512 || len2 > 512) return ELONGPATH;

	strcpy(oldpath,a_oldpath);
	strcpy(newpath,a_newpath);

	if (oldpath[len1-1] == '/' || oldpath[len1-1] == '\\') oldpath[len1-1] = '\0';
	if (newpath[len2-1] == '/' || newpath[len2-1] == '\\') newpath[len2-1] = '\0';
	parse_path(oldpath, &drive1, dir_path1, name_comp1);
	parse_path(newpath, &drive2, dir_path2, name_comp2);

	if (drive1 != drive2) return EDEVICE_DIFFERENT;

	nhandle = open_path(drive2, dir_path2);
	if (nhandle < 0) return nhandle;

	if (name_comp2[0] !='\0')
	{
		if (convert_name(name_comp2, conv_name2) < 0)
		{
			close_dir(nhandle);
			return EINVALIDNAME; // Error
		}

		exist2 = find_entry(nhandle, conv_name2, &dent2);
	}
	
	ohandle = open_path(drive1, dir_path1);
	if (ohandle < 0)
	{
		close_dir(nhandle);
		return ohandle;
	}
	if (name_comp1[0] != '\0')
	{
		if (convert_name(name_comp1, conv_name1) < 0)
		{
			close_dir(nhandle);
			close_dir(ohandle);
			return EINVALIDNAME; // Error
		}

		exist1 = find_entry(ohandle, conv_name1, &dent1);
	}

	// Check whether new path exists and is removable
	if ((exist2 == 1) && ((dent2.attrib & FTYPE_READONLY) || ((dent2.attrib & FTYPE_DIR) && (empty_dir(nhandle, &dent2) != 1))))
	{
		close_dir(nhandle);
		close_dir(ohandle);
		return ETARGET_EXISTS;
	}

	// Check if source exists and is movable
	if (exist1 != 1)
	{
		close_dir(nhandle);
		close_dir(ohandle);
		return EPATH_NOT_EXISTS;
	}
	if ((dent1.attrib & FTYPE_READONLY) != 0)
	{
		close_dir(nhandle);
		close_dir(ohandle);
		return EREADONLY;
	}
	// Check whether oldpath is not a subpath of newpath
	if ((dent1.attrib & FTYPE_DIR) && (ohandle != nhandle))
	{	
		t = nhandle;
		dirf = &dir_file_list[t];

		while (dirf->parent_index >= 0 && dirf->parent_index != ohandle)
		{
			t = dirf->parent_index;
			dirf = &dir_file_list[t];
		}
		
		if (dirf->parent_index == ohandle)
		{
			close_dir(nhandle);
			close_dir(ohandle);
			return EOLDPATH_PARENT_OF_NEWPATH;
		}
	}

	// Check if newpath already exists whether it is compatible or not
	if ((exist2 == 1) && (((dent1.attrib & FTYPE_DIR) != 0 && (dent2.attrib & FTYPE_DIR) == 0) || ((dent1.attrib & FTYPE_DIR) == 0 && (dent2.attrib & FTYPE_DIR) != 0))) 
	{
		close_dir(nhandle);
		close_dir(ohandle);
		return ESRC_DEST_NOT_SAME_TYPE;
	}

	// Remove destination entry if exists
	if (exist2 == 1)
	{
		if (dent2.attrib & FTYPE_DIR)
			syscall_rmdir(newpath);
		else	syscall_unlink(newpath);
	}

	// Add the source dir entry after changing the name
	// to destination directory
	bcopy( (char *)&dent1, (char *)&dent2, sizeof(struct dir_entry));
	for (i=0; i<11; i++)	// Both name and extension
		dent2.name[i] = conv_name2[i];

	t = add_dir_entry(nhandle, &dent2);
	if (t == 1)
	{
		delete_dir_entry(ohandle, dent1.name);
	}

	// Close the handles of parent directories
	close_dir(ohandle);
	close_dir(nhandle);
	
	if (t == 1) return 0;
	else	return t;

}