uint32 gft_get_by_fd(uint32 fd) { if (fd >= process_get_current()->lft.entries.count) return INVALID_FD; return process_get_current()->lft.entries[fd].gfd; }
//prepends cwd, normpathifys, etc static int prepare_path(const unsigned char *pathin, unsigned char *pathout, int outsize) { if (pathin[0] == '/') { //do nothing? strncpy(pathout, pathin, outsize); return 0; } Process *p = process_get_current(0); if (!p) { strncpy(pathout, pathin, outsize); pathout[outsize-1] = 0; return -1; } pathout[0] = 0; strcat(pathout, p->working_path); int len = strlen(pathout); if (len == 0 && pathin[0] != '/') { strcat(pathout, "/"); } else if (len != 0 && pathin[0] == '/' && pathout[len-1] == '/') { pathout[len-1] = 0; } strcat(pathout, (unsigned char*)pathin); normpath(pathout, outsize); return 0; }
int sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { if(sig>=0 && sig<SIGNAL_MAX) { int index; index = _trans_number2index[sig]; if(index != _SIGUNDEF) { struct process *cur; cur = process_get_current(); if(oact != NULL) { *oact = cur->sig_array[index]; } if(act != NULL) { // can't change the actions for SIGKILL or SIGSTOP if(sig == SIGKILL || sig == SIGSTOP) { return -1; } cur->sig_array[index] = *act; } } else { return -1; } } else { return -1; } return 0; }
int sys_pipe2(int pipefd[2], int flags) { struct process *proc; int fdin, fdout; (void)flags; proc = process_get_current(); for(fdin=0; fdin<PROCESS_MAX_FILE && proc->files[fdin] != NULL; fdin++); for(fdout=fdin+1; fdout<PROCESS_MAX_FILE && proc->files[fdout] != NULL; fdout++); if(fdin < PROCESS_MAX_FILE && fdout < PROCESS_MAX_FILE) { struct file *files[2]; if(pipe_create(files) == 0) { proc->files[fdin] = files[0]; pipefd[0] = fdin; proc->files[fdout] = files[1]; pipefd[1] = fdout; return 0; } else { printk(LOG_ERR, "sys_pipe2: pipe creation failed\n"); } } else { printk(LOG_WARNING, "sys_pipe2: no more file desc\n"); } return -1; }
int close(int fd) { FSFile *file = (FSFile*)fd; if (!_valid_file(fd)) return -1; //do reference counting file->refs--; if (file->refs > 0) { return 0; } file->closed = 1; if (file->fs->close) { _lock_file(file); file->fs->close(file->fs, file->device, file->internalfd); _unlock_file(file); } file->magic = 0; Process *p = process_get_current(0); LinkNode *node; for (node=p->open_files.first; node; node=node->next) { if (node->data == file) { klist_remove(&p->open_files, node); kfree(node); break; } } return 0; }
int open(const unsigned char *path, int modeflags) { unsigned char path2[MAX_PATH]; FSInterface *fs=NULL; BlockDeviceIF *device=NULL; prepare_path(path, (unsigned char*)path2, sizeof(path2)); fs_vfs_get((char*) path2, &fs, &device); FSFile *file = kmalloc(sizeof(FSFile)); memset(file, 0, sizeof(*file)); _fs_file_init(file); file->fs = fs; file->device = device; file->access = modeflags; file->internalfd = file->fs->open(file->fs, file->device, path2, strlen(path2), modeflags); if (file->internalfd < 0) { kfree(file); return -1; } LinkNode *node = kmalloc(sizeof(LinkNode)); node->data = file; Process *p = process_get_current(0); klist_append(&p->open_files, node); return (int)file; }
int sys_sigreturn() { struct process *cur = process_get_current(); sched_preempt_block(); arch_signal_restore_sigcontext(cur); sched_preempt_unblock(); process_contextjmp(cur); return -1; }
int sys_getdents(int fd, struct fixos_dirent *buf, size_t len) { struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_dir_getdents(proc->files[fd], buf, len); } else { printk(LOG_DEBUG, "sys_getdents: invalid fd\n"); return -EBADF; } }
ssize_t sys_read(int fd, char *dest, int nb) { struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_read(proc->files[fd], dest, nb); } else { printk(LOG_DEBUG, "sys_read: invalid fd\n"); return -EBADF; } }
ssize_t sys_write(int fd, const char *source, int nb){ struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_write(proc->files[fd], source, nb); } else { printk(LOG_DEBUG, "sys_write: invalid fd (%d)\n", fd); } return -EBADF; }
int sys_fstat(int fd, struct stat *buf) { struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_fstat(proc->files[fd], buf); } else { printk(LOG_DEBUG, "sys_fstat: invalid fd\n"); } return -1; }
int sys_lseek(int fd, off_t offset, int whence) { struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_lseek(proc->files[fd], offset, whence); } else { printk(LOG_DEBUG, "sys_lseek: invalid fd\n"); } return -1; }
int sys_ioctl(int fd, int request, void *arg) { struct process *proc; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { return vfs_ioctl(proc->files[fd], request, arg); } else { printk(LOG_DEBUG, "sys_ioctl: invalid fd (%d)\n", fd); } return -1; }
char *getcwd(char *buf, size_t size) { Process *p = process_get_current(0); if (!p) return NULL; krwlock_rlock(&p->environ_lock); strncpy(buf, p->working_path, size); buf[size-1] = 0; krwlock_unrlock(&p->environ_lock); return buf; }
int sys_close(int fd) { struct process *proc; int ret; proc = process_get_current(); if(fd>=0 && fd<PROCESS_MAX_FILE && proc->files[fd] != NULL) { ret = vfs_close(proc->files[fd]); proc->files[fd] = NULL; } else { printk(LOG_DEBUG, "sys_close: invalid fd\n"); ret = -EBADF; } return ret; }
int sys_open(const char *name, int flags) { struct process *proc; int fd; //printk(LOG_DEBUG, "Received sys_open :\n ('%s', %d)\n", name, flags); proc = process_get_current(); for(fd=0; fd<PROCESS_MAX_FILE && proc->files[fd] != NULL; fd++); if(fd < PROCESS_MAX_FILE) { struct inode *inode; // get the inode associated to file name, and open it inode = vfs_resolve(name); if(inode != NULL) { // O_CLOEXEC flag should not be seen by vfs level if(flags & O_CLOEXEC) { flags &= ~O_CLOEXEC; proc->fdflags[fd] = FD_CLOEXEC; } else { proc->fdflags[fd] = 0; } proc->files[fd] = vfs_open(inode, flags); if(proc->files[fd] != NULL) { //printk(LOG_DEBUG, "sys_open: new fd = %d\n", fd); // done return fd; } else { printk(LOG_DEBUG, "sys_open: unable to open ('%s', f=0x%x)\n", name, flags); } } else { printk(LOG_DEBUG, "sys_open: no such inode found\n"); } } else { printk(LOG_WARNING, "sys_open: no more file desc\n"); } return -1; }
int chdir(char *path) { Process *p = process_get_current(0); if (!p) return -1; DIR *dir = opendir(path); if (!dir) { e9printf("not a directory: '%s'\n", path); return -2; //directory doesn't exist } closedir(dir); krwlock_lock(&p->environ_lock); strncpy(p->working_path, path, sizeof(p->working_path)); p->working_path[sizeof(p->working_path)-1] = 0; krwlock_unlock(&p->environ_lock); return 0; }
void signal_deliver_pending() { sigset_t todeliver; struct process *proc; proc = process_get_current(); todeliver = signal_pending(proc); if(todeliver != 0) { int atomicstate; int cursig; interrupt_atomic_save(&atomicstate); for(cursig=0; cursig<SIGNAL_MAX; cursig++) { if(sigismember(&todeliver, cursig)) { printk(LOG_DEBUG, "signal: try to deliver %d\n", cursig); try_deliver_one(proc, cursig); } } interrupt_atomic_restore(atomicstate); } }
int sys_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { struct process *cur; cur = process_get_current(); if(oldset != NULL) { *oldset = cur->sig_blocked; } if(set != NULL) { switch(how) { case SIG_SETMASK: cur->sig_blocked = *set & ~(SIGKILL | SIGSTOP); break; case SIG_BLOCK: cur->sig_blocked |= (*set & ~(SIGKILL | SIGSTOP)); break; case SIG_UNBLOCK: cur->sig_blocked &= ~(*set); break; } } return 0; }
void page_fault_bottom(thread_exception te) { thread_exception_print(&te); uint32& addr = te.data[0]; uint32& code = te.data[1]; serial_printf("PAGE_FALUT: PROC: %u ADDRESS: %h, THREAD: %u, CODE: %h\n", process_get_current()->id, addr, thread_get_current()->id, code); if (process_get_current()->contract_spinlock == 1) PANIC("PAge fault spinlock is already reserved\n"); spinlock_acquire(&process_get_current()->contract_spinlock); vm_area* p_area = vm_contract_find_area(&thread_get_current()->parent->memory_contract, addr); if (p_area == 0) { serial_printf("could not find address %h in memory contract", addr); PANIC(""); // terminate thread and process with SIGSEGV } vm_area area = *p_area; spinlock_release(&process_get_current()->contract_spinlock); // tried to acccess inaccessible page if ((area.flags & MMAP_PROTECTION) == MMAP_NO_ACCESS) { serial_printf("address: %h is inaccessible\n", addr); PANIC(""); } // tried to write to read-only or inaccessible page if (page_fault_error_is_write(code) && (area.flags & MMAP_WRITE) != MMAP_WRITE) { serial_printf("cannot write to address: %h\n", addr); PANIC(""); } // tried to read a write-only or inaccesible page ???what??? /*if (!page_fault_error_is_write(code) && CHK_BIT(area.flags, MMAP_READ)) { serial_printf("cannot read from address: %h", addr); PANIC(""); }*/ // if the page is present then a violation happened (we do not implement swap out/shared anonymous yet) if (page_fault_error_is_page_present(code) == true) { serial_printf("memory violation at address: %h with code: %h\n", addr, code); serial_printf("area flags: %h\n", area.flags); PANIC(""); } // here we found out that the page is not present, so we need to allocate it properly if (CHK_BIT(area.flags, MMAP_PRIVATE)) { if (CHK_BIT(area.flags, MMAP_ALLOC_IMMEDIATE)) { // loop through all addresses and map them for (virtual_addr address = area.start_addr; address < area.end_addr; address += 4096) //if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) ALLOC_IMMEDIATE works only for anonymous (imposed in mmap) page_fault_alloc_page(area.flags, address); } else { if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) page_fault_alloc_page(area.flags, addr & (~0xFFF)); else { uint32 flags = page_fault_calculate_present_flags(area.flags); vmmngr_alloc_page_f(addr & (~0xFFF), flags); uint32 read_start = area.offset + ((addr - area.start_addr) / PAGE_SIZE) * PAGE_SIZE; // file read start uint32 read_size = PAGE_SIZE; // we read one page at a time (not the whole area as this may not be necessary) //if (read_start < area.start_addr + PAGE_SIZE) // we are reading the first page so subtract offset from read_size // read_size -= area.offset; serial_printf("gfd: %u, reading at mem: %h, phys: %h file: %h, size: %u\n", area.fd, addr & (~0xfff), vmmngr_get_phys_addr(addr & (~0xfff)), read_start, read_size); gfe* entry = gft_get(area.fd); if (entry == 0) { serial_printf("area.fd = %u", area.fd); PANIC("page fault gfd entry = 0"); } // read one page from the file offset given at the 4KB-aligned fault address if (read_file_global(area.fd, read_start, read_size, addr & (~0xFFF), VFS_CAP_READ | VFS_CAP_CACHE) != read_size) { serial_printf("read fd: %u\n", area.fd); PANIC("mmap anonymous file read less bytes than expected"); } } } } else // MMAP_SHARED { if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) PANIC("A shared area cannot be marked as anonymous yet."); else { // in the shared file mapping the address to read is ignored as data are read only to page cache. uint32 read_start = area.offset + ((addr & (~0xfff)) - area.start_addr); gfe* entry = gft_get(area.fd); if (read_file_global(area.fd, read_start, PAGE_SIZE, -1, VFS_CAP_READ | VFS_CAP_CACHE) != PAGE_SIZE) PANIC("mmap shared file failed"); virtual_addr used_cache = page_cache_get_buffer(area.fd, read_start / PAGE_SIZE); //serial_printf("m%h\n", used_cache); uint32 flags = page_fault_calculate_present_flags(area.flags); vmmngr_map_page(vmmngr_get_directory(), vmmngr_get_phys_addr(used_cache), addr & (~0xfff), flags/*DEFAULT_FLAGS*/); //serial_printf("shared mapping fd: %u, cache: %h, phys cache: %h, read: %u, addr: %h\n", area.fd, used_cache, used_cache, read_start, addr); } } }