xref: /xv6-public/sysfile.c (revision 2685309f)
1*2685309fSrsc #include "types.h"
2*2685309fSrsc #include "stat.h"
3*2685309fSrsc #include "param.h"
4*2685309fSrsc #include "mmu.h"
5*2685309fSrsc #include "proc.h"
6*2685309fSrsc #include "defs.h"
7*2685309fSrsc #include "x86.h"
8*2685309fSrsc #include "traps.h"
9*2685309fSrsc #include "syscall.h"
10*2685309fSrsc #include "spinlock.h"
11*2685309fSrsc #include "buf.h"
12*2685309fSrsc #include "fs.h"
13*2685309fSrsc #include "fsvar.h"
14*2685309fSrsc #include "elf.h"
15*2685309fSrsc #include "fd.h"
16*2685309fSrsc #include "fcntl.h"
17*2685309fSrsc 
18*2685309fSrsc int
19*2685309fSrsc sys_pipe(void)
20*2685309fSrsc {
21*2685309fSrsc   struct fd *rfd = 0, *wfd = 0;
22*2685309fSrsc   int f1 = -1, f2 = -1;
23*2685309fSrsc   struct proc *p = curproc[cpu()];
24*2685309fSrsc   uint fdp;
25*2685309fSrsc 
26*2685309fSrsc   if(pipe_alloc(&rfd, &wfd) < 0)
27*2685309fSrsc     goto oops;
28*2685309fSrsc   if((f1 = fd_ualloc()) < 0)
29*2685309fSrsc     goto oops;
30*2685309fSrsc   p->fds[f1] = rfd;
31*2685309fSrsc   if((f2 = fd_ualloc()) < 0)
32*2685309fSrsc     goto oops;
33*2685309fSrsc   p->fds[f2] = wfd;
34*2685309fSrsc   if(fetcharg(0, &fdp) < 0)
35*2685309fSrsc     goto oops;
36*2685309fSrsc   if(putint(p, fdp, f1) < 0)
37*2685309fSrsc     goto oops;
38*2685309fSrsc   if(putint(p, fdp+4, f2) < 0)
39*2685309fSrsc     goto oops;
40*2685309fSrsc   return 0;
41*2685309fSrsc 
42*2685309fSrsc  oops:
43*2685309fSrsc   if(rfd)
44*2685309fSrsc     fd_close(rfd);
45*2685309fSrsc   if(wfd)
46*2685309fSrsc     fd_close(wfd);
47*2685309fSrsc   if(f1 >= 0)
48*2685309fSrsc     p->fds[f1] = 0;
49*2685309fSrsc   if(f2 >= 0)
50*2685309fSrsc     p->fds[f2] = 0;
51*2685309fSrsc   return -1;
52*2685309fSrsc }
53*2685309fSrsc 
54*2685309fSrsc int
55*2685309fSrsc sys_write(void)
56*2685309fSrsc {
57*2685309fSrsc   int fd, n, ret;
58*2685309fSrsc   uint addr;
59*2685309fSrsc   struct proc *p = curproc[cpu()];
60*2685309fSrsc 
61*2685309fSrsc   if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0)
62*2685309fSrsc     return -1;
63*2685309fSrsc   if(fd < 0 || fd >= NOFILE)
64*2685309fSrsc     return -1;
65*2685309fSrsc   if(p->fds[fd] == 0)
66*2685309fSrsc     return -1;
67*2685309fSrsc   if(addr + n > p->sz)
68*2685309fSrsc     return -1;
69*2685309fSrsc 
70*2685309fSrsc   ret = fd_write(p->fds[fd], p->mem + addr, n);
71*2685309fSrsc   return ret;
72*2685309fSrsc }
73*2685309fSrsc 
74*2685309fSrsc int
75*2685309fSrsc sys_read(void)
76*2685309fSrsc {
77*2685309fSrsc   int fd, n, ret;
78*2685309fSrsc   uint addr;
79*2685309fSrsc   struct proc *p = curproc[cpu()];
80*2685309fSrsc 
81*2685309fSrsc   if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0)
82*2685309fSrsc     return -1;
83*2685309fSrsc   if(fd < 0 || fd >= NOFILE)
84*2685309fSrsc     return -1;
85*2685309fSrsc   if(p->fds[fd] == 0)
86*2685309fSrsc     return -1;
87*2685309fSrsc   if(addr + n > p->sz)
88*2685309fSrsc     return -1;
89*2685309fSrsc   ret = fd_read(p->fds[fd], p->mem + addr, n);
90*2685309fSrsc   return ret;
91*2685309fSrsc }
92*2685309fSrsc 
93*2685309fSrsc int
94*2685309fSrsc sys_close(void)
95*2685309fSrsc {
96*2685309fSrsc   int fd;
97*2685309fSrsc   struct proc *p = curproc[cpu()];
98*2685309fSrsc 
99*2685309fSrsc   if(fetcharg(0, &fd) < 0)
100*2685309fSrsc     return -1;
101*2685309fSrsc   if(fd < 0 || fd >= NOFILE)
102*2685309fSrsc     return -1;
103*2685309fSrsc   if(p->fds[fd] == 0)
104*2685309fSrsc     return -1;
105*2685309fSrsc   fd_close(p->fds[fd]);
106*2685309fSrsc   p->fds[fd] = 0;
107*2685309fSrsc   return 0;
108*2685309fSrsc }
109*2685309fSrsc 
110*2685309fSrsc int
111*2685309fSrsc sys_open(void)
112*2685309fSrsc {
113*2685309fSrsc   struct proc *cp = curproc[cpu()];
114*2685309fSrsc   struct inode *ip, *dp;
115*2685309fSrsc   uint arg0, arg1;
116*2685309fSrsc   int ufd;
117*2685309fSrsc   struct fd *fd;
118*2685309fSrsc   int l;
119*2685309fSrsc   char *last;
120*2685309fSrsc 
121*2685309fSrsc   if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0)
122*2685309fSrsc     return -1;
123*2685309fSrsc   if((l = checkstring(arg0)) < 0)
124*2685309fSrsc     return -1;
125*2685309fSrsc 
126*2685309fSrsc   if(arg1 & O_CREATE){
127*2685309fSrsc     dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, &ip);
128*2685309fSrsc     if(dp){
129*2685309fSrsc       ip = mknod1(dp, last, T_FILE, 0, 0);
130*2685309fSrsc       iput(dp);
131*2685309fSrsc       if(ip == 0)
132*2685309fSrsc         return -1;
133*2685309fSrsc     } else if(ip == 0){
134*2685309fSrsc       return -1;
135*2685309fSrsc     } else if(ip->type == T_DIR){
136*2685309fSrsc       iput(ip);
137*2685309fSrsc       return -1;
138*2685309fSrsc     }
139*2685309fSrsc   } else {
140*2685309fSrsc     ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0);
141*2685309fSrsc     if(ip == 0)
142*2685309fSrsc       return -1;
143*2685309fSrsc   }
144*2685309fSrsc   if(ip->type == T_DIR && ((arg1 & O_RDWR) || (arg1 & O_WRONLY))){
145*2685309fSrsc     iput(ip);
146*2685309fSrsc     return -1;
147*2685309fSrsc   }
148*2685309fSrsc 
149*2685309fSrsc   if((fd = fd_alloc()) == 0){
150*2685309fSrsc     iput(ip);
151*2685309fSrsc     return -1;
152*2685309fSrsc   }
153*2685309fSrsc   if((ufd = fd_ualloc()) < 0){
154*2685309fSrsc     iput(ip);
155*2685309fSrsc     fd_close(fd);
156*2685309fSrsc     return -1;
157*2685309fSrsc   }
158*2685309fSrsc 
159*2685309fSrsc   iunlock(ip);
160*2685309fSrsc   fd->type = FD_FILE;
161*2685309fSrsc   if(arg1 & O_RDWR) {
162*2685309fSrsc     fd->readable = 1;
163*2685309fSrsc     fd->writable = 1;
164*2685309fSrsc   } else if(arg1 & O_WRONLY) {
165*2685309fSrsc     fd->readable = 0;
166*2685309fSrsc     fd->writable = 1;
167*2685309fSrsc   } else {
168*2685309fSrsc     fd->readable = 1;
169*2685309fSrsc     fd->writable = 0;
170*2685309fSrsc   }
171*2685309fSrsc   fd->ip = ip;
172*2685309fSrsc   fd->off = 0;
173*2685309fSrsc   cp->fds[ufd] = fd;
174*2685309fSrsc 
175*2685309fSrsc   return ufd;
176*2685309fSrsc }
177*2685309fSrsc 
178*2685309fSrsc int
179*2685309fSrsc sys_mknod(void)
180*2685309fSrsc {
181*2685309fSrsc   struct proc *cp = curproc[cpu()];
182*2685309fSrsc   struct inode *nip;
183*2685309fSrsc   uint arg0, arg1, arg2, arg3;
184*2685309fSrsc   int l;
185*2685309fSrsc 
186*2685309fSrsc   if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0 ||
187*2685309fSrsc      fetcharg(2, &arg2) < 0 || fetcharg(3, &arg3) < 0)
188*2685309fSrsc     return -1;
189*2685309fSrsc 
190*2685309fSrsc   if((l = checkstring(arg0)) < 0)
191*2685309fSrsc     return -1;
192*2685309fSrsc 
193*2685309fSrsc   if(l >= DIRSIZ)
194*2685309fSrsc     return -1;
195*2685309fSrsc 
196*2685309fSrsc   nip = mknod(cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3);
197*2685309fSrsc   if(nip)
198*2685309fSrsc     iput(nip);
199*2685309fSrsc   return (nip == 0) ? -1 : 0;
200*2685309fSrsc }
201*2685309fSrsc 
202*2685309fSrsc int
203*2685309fSrsc sys_mkdir(void)
204*2685309fSrsc {
205*2685309fSrsc   struct proc *cp = curproc[cpu()];
206*2685309fSrsc   struct inode *nip;
207*2685309fSrsc   struct inode *dp;
208*2685309fSrsc   uint arg0;
209*2685309fSrsc   int l;
210*2685309fSrsc   struct dirent de;
211*2685309fSrsc   char *last;
212*2685309fSrsc 
213*2685309fSrsc   if(fetcharg(0, &arg0) < 0)
214*2685309fSrsc     return -1;
215*2685309fSrsc 
216*2685309fSrsc   if((l = checkstring(arg0)) < 0)
217*2685309fSrsc     return -1;
218*2685309fSrsc 
219*2685309fSrsc   dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, 0);
220*2685309fSrsc   if(dp == 0)
221*2685309fSrsc     return -1;
222*2685309fSrsc 
223*2685309fSrsc   nip = mknod1(dp, last, T_DIR, 0, 0);
224*2685309fSrsc   if(nip == 0){
225*2685309fSrsc     iput(dp);
226*2685309fSrsc     return -1;
227*2685309fSrsc   }
228*2685309fSrsc 
229*2685309fSrsc   dp->nlink += 1;
230*2685309fSrsc   iupdate(dp);
231*2685309fSrsc 
232*2685309fSrsc   memset(de.name, '\0', DIRSIZ);
233*2685309fSrsc   de.name[0] = '.';
234*2685309fSrsc   de.inum = nip->inum;
235*2685309fSrsc   writei(nip, (char*) &de, 0, sizeof(de));
236*2685309fSrsc 
237*2685309fSrsc   de.inum = dp->inum;
238*2685309fSrsc   de.name[1] = '.';
239*2685309fSrsc   writei(nip, (char*) &de, sizeof(de), sizeof(de));
240*2685309fSrsc 
241*2685309fSrsc   iput(dp);
242*2685309fSrsc   iput(nip);
243*2685309fSrsc 
244*2685309fSrsc   return 0;
245*2685309fSrsc }
246*2685309fSrsc 
247*2685309fSrsc 
248*2685309fSrsc int
249*2685309fSrsc sys_chdir(void)
250*2685309fSrsc {
251*2685309fSrsc   struct proc *cp = curproc[cpu()];
252*2685309fSrsc   struct inode *ip;
253*2685309fSrsc     uint arg0;
254*2685309fSrsc   int l;
255*2685309fSrsc 
256*2685309fSrsc   if(fetcharg(0, &arg0) < 0)
257*2685309fSrsc     return -1;
258*2685309fSrsc 
259*2685309fSrsc   if((l = checkstring(arg0)) < 0)
260*2685309fSrsc     return -1;
261*2685309fSrsc 
262*2685309fSrsc   if((ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0)) == 0)
263*2685309fSrsc     return -1;
264*2685309fSrsc 
265*2685309fSrsc   if(ip == cp->cwd) {
266*2685309fSrsc     iput(ip);
267*2685309fSrsc     return 0;
268*2685309fSrsc   }
269*2685309fSrsc 
270*2685309fSrsc   if(ip->type != T_DIR) {
271*2685309fSrsc     iput(ip);
272*2685309fSrsc     return -1;
273*2685309fSrsc   }
274*2685309fSrsc 
275*2685309fSrsc   idecref(cp->cwd);
276*2685309fSrsc   cp->cwd = ip;
277*2685309fSrsc   iunlock(cp->cwd);
278*2685309fSrsc   return 0;
279*2685309fSrsc }
280*2685309fSrsc 
281*2685309fSrsc int
282*2685309fSrsc sys_unlink(void)
283*2685309fSrsc {
284*2685309fSrsc   struct proc *cp = curproc[cpu()];
285*2685309fSrsc   uint arg0;
286*2685309fSrsc   int r;
287*2685309fSrsc 
288*2685309fSrsc   if(fetcharg(0, &arg0) < 0)
289*2685309fSrsc     return -1;
290*2685309fSrsc   if(checkstring(arg0) < 0)
291*2685309fSrsc     return -1;
292*2685309fSrsc   r = unlink(cp->mem + arg0);
293*2685309fSrsc   return r;
294*2685309fSrsc }
295*2685309fSrsc 
296*2685309fSrsc int
297*2685309fSrsc sys_fstat(void)
298*2685309fSrsc {
299*2685309fSrsc   struct proc *cp = curproc[cpu()];
300*2685309fSrsc   uint fd, addr;
301*2685309fSrsc   int r;
302*2685309fSrsc 
303*2685309fSrsc   if(fetcharg(0, &fd) < 0)
304*2685309fSrsc     return -1;
305*2685309fSrsc   if(fetcharg(1, &addr) < 0)
306*2685309fSrsc     return -1;
307*2685309fSrsc   if(fd < 0 || fd >= NOFILE)
308*2685309fSrsc     return -1;
309*2685309fSrsc   if(cp->fds[fd] == 0)
310*2685309fSrsc     return -1;
311*2685309fSrsc   if(addr + sizeof(struct stat) > cp->sz)
312*2685309fSrsc     return -1;
313*2685309fSrsc   r = fd_stat(cp->fds[fd], (struct stat*)(cp->mem + addr));
314*2685309fSrsc   return r;
315*2685309fSrsc }
316*2685309fSrsc 
317*2685309fSrsc int
318*2685309fSrsc sys_dup(void)
319*2685309fSrsc {
320*2685309fSrsc   struct proc *cp = curproc[cpu()];
321*2685309fSrsc   uint fd, ufd1;
322*2685309fSrsc 
323*2685309fSrsc   if(fetcharg(0, &fd) < 0)
324*2685309fSrsc     return -1;
325*2685309fSrsc   if(fd < 0 || fd >= NOFILE)
326*2685309fSrsc     return -1;
327*2685309fSrsc   if(cp->fds[fd] == 0)
328*2685309fSrsc     return -1;
329*2685309fSrsc   if((ufd1 = fd_ualloc()) < 0)
330*2685309fSrsc     return -1;
331*2685309fSrsc   cp->fds[ufd1] = cp->fds[fd];
332*2685309fSrsc   fd_incref(cp->fds[ufd1]);
333*2685309fSrsc   return ufd1;
334*2685309fSrsc }
335*2685309fSrsc 
336*2685309fSrsc int
337*2685309fSrsc sys_link(void)
338*2685309fSrsc {
339*2685309fSrsc   struct proc *cp = curproc[cpu()];
340*2685309fSrsc   uint name1, name2;
341*2685309fSrsc   int r;
342*2685309fSrsc 
343*2685309fSrsc   if(fetcharg(0, &name1) < 0 || checkstring(name1) < 0)
344*2685309fSrsc     return -1;
345*2685309fSrsc   if(fetcharg(1, &name2) < 0 || checkstring(name2) < 0)
346*2685309fSrsc     return -1;
347*2685309fSrsc   r = link(cp->mem + name1, cp->mem + name2);
348*2685309fSrsc   return r;
349*2685309fSrsc }
350*2685309fSrsc 
351*2685309fSrsc int
352*2685309fSrsc sys_exec(void)
353*2685309fSrsc {
354*2685309fSrsc   struct proc *cp = curproc[cpu()];
355*2685309fSrsc   uint arg0, arg1, sz=0, ap, sp, p1, p2;
356*2685309fSrsc   int i, nargs, argbytes, len;
357*2685309fSrsc   struct inode *ip;
358*2685309fSrsc   struct elfhdr elf;
359*2685309fSrsc   struct proghdr ph;
360*2685309fSrsc   char *mem = 0;
361*2685309fSrsc 
362*2685309fSrsc   if(fetcharg(0, &arg0) < 0)
363*2685309fSrsc     return -1;
364*2685309fSrsc   if(fetcharg(1, &arg1) < 0)
365*2685309fSrsc     return -1;
366*2685309fSrsc   if(checkstring(arg0) < 0)
367*2685309fSrsc     return -1;
368*2685309fSrsc   ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0);
369*2685309fSrsc   if(ip == 0)
370*2685309fSrsc     return -1;
371*2685309fSrsc 
372*2685309fSrsc   if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
373*2685309fSrsc     goto bad;
374*2685309fSrsc 
375*2685309fSrsc   if(elf.magic != ELF_MAGIC)
376*2685309fSrsc     goto bad;
377*2685309fSrsc 
378*2685309fSrsc   sz = 0;
379*2685309fSrsc   for(i = 0; i < elf.phnum; i++){
380*2685309fSrsc     if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
381*2685309fSrsc              sizeof(ph)) != sizeof(ph))
382*2685309fSrsc       goto bad;
383*2685309fSrsc     if(ph.type != ELF_PROG_LOAD)
384*2685309fSrsc       continue;
385*2685309fSrsc     if(ph.memsz < ph.filesz)
386*2685309fSrsc       goto bad;
387*2685309fSrsc     sz += ph.memsz;
388*2685309fSrsc   }
389*2685309fSrsc 
390*2685309fSrsc   sz += 4096 - (sz % 4096);
391*2685309fSrsc   sz += 4096;
392*2685309fSrsc 
393*2685309fSrsc   mem = kalloc(sz);
394*2685309fSrsc   if(mem == 0)
395*2685309fSrsc     goto bad;
396*2685309fSrsc   memset(mem, 0, sz);
397*2685309fSrsc 
398*2685309fSrsc   // arg1 is a pointer to an array of pointers to string.
399*2685309fSrsc   nargs = 0;
400*2685309fSrsc   argbytes = 0;
401*2685309fSrsc   for(i = 0; ; i++){
402*2685309fSrsc     if(fetchint(cp, arg1 + 4*i, &ap) < 0)
403*2685309fSrsc       goto bad;
404*2685309fSrsc     if(ap == 0)
405*2685309fSrsc       break;
406*2685309fSrsc     len = checkstring(ap);
407*2685309fSrsc     if(len < 0)
408*2685309fSrsc       goto bad;
409*2685309fSrsc     nargs++;
410*2685309fSrsc     argbytes += len + 1;
411*2685309fSrsc   }
412*2685309fSrsc 
413*2685309fSrsc   // argn\0
414*2685309fSrsc   // ...
415*2685309fSrsc   // arg0\0
416*2685309fSrsc   // 0
417*2685309fSrsc   // ptr to argn
418*2685309fSrsc   // ...
419*2685309fSrsc   // 12: ptr to arg0
420*2685309fSrsc   //  8: argv (points to ptr to arg0)
421*2685309fSrsc   //  4: argc
422*2685309fSrsc   //  0: fake return pc
423*2685309fSrsc   sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
424*2685309fSrsc   *(uint*)(mem + sp) = 0xffffffff;
425*2685309fSrsc   *(uint*)(mem + sp + 4) = nargs;
426*2685309fSrsc   *(uint*)(mem + sp + 8) = (uint)(sp + 12);
427*2685309fSrsc 
428*2685309fSrsc   p1 = sp + 12;
429*2685309fSrsc   p2 = sp + 12 + (nargs + 1) * 4;
430*2685309fSrsc   for(i = 0; i < nargs; i++){
431*2685309fSrsc     fetchint(cp, arg1 + 4*i, &ap);
432*2685309fSrsc     len = checkstring(ap);
433*2685309fSrsc     memmove(mem + p2, cp->mem + ap, len + 1);
434*2685309fSrsc     *(uint*)(mem + p1) = p2;
435*2685309fSrsc     p1 += 4;
436*2685309fSrsc     p2 += len + 1;
437*2685309fSrsc   }
438*2685309fSrsc   *(uint*)(mem + p1) = 0;
439*2685309fSrsc 
440*2685309fSrsc   // commit to the new image.
441*2685309fSrsc   kfree(cp->mem, cp->sz);
442*2685309fSrsc   cp->sz = sz;
443*2685309fSrsc   cp->mem = mem;
444*2685309fSrsc   mem = 0;
445*2685309fSrsc 
446*2685309fSrsc   for(i = 0; i < elf.phnum; i++){
447*2685309fSrsc     if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
448*2685309fSrsc              sizeof(ph)) != sizeof(ph))
449*2685309fSrsc       goto bad2;
450*2685309fSrsc     if(ph.type != ELF_PROG_LOAD)
451*2685309fSrsc       continue;
452*2685309fSrsc     if(ph.va + ph.memsz > sz)
453*2685309fSrsc       goto bad2;
454*2685309fSrsc     if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
455*2685309fSrsc       goto bad2;
456*2685309fSrsc     memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
457*2685309fSrsc   }
458*2685309fSrsc 
459*2685309fSrsc   iput(ip);
460*2685309fSrsc 
461*2685309fSrsc   cp->tf->eip = elf.entry;
462*2685309fSrsc   cp->tf->esp = sp;
463*2685309fSrsc   setupsegs(cp);
464*2685309fSrsc 
465*2685309fSrsc   return 0;
466*2685309fSrsc 
467*2685309fSrsc  bad:
468*2685309fSrsc   if(mem)
469*2685309fSrsc     kfree(mem, sz);
470*2685309fSrsc   iput(ip);
471*2685309fSrsc   return -1;
472*2685309fSrsc 
473*2685309fSrsc  bad2:
474*2685309fSrsc   iput(ip);
475*2685309fSrsc   proc_exit();
476*2685309fSrsc   return 0;
477*2685309fSrsc }
478