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