Ejemplo n.º 1
0
/*===========================================================================*
 *				do_open					     *
 *===========================================================================*/
int do_open()
{
/* Perform the open(name, flags,...) system call.
 * syscall might provide 'name' embedded in message when not creating file */

  int create_mode;		/* is really mode_t but this gives problems */
  int open_mode = 0;		/* is really mode_t but this gives problems */
  int r = OK;
  char fullpath[PATH_MAX];
  vir_bytes vname;
  size_t vname_length;

  open_mode = (mode_t) job_m_in.mode;
  create_mode = job_m_in.c_mode;

  /* If O_CREAT is set, open has three parameters, otherwise two. */
  if (open_mode & O_CREAT) {
	vname = (vir_bytes) job_m_in.name1;
	vname_length = (size_t) job_m_in.name1_length;
	r = fetch_name(vname, vname_length, fullpath);
  } else {
	vname = (vir_bytes) job_m_in.name;
	vname_length = (size_t) job_m_in.name_length;
	create_mode = 0;
	if (copy_name(vname_length, fullpath) != OK) {
		/* Direct copy failed, try fetching from user space */
		if (fetch_name(vname, vname_length, fullpath) != OK)
			r = err_code;
	}
  }

  if (r != OK) return(err_code); /* name was bad */
  return common_open(fullpath, open_mode, create_mode);
}
Ejemplo n.º 2
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.º 3
0
/*===========================================================================*
 *				do_link					     *
 *===========================================================================*/
PUBLIC int do_link()
{
/* Perform the link(name1, name2) system call. */
  int r;
  endpoint_t linked_fs_e, link_lastdir_fs_e;
  struct vnode *vp_o, *vp_d;

  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) 
        return(err_code);
        
  /* Request lookup */
  if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r;

  linked_fs_e = vp_o->v_fs_e;

  /* Does the final directory of 'name2' exist? */
  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
	put_vnode(vp_o);
	return(err_code);
  }

  /* Request lookup */
  if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK)
  {
	put_vnode(vp_o);
	return r;
  }

  link_lastdir_fs_e = vp_d->v_fs_e;

  /* Check for links across devices. */
  if (linked_fs_e != link_lastdir_fs_e) 
  {
	put_vnode(vp_o);
	put_vnode(vp_d);
        return EXDEV;
  }

  /* Make sure that the object is a directory */
  if ((vp_d->v_mode & I_TYPE) != I_DIRECTORY)
  {
	put_vnode(vp_o);
	put_vnode(vp_d);
	return ENOTDIR;
  }

  r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/);
  if (r != OK)
  {
	put_vnode(vp_o);
	put_vnode(vp_d);
        return r;
  }
  
  /* Issue request */
  r= req_link(linked_fs_e, vp_d->v_inode_nr, user_fullpath, vp_o->v_inode_nr);
  put_vnode(vp_o);
  put_vnode(vp_d);
  return r;
}
Ejemplo n.º 4
0
/*===========================================================================*
 *				do_link					     *
 *===========================================================================*/
int do_link()
{
/* Perform the link(name1, name2) system call. */
  int r = 0;
  endpoint_t linked_fs_e, link_lastdir_fs_e;
  struct vnode *vp, *vp_d;

  /* See if 'name1' (file to be linked to) exists. */ 
  if(fetch_name(user_fullpath, PATH_MAX, m_in.name1) < 0) return(err_code);
  if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);

  /* Does the final directory of 'name2' exist? */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.name2) < 0)
	r = err_code;
  else if ((vp_d = last_dir()) == NIL_VNODE)
	r = err_code; 
  if (r != 0) {
	  put_vnode(vp);
	  return(r);
  }

  /* Check for links across devices. */
  if(vp->v_fs_e != vp_d->v_fs_e)
  	r = -EXDEV;
  else 
	r = forbidden(vp_d, W_BIT | X_BIT);

  if (r == 0)
	r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath,
		     vp->v_inode_nr);
  
  put_vnode(vp);
  put_vnode(vp_d);
  return(r);
}
Ejemplo n.º 5
0
/*===========================================================================*
 *				do_link					     *
 *===========================================================================*/
int do_link()
{
/* Perform the link(name1, name2) system call. */
  int r = OK;
  struct vnode *vp = NULL, *dirp = NULL;
  struct vmnt *vmp1 = NULL, *vmp2 = NULL;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1, vname2;
  size_t vname1_length, vname2_length;

  vname1 = (vir_bytes) job_m_in.name1;
  vname1_length = job_m_in.name1_length;
  vname2 = (vir_bytes) job_m_in.name2;
  vname2_length = job_m_in.name2_length;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_READ;

  /* See if 'name1' (file to be linked to) exists. */
  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);

  /* Does the final directory of 'name2' exist? */
  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_WRITE;
  if (fetch_name(vname2, vname2_length, fullpath) != OK)
	r = err_code;
  else if ((dirp = last_dir(&resolve, fp)) == NULL)
	r = err_code;

  if (r != OK) {
	unlock_vnode(vp);
	unlock_vmnt(vmp1);
	put_vnode(vp);
	return(r);
  }

  /* Check for links across devices. */
  if (vp->v_fs_e != dirp->v_fs_e)
	r = EXDEV;
  else
	r = forbidden(fp, dirp, W_BIT | X_BIT);

  if (r == OK)
	r = req_link(vp->v_fs_e, dirp->v_inode_nr, fullpath,
		     vp->v_inode_nr);

  unlock_vnode(vp);
  unlock_vnode(dirp);
  if (vmp2 != NULL) unlock_vmnt(vmp2);
  unlock_vmnt(vmp1);
  put_vnode(vp);
  put_vnode(dirp);
  return(r);
}
Ejemplo n.º 6
0
/*===========================================================================*
 *                              do_mount                                     *
 *===========================================================================*/
PUBLIC int do_mount()
{
/* Perform the mount(name, mfile, mount_flags) system call. */
  endpoint_t fs_e;
  int r, slot, rdonly, nodev;
  char fullpath[PATH_MAX];
  char mount_label[LABEL_MAX];
  dev_t dev;

  /* Only the super-user may do MOUNT. */
  if (!super_user) return(EPERM);

  /* FS process' endpoint number */
  if (m_in.mount_flags & MS_LABEL16) {
	/* Get the label from the caller, and ask DS for the endpoint. */
	r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
		(vir_bytes) mount_label, (phys_bytes) sizeof(mount_label));
	if (r != OK) return(r);

	mount_label[sizeof(mount_label)-1] = 0;

	r = ds_retrieve_label_endpt(mount_label, &fs_e);
	if (r != OK) return(r);
  } else {
	/* Legacy support: get the endpoint from the request itself. */
	fs_e = (endpoint_t) m_in.fs_label;
	mount_label[0] = 0;
  }

  /* Sanity check on process number. */
  if (isokendpt(fs_e, &slot) != OK) return(EINVAL);

  /* Should the file system be mounted read-only? */
  rdonly = (m_in.mount_flags & MS_RDONLY);

  /* A null string for block special device means don't use a device at all. */
  nodev = (m_in.name1_length == 0);
  if (!nodev) {
	/* If 'name' is not for a block special file, return error. */
	if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
		return(err_code);
	if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV)
		return(err_code);
  } else {
	/* Find a free pseudo-device as substitute for an actual device. */
	if ((dev = find_free_nonedev()) == NO_DEV)
		return(err_code);
  }

  /* Fetch the name of the mountpoint */
  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
	return(err_code);

  /* Do the actual job */
  return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
}
Ejemplo n.º 7
0
/*===========================================================================*
 *				do_mknod				     *
 *===========================================================================*/
PUBLIC int do_mknod()
{
/* Perform the mknod(name, mode, addr) system call. */
  register mode_t bits, mode_bits;
  int r;
  struct vnode *vp;
  
  /* Only the super_user may make nodes other than fifos. */
  mode_bits = (mode_t) m_in.mk_mode;		/* mode of the inode */
  if(!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) && ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) return(EPERM);
  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);

  /* Open directory that's going to hold the new node. */
  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
  if((vp = last_dir(fp)) == NULL) return(err_code);

  /* Make sure that the object is a directory */
  if((vp->v_mode & I_TYPE) != I_DIRECTORY) {
	  put_vnode(vp);
	  return(ENOTDIR);
  }

  if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
	r = req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid,
		      fp->fp_effgid, bits, m_in.mk_z0);
  }

  put_vnode(vp);
  return(r);
}
Ejemplo n.º 8
0
/*===========================================================================*
 *                             do_lstat					     *
 *===========================================================================*/
int do_lstat()
{
/* Perform the lstat(name, buf) system call. */
  struct vnode *vp;
  struct vmnt *vmp;
  int r;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  int old_stat = 0;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = (vir_bytes) job_m_in.name1;
  vname1_length = (size_t) job_m_in.name1_length;
  statbuf = (vir_bytes) job_m_in.name2;

  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (job_call_nr == PREV_LSTAT)
	old_stat = 1;
  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return(r);
}
Ejemplo n.º 9
0
/*===========================================================================*
 *                              do_umount                                    *
 *===========================================================================*/
PUBLIC int do_umount(void)
{
/* Perform the umount(name) system call. */
  char label[LABEL_MAX];
  dev_t dev;
  int r;
  char fullpath[PATH_MAX];

  /* Only the super-user may do umount. */
  if (!super_user) return(EPERM);

  /* If 'name' is not for a block special file or mountpoint, return error. */
  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
	return(err_code);
  if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV)
	return(err_code);

  if ((r = unmount(dev, label)) != OK) return(r);

  /* Return the label of the mounted file system, so that the caller
   * can shut down the corresponding server process.
   */
  if (strlen(label) >= M3_LONG_STRING)	/* should never evaluate to true */
	label[M3_LONG_STRING-1] = 0;
  strcpy(m_out.umount_label, label);
  return(OK);
}
Ejemplo n.º 10
0
/*===========================================================================*
 *				do_mkdir				     *
 *===========================================================================*/
PUBLIC int do_mkdir()
{
/* Perform the mkdir(name, mode) system call. */
  mode_t bits;			/* mode bits for the new inode */
  int r;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_READ;

  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
	return(err_code);
  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);

  /* Make sure that the object is a directory */
  if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
	r = ENOTDIR;
  } else if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
	r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
		      fp->fp_effgid, bits);
  }

  unlock_vnode(vp);
  unlock_vmnt(vmp);
  put_vnode(vp);
  return(r);
}
Ejemplo n.º 11
0
int do_recinode()
{
    struct vnode *vp;
    struct vmnt *vmp;
    int r;
    size_t nrblks;
    char fullpath[PATH_MAX];
    struct lookup resolve;
    size_t vname1_length;
    vir_bytes vname1;

    vname1 = job_m_in.m_lc_vfs_inodes.name;
    vname1_length = job_m_in.m_lc_vfs_inodes.len;
    
    lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
    resolve.l_vmnt_lock = VMNT_READ;
    resolve.l_vnode_lock = VNODE_READ;

    if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);

    if ((vp = eat_path(&resolve, fp)) == NULL)
        return(err_code);

     r = req_recoverinode(vp->v_fs_e, vp->v_inode_nr);

    unlock_vnode(vp);
    unlock_vmnt(vmp);
     put_vnode(vp);

     return r;
}
Ejemplo n.º 12
0
/*===========================================================================*
 *                             do_lstat					     *
 *===========================================================================*/
int do_lstat(void)
{
/* Perform the lstat(name, buf) system call. */
  struct vnode *vp;
  struct vmnt *vmp;
  int r;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = job_m_in.m_lc_vfs_stat.name;
  vname1_length = job_m_in.m_lc_vfs_stat.len;
  statbuf = job_m_in.m_lc_vfs_stat.buf;

  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return(r);
}
Ejemplo n.º 13
0
/*===========================================================================*
 *				do_statvfs				     *
 *===========================================================================*/
int do_statvfs()
{
/* Perform the stat(name, buf) system call. */
  int r;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = (vir_bytes) job_m_in.name1;
  vname1_length = (size_t) job_m_in.name1_length;
  statbuf = (vir_bytes) job_m_in.name2;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = req_statvfs(vp->v_fs_e, who_e, statbuf);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return r;
}
Ejemplo n.º 14
0
/*===========================================================================*
 *				copy_path				     *
 *===========================================================================*/
int copy_path(char *dest, size_t size)
{
/* Go get the path for a path request. Put the result in in 'dest', which
 * should be at least PATH_MAX in size.
 */
  vir_bytes name;
  size_t len;

  assert(size >= PATH_MAX);

  name = job_m_in.m_lc_vfs_path.name;
  len = job_m_in.m_lc_vfs_path.len;

  if (len > size) {	/* 'len' includes terminating-nul */
	err_code = ENAMETOOLONG;
	return(EGENERIC);
  }

  /* Is the string contained in the message? If not, perform a normal copy. */
  if (len > M_PATH_STRING_MAX)
	return fetch_name(name, len, dest);

  /* Just copy the path from the message */
  strncpy(dest, job_m_in.m_lc_vfs_path.buf, len);

  if (dest[len - 1] != '\0') {
	err_code = ENAMETOOLONG;
	return(EGENERIC);
  }

  return(OK);
}
Ejemplo n.º 15
0
/*===========================================================================*
 *				do_statvfs				     *
 *===========================================================================*/
int do_statvfs(void)
{
/* Perform the statvfs1(name, buf, flags) system call. */
  int r, flags;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = job_m_in.m_lc_vfs_statvfs1.name;
  vname1_length = job_m_in.m_lc_vfs_statvfs1.len;
  statbuf = job_m_in.m_lc_vfs_statvfs1.buf;
  flags = job_m_in.m_lc_vfs_statvfs1.flags;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = fill_statvfs(vp->v_vmnt, who_e, statbuf, flags);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return r;
}
Ejemplo n.º 16
0
/*===========================================================================*
 *				do_mkdir				     *
 *===========================================================================*/
PUBLIC int do_mkdir()
{
/* Perform the mkdir(name, mode) system call. */
  mode_t bits;			/* mode bits for the new inode */
  int r;
  struct vnode *vp;

  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);

  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);

  /* Request lookup */
  if((vp = last_dir(fp)) == NULL) return(err_code);

  /* Make sure that the object is a directory */
  if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
	  put_vnode(vp);
	  return(ENOTDIR);
  }

  if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
	r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid,
		      fp->fp_effgid, bits);
  }

  put_vnode(vp);
  return(r);
}
Ejemplo n.º 17
0
/*===========================================================================*
 *				do_creat				     *
 *===========================================================================*/
PUBLIC int do_creat()
{
/* Perform the creat(name, mode) system call. */
  int r;

  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
  return(r);
}
Ejemplo n.º 18
0
/*===========================================================================*
 *				do_open					     *
 *===========================================================================*/
PUBLIC int do_open()
{
/* Perform the open(name, flags,...) system call. */
  int create_mode = 0;		/* is really mode_t but this gives problems */
  int r;

  /* If O_CREAT is set, open has three parameters, otherwise two. */
  if (m_in.mode & O_CREAT) {
	create_mode = m_in.c_mode;	
	r = fetch_name(m_in.c_name, m_in.name1_length, M1);
  } else {
	r = fetch_name(m_in.name, m_in.name_length, M3);
  }

  if (r != OK) return(err_code); /* name was bad */
  r = common_open(m_in.mode, create_mode);
  return(r);
}
Ejemplo n.º 19
0
/*===========================================================================*
 *				do_creat				     *
 *===========================================================================*/
int do_creat()
{
/* Perform the creat(name, mode) system call. */
  int r;

  if (fetch_name(user_fullpath, PATH_MAX, m_in.name) < 0) return(err_code);
  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.perm_mode);
  return(r);
}
Ejemplo n.º 20
0
/*===========================================================================*
 *				do_unlink				     *
 *===========================================================================*/
PUBLIC int do_unlink()
{
/* Perform the unlink(name) or rmdir(name) system call. The code for these two
 * is almost the same.  They differ only in some condition testing.  Unlink()
 * may be used by the superuser to do dangerous things; rmdir() may not.
 */

  register struct inode *rip;
  struct inode *rldirp;
  int r;
  char string[NAME_MAX];

  /* Get the last directory in the path. */
  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
  if ( (rldirp = last_dir(user_path, string)) == NIL_INODE)
	return(err_code);

  /* The last directory exists.  Does the file also exist? */
  r = OK;
  if ( (rip = advance(rldirp, string)) == NIL_INODE) r = err_code;

  /* If error, return inode. */
  if (r != OK) {
	put_inode(rldirp);
	return(r);
  }

  /* Do not remove a mount point. */
  if (rip->i_num == ROOT_INODE) {
	put_inode(rldirp);
	put_inode(rip);
	return(EBUSY);
  }

  /* Now test if the call is allowed, separately for unlink() and rmdir(). */
  if (call_nr == UNLINK) {
	/* Only the su may unlink directories, but the su can unlink any dir.*/
	if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;

	/* Don't unlink a file if it is the root of a mounted file system. */
	if (rip->i_num == ROOT_INODE) r = EBUSY;

	/* Actually try to unlink the file; fails if parent is mode 0 etc. */
	if (r == OK) r = unlink_file(rldirp, rip, string);

  } else {
	r = remove_dir(rldirp, rip, string); /* call is RMDIR */
  }

  /* If unlink was possible, it has been done, otherwise it has not. */
  put_inode(rip);
  put_inode(rldirp);
  return(r);
}
Ejemplo n.º 21
0
/*===========================================================================*
 *				do_utime				     *
 *===========================================================================*/
PUBLIC int do_utime()
{
/* Perform the utime(name, timep) system call. */
  register int len;
  int r;
  uid_t uid;
  time_t actime, modtime;
  struct vnode *vp;
  
  /* Adjust for case of 'timep' being NULL;
   * utime_strlen then holds the actual size: strlen(name)+1.
   */
  len = m_in.utime_length;
  if (len == 0) len = m_in.utime_strlen;

  if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
  
  /* Request lookup */
  if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;

  /* Fill in request fields.*/
  if (m_in.utime_length == 0) {
        actime = modtime = clock_time();
  } else {
        actime = m_in.utime_actime;
        modtime = m_in.utime_modtime;
  }

  uid= fp->fp_effuid;

  r= OK;
  if (vp->v_uid != uid && uid != SU_UID) r = EPERM;
  if (m_in.utime_length == 0 && r != OK)
  {
	/* With a null times pointer, updating the times (to the current time)
	 * is allow if the object is writable. 
	 */
	r = forbidden(vp, W_BIT, 0 /*!use_realuid*/);
  }

  if (r != OK)
  {
	put_vnode(vp);
	return r;
  }
  
  /* Issue request */
  r= req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
  put_vnode(vp);
  return r;
}
Ejemplo n.º 22
0
/*===========================================================================*
 *				do_mkdir				     *
 *===========================================================================*/
PUBLIC int do_mkdir()
{
/* Perform the mkdir(name, mode) system call. */

  int r1, r2;			/* status codes */
  ino_t dot, dotdot;		/* inode numbers for . and .. */
  mode_t bits;			/* mode bits for the new inode */
  char string[NAME_MAX];	/* last component of the new dir's path name */
  struct inode *rip, *ldirp;

  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);

  /* Next make the inode. If that fails, return error code. */
  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
  rip = new_node(&ldirp, user_path, bits, (zone_t) 0, TRUE, string);
  if (rip == NIL_INODE || err_code == EEXIST) {
	put_inode(rip);		/* can't make dir: it already exists */
	put_inode(ldirp);
	return(err_code);
  }

  /* Get the inode numbers for . and .. to enter in the directory. */
  dotdot = ldirp->i_num;	/* parent's inode number */
  dot = rip->i_num;		/* inode number of the new dir itself */

  /* Now make dir entries for . and .. unless the disk is completely full. */
  /* Use dot1 and dot2, so the mode of the directory isn't important. */
  rip->i_mode = bits;	/* set mode */
  r1 = search_dir(rip, dot1, &dot, ENTER);	/* enter . in the new dir */
  r2 = search_dir(rip, dot2, &dotdot, ENTER);	/* enter .. in the new dir */

  /* If both . and .. were successfully entered, increment the link counts. */
  if (r1 == OK && r2 == OK) {
	/* Normal case.  It was possible to enter . and .. in the new dir. */
	rip->i_nlinks++;	/* this accounts for . */
	ldirp->i_nlinks++;	/* this accounts for .. */
	ldirp->i_dirt = DIRTY;	/* mark parent's inode as dirty */
  } else {
	/* It was not possible to enter . or .. probably disk was full -
	 * links counts haven't been touched.
	 */
	if(search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
		panic(__FILE__, "Dir disappeared ", rip->i_num);
	rip->i_nlinks--;	/* undo the increment done in new_node() */
  }
  rip->i_dirt = DIRTY;		/* either way, i_nlinks has changed */

  put_inode(ldirp);		/* return the inode of the parent dir */
  put_inode(rip);		/* return the inode of the newly made dir */
  return(err_code);		/* new_node() always sets 'err_code' */
}
Ejemplo n.º 23
0
/*===========================================================================*
 *				do_unlink				     *
 *===========================================================================*/
int do_unlink()
{
/* Perform the unlink(name) or rmdir(name) system call. The code for these two
 * is almost the same.  They differ only in some condition testing.  Unlink()
 * may be used by the superuser to do dangerous things; rmdir() may not.
 */
  register struct fproc *rfp;
  struct vnode *vldirp, *vp;
  int r;
  
  /* Get the last directory in the path. */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.name) < 0) return(err_code);
  if ((vldirp = last_dir()) == NIL_VNODE) return(err_code);

  /* Make sure that the object is a directory */
  if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) {
	  put_vnode(vldirp);
	  return(-ENOTDIR);
  }

  /* The caller must have both search and execute permission */
  if ((r = forbidden(vldirp, X_BIT | W_BIT)) != 0) {
	put_vnode(vldirp);
	return(r);
  }
  
  /* Also, if the sticky bit is set, only the owner of the file or a privileged
     user is allowed to unlink */
  if ((vldirp->v_mode & S_ISVTX) == S_ISVTX) {
	/* Look up inode of file to unlink to retrieve owner */
	vp = advance(vldirp, 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(vldirp);
		return(r);
	}
  }

  if(call_nr == __NR_unlink) 
	  r = req_unlink(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
  else 
	  r = req_rmdir(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
  
  put_vnode(vldirp);
  return(r);
}
Ejemplo n.º 24
0
/*===========================================================================*
 *				do_umount				     *
 *===========================================================================*/
PUBLIC int do_umount()
{
/* Perform the umount(name) system call. */
  dev_t dev;

  /* Only the super-user may do UMOUNT. */
  if (!super_user) return(EPERM);

  /* If 'name' is not for a block special file, return error. */
  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);

  return(unmount(dev));
}
Ejemplo n.º 25
0
/*===========================================================================*
 *				scall_open				     *
 *===========================================================================*/
int scall_open()
{
	/* Perform the open(name, flags,...) system call. */
	int r;

	r = fetch_name(user_fullpath, PATH_MAX, m_in.m_data4);

	if (r < 0) {
		return(err_code); /* name was bad */
	}

	r = common_open(m_in.m_data2, m_in.m_data3);

	return r;
}
Ejemplo n.º 26
0
/*===========================================================================*
 *				do_mknod				     *
 *===========================================================================*/
PUBLIC int do_mknod()
{
/* Perform the mknod(name, mode, addr) system call. */

  register mode_t bits, mode_bits;
  struct inode *ip, *ldirp;

  /* Only the super_user may make nodes other than fifos. */
  mode_bits = (mode_t) m_in.mk_mode;		/* mode of the inode */
  if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
  ip = new_node(&ldirp, user_path, bits, (zone_t) m_in.mk_z0, TRUE, NULL);
  put_inode(ip);
  put_inode(ldirp);
  return(err_code);
}
Ejemplo n.º 27
0
/*===========================================================================*
 *				do_utime				     *
 *===========================================================================*/
PUBLIC int do_utime()
{
/* Perform the utime(name, timep) system call. */
  register int len;
  int r;
  time_t actime, modtime;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_READ;

  /* Adjust for case of 'timep' being NULL;
   * utime_strlen then holds the actual size: strlen(name)+1 */
  len = m_in.utime_length;
  if (len == 0) len = m_in.utime_strlen;

  /* Temporarily open the file */
  if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);

  /* Only the owner of a file or the super user can change its name. */
  r = OK;
  if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
  if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
  if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
  if (r == OK) {
	/* Issue request */
	if(m_in.utime_length == 0) {
		actime = modtime = clock_time();
	} else {
		actime = m_in.utime_actime;
		modtime = m_in.utime_modtime;
	}
	r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
  }

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return(r);
}
/*===========================================================================*
 *				do_mknod				     *
 *===========================================================================*/
int do_mknod(void)
{
/* Perform the mknod(name, mode, addr) system call. */
  register mode_t bits, mode_bits;
  int r;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1;
  size_t vname1_length;
  dev_t dev;

  vname1 = job_m_in.m_lc_vfs_mknod.name;
  vname1_length = job_m_in.m_lc_vfs_mknod.len;
  mode_bits = job_m_in.m_lc_vfs_mknod.mode;
  dev = job_m_in.m_lc_vfs_mknod.device;

  /* If the path names a symbolic link, mknod() shall fail with EEXIST. */
  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_WRITE;

  /* Only the super_user may make nodes other than fifos. */
  if (!super_user && !S_ISFIFO(mode_bits))
	return(EPERM);

  bits = (mode_bits & S_IFMT) | (mode_bits & ACCESSPERMS & fp->fp_umask);

  /* Open directory that's going to hold the new node. */
  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);

  /* Make sure that the object is a directory */
  if (!S_ISDIR(vp->v_mode)) {
	r = ENOTDIR;
  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
	r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
		      fp->fp_effgid, bits, dev);
  }

  unlock_vnode(vp);
  unlock_vmnt(vmp);
  put_vnode(vp);
  return(r);
}
Ejemplo n.º 29
0
/*===========================================================================*
 *				do_mknod				     *
 *===========================================================================*/
int do_mknod()
{
/* Perform the mknod(name, mode, addr) system call. */
  register mode_t bits, mode_bits;
  int r;
  struct vnode *vp;
  struct vmnt *vmp;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1;
  size_t vname1_length;
  dev_t dev;

  vname1 = (vir_bytes) job_m_in.name1;
  vname1_length = (size_t) job_m_in.name1_length;
  mode_bits = (mode_t) job_m_in.mk_mode;		/* mode of the inode */
  dev = job_m_in.m1_i3;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_READ;

  /* Only the super_user may make nodes other than fifos. */
  if (!super_user && (!S_ISFIFO(mode_bits) && !S_ISSOCK(mode_bits))) {
	return(EPERM);
  }
  bits = (mode_bits & S_IFMT) | (mode_bits & ACCESSPERMS & fp->fp_umask);

  /* Open directory that's going to hold the new node. */
  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);

  /* Make sure that the object is a directory */
  if (!S_ISDIR(vp->v_mode)) {
	r = ENOTDIR;
  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
	r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
		      fp->fp_effgid, bits, dev);
  }

  unlock_vnode(vp);
  unlock_vmnt(vmp);
  put_vnode(vp);
  return(r);
}
Ejemplo n.º 30
0
/*===========================================================================*
 *				do_unlink				     *
 *===========================================================================*/
PUBLIC int do_unlink()
{
/* Perform the unlink(name) or rmdir(name) system call. The code for these two
 * is almost the same.  They differ only in some condition testing.  Unlink()
 * may be used by the superuser to do dangerous things; rmdir() may not.
 */
  register struct fproc *rfp;
  struct vnode *vp;
  int r;
  
  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);

  r= lookup_lastdir(0 /*!use_realuid*/, &vp);
  if (r != OK)
	return r;

  /* Make sure that the object is a directory */
  if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
  {
	put_vnode(vp);
	return ENOTDIR;
  }

  /* The caller must have both search and execute permission */
  r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/);
  if (r != OK)
  {
	put_vnode(vp);
	return r;
  }
  
  /* If a directory file has to be removed the following conditions have to met:
   *	- The directory must not be the root of a mounted file system
   *	- The directory must not be anybody's root/working directory
   */
  
  /* Issue request */
  r= ((call_nr == UNLINK) ? req_unlink : req_rmdir)(vp->v_fs_e,
	vp->v_inode_nr, user_fullpath);

  put_vnode(vp);

  return r;
}