Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/io/file.c
2093 views
1
#include <types.h>
2
#include <lib.h>
3
#include <kern/errno.h>
4
#include <file.h>
5
#include <vfs.h>
6
7
/*
8
* create a new file associated with the given vnode/flags
9
*/
10
int
11
file_create( struct vnode *vn, int flags, struct file **f ) {
12
struct file *res;
13
14
res = kmalloc( sizeof( struct file ) );
15
if( res == NULL )
16
return ENOMEM;
17
18
//fill the basic fields
19
res->f_oflags = flags;
20
res->f_refcount = 0;
21
res->f_vnode = vn;
22
res->f_offset = 0;
23
24
//attempt to create the lock
25
res->f_lk = lock_create( "f_lk" );
26
if( res->f_lk == NULL ) {
27
kfree( res );
28
return ENOMEM;
29
}
30
31
*f = res;
32
return 0;
33
}
34
35
/*
36
* destroy the given file.
37
* otherwise, lock_destroy will fail.
38
*/
39
void
40
file_destroy( struct file *f ) {
41
//make sure we are not destroying something that is being used
42
KASSERT( f->f_refcount == 0 );
43
44
//close the associated vnode
45
vfs_close( f->f_vnode );
46
47
//release and destroy the lock
48
lock_destroy( f->f_lk );
49
50
//free the memory
51
kfree( f );
52
}
53
54
/**
55
* close the file given by the descriptor
56
*/
57
int
58
file_close_descriptor( struct proc *p, int fd ) {
59
struct file *f = NULL;
60
int err = 0;
61
62
err = file_get( p, fd, &f );
63
if( err )
64
return err;
65
66
//make sure there are programs using it
67
KASSERT( f->f_refcount > 0 );
68
69
//detach from the file descriptor table
70
fd_detach( p->p_fd, fd );
71
72
//decrease both refcounts
73
f->f_refcount--;
74
VOP_DECREF( f->f_vnode );
75
76
//destroy if we are the only ones using it
77
if( f->f_refcount == 0 ) {
78
F_UNLOCK( f );
79
file_destroy( f );
80
return 0;
81
}
82
83
//unlock the file
84
F_UNLOCK( f );
85
return 0;
86
}
87
88
89
/**
90
* find and return the file associated with the filedescriptor
91
* inside the process. it will be returned locked.
92
*/
93
int
94
file_get(struct proc *p, int fd, struct file **f ) {
95
if( fd >= MAX_OPEN_FILES || fd < 0 )
96
return EBADF;
97
98
FD_LOCK( p->p_fd );
99
if( p->p_fd->fd_ofiles[fd] != NULL ) {
100
*f = p->p_fd->fd_ofiles[fd];
101
F_LOCK( *f );
102
FD_UNLOCK( p->p_fd );
103
return 0;
104
}
105
106
FD_UNLOCK( p->p_fd );
107
return EBADF;
108
}
109
110
/**
111
* Checks whether the given file descriptor exists in the table.
112
*/
113
bool
114
file_descriptor_exists( struct proc *p, int fd ) {
115
bool exists = false;
116
117
FD_LOCK( p->p_fd );
118
if( p->p_fd->fd_ofiles[fd] != NULL )
119
exists = true;
120
FD_UNLOCK( p->p_fd );
121
122
return exists;
123
}
124
125
/**
126
* close all open files associated with the given process.
127
*/
128
int
129
file_close_all( struct proc *p ) {
130
int i = 0;
131
int err;
132
133
FD_LOCK( p->p_fd );
134
for( i = 0; i < MAX_OPEN_FILES; ++i ) {
135
if( p->p_fd->fd_ofiles[i] != NULL ) {
136
FD_UNLOCK( p->p_fd );
137
err = file_close_descriptor( p, i );
138
if( err )
139
return -1;
140
FD_LOCK( p->p_fd );
141
}
142
}
143
FD_UNLOCK( p->p_fd );
144
return 0;
145
}
146
147