Newer
Older
#include "types.h"
#include "stat.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
#include "traps.h"
#include "syscall.h"
#include "spinlock.h"
#include "buf.h"
#include "fs.h"
#include "fsvar.h"
#include "elf.h"
// Fetch the nth word-sized system call argument as a file descriptor
// and return both the descriptor and the corresponding struct file.
static int
argfd(int argno, int *pfd, struct file **pf)
int fd;
struct file *f;
if(argint(argno, &fd) < 0)
return -1;
if(fd < 0 || fd >= NOFILE || (f=cp->ofile[fd]) == 0)
// Allocate a file descriptor for the given file.
// Takes over file reference from caller on success.
static int
fdalloc(struct file *f)
{
int fd;
if(cp->ofile[fd] == 0){
cp->ofile[fd] = f;
fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0)
return 0;
}
int
sys_write(void)
{
struct file *f;
int n;
char *cp;
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
return -1;
return filewrite(f, cp, n);
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
}
int
sys_close(void)
{
int fd;
return 0;
}
int
sys_open(void)
{
struct inode *ip, *dp;
if(omode & O_CREATE){
dp = namei(path, NAMEI_CREATE, 0, &last, &ip);
if(dp){
ip = mknod1(dp, last, T_FILE, 0, 0);
iput(dp);
if(ip == 0)
return -1;
} else if(ip == 0){
return -1;
} else if(ip->type == T_DIR){
iput(ip);
return -1;
}
} else {
if(ip->type == T_DIR && ((omode & O_RDWR) || (omode & O_WRONLY))){
return -1;
}
iunlock(ip);
f->type = FD_FILE;
if(omode & O_RDWR) {
f->readable = 1;
f->writable = 1;
} else if(omode & O_WRONLY) {
f->readable = 0;
f->writable = 1;
}
int
sys_mknod(void)
{
struct inode *nip;
char *path;
int len;
int type, major, minor;
if((len=argstr(0, &path)) < 0 || argint(1, &type) < 0 ||
argint(2, &major) < 0 || argint(3, &minor) < 0)
}
int
sys_mkdir(void)
{
struct inode *nip;
struct inode *dp;
struct dirent de;
char *last;
if(dp == 0)
return -1;
nip = mknod1(dp, last, T_DIR, 0, 0);
if(nip == 0){
iput(dp);
return -1;
}
iupdate(dp);
memset(de.name, '\0', DIRSIZ);
de.name[0] = '.';
de.inum = nip->inum;
writei(nip, (char*) &de, 0, sizeof(de));
de.inum = dp->inum;
de.name[1] = '.';
writei(nip, (char*) &de, sizeof(de), sizeof(de));
iput(dp);
iput(nip);
return 0;
}
int
sys_chdir(void)
{
struct inode *ip;
iput(ip);
return 0;
}
if(ip->type != T_DIR) {
iput(ip);
return -1;
}
idecref(cp->cwd);
cp->cwd = ip;
iunlock(cp->cwd);
return 0;
}
int
sys_unlink(void)
{
}
int
sys_fstat(void)
{
struct file *f;
struct stat *st;
if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof *st) < 0)
}
int
sys_dup(void)
{
}
int
sys_link(void)
{
char *old, *new;
if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
}
int
sys_exec(void)
{
int i, nargs, argbytes, len;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
char *mem = 0;
uint argv;
if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
if(ip == 0)
return -1;
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
goto bad;
if(elf.magic != ELF_MAGIC)
goto bad;
sz = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.memsz < ph.filesz)
goto bad;
sz += ph.memsz;
}
sz += 4096 - (sz % 4096);
sz += 4096;
mem = kalloc(sz);
if(mem == 0)
goto bad;
memset(mem, 0, sz);
nargs = 0;
argbytes = 0;
for(i = 0;; i++){
if(fetchint(cp, argv + 4*i, (int*)&ap) < 0)
if(len < 0)
goto bad;
nargs++;
argbytes += len + 1;
}
// argn\0
// ...
// arg0\0
// 0
// ptr to argn
// ...
// 12: ptr to arg0
// 8: argv (points to ptr to arg0)
// 4: argc
// 0: fake return pc
sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
*(uint*)(mem + sp) = 0xffffffff;
*(uint*)(mem + sp + 4) = nargs;
*(uint*)(mem + sp + 8) = (uint)(sp + 12);
p1 = sp + 12;
p2 = sp + 12 + (nargs + 1) * 4;
for(i = 0; i < nargs; i++){
fetchint(cp, argv + 4*i, (int*)&ap);
len = fetchstr(cp, ap, &s);
memmove(mem + p2, s, len + 1);
*(uint*)(mem + p1) = p2;
p1 += 4;
p2 += len + 1;
}
*(uint*)(mem + p1) = 0;
// Save name for debugging.
for(last=s=path; *s; s++)
if(*s == '/')
last = s+1;
safestrcpy(cp->name, last, sizeof cp->name);
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = mem;
mem = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad2;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad2;
if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad2;
memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
}
iput(ip);