int main(int argc, char *argv[]){ if(argc != 2){ printf("usage:\ntouch file\n"); return 1; } putenv("LOCALFS=some_fs.filesystem"); char *fs_name = getenv("LOCALFS"); struct fs *file_system; file_system = open_fs(fs_name); char *file = get_file(file_system, argv[1]); if(file == NULL){ //create the file create_file(file_system, argv[1], "", 0, 0x0000); } else { // update the timestamp on the file update_timestamp(file_system, argv[1]); } close_fs(file_system); return 1; }
static int sys_close(int fd) { if (FD_CHECK(fd)) { close_fs(FD_ENTRY(fd)); FD_ENTRY(fd) = NULL; return 0; } return -1; }
static int sys_access(const char * file, int flags) { PTR_VALIDATE(file); debug_print(INFO, "access(%s, 0x%x) from pid=%d", file, flags, getpid()); fs_node_t * node = kopen((char *)file, 0); if (!node) return -1; close_fs(node); return 0; }
static int sys_chown(char * file, int uid, int gid) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { /* TODO: Owners can change groups... */ if (current_process->user != 0) { close_fs(fn); return -EACCES; } result = chown_fs(fn, uid, gid); close_fs(fn); return result; } else { return -ENOENT; } }
static int sys_chmod(char * file, int mode) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { /* Can group members change bits? I think it's only owners. */ if (current_process->user != 0 && current_process->user != fn->uid) { close_fs(fn); return -EACCES; } result = chmod_fs(fn, mode); close_fs(fn); return result; } else { return -ENOENT; } }
static int sys_statf(char * file, uintptr_t st) { int result; PTR_VALIDATE(file); PTR_VALIDATE(st); fs_node_t * fn = kopen(file, 0); result = stat_node(fn, st); if (fn) close_fs(fn); return result; }
static int sys_chmod(char * file, int mode) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { result = chmod_fs(fn, mode); close_fs(fn); return result; } else { return -1; } }
static int sys_chown(char * file, int uid, int gid) { int result; PTR_VALIDATE(file); fs_node_t * fn = kopen(file, 0); if (fn) { result = chown_fs(fn, uid, gid); close_fs(fn); return result; } else { return -1; } }
int sys_close(int fd) { if (fd < 0 || fd >= NR_OPEN) return -EBADF; if (!current_task->files[fd]) return -EBADF; FILE *f = current_task->files[fd]; current_task->close_on_exec &= ~(1 << fd); current_task->files[fd] = 0; if (f->count && !(--f->count)) { close_fs(f->node); iput(f->node); free(f); } return 0; }
int exec_shebang(char * path, fs_node_t * file, int argc, char ** argv, char ** env, int interp) { /* Read MAX_LINE... */ char tmp[100]; read_fs(file, 0, 100, (unsigned char *)tmp); close_fs(file); char * cmd = (char *)&tmp[2]; char * space_or_linefeed = strpbrk(cmd, " \n"); char * arg = NULL; if (!space_or_linefeed) { debug_print(WARNING, "No space or linefeed found."); return -ENOEXEC; } if (*space_or_linefeed == ' ') { /* Oh lovely, an argument */ *space_or_linefeed = '\0'; space_or_linefeed++; arg = space_or_linefeed; space_or_linefeed = strpbrk(space_or_linefeed, "\n"); if (!space_or_linefeed) { debug_print(WARNING, "Argument exceeded maximum length"); return -ENOEXEC; } } *space_or_linefeed = '\0'; char script[strlen(path)+1]; memcpy(script, path, strlen(path)+1); unsigned int nargc = argc + (arg ? 2 : 1); char * args[nargc]; args[0] = cmd; args[1] = arg ? arg : script; args[2] = arg ? script : NULL; args[3] = NULL; int j = arg ? 3 : 2; for (int i = 1; i < argc; ++i, ++j) { args[j] = argv[i]; } args[j] = NULL; return exec(cmd, nargc, args, env); }
void onClose( GtkWidget *widget, gpointer data) { GtkTextBuffer *buffer; GtkTextIter start, end; // GtkTreePath *path; if ( fs.isopen ) { // get the buffer buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (centre.texte)); // empty the text area gtk_text_buffer_get_bounds ( buffer, &start, &end); gtk_text_buffer_delete ( buffer, &start, &end ); // empty the tree gtk_tree_store_clear ( tree.treeStore ); fs.isopen = 0; close_fs(fs.fd); } }
int exec_elf(char * path, fs_node_t * file, int argc, char ** argv, char ** env, int interp) { Elf32_Header header; read_fs(file, 0, sizeof(Elf32_Header), (uint8_t *)&header); if (header.e_ident[0] != ELFMAG0 || header.e_ident[1] != ELFMAG1 || header.e_ident[2] != ELFMAG2 || header.e_ident[3] != ELFMAG3) { debug_print(ERROR, "Not a valid ELF executable."); close_fs(file); return -1; } if (!interp) { current_process->name = strdup(path); current_process->cmdline = argv; } if (file->mask & 0x800) { debug_print(WARNING, "setuid binary executed [%s, uid:%d]", file->name, file->uid); current_process->user = file->uid; } for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) { Elf32_Phdr phdr; read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr); if (phdr.p_type == PT_DYNAMIC) { /* Dynamic */ close_fs(file); /* Find interpreter? */ debug_print(WARNING, "Dynamic executable"); unsigned int nargc = argc + 3; char * args[nargc]; args[0] = "ld.so"; args[1] = "-e"; args[2] = strdup(current_process->name); int j = 3; for (int i = 0; i < argc; ++i, ++j) { args[j] = argv[i]; } args[j] = NULL; fs_node_t * file = kopen("/lib/ld.so",0); if (!file) return -1; return exec_elf(NULL, file, nargc, args, env, 1); } } uintptr_t entry = (uintptr_t)header.e_entry; uintptr_t base_addr = 0xFFFFFFFF; uintptr_t end_addr = 0x0; for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) { Elf32_Phdr phdr; read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr); if (phdr.p_type == PT_LOAD) { if (phdr.p_vaddr < base_addr) { base_addr = phdr.p_vaddr; } if (phdr.p_memsz + phdr.p_vaddr > end_addr) { end_addr = phdr.p_memsz + phdr.p_vaddr; } } } current_process->image.entry = base_addr; current_process->image.size = end_addr - base_addr; release_directory_for_exec(current_directory); invalidate_page_tables(); for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) { Elf32_Phdr phdr; read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr); if (phdr.p_type == PT_LOAD) { for (uintptr_t i = phdr.p_vaddr; i < phdr.p_vaddr + phdr.p_memsz; i += 0x1000) { /* This doesn't care if we already allocated this page */ alloc_frame(get_page(i, 1, current_directory), 0, 1); invalidate_tables_at(i); } IRQ_RES; read_fs(file, phdr.p_offset, phdr.p_filesz, (uint8_t *)phdr.p_vaddr); IRQ_OFF; size_t r = phdr.p_filesz; while (r < phdr.p_memsz) { *(char *)(phdr.p_vaddr + r) = 0; r++; } } } close_fs(file); for (uintptr_t stack_pointer = USER_STACK_BOTTOM; stack_pointer < USER_STACK_TOP; stack_pointer += 0x1000) { alloc_frame(get_page(stack_pointer, 1, current_directory), 0, 1); invalidate_tables_at(stack_pointer); } /* Collect arguments */ int envc = 0; for (envc = 0; env[envc] != NULL; ++envc); /* Format auxv */ Elf32_auxv auxv[] = { {256, 0xDEADBEEF}, {0, 0} }; int auxvc = 0; for (auxvc = 0; auxv[auxvc].id != 0; ++auxvc); auxvc++; uintptr_t heap = current_process->image.entry + current_process->image.size; while (heap & 0xFFF) heap++; alloc_frame(get_page(heap, 1, current_directory), 0, 1); invalidate_tables_at(heap); char ** argv_ = (char **)heap; heap += sizeof(char *) * (argc + 1); char ** env_ = (char **)heap; heap += sizeof(char *) * (envc + 1); void * auxv_ptr = (void *)heap; heap += sizeof(Elf32_auxv) * (auxvc); for (int i = 0; i < argc; ++i) { size_t size = strlen(argv[i]) * sizeof(char) + 1; for (uintptr_t x = heap; x < heap + size + 0x1000; x += 0x1000) { alloc_frame(get_page(x, 1, current_directory), 0, 1); } invalidate_tables_at(heap); argv_[i] = (char *)heap; memcpy((void *)heap, argv[i], size); heap += size; } /* Don't forget the NULL at the end of that... */ argv_[argc] = 0; for (int i = 0; i < envc; ++i) { size_t size = strlen(env[i]) * sizeof(char) + 1; for (uintptr_t x = heap; x < heap + size + 0x1000; x += 0x1000) { alloc_frame(get_page(x, 1, current_directory), 0, 1); } invalidate_tables_at(heap); env_[i] = (char *)heap; memcpy((void *)heap, env[i], size); heap += size; } env_[envc] = 0; memcpy(auxv_ptr, auxv, sizeof(Elf32_auxv) * (auxvc)); current_process->image.heap = heap; /* heap end */ current_process->image.heap_actual = heap + (0x1000 - heap % 0x1000); alloc_frame(get_page(current_process->image.heap_actual, 1, current_directory), 0, 1); invalidate_tables_at(current_process->image.heap_actual); current_process->image.user_stack = USER_STACK_TOP; current_process->image.start = entry; /* Go go go */ enter_user_jmp(entry, argc, argv_, USER_STACK_TOP); /* We should never reach this code */ return -1; }
/** * Load and execute a static ELF binary. * * We make one assumption on the location the binary expects to be loaded * at: that it be outside of the kernel memory space. * * Arguments are passed to the stack of the user application so that they * can be read properly. * * TODO: Environment variables should be loaded somewhere. * * HACK: ELF verification isn't complete. * * @param path Path to the executable to attempt to execute. * @param argc Number of arguments (because I'm not counting for you) * @param argv Pointer to a string of arguments */ int exec( char * path, /* Path to the executable to run */ int argc, /* Argument count (ie, /bin/echo hello world = 3) */ char ** argv, /* Argument strings (including executable path) */ char ** env /* Environmen variables */ ) { /* Open the file */ fs_node_t * file = kopen(path,0); if (!file) { /* Command not found */ return 0; } /* Read in the binary contents */ for (uintptr_t x = 0x30000000; x < 0x30000000 + file->length; x += 0x1000) { alloc_frame(get_page(x, 1, current_directory), 0, 1); } Elf32_Header * header = (Elf32_Header *)0x30000000; //(Elf32_Header *)malloc(file->length + 100); read_fs(file, 0, file->length, (uint8_t *)header); current_process->name = malloc(strlen(path) + 1); memcpy(current_process->name, path, strlen(path) + 1); /* Alright, we've read the binary, time to load the loadable sections */ /* Verify the magic */ if ( header->e_ident[0] != ELFMAG0 || header->e_ident[1] != ELFMAG1 || header->e_ident[2] != ELFMAG2 || header->e_ident[3] != ELFMAG3) { /* What? This isn't an ELF... */ kprintf("Fatal: Not a valid ELF executable.\n"); for (uintptr_t x = 0x30000000; x < 0x30000000 + file->length; x += 0x1000) { free_frame(get_page(x, 0, current_directory)); } close_fs(file); return -1; } /* Load the loadable segments from the binary */ for (uintptr_t x = 0; x < (uint32_t)header->e_shentsize * header->e_shnum; x += header->e_shentsize) { /* read a section header */ Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)header + (header->e_shoff + x)); if (shdr->sh_addr) { /* If this is a loadable section, load it up. */ if (shdr->sh_addr < current_process->image.entry) { /* If this is the lowest entry point, store it for memory reasons */ current_process->image.entry = shdr->sh_addr; } if (shdr->sh_addr + shdr->sh_size - current_process->image.entry > current_process->image.size) { /* We also store the total size of the memory region used by the application */ current_process->image.size = shdr->sh_addr + shdr->sh_size - current_process->image.entry; } for (uintptr_t i = 0; i < shdr->sh_size + 0x2000; i += 0x1000) { /* This doesn't care if we already allocated this page */ alloc_frame(get_page(shdr->sh_addr + i, 1, current_directory), 0, 1); } if (shdr->sh_type == SHT_NOBITS) { /* This is the .bss, zero it */ memset((void *)(shdr->sh_addr), 0x0, shdr->sh_size); } else { /* Copy the section into memory */ memcpy((void *)(shdr->sh_addr), (void *)((uintptr_t)header + shdr->sh_offset), shdr->sh_size); } } } /* Store the entry point to the code segment */ uintptr_t entry = (uintptr_t)header->e_entry; /* Free the space we used for the ELF headers and files */ for (uintptr_t x = 0x30000000; x < 0x30000000 + file->length; x += 0x1000) { free_frame(get_page(x, 0, current_directory)); } close_fs(file); for (uintptr_t stack_pointer = USER_STACK_BOTTOM; stack_pointer < USER_STACK_TOP; stack_pointer += 0x1000) { alloc_frame(get_page(stack_pointer, 1, current_directory), 0, 1); } /* Collect arguments */ int envc = 0; for (envc = 0; env[envc] != NULL; ++envc); /* Format auxv */ Elf32_auxv auxv[] = { {256, 0xDEADBEEF}, {0, 0} }; int auxvc = 0; for (auxvc = 0; auxv[auxvc].id != 0; ++auxvc); uintptr_t heap = current_process->image.entry + current_process->image.size; alloc_frame(get_page(heap, 1, current_directory), 0, 1); char ** argv_ = (char **)heap; heap += sizeof(char *) * (argc + 1); char ** env_ = (char **)heap; heap += sizeof(char *) * (envc + 1); void * auxv_ptr = (void *)heap; heap += sizeof(Elf32_auxv) * (auxvc); for (int i = 0; i < argc; ++i) { alloc_frame(get_page(heap, 1, current_directory), 0, 1); argv_[i] = (char *)heap; memcpy((void *)heap, argv[i], strlen(argv[i]) * sizeof(char) + 1); heap += strlen(argv[i]) + 1; } /* Don't forget the NULL at the end of that... */ argv_[argc] = 0; for (int i = 0; i < envc; ++i) { alloc_frame(get_page(heap, 1, current_directory), 0, 1); env_[i] = (char *)heap; memcpy((void *)heap, env[i], strlen(env[i]) * sizeof(char) + 1); heap += strlen(env[i]) + 1; } env_[envc] = 0; memcpy(auxv_ptr, auxv, sizeof(Elf32_auxv) * (auxvc)); current_process->image.heap = heap; /* heap end */ current_process->image.heap_actual = heap + (0x1000 - heap % 0x1000); current_process->image.user_stack = USER_STACK_TOP; while (current_process->fds->length < 3) { process_append_fd((process_t *)current_process, NULL); } current_process->image.start = entry; /* Go go go */ enter_user_jmp(entry, argc, argv_, USER_STACK_TOP); /* We should never reach this code */ return -1; }
static int sys_open(const char * file, int flags, int mode) { PTR_VALIDATE(file); debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode); fs_node_t * node = kopen((char *)file, flags); int access_bits = 0; if (node && (flags & O_CREAT) && (flags & O_EXCL)) { close_fs(node); return -EEXIST; } if (!(flags & O_WRONLY) || (flags & O_RDWR)) { if (node && !has_permission(node, 04)) { debug_print(WARNING, "access denied (read, sys_open, file=%s)", file); close_fs(node); return -EACCES; } else { access_bits |= 01; } } if ((flags & O_RDWR) || (flags & O_WRONLY)) { if (node && !has_permission(node, 02)) { close_fs(node); return -EACCES; } if (node && (node->flags & FS_DIRECTORY)) { return -EISDIR; } if ((flags & O_RDWR) || (flags & O_WRONLY)) { /* truncate doesn't grant write permissions */ access_bits |= 02; } } if (!node && (flags & O_CREAT)) { /* TODO check directory permissions */ debug_print(NOTICE, "- file does not exist and create was requested."); /* Um, make one */ int result = create_file_fs((char *)file, mode); if (!result) { node = kopen((char *)file, flags); } else { return result; } } if (node && (flags & O_DIRECTORY)) { if (!(node->flags & FS_DIRECTORY)) { return -ENOTDIR; } } if (node && (flags & O_TRUNC)) { if (!(access_bits & 02)) { close_fs(node); return -EINVAL; } truncate_fs(node); } if (!node) { return -ENOENT; } if (node && (flags & O_CREAT) && (node->flags & FS_DIRECTORY)) { close_fs(node); return -EISDIR; } int fd = process_append_fd((process_t *)current_process, node); FD_MODE(fd) = access_bits; if (flags & O_APPEND) { FD_OFFSET(fd) = node->length; } else { FD_OFFSET(fd) = 0; } debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd); return fd; }
void onQuit(GtkWidget *pWidget, gpointer pData) { if ( fs.isopen ) { close_fs(fs.fd); } gtk_main_quit(); }