12685309fSrsc #include "types.h" 22685309fSrsc #include "stat.h" 32685309fSrsc #include "param.h" 42685309fSrsc #include "mmu.h" 52685309fSrsc #include "proc.h" 62685309fSrsc #include "defs.h" 72685309fSrsc #include "x86.h" 82685309fSrsc #include "traps.h" 92685309fSrsc #include "syscall.h" 102685309fSrsc #include "spinlock.h" 112685309fSrsc #include "buf.h" 122685309fSrsc #include "fs.h" 132685309fSrsc #include "fsvar.h" 142685309fSrsc #include "elf.h" 15*9936bffaSrsc #include "file.h" 162685309fSrsc #include "fcntl.h" 172685309fSrsc 182685309fSrsc int 192685309fSrsc sys_pipe(void) 202685309fSrsc { 2139593d2fSrsc struct file *rfd = 0, *wfd = 0; 222685309fSrsc int f1 = -1, f2 = -1; 232685309fSrsc struct proc *p = curproc[cpu()]; 242685309fSrsc uint fdp; 252685309fSrsc 262685309fSrsc if(pipe_alloc(&rfd, &wfd) < 0) 272685309fSrsc goto oops; 282685309fSrsc if((f1 = fd_ualloc()) < 0) 292685309fSrsc goto oops; 3039593d2fSrsc p->ofile[f1] = rfd; 312685309fSrsc if((f2 = fd_ualloc()) < 0) 322685309fSrsc goto oops; 3339593d2fSrsc p->ofile[f2] = wfd; 342685309fSrsc if(fetcharg(0, &fdp) < 0) 352685309fSrsc goto oops; 362685309fSrsc if(putint(p, fdp, f1) < 0) 372685309fSrsc goto oops; 382685309fSrsc if(putint(p, fdp+4, f2) < 0) 392685309fSrsc goto oops; 402685309fSrsc return 0; 412685309fSrsc 422685309fSrsc oops: 432685309fSrsc if(rfd) 442685309fSrsc fd_close(rfd); 452685309fSrsc if(wfd) 462685309fSrsc fd_close(wfd); 472685309fSrsc if(f1 >= 0) 4839593d2fSrsc p->ofile[f1] = 0; 492685309fSrsc if(f2 >= 0) 5039593d2fSrsc p->ofile[f2] = 0; 512685309fSrsc return -1; 522685309fSrsc } 532685309fSrsc 542685309fSrsc int 552685309fSrsc sys_write(void) 562685309fSrsc { 572685309fSrsc int fd, n, ret; 582685309fSrsc uint addr; 592685309fSrsc struct proc *p = curproc[cpu()]; 602685309fSrsc 612685309fSrsc if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0) 622685309fSrsc return -1; 632685309fSrsc if(fd < 0 || fd >= NOFILE) 642685309fSrsc return -1; 6539593d2fSrsc if(p->ofile[fd] == 0) 662685309fSrsc return -1; 672685309fSrsc if(addr + n > p->sz) 682685309fSrsc return -1; 692685309fSrsc 7039593d2fSrsc ret = fd_write(p->ofile[fd], p->mem + addr, n); 712685309fSrsc return ret; 722685309fSrsc } 732685309fSrsc 742685309fSrsc int 752685309fSrsc sys_read(void) 762685309fSrsc { 772685309fSrsc int fd, n, ret; 782685309fSrsc uint addr; 792685309fSrsc struct proc *p = curproc[cpu()]; 802685309fSrsc 812685309fSrsc if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0) 822685309fSrsc return -1; 832685309fSrsc if(fd < 0 || fd >= NOFILE) 842685309fSrsc return -1; 8539593d2fSrsc if(p->ofile[fd] == 0) 862685309fSrsc return -1; 872685309fSrsc if(addr + n > p->sz) 882685309fSrsc return -1; 8939593d2fSrsc ret = fd_read(p->ofile[fd], p->mem + addr, n); 902685309fSrsc return ret; 912685309fSrsc } 922685309fSrsc 932685309fSrsc int 942685309fSrsc sys_close(void) 952685309fSrsc { 962685309fSrsc int fd; 972685309fSrsc struct proc *p = curproc[cpu()]; 982685309fSrsc 992685309fSrsc if(fetcharg(0, &fd) < 0) 1002685309fSrsc return -1; 1012685309fSrsc if(fd < 0 || fd >= NOFILE) 1022685309fSrsc return -1; 10339593d2fSrsc if(p->ofile[fd] == 0) 1042685309fSrsc return -1; 10539593d2fSrsc fd_close(p->ofile[fd]); 10639593d2fSrsc p->ofile[fd] = 0; 1072685309fSrsc return 0; 1082685309fSrsc } 1092685309fSrsc 1102685309fSrsc int 1112685309fSrsc sys_open(void) 1122685309fSrsc { 1132685309fSrsc struct proc *cp = curproc[cpu()]; 1142685309fSrsc struct inode *ip, *dp; 1152685309fSrsc uint arg0, arg1; 1162685309fSrsc int ufd; 11739593d2fSrsc struct file *fd; 1182685309fSrsc int l; 1192685309fSrsc char *last; 1202685309fSrsc 1212685309fSrsc if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0) 1222685309fSrsc return -1; 1232685309fSrsc if((l = checkstring(arg0)) < 0) 1242685309fSrsc return -1; 1252685309fSrsc 1262685309fSrsc if(arg1 & O_CREATE){ 1272685309fSrsc dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, &ip); 1282685309fSrsc if(dp){ 1292685309fSrsc ip = mknod1(dp, last, T_FILE, 0, 0); 1302685309fSrsc iput(dp); 1312685309fSrsc if(ip == 0) 1322685309fSrsc return -1; 1332685309fSrsc } else if(ip == 0){ 1342685309fSrsc return -1; 1352685309fSrsc } else if(ip->type == T_DIR){ 1362685309fSrsc iput(ip); 1372685309fSrsc return -1; 1382685309fSrsc } 1392685309fSrsc } else { 1402685309fSrsc ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0); 1412685309fSrsc if(ip == 0) 1422685309fSrsc return -1; 1432685309fSrsc } 1442685309fSrsc if(ip->type == T_DIR && ((arg1 & O_RDWR) || (arg1 & O_WRONLY))){ 1452685309fSrsc iput(ip); 1462685309fSrsc return -1; 1472685309fSrsc } 1482685309fSrsc 1492685309fSrsc if((fd = fd_alloc()) == 0){ 1502685309fSrsc iput(ip); 1512685309fSrsc return -1; 1522685309fSrsc } 1532685309fSrsc if((ufd = fd_ualloc()) < 0){ 1542685309fSrsc iput(ip); 1552685309fSrsc fd_close(fd); 1562685309fSrsc return -1; 1572685309fSrsc } 1582685309fSrsc 1592685309fSrsc iunlock(ip); 1602685309fSrsc fd->type = FD_FILE; 1612685309fSrsc if(arg1 & O_RDWR) { 1622685309fSrsc fd->readable = 1; 1632685309fSrsc fd->writable = 1; 1642685309fSrsc } else if(arg1 & O_WRONLY) { 1652685309fSrsc fd->readable = 0; 1662685309fSrsc fd->writable = 1; 1672685309fSrsc } else { 1682685309fSrsc fd->readable = 1; 1692685309fSrsc fd->writable = 0; 1702685309fSrsc } 1712685309fSrsc fd->ip = ip; 1722685309fSrsc fd->off = 0; 17339593d2fSrsc cp->ofile[ufd] = fd; 1742685309fSrsc 1752685309fSrsc return ufd; 1762685309fSrsc } 1772685309fSrsc 1782685309fSrsc int 1792685309fSrsc sys_mknod(void) 1802685309fSrsc { 1812685309fSrsc struct proc *cp = curproc[cpu()]; 1822685309fSrsc struct inode *nip; 1832685309fSrsc uint arg0, arg1, arg2, arg3; 1842685309fSrsc int l; 1852685309fSrsc 1862685309fSrsc if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0 || 1872685309fSrsc fetcharg(2, &arg2) < 0 || fetcharg(3, &arg3) < 0) 1882685309fSrsc return -1; 1892685309fSrsc 1902685309fSrsc if((l = checkstring(arg0)) < 0) 1912685309fSrsc return -1; 1922685309fSrsc 1932685309fSrsc if(l >= DIRSIZ) 1942685309fSrsc return -1; 1952685309fSrsc 1962685309fSrsc nip = mknod(cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3); 1972685309fSrsc if(nip) 1982685309fSrsc iput(nip); 1992685309fSrsc return (nip == 0) ? -1 : 0; 2002685309fSrsc } 2012685309fSrsc 2022685309fSrsc int 2032685309fSrsc sys_mkdir(void) 2042685309fSrsc { 2052685309fSrsc struct proc *cp = curproc[cpu()]; 2062685309fSrsc struct inode *nip; 2072685309fSrsc struct inode *dp; 2082685309fSrsc uint arg0; 2092685309fSrsc int l; 2102685309fSrsc struct dirent de; 2112685309fSrsc char *last; 2122685309fSrsc 2132685309fSrsc if(fetcharg(0, &arg0) < 0) 2142685309fSrsc return -1; 2152685309fSrsc 2162685309fSrsc if((l = checkstring(arg0)) < 0) 2172685309fSrsc return -1; 2182685309fSrsc 2192685309fSrsc dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, 0); 2202685309fSrsc if(dp == 0) 2212685309fSrsc return -1; 2222685309fSrsc 2232685309fSrsc nip = mknod1(dp, last, T_DIR, 0, 0); 2242685309fSrsc if(nip == 0){ 2252685309fSrsc iput(dp); 2262685309fSrsc return -1; 2272685309fSrsc } 2282685309fSrsc 2292685309fSrsc dp->nlink += 1; 2302685309fSrsc iupdate(dp); 2312685309fSrsc 2322685309fSrsc memset(de.name, '\0', DIRSIZ); 2332685309fSrsc de.name[0] = '.'; 2342685309fSrsc de.inum = nip->inum; 2352685309fSrsc writei(nip, (char*) &de, 0, sizeof(de)); 2362685309fSrsc 2372685309fSrsc de.inum = dp->inum; 2382685309fSrsc de.name[1] = '.'; 2392685309fSrsc writei(nip, (char*) &de, sizeof(de), sizeof(de)); 2402685309fSrsc 2412685309fSrsc iput(dp); 2422685309fSrsc iput(nip); 2432685309fSrsc 2442685309fSrsc return 0; 2452685309fSrsc } 2462685309fSrsc 2472685309fSrsc 2482685309fSrsc int 2492685309fSrsc sys_chdir(void) 2502685309fSrsc { 2512685309fSrsc struct proc *cp = curproc[cpu()]; 2522685309fSrsc struct inode *ip; 2532685309fSrsc uint arg0; 2542685309fSrsc int l; 2552685309fSrsc 2562685309fSrsc if(fetcharg(0, &arg0) < 0) 2572685309fSrsc return -1; 2582685309fSrsc 2592685309fSrsc if((l = checkstring(arg0)) < 0) 2602685309fSrsc return -1; 2612685309fSrsc 2622685309fSrsc if((ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0)) == 0) 2632685309fSrsc return -1; 2642685309fSrsc 2652685309fSrsc if(ip == cp->cwd) { 2662685309fSrsc iput(ip); 2672685309fSrsc return 0; 2682685309fSrsc } 2692685309fSrsc 2702685309fSrsc if(ip->type != T_DIR) { 2712685309fSrsc iput(ip); 2722685309fSrsc return -1; 2732685309fSrsc } 2742685309fSrsc 2752685309fSrsc idecref(cp->cwd); 2762685309fSrsc cp->cwd = ip; 2772685309fSrsc iunlock(cp->cwd); 2782685309fSrsc return 0; 2792685309fSrsc } 2802685309fSrsc 2812685309fSrsc int 2822685309fSrsc sys_unlink(void) 2832685309fSrsc { 2842685309fSrsc struct proc *cp = curproc[cpu()]; 2852685309fSrsc uint arg0; 2862685309fSrsc int r; 2872685309fSrsc 2882685309fSrsc if(fetcharg(0, &arg0) < 0) 2892685309fSrsc return -1; 2902685309fSrsc if(checkstring(arg0) < 0) 2912685309fSrsc return -1; 2922685309fSrsc r = unlink(cp->mem + arg0); 2932685309fSrsc return r; 2942685309fSrsc } 2952685309fSrsc 2962685309fSrsc int 2972685309fSrsc sys_fstat(void) 2982685309fSrsc { 2992685309fSrsc struct proc *cp = curproc[cpu()]; 3002685309fSrsc uint fd, addr; 3012685309fSrsc int r; 3022685309fSrsc 3032685309fSrsc if(fetcharg(0, &fd) < 0) 3042685309fSrsc return -1; 3052685309fSrsc if(fetcharg(1, &addr) < 0) 3062685309fSrsc return -1; 3072685309fSrsc if(fd < 0 || fd >= NOFILE) 3082685309fSrsc return -1; 30939593d2fSrsc if(cp->ofile[fd] == 0) 3102685309fSrsc return -1; 3112685309fSrsc if(addr + sizeof(struct stat) > cp->sz) 3122685309fSrsc return -1; 31339593d2fSrsc r = fd_stat(cp->ofile[fd], (struct stat*)(cp->mem + addr)); 3142685309fSrsc return r; 3152685309fSrsc } 3162685309fSrsc 3172685309fSrsc int 3182685309fSrsc sys_dup(void) 3192685309fSrsc { 3202685309fSrsc struct proc *cp = curproc[cpu()]; 3212685309fSrsc uint fd, ufd1; 3222685309fSrsc 3232685309fSrsc if(fetcharg(0, &fd) < 0) 3242685309fSrsc return -1; 3252685309fSrsc if(fd < 0 || fd >= NOFILE) 3262685309fSrsc return -1; 32739593d2fSrsc if(cp->ofile[fd] == 0) 3282685309fSrsc return -1; 3292685309fSrsc if((ufd1 = fd_ualloc()) < 0) 3302685309fSrsc return -1; 33139593d2fSrsc cp->ofile[ufd1] = cp->ofile[fd]; 33239593d2fSrsc fd_incref(cp->ofile[ufd1]); 3332685309fSrsc return ufd1; 3342685309fSrsc } 3352685309fSrsc 3362685309fSrsc int 3372685309fSrsc sys_link(void) 3382685309fSrsc { 3392685309fSrsc struct proc *cp = curproc[cpu()]; 3402685309fSrsc uint name1, name2; 3412685309fSrsc int r; 3422685309fSrsc 3432685309fSrsc if(fetcharg(0, &name1) < 0 || checkstring(name1) < 0) 3442685309fSrsc return -1; 3452685309fSrsc if(fetcharg(1, &name2) < 0 || checkstring(name2) < 0) 3462685309fSrsc return -1; 3472685309fSrsc r = link(cp->mem + name1, cp->mem + name2); 3482685309fSrsc return r; 3492685309fSrsc } 3502685309fSrsc 3512685309fSrsc int 3522685309fSrsc sys_exec(void) 3532685309fSrsc { 3542685309fSrsc struct proc *cp = curproc[cpu()]; 3552685309fSrsc uint arg0, arg1, sz=0, ap, sp, p1, p2; 3562685309fSrsc int i, nargs, argbytes, len; 3572685309fSrsc struct inode *ip; 3582685309fSrsc struct elfhdr elf; 3592685309fSrsc struct proghdr ph; 3602685309fSrsc char *mem = 0; 3612685309fSrsc 3622685309fSrsc if(fetcharg(0, &arg0) < 0) 3632685309fSrsc return -1; 3642685309fSrsc if(fetcharg(1, &arg1) < 0) 3652685309fSrsc return -1; 3662685309fSrsc if(checkstring(arg0) < 0) 3672685309fSrsc return -1; 3682685309fSrsc ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0); 3692685309fSrsc if(ip == 0) 3702685309fSrsc return -1; 3712685309fSrsc 3722685309fSrsc if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) 3732685309fSrsc goto bad; 3742685309fSrsc 3752685309fSrsc if(elf.magic != ELF_MAGIC) 3762685309fSrsc goto bad; 3772685309fSrsc 3782685309fSrsc sz = 0; 3792685309fSrsc for(i = 0; i < elf.phnum; i++){ 3802685309fSrsc if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph), 3812685309fSrsc sizeof(ph)) != sizeof(ph)) 3822685309fSrsc goto bad; 3832685309fSrsc if(ph.type != ELF_PROG_LOAD) 3842685309fSrsc continue; 3852685309fSrsc if(ph.memsz < ph.filesz) 3862685309fSrsc goto bad; 3872685309fSrsc sz += ph.memsz; 3882685309fSrsc } 3892685309fSrsc 3902685309fSrsc sz += 4096 - (sz % 4096); 3912685309fSrsc sz += 4096; 3922685309fSrsc 3932685309fSrsc mem = kalloc(sz); 3942685309fSrsc if(mem == 0) 3952685309fSrsc goto bad; 3962685309fSrsc memset(mem, 0, sz); 3972685309fSrsc 3982685309fSrsc // arg1 is a pointer to an array of pointers to string. 3992685309fSrsc nargs = 0; 4002685309fSrsc argbytes = 0; 4012685309fSrsc for(i = 0; ; i++){ 4022685309fSrsc if(fetchint(cp, arg1 + 4*i, &ap) < 0) 4032685309fSrsc goto bad; 4042685309fSrsc if(ap == 0) 4052685309fSrsc break; 4062685309fSrsc len = checkstring(ap); 4072685309fSrsc if(len < 0) 4082685309fSrsc goto bad; 4092685309fSrsc nargs++; 4102685309fSrsc argbytes += len + 1; 4112685309fSrsc } 4122685309fSrsc 4132685309fSrsc // argn\0 4142685309fSrsc // ... 4152685309fSrsc // arg0\0 4162685309fSrsc // 0 4172685309fSrsc // ptr to argn 4182685309fSrsc // ... 4192685309fSrsc // 12: ptr to arg0 4202685309fSrsc // 8: argv (points to ptr to arg0) 4212685309fSrsc // 4: argc 4222685309fSrsc // 0: fake return pc 4232685309fSrsc sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4; 4242685309fSrsc *(uint*)(mem + sp) = 0xffffffff; 4252685309fSrsc *(uint*)(mem + sp + 4) = nargs; 4262685309fSrsc *(uint*)(mem + sp + 8) = (uint)(sp + 12); 4272685309fSrsc 4282685309fSrsc p1 = sp + 12; 4292685309fSrsc p2 = sp + 12 + (nargs + 1) * 4; 4302685309fSrsc for(i = 0; i < nargs; i++){ 4312685309fSrsc fetchint(cp, arg1 + 4*i, &ap); 4322685309fSrsc len = checkstring(ap); 4332685309fSrsc memmove(mem + p2, cp->mem + ap, len + 1); 4342685309fSrsc *(uint*)(mem + p1) = p2; 4352685309fSrsc p1 += 4; 4362685309fSrsc p2 += len + 1; 4372685309fSrsc } 4382685309fSrsc *(uint*)(mem + p1) = 0; 4392685309fSrsc 4402685309fSrsc // commit to the new image. 4412685309fSrsc kfree(cp->mem, cp->sz); 4422685309fSrsc cp->sz = sz; 4432685309fSrsc cp->mem = mem; 4442685309fSrsc mem = 0; 4452685309fSrsc 4462685309fSrsc for(i = 0; i < elf.phnum; i++){ 4472685309fSrsc if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph), 4482685309fSrsc sizeof(ph)) != sizeof(ph)) 4492685309fSrsc goto bad2; 4502685309fSrsc if(ph.type != ELF_PROG_LOAD) 4512685309fSrsc continue; 4522685309fSrsc if(ph.va + ph.memsz > sz) 4532685309fSrsc goto bad2; 4542685309fSrsc if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz) 4552685309fSrsc goto bad2; 4562685309fSrsc memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); 4572685309fSrsc } 4582685309fSrsc 4592685309fSrsc iput(ip); 4602685309fSrsc 4612685309fSrsc cp->tf->eip = elf.entry; 4622685309fSrsc cp->tf->esp = sp; 4632685309fSrsc setupsegs(cp); 4642685309fSrsc 4652685309fSrsc return 0; 4662685309fSrsc 4672685309fSrsc bad: 4682685309fSrsc if(mem) 4692685309fSrsc kfree(mem, sz); 4702685309fSrsc iput(ip); 4712685309fSrsc return -1; 4722685309fSrsc 4732685309fSrsc bad2: 4742685309fSrsc iput(ip); 4752685309fSrsc proc_exit(); 4762685309fSrsc return 0; 4772685309fSrsc } 478