diff options
Diffstat (limited to 'kernel/syscalls.c')
| -rw-r--r-- | kernel/syscalls.c | 139 |
1 files changed, 117 insertions, 22 deletions
diff --git a/kernel/syscalls.c b/kernel/syscalls.c index 1c1d2c7..e73f89c 100644 --- a/kernel/syscalls.c +++ b/kernel/syscalls.c @@ -31,6 +31,8 @@ //TODO move to process.c and implement per process // static fd fds[MAX_PID][MAX_FD]; +//static uint32_t opendir_pos[MAX_PID][MAX_FD]; +//static char opendir_name[MAX_PID][MAX_FD][256]; static int tty[MAX_PID]; // keep track of /dev/tty fd for each process :P static bool open_fd[MAX_PID][MAX_FD]; @@ -55,6 +57,19 @@ void fd_init_std_streams(uint32_t pid) } // +/** helper */ +int nextfd(int pid) +{ + for(int i=0;i<MAX_FD;i++) + { + if(!open_fd[pid][i]) + { + open_fd[pid][i]=true; + return i; + } + } + return -1; +} /** errno helper */ void set_errno(int no) { @@ -107,6 +122,8 @@ char* syscall_get_name(uint32_t num) return "SYSCALL_GETTIMEOFDAY"; case SYSCALL_READDIR: return "SYSCALL_READDIR"; + case SYSCALL_OPENDIR: + return "SYSCALL_OPENDIR"; case SYSCALL_KILL: return "SYSCALL_KILL"; case SYSCALL_CLONE: @@ -121,8 +138,12 @@ char* syscall_get_name(uint32_t num) return "SYSCALL_GUI_WIN"; case SYSCALL_SELECT: return "SYSCALL_SELECT"; + case SYSCALL_TCGETATTR: + return "SYSCALL_TCGETATTR"; + case SYSCALL_TCSETATTR: + return "SYSCALL_TCSETATTR"; case SYSCALL_UNIMPLEMENTED: - return "SYSCALL_UNKNOWN"; + return "SYSCALL_UNIMPLEMENTED"; } kpanic("UNKNOWN SYSCALL NUM: %d",num); } @@ -154,8 +175,21 @@ int syscall_lseek(int file,int ptr,int dir,uint32_t pid) dat[1]+=ptr; return dat[1]; } + else if(dir==SEEK_SET) + { + uint32_t *dat=fds[pid][file].data; + dat[1]=ptr; + return dat[1]; + } + else if(dir==SEEK_END) + { + kpanic("SEEK_END dir for lseek!"); + } + else + { + kpanic("wrong dir for lseek!"); + } - kpanic("not fully handled lseek! dir=%d",dir); return 0; } @@ -177,12 +211,40 @@ int syscall_write(int file, char *buf, int len,uint32_t pid) */ int syscall_read(int file, char *buf, int len,uint32_t pid) { + int ret=0; + if(!open_fd[pid][file])kpanic("reading from closed file descriptor"); if(fd_eof(&fds[pid][file]))return 0; - *buf=fd_read(&fds[pid][file]); - return 1; + + while((fd_has(&fds[pid][file])||fd_eof(&fds[pid][file]))&&len-->0) + { + if(fd_eof(&fds[pid][file]))return ret; + *buf++=fd_read(&fds[pid][file]); + ret++; + } + return ret; } + /** + * Monitor multiple descriptors + * ============================ + * + * nfds is the MAX file descriptor number +1. + * + * It is possible to provide 3 different sets of filedescriptors + * (they can be NULL as well) + * + * - readfds - reading + * - writefds - writing + * - exceptfds - exceptions (all cleared unless exception occurs) + * + * The call returns the total number of descriptors contained in all + * sets after returning. + * + * This call will block until time (timeout) runs out + * OR a file descriptor becomes ready. + */ + int syscall_select(int maxxfd,struct timeval *tv, fd_set **fd_sets, uint32_t pid, bool test) { int ret=0; @@ -251,15 +313,47 @@ int syscall_select(int maxxfd,struct timeval *tv, fd_set **fd_sets, uint32_t pid } -//TODO: replace with dirent! -int syscall_readdir(const char *name,fs_dirent *dirs,int *pos,uint32_t pid) +//TODO: use fd and inode (instead of path)... now this is a crazy trick how it works.. +//is it that bad??? yes it was bad and vim crashed so we changed to even more hacky approach now.. :( :( +//ok it was other reason but we should not use it ... +//since userspace might zero or reuse dirent* and corrupt our DIR* ! TODO TODO TODO danger! +struct dirent *syscall_opendir(const char *name,struct dirent *dirs,int none,uint32_t pid) { - int ret=mount_read_dir(name, dirs, pos); + strcpy(dirs->dirname,name); + if(dirs->dirname[strlen(dirs->dirname)-1]=='/')dirs->dirname[strlen(dirs->dirname)-1]=0; + klog("syscall to opendir(%s)",dirs->dirname); + + // test if exists.... + struct dirent testdirent; + uint32_t testpos; + int ret=mount_read_dir(dirs->dirname, &testdirent, &testpos); if(ret==-1) { + // no it does not! set_errno(ENOENT); + return NULL; } - return ret; + + dirs->pos=0; + + /* + uint32_t fdn=nextfd(pid); + strcpy(opendir_name[pid][fdn],dirs->dirname); + opendir_pos[pid][fdn]=0; + */ + + return dirs; +} + +struct dirent *syscall_readdir(struct dirent *dirs,int none1, int none2,uint32_t pid) +{ + // this dirent will get filled with next entry... + int ret=mount_read_dir(dirs->dirname, dirs, &dirs->pos); + + // no more entries + if(ret==0)return NULL; + + return dirs; } /** execve helper */ @@ -327,22 +421,10 @@ int syscall_execve(const char *name, char *const argv[], char *const env[], int return 0; } -/** helper */ -int nextfd(int pid) -{ - for(int i=0;i<MAX_FD;i++) - { - if(!open_fd[pid][i]) - { - open_fd[pid][i]=true; - return i; - } - } - return -1; -} int syscall_open(char *name, int flags, int mode,uint32_t pid) { + klog("open %s",name); if(!strcmp("/dev/tty",name))return tty[pid]; uint32_t fdn=nextfd(pid); @@ -434,6 +516,10 @@ uint32_t syscall_sbrk(uint32_t incr, int none1, int none2, uint32_t pid) uint32_t oldalloc=alloc; alloc+=incr; task_set_brk(pid,alloc); + + uint32_t max_addy=VMEM_USER_PROG+VMEM_USER_PROG_PAGES*4096; + + if(alloc>max_addy)kpanic("can not set sbrk . TODO: dynamic allocation!"); fixme("fake syscall_sbrk(0x%08X) return %08X",incr,oldalloc); return oldalloc; } @@ -568,7 +654,9 @@ uint32_t syscall_generic_test(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint32_t syscall_generic(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) { -// klog("processing syscall [%s] for pid:%d",syscall_get_name(nr),pid); +#ifdef LOG_SYSCALLS + klog("processing syscall [%s] for pid:%d",syscall_get_name(nr),pid); +#endif switch(nr){ case SYSCALL_EXIT : @@ -617,6 +705,8 @@ uint32_t syscall_generic(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint return syscall_gettimeofday(p1,p2,p3,pid); case SYSCALL_READDIR : return syscall_readdir(p1,p2,p3,pid); + case SYSCALL_OPENDIR : + return syscall_opendir(p1,p2,p3,pid); case SYSCALL_KILL : // return task_kill(p1,p2,p3); return -1; @@ -634,6 +724,11 @@ uint32_t syscall_generic(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint return syscall_tcgetattr(p1,p2,p3,pid); case SYSCALL_TCSETATTR: return syscall_tcsetattr(p1,p2,p3,pid); + case SYSCALL_UNIMPLEMENTED: + if(!strcmp(p1,"fcntl")){ + klog("todo: quickfix hack for fcntl"); + } + } klog("unknown syscall %s / %d we just return 0",p1,nr); return 0; |
