Mercurial > hg > Members > anatofuz > CbC_xv6
annotate src/sysfile.cbc @ 93:7d0ec88cdd22
fix read interface
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 19 Oct 2019 18:44:57 +0900 |
parents | bc5bcfd2f6d6 |
children |
rev | line source |
---|---|
0 | 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 | |
92
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
17 #include "arm.h" |
93 | 18 #include "syscall.h" |
92
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
19 #interface "CbCSysFile.h" |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
20 |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
21 #define __ncode __code |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
22 |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
23 struct CbCSysFile* create_cbc_sys_file(struct Context* cbc_context) { |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
24 struct CbCSysFile* cbc_file = new CbCSysFile(); |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
25 cbc_file->read = C_cbc_fileread; |
93 | 26 cbc_file->cbc_file_ret = C_cbc_file_ret; |
92
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
27 return cbc_file; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
28 } |
91
b5ddf6fb0a6d
use CbCFile instead of File struct Interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
88
diff
changeset
|
29 |
92
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
30 __code cbc_file_trap_return(){ |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
31 return; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
32 } |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
33 |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
34 __code cbc_file_ret(struct CbCSysFile* cbc_sys_file, struct UInteger* ret){ |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
35 int num = cbc_sys_file->num->value; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
36 uint return_value = ret->value; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
37 //int num = proc->cbc_arg.cbc_console_arg.num; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
38 if (num != SYS_exec) { |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
39 proc->tf->r0 = return_value; |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
40 } |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
41 goto cbc_file_trap_return(); |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
42 } |
52 | 43 |
0 | 44 // Fetch the nth word-sized system call argument as a file descriptor |
45 // and return both the descriptor and the corresponding struct file. | |
46 static int argfd(int n, int *pfd, struct file **pf) | |
47 { | |
48 int fd; | |
49 struct file *f; | |
50 | |
51 if(argint(n, &fd) < 0) { | |
52 return -1; | |
53 } | |
54 | |
55 if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0) { | |
56 return -1; | |
57 } | |
58 | |
59 if(pfd) { | |
60 *pfd = fd; | |
61 } | |
62 | |
63 if(pf) { | |
64 *pf = f; | |
65 } | |
66 | |
67 return 0; | |
68 } | |
69 | |
70 // Allocate a file descriptor for the given file. | |
71 // Takes over file reference from caller on success. | |
72 static int fdalloc(struct file *f) | |
73 { | |
74 int fd; | |
75 | |
76 for(fd = 0; fd < NOFILE; fd++){ | |
77 if(proc->ofile[fd] == 0){ | |
78 proc->ofile[fd] = f; | |
79 return fd; | |
80 } | |
81 } | |
82 | |
83 return -1; | |
84 } | |
85 | |
86 int sys_dup(void) | |
87 { | |
88 struct file *f; | |
89 int fd; | |
90 | |
91 if(argfd(0, 0, &f) < 0) { | |
92 return -1; | |
93 } | |
94 | |
95 if((fd=fdalloc(f)) < 0) { | |
96 return -1; | |
97 } | |
98 | |
99 filedup(f); | |
100 | |
101 return fd; | |
102 } | |
103 | |
93 | 104 __code cbc_read(struct CbCSysFile* cbc_file){ |
105 //struct CbCSysFile* cbc_file = create_cbc_sys_file(cbc_context); | |
106 goto cbc_fileread(); | |
107 } | |
108 | |
109 __code cbc_read_stub(struct Context* cbc_context){ | |
24 | 110 struct file *f; |
111 int n; | |
112 char *p; | |
93 | 113 |
114 CbCSysFile* cbc_sys_file = (CbCSysFile*)Gearef(cbc_context,CbCSysFile); | |
24 | 115 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { |
93 | 116 //__code cbc_file_ret(struct CbCSysFile* cbc_sys_file, struct UInteger* ret){ |
117 UInteger* ret = (UInteger*)Gearef(cbc_context,UInteger); | |
118 ret->value = -1; | |
119 goto cbc_file_ret(cbc_context, cbc_sys_file, ret); | |
24 | 120 } |
93 | 121 cbc_sys_file->f = f; |
122 cbc_sys_file->n = n; | |
123 cbc_sys_file->p = p; | |
124 goto cbc_read(cbc_context,cbc_sys_file); | |
88 | 125 } |
126 | |
0 | 127 int sys_read(void) |
128 { | |
129 struct file *f; | |
130 int n; | |
131 char *p; | |
132 | |
133 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { | |
134 return -1; | |
135 } | |
136 | |
137 return fileread(f, p, n); | |
138 } | |
139 | |
140 int sys_write(void) | |
141 { | |
142 struct file *f; | |
143 int n; | |
144 char *p; | |
145 | |
146 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { | |
147 return -1; | |
148 } | |
149 | |
150 return filewrite(f, p, n); | |
151 } | |
152 | |
153 int sys_close(void) | |
154 { | |
155 int fd; | |
156 struct file *f; | |
157 | |
158 if(argfd(0, &fd, &f) < 0) { | |
159 return -1; | |
160 } | |
161 | |
162 proc->ofile[fd] = 0; | |
163 fileclose(f); | |
164 | |
165 return 0; | |
166 } | |
167 | |
168 int sys_fstat(void) | |
169 { | |
170 struct file *f; | |
171 struct stat *st; | |
172 | |
173 if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0) { | |
174 return -1; | |
175 } | |
176 | |
177 return filestat(f, st); | |
178 } | |
179 | |
180 // Create the path new as a link to the same inode as old. | |
181 int sys_link(void) | |
182 { | |
183 char name[DIRSIZ], *new, *old; | |
184 struct inode *dp, *ip; | |
185 | |
186 if(argstr(0, &old) < 0 || argstr(1, &new) < 0) { | |
187 return -1; | |
188 } | |
189 | |
190 if((ip = namei(old)) == 0) { | |
191 return -1; | |
192 } | |
193 | |
194 begin_trans(); | |
195 | |
196 ilock(ip); | |
197 | |
198 if(ip->type == T_DIR){ | |
199 iunlockput(ip); | |
200 commit_trans(); | |
201 return -1; | |
202 } | |
203 | |
204 ip->nlink++; | |
205 iupdate(ip); | |
206 iunlock(ip); | |
207 | |
208 if((dp = nameiparent(new, name)) == 0) { | |
209 goto bad; | |
210 } | |
211 | |
212 ilock(dp); | |
213 | |
214 if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ | |
215 iunlockput(dp); | |
216 goto bad; | |
217 } | |
218 | |
219 iunlockput(dp); | |
220 iput(ip); | |
221 | |
222 commit_trans(); | |
223 | |
224 return 0; | |
225 | |
226 bad: | |
227 ilock(ip); | |
228 ip->nlink--; | |
229 iupdate(ip); | |
230 iunlockput(ip); | |
231 commit_trans(); | |
232 return -1; | |
233 } | |
234 | |
235 // Is the directory dp empty except for "." and ".." ? | |
236 static int isdirempty(struct inode *dp) | |
237 { | |
238 int off; | |
239 struct dirent de; | |
240 | |
241 for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){ | |
242 if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { | |
243 panic("isdirempty: readi"); | |
244 } | |
245 | |
246 if(de.inum != 0) { | |
247 return 0; | |
248 } | |
249 } | |
250 return 1; | |
251 } | |
252 | |
253 //PAGEBREAK! | |
254 int sys_unlink(void) | |
255 { | |
256 struct inode *ip, *dp; | |
257 struct dirent de; | |
258 char name[DIRSIZ], *path; | |
259 uint off; | |
260 | |
261 if(argstr(0, &path) < 0) { | |
262 return -1; | |
263 } | |
264 | |
265 if((dp = nameiparent(path, name)) == 0) { | |
266 return -1; | |
267 } | |
268 | |
269 begin_trans(); | |
270 | |
271 ilock(dp); | |
272 | |
273 // Cannot unlink "." or "..". | |
274 if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) { | |
275 goto bad; | |
276 } | |
277 | |
278 if((ip = dirlookup(dp, name, &off)) == 0) { | |
279 goto bad; | |
280 } | |
281 | |
282 ilock(ip); | |
283 | |
284 if(ip->nlink < 1) { | |
285 panic("unlink: nlink < 1"); | |
286 } | |
287 | |
288 if(ip->type == T_DIR && !isdirempty(ip)){ | |
289 iunlockput(ip); | |
290 goto bad; | |
291 } | |
292 | |
293 memset(&de, 0, sizeof(de)); | |
294 | |
295 if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { | |
296 panic("unlink: writei"); | |
297 } | |
298 | |
299 if(ip->type == T_DIR){ | |
300 dp->nlink--; | |
301 iupdate(dp); | |
302 } | |
303 | |
304 iunlockput(dp); | |
305 | |
306 ip->nlink--; | |
307 iupdate(ip); | |
308 iunlockput(ip); | |
309 | |
310 commit_trans(); | |
311 | |
312 return 0; | |
313 | |
314 bad: | |
315 iunlockput(dp); | |
316 commit_trans(); | |
317 return -1; | |
318 } | |
319 | |
320 static struct inode* create(char *path, short type, short major, short minor) | |
321 { | |
322 uint off; | |
323 struct inode *ip, *dp; | |
324 char name[DIRSIZ]; | |
325 | |
326 if((dp = nameiparent(path, name)) == 0) { | |
327 return 0; | |
328 } | |
329 | |
330 ilock(dp); | |
331 | |
332 if((ip = dirlookup(dp, name, &off)) != 0){ | |
333 iunlockput(dp); | |
334 ilock(ip); | |
335 | |
336 if(type == T_FILE && ip->type == T_FILE) { | |
337 return ip; | |
338 } | |
339 | |
340 iunlockput(ip); | |
341 | |
342 return 0; | |
343 } | |
344 | |
345 if((ip = ialloc(dp->dev, type)) == 0) { | |
346 panic("create: ialloc"); | |
347 } | |
348 | |
349 ilock(ip); | |
350 ip->major = major; | |
351 ip->minor = minor; | |
352 ip->nlink = 1; | |
353 iupdate(ip); | |
354 | |
355 if(type == T_DIR){ // Create . and .. entries. | |
92
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
356 dp->nlink++; // for ".." |
bc5bcfd2f6d6
rename CbCFile to CbCSysFile
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
91
diff
changeset
|
357 iupdate(dp); |
0 | 358 |
359 // No ip->nlink++ for ".": avoid cyclic ref count. | |
360 if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) { | |
361 panic("create dots"); | |
362 } | |
363 } | |
364 | |
365 if(dirlink(dp, name, ip->inum) < 0) { | |
366 panic("create: dirlink"); | |
367 } | |
368 | |
369 iunlockput(dp); | |
370 | |
371 return ip; | |
372 } | |
373 | |
374 int sys_open(void) | |
375 { | |
376 char *path; | |
377 int fd, omode; | |
378 struct file *f; | |
379 struct inode *ip; | |
380 | |
381 if(argstr(0, &path) < 0 || argint(1, &omode) < 0) { | |
382 return -1; | |
383 } | |
384 | |
385 if(omode & O_CREATE){ | |
386 begin_trans(); | |
387 ip = create(path, T_FILE, 0, 0); | |
388 commit_trans(); | |
389 | |
390 if(ip == 0) { | |
391 return -1; | |
392 } | |
393 | |
394 } else { | |
395 if((ip = namei(path)) == 0) { | |
396 return -1; | |
397 } | |
398 | |
399 ilock(ip); | |
400 | |
401 if(ip->type == T_DIR && omode != O_RDONLY){ | |
402 iunlockput(ip); | |
403 return -1; | |
404 } | |
405 } | |
406 | |
407 if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ | |
408 if(f) { | |
409 fileclose(f); | |
410 } | |
411 | |
412 iunlockput(ip); | |
413 return -1; | |
414 } | |
415 | |
416 iunlock(ip); | |
417 | |
418 f->type = FD_INODE; | |
419 f->ip = ip; | |
420 f->off = 0; | |
421 f->readable = !(omode & O_WRONLY); | |
422 f->writable = (omode & O_WRONLY) || (omode & O_RDWR); | |
423 | |
424 return fd; | |
425 } | |
426 | |
427 int sys_mkdir(void) | |
428 { | |
429 char *path; | |
430 struct inode *ip; | |
431 | |
432 begin_trans(); | |
433 | |
434 if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ | |
435 commit_trans(); | |
436 return -1; | |
437 } | |
438 | |
439 iunlockput(ip); | |
440 commit_trans(); | |
441 | |
442 return 0; | |
443 } | |
444 | |
445 int sys_mknod(void) | |
446 { | |
447 struct inode *ip; | |
448 char *path; | |
449 int len; | |
450 int major, minor; | |
451 | |
452 begin_trans(); | |
453 | |
454 if((len=argstr(0, &path)) < 0 || | |
455 argint(1, &major) < 0 || argint(2, &minor) < 0 || | |
456 (ip = create(path, T_DEV, major, minor)) == 0){ | |
457 | |
458 commit_trans(); | |
459 return -1; | |
460 } | |
461 | |
462 iunlockput(ip); | |
463 commit_trans(); | |
464 | |
465 return 0; | |
466 } | |
467 | |
468 int sys_chdir(void) | |
469 { | |
470 char *path; | |
471 struct inode *ip; | |
472 | |
473 if(argstr(0, &path) < 0 || (ip = namei(path)) == 0) { | |
474 return -1; | |
475 } | |
476 | |
477 ilock(ip); | |
478 | |
479 if(ip->type != T_DIR){ | |
480 iunlockput(ip); | |
481 return -1; | |
482 } | |
483 | |
484 iunlock(ip); | |
485 | |
486 iput(proc->cwd); | |
487 proc->cwd = ip; | |
488 | |
489 return 0; | |
490 } | |
491 | |
492 int sys_exec(void) | |
493 { | |
494 char *path, *argv[MAXARG]; | |
495 int i; | |
496 uint uargv, uarg; | |
497 | |
498 if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){ | |
499 return -1; | |
500 } | |
501 | |
502 memset(argv, 0, sizeof(argv)); | |
503 | |
504 for(i=0;; i++){ | |
505 if(i >= NELEM(argv)) { | |
506 return -1; | |
507 } | |
508 | |
509 if(fetchint(uargv+4*i, (int*)&uarg) < 0) { | |
510 return -1; | |
511 } | |
512 | |
513 if(uarg == 0){ | |
514 argv[i] = 0; | |
515 break; | |
516 } | |
517 | |
518 if(fetchstr(uarg, &argv[i]) < 0) { | |
519 return -1; | |
520 } | |
521 } | |
522 | |
523 return exec(path, argv); | |
524 } | |
525 | |
526 int sys_pipe(void) | |
527 { | |
528 int *fd; | |
529 struct file *rf, *wf; | |
530 int fd0, fd1; | |
531 | |
532 if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0) { | |
533 return -1; | |
534 } | |
535 | |
536 if(pipealloc(&rf, &wf) < 0) { | |
537 return -1; | |
538 } | |
539 | |
540 fd0 = -1; | |
541 | |
542 if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ | |
543 if(fd0 >= 0) { | |
544 proc->ofile[fd0] = 0; | |
545 } | |
546 | |
547 fileclose(rf); | |
548 fileclose(wf); | |
549 | |
550 return -1; | |
551 } | |
552 | |
553 fd[0] = fd0; | |
554 fd[1] = fd1; | |
555 | |
556 return 0; | |
557 } |