#include <types.h>
#include <lib.h>
#include <kern/errno.h>
#include <file.h>
#include <vfs.h>
int
file_create( struct vnode *vn, int flags, struct file **f ) {
struct file *res;
res = kmalloc( sizeof( struct file ) );
if( res == NULL )
return ENOMEM;
res->f_oflags = flags;
res->f_refcount = 0;
res->f_vnode = vn;
res->f_offset = 0;
res->f_lk = lock_create( "f_lk" );
if( res->f_lk == NULL ) {
kfree( res );
return ENOMEM;
}
*f = res;
return 0;
}
void
file_destroy( struct file *f ) {
KASSERT( f->f_refcount == 0 );
vfs_close( f->f_vnode );
lock_destroy( f->f_lk );
kfree( f );
}
int
file_close_descriptor( struct proc *p, int fd ) {
struct file *f = NULL;
int err = 0;
err = file_get( p, fd, &f );
if( err )
return err;
KASSERT( f->f_refcount > 0 );
fd_detach( p->p_fd, fd );
f->f_refcount--;
VOP_DECREF( f->f_vnode );
if( f->f_refcount == 0 ) {
F_UNLOCK( f );
file_destroy( f );
return 0;
}
F_UNLOCK( f );
return 0;
}
int
file_get(struct proc *p, int fd, struct file **f ) {
if( fd >= MAX_OPEN_FILES || fd < 0 )
return EBADF;
FD_LOCK( p->p_fd );
if( p->p_fd->fd_ofiles[fd] != NULL ) {
*f = p->p_fd->fd_ofiles[fd];
F_LOCK( *f );
FD_UNLOCK( p->p_fd );
return 0;
}
FD_UNLOCK( p->p_fd );
return EBADF;
}
bool
file_descriptor_exists( struct proc *p, int fd ) {
bool exists = false;
FD_LOCK( p->p_fd );
if( p->p_fd->fd_ofiles[fd] != NULL )
exists = true;
FD_UNLOCK( p->p_fd );
return exists;
}
int
file_close_all( struct proc *p ) {
int i = 0;
int err;
FD_LOCK( p->p_fd );
for( i = 0; i < MAX_OPEN_FILES; ++i ) {
if( p->p_fd->fd_ofiles[i] != NULL ) {
FD_UNLOCK( p->p_fd );
err = file_close_descriptor( p, i );
if( err )
return -1;
FD_LOCK( p->p_fd );
}
}
FD_UNLOCK( p->p_fd );
return 0;
}