/* * 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; }
// spinlock_acquire(&ft->filetable_lock); // // update file seeking position // ft->ft_entries[fd]->pos += *retval; // spinlock_release(&ft->filetable_lock); // return 0; // } int sys_read(int fd, userptr_t buf, size_t size, int *retval) { struct uio user_uio; struct iovec user_iov; int result; // Check fd is a valid file handle if ((fd < 0) || (fd >= __OPEN_MAX)){ return EBADF; } struct filetable *ft = curthread->t_filetable; spinlock_acquire(&ft->filetable_lock); // Check fd is a valid file handle in filetable and the vnode is not empty if ((ft->ft_entries[fd] == NULL) || (ft->ft_entries[fd]->file_vnode == NULL)) { spinlock_release(&ft->filetable_lock); return EBADF; } // Check the file handle has the permission to read int fl = ft->ft_entries[fd]->flags & O_ACCMODE; if ((fl != O_RDONLY) && (fl != O_RDWR)) { spinlock_release(&ft->filetable_lock); return EBADF; } // Init the offset by the position of the file handle int offset = ft->ft_entries[fd]->pos; /* set up a uio with the buffer, its size, and the current offset */ mk_useruio(&user_iov, &user_uio, buf, size, offset, UIO_READ); // before read you do the vop_read you have to release the lock spinlock_release(&ft->filetable_lock); /* does the read */ result = VOP_READ(ft->ft_entries[fd]->file_vnode, &user_uio); if (result) { spinlock_release(&ft->filetable_lock); return result; } /* * The amount read is the size of the buffer originally, minus * how much is left in it. */ *retval = size - user_uio.uio_resid; ft->ft_entries[fd]->pos += *retval; spinlock_release(&ft->filetable_lock); return 0; }
/* * sys_read * calls VOP_READ. * * A4: This is the "dumb" implementation of sys_write: * it only deals with file descriptors 1 and 2, and * assumes they are permanently associated with the * console vnode (which must have been previously initialized). * * In your implementation, you should use the file descriptor * to find a vnode from your file table, and then read from it. * * Note that any problems with the address supplied by the * user as "buf" will be handled by the VOP_READ / uio code * so you do not have to try to verify "buf" yourself. * * Most of this code should be replaced. */ int sys_read(int fd, userptr_t buf, size_t size, int *retval) { DEBUG(DB_VFS, "*** Reading fd %d\n", fd); struct uio user_uio; struct iovec user_iov; int result; int offset = 0; /* 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; } /* set up a uio with the buffer, its size, and the current offset */ offset = ft->ft_entries[fd]->ft_pos; mk_useruio(&user_iov, &user_uio, buf, size, offset, UIO_READ); /* does the read */ spinlock_release(&ft->ft_spinlock); result = VOP_READ(ft->ft_entries[fd]->ft_vnode, &user_uio); if (result) { return result; } /* * The amount read is the size of the buffer originally, minus * how much is left in it. */ *retval = size - user_uio.uio_resid; /* Advance file seek position. */ spinlock_acquire(&ft->ft_spinlock); ft->ft_entries[fd]->ft_pos += *retval; spinlock_release(&ft->ft_spinlock); return 0; }
/* * sys___getcwd * Sets up the uio and call vfs_cwd. */ int sys___getcwd(userptr_t buf, size_t buflen, int *retval) { struct uio user_uio; struct iovec user_iov; int result; /* set up a uio with the buffer, its size, and the current offset */ mk_useruio(&user_iov, &user_uio, buf, buflen, 0, UIO_READ); result = vfs_getcwd(&user_uio); *retval = result; return result; }
/* * sys___getcwd * */ int sys___getcwd(userptr_t buf, size_t buflen, int *retval) { //get the uio construct way from sys_read kprintf(" doing getcwd"); struct uio user_uio; struct iovec user_iov; int result; //consturct uio mk_useruio(&user_iov, &user_uio, buf, buflen, 0, UIO_READ); //use vfs_getcwd to do the work result = vfs_getcwd(&user_uio); //return what vfs_getcwd returned *retval = result; return result; }
/* * 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; }