Пример #1
0
/*
 * sys_getdirentry
 */
int
sys_getdirentry(int fd, userptr_t buf, size_t buflen, int *retval)
{
    DEBUG(DB_VFS, "*** getdirentry %d\n", fd);
	struct vnode *vn;
	off_t offset = 0;
	int err;
	struct uio my_uio;
	struct iovec uio_iov;

	/* Check if fd is a valid file descriptor. */
    struct filetable *ft = curthread->t_filetable;
    spinlock_acquire(&ft->ft_spinlock);
    
    /* If fd is not a valid file descriptor, or was not opened for reading,
     * return error */
    if ((fd < 0) || (fd >= __OPEN_MAX) || (ft->ft_entries[fd] == NULL) ||
            (ft->ft_entries[fd]->ft_vnode == NULL)) {
        spinlock_release(&ft->ft_spinlock);
        return EBADF;
    }
    int how = ft->ft_entries[fd]->ft_flags & O_ACCMODE;
    if ((how != O_RDONLY) && (how != O_RDWR)) {
        spinlock_release(&ft->ft_spinlock);
        return EBADF;
    }

	/* Initialize vn and offset using your filetable info for fd */
    vn = ft->ft_entries[fd]->ft_vnode;
    offset = ft->ft_entries[fd]->ft_pos;

	/* set up a uio with the buffer, its size, and the current offset */
	mk_useruio(&uio_iov, &my_uio, buf, buflen, offset, UIO_READ);

	/* does the read */
	err = VOP_GETDIRENTRY(vn, &my_uio);
	if (err) {
        spinlock_release(&ft->ft_spinlock);
		return err;
	}

	/* Set the offset to the updated offset in the uio. 
	 * Save the new offset with your filetable info for fd.
	 */
	offset = my_uio.uio_offset;
    ft->ft_entries[fd]->ft_pos = offset;
	
	/*
	 * the amount read is the size of the buffer originally, minus
	 * how much is left in it. Note: it is not correct to use
	 * uio_offset for this!
	 */
	*retval = buflen - my_uio.uio_resid;
    spinlock_release(&ft->ft_spinlock);
	return 0;
}
Пример #2
0
/*
 * sys_getdirentry
 */
int
sys_getdirentry(int fd, userptr_t buf, size_t buflen, int *retval)
{
  struct filetable *file_table = curthread->t_filetable;
  spinlock_acquire(&file_table->filetable_lock);
  //kprintf("doing get dir");
  //check the fd is valid or not like we do in file_close
  if((fd > __OPEN_MAX) || (curthread->t_filetable->ft_entries[fd] == NULL) || (fd<0)){
    return EBADF;
  }

  //check the flag
  int how;
  how = file_table->ft_entries[fd]->flags & O_ACCMODE;
  if(how == O_WRONLY){
    spinlock_release(&file_table->filetable_lock);
    return EBADF;
  }

  //construct uio
  struct uio user_uio;
  struct iovec user_iov;
  int offset = file_table->ft_entries[fd]->pos;
  mk_useruio(&user_iov, &user_uio, buf, buflen, offset, UIO_READ);

  int result;
  struct vnode *vn;
  vn = file_table->ft_entries[fd]->file_vnode;
  //read the file into uio
  result = VOP_GETDIRENTRY(vn,&user_uio);
  //if fail
  if(result){
    spinlock_release(&file_table->filetable_lock);
    return result;
  }

  //on success upadate the offset
  file_table->ft_entries[fd]->pos = user_uio.uio_offset;
  //set retval to be the amount we read
  *retval = buflen - user_uio.uio_resid;
  spinlock_release(&file_table->filetable_lock);
  //kprintf("get dir done");
	return 0;
}