comparison source/sysfile.c @ 0:c450faca55f4

Init
author Tatsuki IHA <innparusu@cr.ie.u-ryukyu.ac.jp>
date Sun, 22 Oct 2017 18:25:39 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:c450faca55f4
1 //
2 // File-system system calls.
3 // Mostly argument checking, since we don't trust
4 // user code, and calls into file.c and fs.c.
5 //
6
7 #include "types.h"
8 #include "defs.h"
9 #include "param.h"
10 #include "stat.h"
11 #include "mmu.h"
12 #include "proc.h"
13 #include "fs.h"
14 #include "file.h"
15 #include "fcntl.h"
16
17 // Fetch the nth word-sized system call argument as a file descriptor
18 // and return both the descriptor and the corresponding struct file.
19 static int
20 argfd(int n, int *pfd, struct file **pf)
21 {
22 int fd;
23 struct file *f;
24
25 if(argint(n, &fd) < 0)
26 return -1;
27 if(fd < 0 || fd >= NOFILE || (f=curr_proc->ofile[fd]) == 0)
28 return -1;
29 if(pfd)
30 *pfd = fd;
31 if(pf)
32 *pf = f;
33 return 0;
34 }
35
36 // Allocate a file descriptor for the given file.
37 // Takes over file reference from caller on success.
38 static int
39 fdalloc(struct file *f)
40 {
41 int fd;
42
43 for(fd = 0; fd < NOFILE; fd++){
44 if(curr_proc->ofile[fd] == 0){
45 curr_proc->ofile[fd] = f;
46 return fd;
47 }
48 }
49 return -1;
50 }
51
52 int
53 sys_dup(void)
54 {
55 struct file *f;
56 int fd;
57
58 if(argfd(0, 0, &f) < 0)
59 return -1;
60 if((fd=fdalloc(f)) < 0)
61 return -1;
62 filedup(f);
63 return fd;
64 }
65
66 int
67 sys_read(void)
68 {
69 struct file *f;
70 int n;
71 char *p;
72
73 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
74 return -1;
75 return fileread(f, p, n);
76 }
77
78 int
79 sys_write(void)
80 {
81 struct file *f;
82 int n;
83 char *p;
84
85 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
86 return -1;
87 //cprintf("inside sys_write\n");
88 return filewrite(f, p, n);
89 }
90
91 int
92 sys_close(void)
93 {
94 int fd;
95 struct file *f;
96
97 if(argfd(0, &fd, &f) < 0)
98 return -1;
99 curr_proc->ofile[fd] = 0;
100 fileclose(f);
101 return 0;
102 }
103
104 int
105 sys_fstat(void)
106 {
107 struct file *f;
108 struct stat *st;
109
110 if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
111 return -1;
112 return filestat(f, st);
113 }
114
115 // Create the path new as a link to the same inode as old.
116 int
117 sys_link(void)
118 {
119 char name[DIRSIZ], *new, *old;
120 struct inode *dp, *ip;
121
122 if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
123 return -1;
124 if((ip = namei(old)) == 0)
125 return -1;
126
127 begin_trans();
128
129 ilock(ip);
130 if(ip->type == T_DIR){
131 iunlockput(ip);
132 commit_trans();
133 return -1;
134 }
135
136 ip->nlink++;
137 iupdate(ip);
138 iunlock(ip);
139
140 if((dp = nameiparent(new, name)) == 0)
141 goto bad;
142 ilock(dp);
143 if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){
144 iunlockput(dp);
145 goto bad;
146 }
147 iunlockput(dp);
148 iput(ip);
149
150 commit_trans();
151
152 return 0;
153
154 bad:
155 ilock(ip);
156 ip->nlink--;
157 iupdate(ip);
158 iunlockput(ip);
159 commit_trans();
160 return -1;
161 }
162
163 // Is the directory dp empty except for "." and ".." ?
164 static int
165 isdirempty(struct inode *dp)
166 {
167 int off;
168 struct dirent de;
169
170 for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){
171 if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
172 panic("isdirempty: readi");
173 if(de.inum != 0)
174 return 0;
175 }
176 return 1;
177 }
178
179 //PAGEBREAK!
180 int
181 sys_unlink(void)
182 {
183 struct inode *ip, *dp;
184 struct dirent de;
185 char name[DIRSIZ], *path;
186 uint off;
187
188 if(argstr(0, &path) < 0)
189 return -1;
190 if((dp = nameiparent(path, name)) == 0)
191 return -1;
192
193 begin_trans();
194
195 ilock(dp);
196
197 // Cannot unlink "." or "..".
198 if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0)
199 goto bad;
200
201 if((ip = dirlookup(dp, name, &off)) == 0)
202 goto bad;
203 ilock(ip);
204
205 if(ip->nlink < 1)
206 panic("unlink: nlink < 1");
207 if(ip->type == T_DIR && !isdirempty(ip)){
208 iunlockput(ip);
209 goto bad;
210 }
211
212 memset(&de, 0, sizeof(de));
213 if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
214 panic("unlink: writei");
215 if(ip->type == T_DIR){
216 dp->nlink--;
217 iupdate(dp);
218 }
219 iunlockput(dp);
220
221 ip->nlink--;
222 iupdate(ip);
223 iunlockput(ip);
224
225 commit_trans();
226
227 return 0;
228
229 bad:
230 iunlockput(dp);
231 commit_trans();
232 return -1;
233 }
234
235 static struct inode*
236 create(char *path, short type, short major, short minor)
237 {
238 uint off;
239 struct inode *ip, *dp;
240 char name[DIRSIZ];
241
242 if((dp = nameiparent(path, name)) == 0)
243 return 0;
244 ilock(dp);
245
246 if((ip = dirlookup(dp, name, &off)) != 0){
247 iunlockput(dp);
248 ilock(ip);
249 if(type == T_FILE && ip->type == T_FILE)
250 return ip;
251 iunlockput(ip);
252 return 0;
253 }
254
255 if((ip = ialloc(dp->dev, type)) == 0)
256 panic("create: ialloc");
257
258 ilock(ip);
259 ip->major = major;
260 ip->minor = minor;
261 ip->nlink = 1;
262 iupdate(ip);
263
264 if(type == T_DIR){ // Create . and .. entries.
265 dp->nlink++; // for ".."
266 iupdate(dp);
267 // No ip->nlink++ for ".": avoid cyclic ref count.
268 if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
269 panic("create dots");
270 }
271
272 if(dirlink(dp, name, ip->inum) < 0)
273 panic("create: dirlink");
274
275 iunlockput(dp);
276
277 return ip;
278 }
279
280 int
281 sys_open(void)
282 {
283 char *path;
284 int fd, omode;
285 struct file *f;
286 struct inode *ip;
287
288 if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
289 return -1;
290 if(omode & O_CREATE){
291 begin_trans();
292 ip = create(path, T_FILE, 0, 0);
293 commit_trans();
294 if(ip == 0)
295 return -1;
296 } else {
297 if((ip = namei(path)) == 0)
298 return -1;
299 ilock(ip);
300 if(ip->type == T_DIR && omode != O_RDONLY){
301 iunlockput(ip);
302 return -1;
303 }
304 }
305
306 if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
307 if(f)
308 fileclose(f);
309 iunlockput(ip);
310 return -1;
311 }
312 iunlock(ip);
313
314 f->type = FD_INODE;
315 f->ip = ip;
316 f->off = 0;
317 f->readable = !(omode & O_WRONLY);
318 f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
319 return fd;
320 }
321
322 int
323 sys_mkdir(void)
324 {
325 char *path;
326 struct inode *ip;
327
328 begin_trans();
329 if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){
330 commit_trans();
331 return -1;
332 }
333 iunlockput(ip);
334 commit_trans();
335 return 0;
336 }
337
338 int
339 sys_mknod(void)
340 {
341 struct inode *ip;
342 char *path;
343 int len;
344 int major, minor;
345
346 begin_trans();
347 if((len=argstr(0, &path)) < 0 ||
348 argint(1, &major) < 0 ||
349 argint(2, &minor) < 0 ||
350 (ip = create(path, T_DEV, major, minor)) == 0){
351 commit_trans();
352 return -1;
353 }
354 iunlockput(ip);
355 commit_trans();
356 return 0;
357 }
358
359 int
360 sys_chdir(void)
361 {
362 char *path;
363 struct inode *ip;
364
365 if(argstr(0, &path) < 0 || (ip = namei(path)) == 0)
366 return -1;
367 ilock(ip);
368 if(ip->type != T_DIR){
369 iunlockput(ip);
370 return -1;
371 }
372 iunlock(ip);
373 iput(curr_proc->cwd);
374 curr_proc->cwd = ip;
375 return 0;
376 }
377
378 int
379 sys_exec(void)
380 {
381 char *path, *argv[MAXARG];
382 int i;
383 uint uargv, uarg;
384
385 if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){
386 return -1;
387 }
388 memset(argv, 0, sizeof(char *)*MAXARG);
389 for(i=0;; i++){
390 if(i >= NELEM(argv))
391 return -1;
392 if(fetchint(uargv+4*i, (int*)&uarg) < 0)
393 return -1;
394 if(uarg == 0){
395 argv[i] = 0;
396 break;
397 }
398 if(fetchstr(uarg, &argv[i]) < 0)
399 return -1;
400 }
401 return exec(path, argv);
402 }
403
404 int
405 sys_pipe(void)
406 {
407 int *fd;
408 struct file *rf, *wf;
409 int fd0, fd1;
410
411 if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0)
412 return -1;
413 if(pipealloc(&rf, &wf) < 0)
414 return -1;
415 fd0 = -1;
416 if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
417 if(fd0 >= 0)
418 curr_proc->ofile[fd0] = 0;
419 fileclose(rf);
420 fileclose(wf);
421 return -1;
422 }
423 fd[0] = fd0;
424 fd[1] = fd1;
425 return 0;
426 }