int html_load_file(struct html_output *output, int fd) { filestat_t sb; size_t size = 0; void *p = MAP_FAILED; char *buf = NULL; int ret = -1; if (fstat(fd, &sb)) { perror("open"); goto error; } if (!S_ISREG(sb.st_mode)) { g_warning("not a regular file"); goto error; } if (sb.st_size < 0 || UNSIGNED(sb.st_size) >= (size_t)-1) { g_warning("file is too large"); goto error; } size = sb.st_size; #ifdef HAS_MMAP /* FIXME: Not available on MINGW! Replace with vmm_loadfile() */ p = vmm_mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); if (MAP_FAILED == p) { perror("open"); goto error; } fd_forget_and_close(&fd); #else { size_t left = size; buf = g_malloc(size); p = buf; while (left > 0) { ssize_t n = read(fd, &buf[size - left], left); if ((ssize_t) -1 == n || 0 == n) goto error; left -= n; } } #endif ret = html_load_memory(output, array_init(p, size)); error: fd_forget_and_close(&fd); G_FREE_NULL(buf); #ifdef HAS_MMAP if (MAP_FAILED != p) { vmm_munmap(p, size); } #endif /* HAS_MMAP*/ return ret; }
static error_t elf_segments_load(struct vfs_file_s *file, Elf32_Ehdr *e_header, Elf32_Phdr *p_entry, struct task_s *task) { register error_t err; register uint_t index; register size_t size; register uint_t start; register uint_t limit; uint_t proto; uint_t flags; for(index = 0; index < e_header->e_phnum; index++, p_entry++) { if(p_entry->p_type != PT_LOAD) continue; #if 1 if((p_entry->p_vaddr < USR_OFFSET) || (p_entry->p_vaddr >= USR_LIMIT)) { err = EPERM; printk(ERROR, "\nERROR: %s: p_vaddr %x, index %d [ EPERM ]\n", __FUNCTION__, p_entry->p_vaddr, index); return err; } #endif if((err=vfs_lseek(file, p_entry->p_offset, VFS_SEEK_SET, NULL))) { printk(ERROR, "\nERROR: %s: faild to localise segment @index %d\n", __FUNCTION__, index); return err; } size = 0; start = p_entry->p_vaddr; limit = p_entry->p_vaddr + p_entry->p_memsz; if((start & PMM_PAGE_MASK) || (limit & PMM_PAGE_MASK)) return EACCES; if(task->vmm.text_start == 0) { proto = VM_REG_RD | VM_REG_EX; flags = VM_REG_SHARED | VM_REG_FIXED | VM_REG_INST; task->vmm.text_start = start; task->vmm.text_end = limit; printk(INFO, "INFO: %s: Text <0x%x - 0x%x>\n", __FUNCTION__, start, limit); } else { if(task->vmm.data_start != 0) continue; proto = VM_REG_RD | VM_REG_WR; flags = VM_REG_PRIVATE | VM_REG_FIXED; task->vmm.data_start = start; task->vmm.data_end = limit; task->vmm.heap_start = limit; task->vmm.heap_current = limit; printk(INFO, "INFO: %s: Data <0x%x - 0x%x>\n", __FUNCTION__, start, limit); } err = (error_t) vmm_mmap(task, file, (void*)start, limit - start, proto, flags, p_entry->p_offset); if(err == (error_t)VM_FAILED) { printk(WARNING,"WARNING: %s: Faild to map segment <0x%x - 0x%x>, proto %x, file name %x\n", __FUNCTION__, start, limit, proto, file->f_node->n_name); return current_thread->info.errno; } atomic_add(&file->f_count, 1); } return 0; }
int sys_mmap(mmap_attr_t *mattr) { error_t err; uint_t count; struct thread_s *this; struct task_s *task; struct vfs_file_s *file; mmap_attr_t attr; int retval; this = current_thread; task = this->task; err = EINVAL; file = NULL; if((err = cpu_uspace_copy(&attr, mattr, sizeof(mmap_attr_t)))) { printk(INFO, "%s: failed, copying from uspace @%x\n", __FUNCTION__, mattr); this->info.errno = EFAULT; return (int)VM_FAILED; } if((attr.flags & VM_REG_HEAP) || ((attr.flags & VM_REG_PVSH) == VM_REG_PVSH) || ((attr.flags & VM_REG_PVSH) == 0) || (attr.length == 0) || (attr.offset & PMM_PAGE_MASK) || ((attr.addr != NULL) && (((uint_t)attr.addr & PMM_PAGE_MASK) || ((attr.length + (uint_t)attr.addr) > CONFIG_USR_LIMIT)))) { printk(INFO, "%s: failed, we don't like flags (%x), length (%d), or addr (%x)\n", __FUNCTION__, attr.flags, attr.length, attr.addr); this->info.errno = EINVAL; return (int)VM_FAILED; } if(attr.flags & VM_REG_ANON) { attr.offset = 0; attr.addr = (attr.flags & VM_REG_FIXED) ? attr.addr : NULL; } else { if((attr.fd > CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task,attr.fd) == NULL)) { printk(INFO, "%s: failed, bad file descriptor (%d)\n", __FUNCTION__, attr.fd); this->info.errno = EBADFD; return (int)VM_FAILED; } /* FIXEME: possible concurent delete of file from another bugy thread closing it */ file = task_fd_lookup(task,attr.fd); atomic_add(&file->f_count, 1); if((attr.offset + attr.length) > file->f_node->n_size) { printk(INFO, "%s: failed, offset (%d) + len (%d) >= file's size (%d)\n", __FUNCTION__, attr.offset, attr.length, file->f_node->n_size); this->info.errno = ERANGE; goto SYS_MMAP_FILE_ERR; } if(((attr.prot & VM_REG_RD) && !(VFS_IS(file->f_flags, VFS_O_RDONLY))) || ((attr.prot & VM_REG_WR) && !(VFS_IS(file->f_flags, VFS_O_WRONLY))) || ((attr.prot & VM_REG_WR) && (VFS_IS(file->f_flags, VFS_O_APPEND))))// || //(!(attr.prot & VM_REG_RD) && (attr.flags & VM_REG_PRIVATE))) { printk(INFO, "%s: failed, EACCES prot (%x), f_flags (%x)\n", __FUNCTION__, attr.prot, file->f_flags); this->info.errno = EACCES; goto SYS_MMAP_FILE_ERR; } } retval = (int) vmm_mmap(task, file, attr.addr, attr.length, attr.prot, attr.flags, attr.offset); if((retval != (int)VM_FAILED) || (attr.flags & VM_REG_ANON)) return retval; SYS_MMAP_FILE_ERR: printk(INFO, "%s: Failed, Droping file count (%d)\n", __FUNCTION__, file->f_count); vfs_close(file, &count); if(count == 1) task_fd_put(task, attr.fd); return (int)VM_FAILED; }