Ejemplo n.º 1
0
/*===========================================================================*
 *				do_rename				     *
 *===========================================================================*/
int do_rename()
{
/* Perform the rename(name1, name2) system call. */
  int r = 0, r1;
  size_t len;
  struct vnode *old_dirp, *new_dirp, *vp;
  char old_name[PATH_MAX+1];
  
  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.name1) < 0) return(err_code);
  if ((old_dirp = last_dir()) == NIL_VNODE) return(err_code);
  
  /* If the sticky bit is set, only the owner of the file or a privileged
     user is allowed to rename */
  if((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
	/* Look up inode of file to unlink to retrieve owner */
	vp = advance(old_dirp, PATH_RET_SYMLINK);
	if (vp != NIL_VNODE) {
		if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) 
			r = -EPERM;
		put_vnode(vp);
	} else
		r = err_code;
	if (r != 0) {	
		put_vnode(old_dirp);
		return(r);
	}
  }

  /* Save the last component of the old name */
  if(strlen(user_fullpath) >= sizeof(old_name)) {
	put_vnode(old_dirp);
	return(-ENAMETOOLONG);
  }
  strcpy(old_name, user_fullpath);

  /* See if 'name2' (new name) exists.  Get dir inode */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.name2) < 0)
	r = err_code;
  else if ((new_dirp = last_dir()) == NIL_VNODE)
	r = err_code; 
  if (r != 0) {
  	put_vnode(old_dirp);
	return r;
  }

  /* Both parent directories must be on the same device. */
  if(old_dirp->v_fs_e != new_dirp->v_fs_e) r = -EXDEV; 

  /* Parent dirs must be writable, searchable and on a writable device */
  if ((r1 = forbidden(old_dirp, W_BIT|X_BIT)) != 0 ||
      (r1 = forbidden(new_dirp, W_BIT|X_BIT)) != 0) r = r1;
  
  if(r == 0)
	  r = req_rename(old_dirp->v_fs_e, old_dirp->v_inode_nr, old_name,
  			 new_dirp->v_inode_nr, user_fullpath);
  put_vnode(old_dirp);
  put_vnode(new_dirp);
  return(r);
}
Ejemplo n.º 2
0
/*===========================================================================*
 *				do_rename				     *
 *===========================================================================*/
PUBLIC int do_rename()
{
/* Perform the rename(name1, name2) system call. */
  int r;
  int old_dir_inode;
  int old_fs_e;
  int new_dir_inode;
  int new_fs_e;
  size_t len;
  struct vnode *vp_od, *vp_nd;
  char old_name[PATH_MAX+1];
  
  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
  
  /* Request lookup */
  if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r;

  r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/);
  if (r != OK)
  {
	put_vnode(vp_od);
	return r;
  }
  
  /* Remeber FS endpoint */
  old_fs_e = vp_od->v_fs_e;

  /* Save the last component of the old name */
  len= strlen(user_fullpath);
  if (len >= sizeof(old_name))
  {
	put_vnode(vp_od);
	return ENAMETOOLONG;
  }
  memcpy(old_name, user_fullpath, len+1);

  /* See if 'name2' (new name) exists.  Get dir inode */
  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
  {
	put_vnode(vp_od);
	return err_code;
  }
  
  /* Request lookup */
  r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd);
  if (r != OK)
  {
	put_vnode(vp_od);
	return r;
  }

  r= forbidden(vp_nd, W_BIT|X_BIT, 0 /*!use_realuid*/);
  if (r != OK)
  {
	put_vnode(vp_od);
	put_vnode(vp_nd);
	return r;
  }
  
  
  /* Remeber FS endpoint */
  new_fs_e = vp_nd->v_fs_e;
  
  /* Both parent directories must be on the same device. */
  if (old_fs_e != new_fs_e)
  {
	put_vnode(vp_od);
	put_vnode(vp_nd);
	return EXDEV;
  }

  /* Issue request */
  r= req_rename(old_fs_e, vp_od->v_inode_nr, old_name, vp_nd->v_inode_nr,
	user_fullpath);
  put_vnode(vp_od);
  put_vnode(vp_nd);
  return r;
}