BOOL file_list_rename(u16 *p_old, u16 *p_new)
{
  u16 *p_old_temp = p_old;
  u16 *p_new_temp = p_new;
  
  CHECK_FAIL_RET_FALSE(p_old_temp != NULL);
  CHECK_FAIL_RET_FALSE(p_new_temp != NULL);
#ifndef WIN32
  if (p_old_temp[1] == 0x3A
    && (p_old_temp[2] == 0x5C || p_old_temp[2] == 0x2F))//:\ or :/
  {
    p_old_temp += 3;
  }
  
  if (p_new_temp[1] == 0x3A
    && (p_new_temp[2] == 0x5C || p_new_temp[2] == 0x2F))//:\ or :/
  {
    p_new_temp += 3;
  }
#endif
  if(vfs_rename(p_old_temp, p_new_temp) == ERR_FAILURE)
  {
    return FALSE;
  }

  return TRUE;
}
示例#2
0
/* utility to rename a file */
int lustre_rename(struct dentry *dir, struct vfsmount *mnt,
		  char *oldname, char *newname)
{
	struct dentry *dchild_old, *dchild_new;
	int err = 0;
	ENTRY;

	ASSERT_KERNEL_CTXT("kernel doing rename outside kernel context\n");
	CDEBUG(D_INODE, "renaming file %.*s to %.*s\n",
	       (int)strlen(oldname), oldname, (int)strlen(newname), newname);

	dchild_old = ll_lookup_one_len(oldname, dir, strlen(oldname));
	if (IS_ERR(dchild_old))
		RETURN(PTR_ERR(dchild_old));

	if (!dchild_old->d_inode)
		GOTO(put_old, err = -ENOENT);

	dchild_new = ll_lookup_one_len(newname, dir, strlen(newname));
	if (IS_ERR(dchild_new))
		GOTO(put_old, err = PTR_ERR(dchild_new));

	err = vfs_rename(dir->d_inode, dchild_old, dir->d_inode, dchild_new);

	dput(dchild_new);
put_old:
	dput(dchild_old);
	RETURN(err);
}
示例#3
0
static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
		struct inode *new_dir, struct dentry *new_dentry)
{
	int rc;
	struct dentry *lower_old_dentry;
	struct dentry *lower_new_dentry;
	struct dentry *lower_old_dir_dentry;
	struct dentry *lower_new_dir_dentry;

	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
	dget(lower_old_dentry);
	dget(lower_new_dentry);
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);
	lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (rc)
		goto out_lock;
	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
	if (new_dir != old_dir)
		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
out_lock:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_new_dentry->d_parent);
	dput(lower_old_dentry->d_parent);
	dput(lower_new_dentry);
	dput(lower_old_dentry);
	return rc;
}
static int file_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) {
    int err=0;
    err = vfs_rename(old_dir, old_dentry,
                     new_dir, new_dentry,
                     NULL, 0);
    return err;
}
示例#5
0
/*
 * The locking rules in wrapfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;

	wrapfs_get_lower_path(old_dentry, &lower_old_path);
	wrapfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry,
			 NULL, 0);
	if (err)
		goto out;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	wrapfs_put_lower_path(old_dentry, &lower_old_path);
	wrapfs_put_lower_path(new_dentry, &lower_new_path);
#ifdef NEKTECH_LOGGER /*NEKTECH LOGGING*/
            nektech_logger (new_dir, new_dentry, NEKTECH_RENAME);
#endif          /*NEKTECH LOGGING*/

	return err;
}
示例#6
0
static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
		struct inode *new_dir, struct dentry *new_dentry)
{
	int rc;
	struct dentry *lower_old_dentry;
	struct dentry *lower_new_dentry;
	struct dentry *lower_old_dir_dentry;
	struct dentry *lower_new_dir_dentry;
	struct dentry *trap = NULL;
	struct inode *target_inode;

#ifdef CONFIG_SDP
	if(IS_CHAMBER_DENTRY(old_dentry)) {
		printk("You're renaming chamber directory. I/O error\n");
		return -EIO;
	}
#endif

	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
	dget(lower_old_dentry);
	dget(lower_new_dentry);
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);
	target_inode = new_dentry->d_inode;
	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		rc = -EINVAL;
		goto out_lock;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		rc = -ENOTEMPTY;
		goto out_lock;
	}
	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (rc)
		goto out_lock;
	if (target_inode)
		fsstack_copy_attr_all(target_inode,
				      ecryptfs_inode_to_lower(target_inode));
	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir)
		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
out_lock:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dentry);
	dput(lower_old_dentry);
	return rc;
}
示例#7
0
文件: inode.c 项目: acton393/linux
static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
		struct inode *new_dir, struct dentry *new_dentry,
		unsigned int flags)
{
	int rc;
	struct dentry *lower_old_dentry;
	struct dentry *lower_new_dentry;
	struct dentry *lower_old_dir_dentry;
	struct dentry *lower_new_dir_dentry;
	struct dentry *trap = NULL;
	struct inode *target_inode;

	if (flags)
		return -EINVAL;

	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
	dget(lower_old_dentry);
	dget(lower_new_dentry);
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);
	target_inode = d_inode(new_dentry);
	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		rc = -EINVAL;
		goto out_lock;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		rc = -ENOTEMPTY;
		goto out_lock;
	}
	rc = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
			d_inode(lower_new_dir_dentry), lower_new_dentry,
			NULL, 0);
	if (rc)
		goto out_lock;
	if (target_inode)
		fsstack_copy_attr_all(target_inode,
				      ecryptfs_inode_to_lower(target_inode));
	fsstack_copy_attr_all(new_dir, d_inode(lower_new_dir_dentry));
	if (new_dir != old_dir)
		fsstack_copy_attr_all(old_dir, d_inode(lower_old_dir_dentry));
out_lock:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dentry);
	dput(lower_old_dentry);
	return rc;
}
示例#8
0
/*
 * The locking rules in diaryfs_rename are complex. We could use a simpler
 * superblock level namespace lock for renames and copy-ups 
 */
static int diaryfs_rename(struct inode * old_dir, struct dentry * old_dentry,
			struct inode * new_dir, struct dentry * new_dentry) {

	int err = 0; 
	struct dentry * lower_old_dentry = NULL;
	struct dentry * lower_new_dentry = NULL;
	struct dentry * lower_old_dir_dentry = NULL; 
	struct dentry * lower_new_dir_dentry = NULL; 
	struct dentry * trap = NULL;
	struct path lower_old_path, lower_new_path; 

	diaryfs_get_lower_path(old_dentry, &lower_old_path); 
	diaryfs_get_lower_path(new_dentry, &lower_new_path); 
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry; 
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry); 

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of the target */ 
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -EINVAL;
		goto out; 
	} err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry, NULL, 0);

	if (err)
		goto out;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir, 
				lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
				lower_old_dir_dentry->d_inode);
	}
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	diaryfs_put_lower_path(old_dentry, &lower_old_path);
	diaryfs_put_lower_path(new_dentry, &lower_new_path);
	return err;
}
示例#9
0
/* sysfile_rename - rename file */
int
sysfile_rename(const char *__path1, const char *__path2) {
    int ret;
    char *old_path, *new_path;
    if ((ret = copy_path(&old_path, __path1)) != 0) {
        return ret;
    }
    if ((ret = copy_path(&new_path, __path2)) != 0) {
        kfree(old_path);
        return ret;
    }
    ret = vfs_rename(old_path, new_path);
    kfree(old_path), kfree(new_path);
    return ret;
}
static int rename_temp_file(struct file *fp_old, struct file *fp_new)
{
	int rc;
	struct inode *pi_old = fp_old->f_path.dentry->d_parent->d_inode;
	struct inode *pi_new = fp_new->f_path.dentry->d_parent->d_inode;
	
	struct dentry *d_old = fp_old->f_path.dentry;
	struct dentry *d_new = fp_new->f_path.dentry;
	
	struct dentry *pd_old = NULL;
	struct dentry *pd_new = NULL;
	struct dentry *trap = NULL;
	
	dget(d_old);
	dget(d_new);
	pd_old=dget_parent(d_old);
	pd_new=dget_parent(d_new);

	trap = lock_rename(pd_old,pd_new);

	if(trap == d_old){
		rc = -EINVAL;
		goto out;
	}

	if(trap == d_new){
		rc = -ENOTEMPTY;
		goto out;
	}

	rc = vfs_rename(pi_old,d_old,pi_new,d_new,NULL,0);
	if(rc){
		printk("Error in vfs_rename() \n");
		rc= -ECANCELED;
		goto out;
	}

out:
	unlock_rename(pd_old,pd_new);
	dput(pd_new);
	dput(pd_old);
	dput(d_new);
	dput(d_old);
	
	return rc;
}
示例#11
0
文件: ovl_misc.c 项目: raven-au/ovlfs
int	do_rename (struct inode *olddir, const char *oname, int olen,
	           struct inode *newdir, const char *nname, int nlen,
	           int must_be_dir)
{
#if POST_20_KERNEL_F
	struct dentry	*old_dent;
	struct dentry	*new_dent;
#endif
	int	ret;

#if POST_20_KERNEL_F

	ret = ovlfs_inode_get_child_dentry(olddir, oname, olen, &old_dent,
	                                   OVLFS_DENT_GET_POSITIVE);

	if ( ret == 0 )
	{
			/* Get a dentry for the target; note that this may */
			/*  be a positive or negative dentry.              */

		ret = ovlfs_inode_get_child_dentry(newdir, nname, nlen,
		                                   &new_dent,
		                                   OVLFS_DENT_GET_ANY);

		if ( ret != 0 )
			dput(old_dent);
	}

	if ( ret == 0 )
	{
		ret = vfs_rename(olddir, old_dent, newdir, new_dent);

		dput(old_dent);
		dput(new_dent);
	}
#else
	DOWN(&(newdir->i_sem));
	IMARK(olddir);
	IMARK(newdir);
	ret = o_olddir->i_op->rename(o_olddir, oname, olen,
	                             o_newdir, nname, nlen, must_be_dir);
	UP(&(newdir->i_sem));
#endif

	return	ret;
}
static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
		struct inode *new_dir, struct dentry *new_dentry)
{
	int rc;
	struct dentry *lower_old_dentry;
	struct dentry *lower_new_dentry;
	struct dentry *lower_old_dir_dentry;
	struct dentry *lower_new_dir_dentry;
	struct dentry *trap = NULL;

	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
		dentry_unhash(new_dentry);

	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
	dget(lower_old_dentry);
	dget(lower_new_dentry);
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);
	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		rc = -EINVAL;
		goto out_lock;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		rc = -ENOTEMPTY;
		goto out_lock;
	}
	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (rc)
		goto out_lock;
	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir)
		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
out_lock:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dentry);
	dput(lower_old_dentry);
	return rc;
}
示例#13
0
文件: sc_vfs.c 项目: ryankurte/RIOT
static int _mv_handler(int argc, char **argv)
{
    if (argc < 3) {
        _vfs_usage(argv);
        return 1;
    }
    char *src_name = argv[1];
    char *dest_name = argv[2];
    printf("%s: move src: %s dest: %s\n", argv[0], src_name, dest_name);

    int res = vfs_rename(src_name, dest_name);
    if (res < 0) {
        char errbuf[16];
        _errno_string(res, (char *)errbuf, sizeof(errbuf));
        printf("mv ERR: %s\n", errbuf);
        return 2;
    }
    return 0;
}
示例#14
0
static int cmd_vfs_mv(struct vmm_chardev *cdev, 
			const char *old_path, const char *new_path)
{
	int rc;
	struct stat st;

	rc = vfs_stat(old_path, &st);
	if (rc) {
		vmm_cprintf(cdev, "Path %s does not exist.\n", old_path);
		return rc;
	}

	rc = vfs_rename(old_path, new_path);
	if (rc) {
		vmm_cprintf(cdev, "Failed to rename.\n");
		return rc;
	}

	return VMM_OK;
}
示例#15
0
static void cmd_rnto(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm)
{
	if (fsm->state != FTPD_RNFR) {
		send_msg(pcb, fsm, msg503);
		return;
	}
	fsm->state = FTPD_IDLE;
	if (arg == NULL) {
		send_msg(pcb, fsm, msg501);
		return;
	}
	if (*arg == '\0') {
		send_msg(pcb, fsm, msg501);
		return;
	}
	if (vfs_rename(fsm->vfs, fsm->renamefrom, arg)) {
		send_msg(pcb, fsm, msg450);
	} else {
		send_msg(pcb, fsm, msg250);
	}
}
示例#16
0
文件: vfsub.c 项目: wosigh/patches
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
		    struct inode *dir, struct dentry *dentry)
{
	int err;

	LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
		  src_dir->i_ino, AuDLNPair(src_dentry),
		  dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);
	IMustLock(src_dir);
	AuDebugOn(src_dir != dir && !vfsub_is_rename_mutex_locked(dir->i_sb));

	lockdep_off();
	err = vfs_rename(src_dir, src_dentry, dir, dentry);
	lockdep_on();
	if (!err) {
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
	}
	return err;
}
示例#17
0
static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
		     struct inode *new_dir, struct dentry *new_dentry,
		     int bindex, struct dentry **wh_old)
{
	int err = 0;
	struct dentry *hidden_old_dentry;
	struct dentry *hidden_new_dentry;
	struct dentry *hidden_old_dir_dentry;
	struct dentry *hidden_new_dir_dentry;
	struct dentry *hidden_wh_dentry;
	struct dentry *hidden_wh_dir_dentry;
	char *wh_name = NULL;

	hidden_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
	hidden_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);

	if (!hidden_new_dentry) {
		hidden_new_dentry =
		    create_parents(new_dentry->d_parent->d_inode, new_dentry, bindex);
		if (IS_ERR(hidden_new_dentry)) {
			printk(KERN_DEBUG "error creating directory tree for"
					  " rename, bindex = %d, err = %ld\n",
				          bindex, PTR_ERR(hidden_new_dentry));
			err = PTR_ERR(hidden_new_dentry);
			goto out;
		}
	}

	wh_name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
	if (IS_ERR(wh_name)) {
		err = PTR_ERR(wh_name);
		goto out;
	}

	hidden_wh_dentry = lookup_one_len(wh_name, hidden_new_dentry->d_parent,
				new_dentry->d_name.len + UNIONFS_WHLEN);
	if (IS_ERR(hidden_wh_dentry)) {
		err = PTR_ERR(hidden_wh_dentry);
		goto out;
	}

	if (hidden_wh_dentry->d_inode) {
		/* get rid of the whiteout that is existing */
		if (hidden_new_dentry->d_inode) {
			printk(KERN_WARNING "Both a whiteout and a dentry"
					" exist when doing a rename!\n");
			err = -EIO;

			dput(hidden_wh_dentry);
			goto out;
		}

		hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry);
		if (!(err = is_robranch_super(old_dentry->d_sb, bindex)))
			err = vfs_unlink(hidden_wh_dir_dentry->d_inode,
					       hidden_wh_dentry);

		dput(hidden_wh_dentry);
		unlock_dir(hidden_wh_dir_dentry);
		if (err)
			goto out;
	} else
		dput(hidden_wh_dentry);

	dget(hidden_old_dentry);
	hidden_old_dir_dentry = dget_parent(hidden_old_dentry);
	hidden_new_dir_dentry = dget_parent(hidden_new_dentry);

	lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);

	err = is_robranch_super(old_dentry->d_sb, bindex);
	if (err)
		goto out_unlock;

	/* ready to whiteout for old_dentry. caller will create the actual
	 * whiteout, and must dput(*wh_old)
	 */
	if (wh_old) {
		char *whname;
		whname = alloc_whname(old_dentry->d_name.name,
				      old_dentry->d_name.len);
		err = PTR_ERR(whname);
		if (IS_ERR(whname))
			goto out_unlock;
		*wh_old = lookup_one_len(whname, hidden_old_dir_dentry,
					 old_dentry->d_name.len + UNIONFS_WHLEN);
		kfree(whname);
		err = PTR_ERR(*wh_old);
		if (IS_ERR(*wh_old)) {
			*wh_old = NULL;
			goto out_unlock;
		}
	}

	err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,
			 hidden_new_dir_dentry->d_inode, hidden_new_dentry);

out_unlock:
	unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);

	dput(hidden_old_dir_dentry);
	dput(hidden_new_dir_dentry);
	dput(hidden_old_dentry);

out:
	if (!err) {
		/* Fixup the newdentry. */
		if (bindex < dbstart(new_dentry))
			set_dbstart(new_dentry, bindex);
		else if (bindex > dbend(new_dentry))
			set_dbend(new_dentry, bindex);
	}

	kfree(wh_name);

	return err;
}
/*
 * The locking rules in wrapfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;

	wrapfs_get_lower_path(old_dentry, &lower_old_path);
	wrapfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	wrapfs_put_lower_path(old_dentry, &lower_old_path);
	wrapfs_put_lower_path(new_dentry, &lower_new_path);
	return err;
}
示例#19
0
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	bool cont = true;
	
	/*
	 * The connection was opened via the IPC_CONNECT_ME_TO call.
	 * This call needs to be answered.
	 */
	async_answer_0(iid, EOK);
	
	while (cont) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call))
			break;
		
		switch (IPC_GET_IMETHOD(call)) {
		case VFS_IN_REGISTER:
			vfs_register(callid, &call);
			cont = false;
			break;
		case VFS_IN_MOUNT:
			vfs_mount(callid, &call);
			break;
		case VFS_IN_UNMOUNT:
			vfs_unmount(callid, &call);
			break;
		case VFS_IN_OPEN:
			vfs_open(callid, &call);
			break;
		case VFS_IN_CLOSE:
			vfs_close(callid, &call);
			break;
		case VFS_IN_READ:
			vfs_read(callid, &call);
			break;
		case VFS_IN_WRITE:
			vfs_write(callid, &call);
			break;
		case VFS_IN_SEEK:
			vfs_seek(callid, &call);
			break;
		case VFS_IN_TRUNCATE:
			vfs_truncate(callid, &call);
			break;
		case VFS_IN_FSTAT:
			vfs_fstat(callid, &call);
			break;
		case VFS_IN_STAT:
			vfs_stat(callid, &call);
			break;
		case VFS_IN_MKDIR:
			vfs_mkdir(callid, &call);
			break;
		case VFS_IN_UNLINK:
			vfs_unlink(callid, &call);
			break;
		case VFS_IN_RENAME:
			vfs_rename(callid, &call);
			break;
		case VFS_IN_SYNC:
			vfs_sync(callid, &call);
			break;
		case VFS_IN_DUP:
			vfs_dup(callid, &call);
			break;
		case VFS_IN_WAIT_HANDLE:
			vfs_wait_handle(callid, &call);
			break;
		case VFS_IN_MTAB_GET:
			vfs_get_mtab(callid, &call);
			break;
		default:
			async_answer_0(callid, ENOTSUP);
			break;
		}
	}
	
	/*
	 * Open files for this client will be cleaned up when its last
	 * connection fibril terminates.
	 */
}
示例#20
0
文件: vfsub.c 项目: aywq2008/omniplay
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
		 struct inode *dir, struct path *path)
{
	int err;
	struct path tmp = {
		.mnt	= path->mnt
	};
	struct dentry *d;

	IMustLock(dir);
	IMustLock(src_dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	tmp.dentry = src_dentry->d_parent;
	err = security_path_rename(&tmp, src_dentry, path, d);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	lockdep_off();
	err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
	lockdep_on();
	if (!err) {
		int did;

		tmp.dentry = d->d_parent;
		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = src_dentry;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
			tmp.dentry = src_dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}

int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_mkdir(path, d, mode);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	err = vfs_mkdir(dir, path->dentry, mode);
	if (!err) {
		struct path tmp = *path;
		int did;

		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = path->dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}
/*
 * The locking rules in amfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int amfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;
	/*******Variable which will help in checking XATTR***************/
	char *value = NULL;

	if (old_dentry->d_inode->i_ino ==
				AMFS_SB(old_dentry->d_sb)->inode_no) {
		err = -EPERM;
		goto exitcode;
	}

	value = kzalloc(5, __GFP_WAIT);
	if (value == NULL) {
		err = -ENOMEM;
		goto exitcode;
	}
	if (amfs_getxattr(old_dentry, AMFS_XATTR_NAME, value, 5) > 0) {
		if (!strncmp(value, AMFS_BADFILE, 3)) {
			err = -EPERM;
			goto freevalue;
		}
	} else if (amfs_getxattr(old_dentry, AMFS_XATTR_NAME, value, 5)
			!= -ENODATA) {
		err = amfs_getxattr(old_dentry, AMFS_XATTR_NAME, value, 5);
		goto freevalue;
	}
	/****************************************************************/
	amfs_get_lower_path(old_dentry, &lower_old_path);
	amfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry,
			 NULL, 0);
	if (err)
		goto out;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	amfs_put_lower_path(old_dentry, &lower_old_path);
	amfs_put_lower_path(new_dentry, &lower_new_path);
freevalue:
	kfree(value);
exitcode:
	return err;
}
示例#22
0
/*
 * The locking rules in sdcardfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct dentry *new_parent = NULL;
	struct path lower_old_path, lower_new_path;
	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(old_dentry->d_sb);
	const struct cred *saved_cred = NULL;

	int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
	if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name,
			sbi->options.derive, 1, has_rw) ||
		!check_caller_access_to_name(new_dir, new_dentry->d_name.name,
			sbi->options.derive, 1, has_rw)) {
		err = -EACCES;
		goto out_eacces;
	}

	/* save current_cred and override it */
	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred);

	sdcardfs_get_real_lower(old_dentry, &lower_old_path);
	sdcardfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	/* Copy attrs from lower dir, but i_uid/i_gid */
	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	fix_derived_permission(new_dir); 
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode);
		fix_derived_permission(old_dir);
		/* update the derived permission of the old_dentry
		 * with its new parent
		 */
		new_parent = dget_parent(new_dentry);
		if(new_parent) {
			if(old_dentry->d_inode) {
				get_derived_permission(new_parent, old_dentry);
				fix_derived_permission(old_dentry->d_inode);
			}
			dput(new_parent);
		}
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	sdcardfs_put_real_lower(old_dentry, &lower_old_path);
	sdcardfs_put_lower_path(new_dentry, &lower_new_path);
	REVERT_CRED(saved_cred);
out_eacces:
	return err;
}
/*
 * The locking rules in u2fs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int u2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct dentry *ret = NULL;
	struct path lower_old_path, lower_new_path;
	
	/* creating parent directories if destination is read-only */
	if((U2FS_D(old_dentry)->lower_path[LEFT].dentry) == NULL && 
		(U2FS_D(old_dentry)->lower_path[LEFT].mnt) == NULL){

		err = create_whiteout(old_dentry);	
		if(err){
			err = -EIO;
			goto out_copyup;
		}

		err = copyup_dentry(old_dir, old_dentry,
			  old_dentry->d_name.name, old_dentry->d_name.len,
			  NULL, i_size_read(old_dentry->d_inode));
		if(err)
			goto out_copyup;
	}
	
	if((U2FS_D(new_dentry)->lower_path[LEFT].dentry) == NULL && 
		(U2FS_D(new_dentry)->lower_path[LEFT].mnt) == NULL){

		ret = create_parents(new_dir, new_dentry, 
					new_dentry->d_name.name);

		if (!ret || IS_ERR(ret)) {
					err = PTR_ERR(ret);
					if (!IS_COPYUP_ERR(err))
						printk(KERN_ERR
					      	 "u2fs: create_parents for "
				     		  "u2fs_rename failed"
					      	 "err=%d\n", err);
					goto out_copyup;
		}
		u2fs_postcopyup_setmnt(new_dentry);
		u2fs_put_reset_lower_path(new_dentry, RIGHT);
		
		if(err)
			goto out_copyup;
	}
	
	u2fs_get_lower_path(old_dentry, &lower_old_path, LEFT);
	u2fs_get_lower_path(new_dentry, &lower_new_path, LEFT);

	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	u2fs_put_lower_path(old_dentry, &lower_old_path);
	u2fs_put_lower_path(new_dentry, &lower_new_path);
out_copyup:
	return err;
}
示例#24
0
/*
 * Rename a file
 * N.B. After this call _both_ ffhp and tfhp need an fh_put
 */
int
nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
			    struct svc_fh *tfhp, char *tname, int tlen)
{
	struct dentry	*fdentry, *tdentry, *odentry, *ndentry;
	struct inode	*fdir, *tdir;
	int		err;

	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
	if (err)
		goto out;
	err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;

	fdentry = ffhp->fh_dentry;
	fdir = fdentry->d_inode;

	tdentry = tfhp->fh_dentry;
	tdir = tdentry->d_inode;

	/* N.B. We shouldn't need this ... dentry layer handles it */
	err = nfserr_perm;
	if (!flen || (fname[0] == '.' && 
	    (flen == 1 || (flen == 2 && fname[1] == '.'))) ||
	    !tlen || (tname[0] == '.' && 
	    (tlen == 1 || (tlen == 2 && tname[1] == '.'))))
		goto out;

	odentry = lookup_dentry(fname, dget(fdentry), 0);
	err = PTR_ERR(odentry);
	if (IS_ERR(odentry))
		goto out_nfserr;

	err = -ENOENT;
	if (!odentry->d_inode)
		goto out_dput_old;

	ndentry = lookup_dentry(tname, dget(tdentry), 0);
	err = PTR_ERR(ndentry);
	if (IS_ERR(ndentry))
		goto out_dput_old;

	/*
	 * Lock the parent directories.
	 */
	nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
	err = -ENOENT;
	/* GAM3 check for parent changes after locking. */
	if (check_parent(fdir, odentry) &&
	    check_parent(tdir, ndentry)) {

		err = vfs_rename(fdir, odentry, tdir, ndentry);
		if (!err && EX_ISSYNC(tfhp->fh_export)) {
			write_inode_now(fdir);
			write_inode_now(tdir);
		}
	} else
		dprintk("nfsd: Caught race in nfsd_rename");
	DQUOT_DROP(fdir);
	DQUOT_DROP(tdir);

	nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
	dput(ndentry);

out_dput_old:
	dput(odentry);
	if (err)
		goto out_nfserr;
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
示例#25
0
文件: inode.c 项目: Mortifix/SM-G920T
/*
 * The locking rules in sdcardfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct dentry *new_parent = NULL;
	struct path lower_old_path, lower_new_path;
	const struct cred *saved_cred = NULL;

	if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) ||
		!check_caller_access_to_name(new_dir, new_dentry->d_name.name)) {
		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" 
						 "  new_dentry: %s, task:%s\n",
						 __func__, new_dentry->d_name.name, current->comm);
		err = -EACCES;
		goto out_eacces;
	}

	/* save current_cred and override it */
	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred);

	sdcardfs_get_real_lower(old_dentry, &lower_old_path);
	sdcardfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	/* Copy attrs from lower dir, but i_uid/i_gid */
	sdcardfs_copy_inode_attr(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	fix_derived_permission(new_dir);
	if (new_dir != old_dir) {
		sdcardfs_copy_inode_attr(old_dir, lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode);
		fix_derived_permission(old_dir);
		/* update the derived permission of the old_dentry
		 * with its new parent
		 */
		new_parent = dget_parent(new_dentry);
		if(new_parent) {
			if(old_dentry->d_inode) {
				get_derived_permission(new_parent, old_dentry);
				fix_derived_permission(old_dentry->d_inode);
			}
			dput(new_parent);
		}
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	sdcardfs_put_real_lower(old_dentry, &lower_old_path);
	sdcardfs_put_lower_path(new_dentry, &lower_new_path);
	REVERT_CRED(saved_cred);
out_eacces:
	return err;
}
示例#26
0
static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
{
	int err = 0;
	struct dentry *hidden_old_dentry;
	struct dentry *hidden_wh_dentry = NULL;
	struct dentry *hidden_old_dir_dentry, *hidden_new_dir_dentry;
	char *name = NULL;
	struct iattr newattrs;

	print_entry_location();
	fist_print_dentry("IN unionfs_unlink_whiteout: ", dentry);

	/* create whiteout, get the leftmost underlying dentry and rename it */
	hidden_old_dentry = dtohd(dentry);

	/* lookup .wh.foo first, MUST NOT EXIST */
	name = KMALLOC(dentry->d_name.len + sizeof(".wh."), GFP_UNIONFS);
	if (!name) {
		err = -ENOMEM;
		goto out;
	}
	strcpy(name, ".wh.");
	strncat(name, dentry->d_name.name, dentry->d_name.len);
	name[4 + dentry->d_name.len] = '\0';

	hidden_wh_dentry =
	    LOOKUP_ONE_LEN(name, hidden_old_dentry->d_parent,
			   dentry->d_name.len + 4);
	if (IS_ERR(hidden_wh_dentry)) {
		err = PTR_ERR(hidden_wh_dentry);
		goto out;
	}
	ASSERT(hidden_wh_dentry->d_inode == NULL);

	DGET(hidden_old_dentry);

	hidden_old_dir_dentry = GET_PARENT(hidden_old_dentry);
	hidden_new_dir_dentry = GET_PARENT(hidden_wh_dentry);
	double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry);

	if (!(err = is_robranch(dentry))) {
		if (S_ISREG(hidden_old_dentry->d_inode->i_mode)) {
			err = vfs_rename(hidden_old_dir_dentry->d_inode,
					 hidden_old_dentry,
					 hidden_new_dir_dentry->d_inode,
					 hidden_wh_dentry);
		} else {
			err = vfs_unlink(hidden_old_dir_dentry->d_inode,
					 hidden_old_dentry);
			if (!err)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
				err = vfs_create(hidden_new_dir_dentry->d_inode,
						 hidden_wh_dentry, 0666, NULL);
#else
				err = vfs_create(hidden_new_dir_dentry->d_inode,
						 hidden_wh_dentry, 0666);
#endif
		}
	}

	double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry);
	DPUT(hidden_old_dentry);
	DPUT(hidden_wh_dentry);

	if (!err) {
		hidden_wh_dentry = LOOKUP_ONE_LEN(name,
						  hidden_old_dentry->d_parent,
						  dentry->d_name.len + 4);
		if (IS_ERR(hidden_wh_dentry)) {
			err = PTR_ERR(hidden_wh_dentry);
			goto out;
		}
		PASSERT(hidden_wh_dentry->d_inode);
		down(&hidden_wh_dentry->d_inode->i_sem);
		newattrs.ia_valid = ATTR_CTIME;
		if (hidden_wh_dentry->d_inode->i_size != 0) {
			newattrs.ia_valid |= ATTR_SIZE;
			newattrs.ia_size = 0;
		}
		/* We discard this error, because the entry is whited out
		 * even if we fail here. */
		notify_change(hidden_wh_dentry, &newattrs);
		up(&hidden_wh_dentry->d_inode->i_sem);
		DPUT(hidden_wh_dentry);
	}

	if (err) {
		if (dbstart(dentry) == 0)
			goto out;
		/* exit if the error returned was NOT -EROFS */
		if (!IS_COPYUP_ERR(err))
			goto out;
		err = create_whiteout(dentry, dbstart(dentry) - 1);
	} else {
		fist_copy_attr_all(dir, hidden_new_dir_dentry->d_inode);
	}

      out:
	KFREE(name);
	print_exit_status(err);
	return err;
}
示例#27
0
SYSCALL_HANDLER3(sys_rename, const char *oldpath, const char *newpath, int *ret) {
	*ret = vfs_rename(oldpath, newpath);
}
示例#28
0
/*
 * The locking rules in esdfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int esdfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;
	int mask;
	const struct cred *creds =
			esdfs_override_creds(ESDFS_SB(old_dir->i_sb), &mask);
	if (!creds)
		return -ENOMEM;

	/* Never rename to or from a pseudo hard link target. */
	if (ESDFS_DENTRY_HAS_STUB(old_dentry))
		esdfs_get_lower_stub_path(old_dentry, &lower_old_path);
	else
		esdfs_get_lower_path(old_dentry, &lower_old_path);
	if (ESDFS_DENTRY_HAS_STUB(new_dentry))
		esdfs_get_lower_stub_path(new_dentry, &lower_new_path);
	else
		esdfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	esdfs_get_lower_parent(old_dentry, lower_old_dentry,
			       &lower_old_dir_dentry);
	esdfs_get_lower_parent(new_dentry, lower_new_dentry,
			       &lower_new_dir_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	esdfs_copy_attr(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	if (new_dir != old_dir) {
		esdfs_copy_attr(old_dir,
				      lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir,
					lower_old_dir_dentry->d_inode);
	}

	/* Drop any old links */
	if (ESDFS_DENTRY_HAS_STUB(old_dentry))
		d_drop(old_dentry);
	if (ESDFS_DENTRY_HAS_STUB(new_dentry))
		d_drop(new_dentry);
out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	esdfs_put_lower_parent(old_dentry, &lower_old_dir_dentry);
	esdfs_put_lower_parent(new_dentry, &lower_new_dir_dentry);
	esdfs_put_lower_path(old_dentry, &lower_old_path);
	esdfs_put_lower_path(new_dentry, &lower_new_path);
	esdfs_revert_creds(creds, &mask);
	return err;
}
/*
 * The locking rules in sdcardfs_rename are complex.  We could use a simpler
 * superblock-level name-space lock for renames and copy-ups.
 */
static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			 struct inode *new_dir, struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_old_dir_dentry = NULL;
	struct dentry *lower_new_dir_dentry = NULL;
	struct dentry *trap = NULL;
	struct path lower_old_path, lower_new_path;

	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb));

	sdcardfs_get_lower_path(old_dentry, &lower_old_path);
	sdcardfs_get_lower_path(new_dentry, &lower_new_path);
	lower_old_dentry = lower_old_path.dentry;
	lower_new_dentry = lower_new_path.dentry;
	lower_old_dir_dentry = dget_parent(lower_old_dentry);
	lower_new_dir_dentry = dget_parent(lower_new_dentry);

	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	/* source should not be ancestor of target */
	if (trap == lower_old_dentry) {
		err = -EINVAL;
		goto out;
	}
	/* target should not be ancestor of source */
	if (trap == lower_new_dentry) {
		err = -ENOTEMPTY;
		goto out;
	}

	err = mnt_want_write(lower_old_path.mnt);
	if (err)
		goto out;
	err = mnt_want_write(lower_new_path.mnt);
	if (err)
		goto out_drop_old_write;

	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
			 lower_new_dir_dentry->d_inode, lower_new_dentry);
	if (err)
		goto out_err;

	/* Copy attrs from lower dir, but i_uid/i_gid */
	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
	fix_fat_permission(new_dir); 
	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
		fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode);
		fix_fat_permission(old_dir); 
	}

out_err:
	mnt_drop_write(lower_new_path.mnt);
out_drop_old_write:
	mnt_drop_write(lower_old_path.mnt);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
	dput(lower_new_dir_dentry);
	sdcardfs_put_lower_path(old_dentry, &lower_old_path);
	sdcardfs_put_lower_path(new_dentry, &lower_new_path);
	REVERT_CRED();
	return err;
}
示例#30
0
static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
		     struct inode *new_dir, struct dentry *new_dentry,
		     int bindex, struct dentry **wh_old)
{
	int err = 0;
	struct dentry *hidden_old_dentry;
	struct dentry *hidden_new_dentry;
	struct dentry *hidden_old_dir_dentry;
	struct dentry *hidden_new_dir_dentry;
	struct dentry *hidden_wh_dentry;
	struct dentry *hidden_wh_dir_dentry;
	char *wh_name = NULL;

	print_entry(" bindex=%d", bindex);

	fist_print_dentry("IN: do_rename, old_dentry", old_dentry);
	fist_print_dentry("IN: do_rename, new_dentry", new_dentry);
	fist_dprint(7, "do_rename for bindex = %d\n", bindex);

	hidden_new_dentry = dtohd_index(new_dentry, bindex);
	hidden_old_dentry = dtohd_index(old_dentry, bindex);

	if (!hidden_new_dentry) {
		hidden_new_dentry =
		    create_parents(new_dentry->d_parent->d_inode, new_dentry,
				   bindex);
		if (IS_ERR(hidden_new_dentry)) {
			fist_dprint(7,
				    "error creating directory tree for rename, bindex = %d\n",
				    bindex);
			err = PTR_ERR(hidden_new_dentry);
			goto out;
		}
	}

	wh_name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
	if (IS_ERR(wh_name)) {
		err = PTR_ERR(wh_name);
		goto out;
	}

	hidden_wh_dentry =
	    LOOKUP_ONE_LEN(wh_name, hidden_new_dentry->d_parent,
			   new_dentry->d_name.len + WHLEN);
	if (IS_ERR(hidden_wh_dentry)) {
		err = PTR_ERR(hidden_wh_dentry);
		goto out;
	}

	if (hidden_wh_dentry->d_inode) {
		/* get rid of the whiteout that is existing */
		if (hidden_new_dentry->d_inode) {
			printk(KERN_WARNING
			       "Both a whiteout and a dentry exist when doing a rename!\n");
			err = -EIO;

			DPUT(hidden_wh_dentry);
			goto out;
		}

		hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry);
		if (!(err = is_robranch_super(old_dentry->d_sb, bindex))) {
			err =
			    vfs_unlink(hidden_wh_dir_dentry->d_inode,
				       hidden_wh_dentry);
		}
		DPUT(hidden_wh_dentry);
		unlock_dir(hidden_wh_dir_dentry);
		if (err)
			goto out;
	} else
		DPUT(hidden_wh_dentry);

	DGET(hidden_old_dentry);
	hidden_old_dir_dentry = GET_PARENT(hidden_old_dentry);
	hidden_new_dir_dentry = GET_PARENT(hidden_new_dentry);

	lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);

	err = is_robranch_super(old_dentry->d_sb, bindex);
	if (err)
		goto out_unlock;

	/* ready to whiteout for old_dentry.
	   caller will create the actual whiteout,
	   and must dput(*wh_old) */
	if (wh_old) {
		char *whname;
		whname = alloc_whname(old_dentry->d_name.name,
				      old_dentry->d_name.len);
		err = PTR_ERR(whname);
		if (IS_ERR(whname))
			goto out_unlock;
		*wh_old = LOOKUP_ONE_LEN(whname, hidden_old_dir_dentry,
					 old_dentry->d_name.len + WHLEN);
		KFREE(whname);
		err = PTR_ERR(*wh_old);
		if (IS_ERR(*wh_old)) {
			*wh_old = NULL;
			goto out_unlock;
		}
	}

		fist_print_dentry("NEWBEF", new_dentry);
		fist_print_dentry("OLDBEF", old_dentry);
	err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,
			 hidden_new_dir_dentry->d_inode, hidden_new_dentry);
		fist_print_dentry("NEWAFT", new_dentry);
		fist_print_dentry("OLDAFT", old_dentry);

      out_unlock:
	unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);

	DPUT(hidden_old_dir_dentry);
	DPUT(hidden_new_dir_dentry);
	DPUT(hidden_old_dentry);

      out:
	if (!err) {
		/* Fixup the newdentry. */
		if (bindex < dbstart(new_dentry))
			set_dbstart(new_dentry, bindex);
		else if (bindex > dbend(new_dentry))
			set_dbend(new_dentry, bindex);
	}

	KFREE(wh_name);

	fist_print_dentry("OUT: do_rename, old_dentry", old_dentry);
	fist_print_dentry("OUT: do_rename, new_dentry", new_dentry);

	print_exit_status(err);
	return err;
}