/* * 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; }
/* * 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; }