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 }