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