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