Mercurial > hg > Members > innparusu > xv6_rpi_port
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 } |