#include <types.h>
#include <lib.h>
#include <kern/errno.h>
#include <syscall.h>
#include <file.h>
#include <filedesc.h>
#include <copyinout.h>
#include <kern/fcntl.h>
#include <stat.h>
#include <vfs.h>
#include <current.h>
static
bool
valid_flags( int flags ) {
int count = 0;
int accmode = flags & O_ACCMODE;
if( accmode == O_RDWR )
++count;
if( accmode == O_RDONLY )
++count;
if( accmode == O_WRONLY )
++count;
return count == 1;
}
int
___open( struct proc *p, char *path, int flags, int *retval ) {
struct vnode *vn = NULL;
int err;
struct file *f = NULL;
struct stat st;
err = vfs_open( path, flags, 0, &vn );
if( err )
return err;
err = file_create( vn, flags, &f );
if( err ) {
vfs_close( vn );
return err;
}
if( flags & O_APPEND ) {
err = VOP_STAT( f->f_vnode, &st );
if( err ) {
vfs_close( vn );
file_destroy( f );
return err;
}
f->f_offset = st.st_size;
}
F_LOCK( f );
err = fd_attach( p->p_fd, f, retval );
if( err ) {
F_UNLOCK( f );
vfs_close( vn );
file_destroy( f );
return err;
}
f->f_refcount++;
VOP_INCREF( f->f_vnode );
F_UNLOCK( f );
return 0;
}
int
sys_open( userptr_t upath, int flags, int *retval ) {
char k_filename[MAX_FILE_NAME];
int err;
struct proc *p;
KASSERT( curthread != NULL );
KASSERT( curthread->td_proc != NULL );
p = curthread->td_proc;
if( !valid_flags( flags ) )
return EINVAL;
err = copyinstr( upath, k_filename, sizeof( k_filename ), NULL );
if( err )
return err;
return ___open( p, k_filename, flags, retval );
}