Beispiel #1
0
/*===========================================================================*
 *				fs_getdents				     *
 *===========================================================================*/
PUBLIC int fs_getdents(void)
{
  int r;
  register struct puffs_node *pn;
  ino_t ino;
  cp_grant_id_t gid;
  size_t size, buf_left;
  off_t pos;
  struct dirent *dent;
  int eofflag = 0;
  size_t written;
  PUFFS_MAKECRED(pcr, &global_kcred);

  ino = (ino_t) fs_m_in.REQ_INODE_NR;
  gid = (gid_t) fs_m_in.REQ_GRANT;
  size = buf_left = (size_t) fs_m_in.REQ_MEM_SIZE;
  pos = (off_t) fs_m_in.REQ_SEEK_POS_LO;

  if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino)) == NULL) {
	lpuffs_debug("walk failed...\n");
        return(EINVAL);
  }

  if (GETDENTS_BUFSIZ < size)
	  size = buf_left = GETDENTS_BUFSIZ;
  memset(getdents_buf, '\0', GETDENTS_BUFSIZ);  /* Avoid leaking any data */

  dent = (struct dirent*) getdents_buf;

  r = global_pu->pu_ops.puffs_node_readdir(global_pu, pn, dent, &pos,
						&buf_left, pcr, &eofflag, 0, 0);
  if (r) {
	lpuffs_debug("puffs_node_readdir returned error\n");
	return(EINVAL);
  }

  assert(buf_left <= size);
  written = size - buf_left;

  if (written == 0 && !eofflag) {
	lpuffs_debug("The user's buffer is too small\n");
	return(EINVAL);
  }

  if (written) {
	r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
			     (vir_bytes) getdents_buf, written, D);
	if (r != OK) return(r);
  }

  update_times(pn, ATIME, 0);

  fs_m_out.RES_NBYTES = written;
  fs_m_out.RES_SEEK_POS_LO = pos;

  return(OK);
}
Beispiel #2
0
/*===========================================================================*
 *                             fs_stat					     *
 *===========================================================================*/
int fs_stat()
{
  register int r;              /* return value */
  register struct puffs_node *pn;  /* target pnode */
  struct vattr va;
  struct stat statbuf;
  mode_t mo;
  int s;
  PUFFS_MAKECRED(pcr, &global_kcred);

  if (global_pu->pu_ops.puffs_node_getattr == NULL) {
	lpuffs_debug("fs_stat: puffs_node_getattr is missing\n");
	return(EINVAL);
  }

  if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) {
  	lpuffs_debug("walk failed...\n");
        return(EINVAL);
  }

  if (global_pu->pu_ops.puffs_node_getattr(global_pu, pn, &va, pcr) != 0) {
	if (errno) {
		if (errno > 0) errno = -errno;
		return(errno);
	}
	return(EINVAL);
  }

  /* Fill in the statbuf struct. */
  mo = va.va_mode & I_TYPE;

  /* true iff special */
  s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);

  statbuf.st_dev = fs_dev;
  statbuf.st_ino = va.va_fileid;
  statbuf.st_mode = va.va_mode;
  statbuf.st_nlink = va.va_nlink;
  statbuf.st_uid = va.va_uid;
  statbuf.st_gid = va.va_gid;
  statbuf.st_rdev = (s ? va.va_rdev : NO_DEV);
  statbuf.st_size = va.va_size;
  statbuf.st_atime = va.va_atime.tv_sec;
  statbuf.st_mtime = va.va_mtime.tv_sec;
  statbuf.st_ctime = va.va_ctime.tv_sec;

  /* Copy the struct to user space. */
  r = sys_safecopyto(fs_m_in.m_source, (cp_grant_id_t) fs_m_in.REQ_GRANT,
		     (vir_bytes) 0, (vir_bytes) &statbuf,
		     (size_t) sizeof(statbuf));

  return(r);
}
Beispiel #3
0
/*===========================================================================*
 *                             fs_stat					     *
 *===========================================================================*/
int fs_stat(ino_t ino_nr, struct stat *statbuf)
{
  register struct puffs_node *pn;  /* target pnode */
  struct vattr va;
  mode_t mo;
  int s;
  PUFFS_MAKECRED(pcr, &global_kcred);

  if (global_pu->pu_ops.puffs_node_getattr == NULL) {
	lpuffs_debug("fs_stat: puffs_node_getattr is missing\n");
	return(EINVAL);
  }

  if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) {
  	lpuffs_debug("walk failed...\n");
        return(EINVAL);
  }

  if (global_pu->pu_ops.puffs_node_getattr(global_pu, pn, &va, pcr) != 0) {
	if (errno) {
		if (errno > 0) errno = -errno;
		return(errno);
	}
	return(EINVAL);
  }

  /* Fill in the statbuf struct. */
  mo = va.va_mode & I_TYPE;

  /* true iff special */
  s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);

  statbuf->st_ino = va.va_fileid;
  statbuf->st_mode = va.va_mode;
  statbuf->st_nlink = va.va_nlink;
  statbuf->st_uid = va.va_uid;
  statbuf->st_gid = va.va_gid;
  statbuf->st_rdev = (s ? va.va_rdev : NO_DEV);
  statbuf->st_size = va.va_size;
  statbuf->st_atimespec = va.va_atime;
  statbuf->st_mtimespec = va.va_mtime;
  statbuf->st_ctimespec = va.va_ctime;

  statbuf->st_birthtimespec = va.va_birthtime;
  statbuf->st_blksize = va.va_blocksize;
  statbuf->st_blocks = va.va_bytes / va.va_blocksize;
  statbuf->st_flags = va.va_flags;
  statbuf->st_gen = va.va_gen;

  return(OK);
}
Beispiel #4
0
/*===========================================================================*
 *                             fs_statvfs                                    *
 *===========================================================================*/
int fs_statvfs(struct statvfs *st)
{

  if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, st) != 0) {
	lpuffs_debug("statvfs failed\n");
	return(EINVAL);
  }

  /* libpuffs doesn't truncate filenames */
  st->f_flag |= ST_NOTRUNC;

  return(OK);
}
Beispiel #5
0
/*===========================================================================*
 *				fs_sync					     *
 *===========================================================================*/
int fs_sync()
{
/* Perform the sync() system call.  Flush all the tables.
 * The order in which the various tables are flushed is critical.
 */
  int r;
  PUFFS_MAKECRED(pcr, &global_kcred);

  if (is_readonly_fs)
	return(OK); /* nothing to sync */

  r = global_pu->pu_ops.puffs_fs_sync(global_pu, MNT_WAIT, pcr);
  if (r) {
	lpuffs_debug("Warning: sync failed!\n");
  }

  return(OK);		/* sync() can't fail */
}
Beispiel #6
0
/*===========================================================================*
 *				fs_fstatfs				     *
 *===========================================================================*/
int fs_fstatfs()
{
  int r;
  struct statvfs st_vfs;
  struct statfs st;

  if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, &st_vfs) != 0) {
	lpuffs_debug("statfs failed\n");
	return(EINVAL);
  }

  st.f_bsize = st_vfs.f_bsize;

  /* Copy the struct to user space. */
  r = sys_safecopyto(fs_m_in.m_source, (cp_grant_id_t) fs_m_in.REQ_GRANT,
		     (vir_bytes) 0, (vir_bytes) &st, (size_t) sizeof(st));

  return(r);
}
Beispiel #7
0
/*===========================================================================*
 *                             fs_statvfs                                    *
 *===========================================================================*/
int fs_statvfs()
{
  int r;
  struct statvfs st;

  if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, &st) != 0) {
	lpuffs_debug("statvfs failed\n");
	return(EINVAL);
  }

  /* XXX libpuffs doesn't truncate filenames and returns ENAMETOOLONG,
   * though some servers would like to behave differently.
   * See subtest 2.18-19 of test23 and test/common.c:does_fs_truncate().
   */
  st.f_flag |= ST_NOTRUNC;

  /* Copy the struct to user space. */
  r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, (vir_bytes) &st,
                    (phys_bytes) sizeof(st));

  return(r);
}
Beispiel #8
0
/*===========================================================================*
 *				fs_readwrite				     *
 *===========================================================================*/
PUBLIC int fs_readwrite(void)
{
  int r = OK, rw_flag;
  cp_grant_id_t gid;
  off_t pos;
  size_t nrbytes, bytes_left, bytes_done;
  struct puffs_node *pn;
  struct vattr va;
  PUFFS_MAKECRED(pcr, &global_kcred);

  if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) {
  	lpuffs_debug("walk failed...\n");
        return(EINVAL);
  }

  /* Get the values from the request message */
  rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
  gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
  pos = (off_t) fs_m_in.REQ_SEEK_POS_LO;
  nrbytes = bytes_left = (size_t) fs_m_in.REQ_NBYTES;

  if (nrbytes > RW_BUFSIZ)
	nrbytes = bytes_left = RW_BUFSIZ;

  memset(getdents_buf, '\0', RW_BUFSIZ);  /* Avoid leaking any data */

  if (rw_flag == READING) {
	if (global_pu->pu_ops.puffs_node_read == NULL)
		return(EINVAL);

	r = global_pu->pu_ops.puffs_node_read(global_pu, pn, (uint8_t *)rw_buf,
						pos, &bytes_left, pcr, 0);
	if (r) {
		lpuffs_debug("puffs_node_read failed\n");
		return(EINVAL);
	}

	bytes_done = nrbytes - bytes_left;
	if (bytes_done) {
		r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
				   (vir_bytes) rw_buf, bytes_done, D);
		update_times(pn, ATIME, 0);
	}
  } else if (rw_flag == WRITING) {
	/* At first try to change vattr */
	if (global_pu->pu_ops.puffs_node_setattr == NULL)
		return(EINVAL);

	puffs_vattr_null(&va);
	if ( (pos + bytes_left) > pn->pn_va.va_size)
		va.va_size = bytes_left + pos;
	va.va_ctime.tv_sec = va.va_mtime.tv_sec = clock_time();
	va.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec;

	r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr);
	if (r) return(EINVAL);

	r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
			     (vir_bytes) rw_buf, nrbytes, D);
	if (r != OK) return(EINVAL);

	if (global_pu->pu_ops.puffs_node_write == NULL)
		return(EINVAL);

	r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf,
						pos, &bytes_left, pcr, 0);
	bytes_done = nrbytes - bytes_left;
  }

  if (r != OK) return(EINVAL);

  fs_m_out.RES_SEEK_POS_LO = pos + bytes_done;
  fs_m_out.RES_NBYTES = bytes_done;

  return(r);
}