/apimod/lib.c
C | 792 lines | 671 code | 83 blank | 38 comment | 112 complexity | 14d8d4cc3da021968ad8f29867ad2e0e MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
- /*
- Copyright (C) 2011 Salil Bhagurkar
-
- This file is part of illusion
-
- illusion is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- illusion is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with illusion. If not, see <http://www.gnu.org/licenses/>.
- */
-
- /*
- * These headers are only used for the macros/constants defined. No functions
- * from the kernel can be called from here, as we will be in user mode.
- */
- #include <klib/lib.h>
- #include <apimod/apimod.h>
- #include <kernel/errors.h>
- #include <kernel/page.h>
- #include <kernel/input.h>
- #include <kernel/vfs.h>
-
-
- /*
- * The user mode library provided by APIMOD to any application
- */
-
-
- static int dummy()
- {
- return ENOSUP;
- }
-
- uint_t string_length(const char *c)
- {
- uint_t len = 0;
- while((*c) != '\0') {
- len++;
- c++;
- }
- return len;
- }
-
- bool string_equals(const char *s1, const char *s2)
- {
- while(1) {
- if((*s1) != (*s2))
- return false;
- if((*s1) == '\0' && (*s2) == '\0')
- return true;
- else if((*s1) == '\0' || (*s2) == '\0')
- return false;
- s1++;
- s2++;
- }
- }
-
- char *string_copy(char *dest, const char *src, uint_t max_len)
- {
- char *dest_orig = dest;
- uint_t i = 0;
- while(i < (max_len - 1) && (*src) != '\0') {
- *dest = *src;
- dest++;
- src++;
- }
- if(i == (max_len - 1) || (*src) == '\0')
- *dest = '\0';
- return dest_orig;
- }
-
- void *memory_set(void *start, u8 value, uint_t count)
- {
- u32 value_l = value | (value << 8) | (value << 16) | (value << 24);
- u32 *start_l = (u32 *)start;
- uint_t count_l = count / sizeof(u32);
- uint_t final = count - count_l * sizeof(u32);
- uint_t i;
- for(i = 0; i < count_l; i++) {
- *start_l++ = value_l;
- }
- char *start_c = (char *)start_l;
- for(i = 0; i < final; i++) {
- *start_c++ = value;
- }
- return start;
- }
-
-
- void *memory_copy(void *dst, void *src, uint_t count)
- {
- u32 *dst_l = (u32 *)dst;
- u32 *src_l = (u32 *)src;
- uint_t count_l = count / sizeof(u32);
- uint_t final = count - count_l * sizeof(u32);
- uint_t i;
- for(i = 0; i < count_l; i++) {
- *dst_l++ = *src_l++;
- }
- char *dst_c = (char *)dst_l;
- char *src_c = (char *)src_l;
- for(i = 0; i < final; i++) {
- *dst_c++ = *src_c++;
- }
- return dst;
- }
-
- bool memory_equals(void *m1, void *m2, uint_t count)
- {
- u8 *m1_c = (u8 *)m1;
- u8 *m2_c = (u8 *)m2;
- for(uint_t i = 0; i < count; i++) {
- if(m1_c[i] != m2_c[i])
- return false;
- }
- return true;
- }
-
- int get_version(uint_t *build_number,
- uint_t *build_date)
- {
- return _syscall(SYS_VERSION, (u32)build_number,
- (u32)build_date, 0, 0, 0);
- }
-
- int release(uint_t reason)
- {
- return _syscall(SYS_RELEASE, reason, 0, 0, 0, 0);
- }
-
-
- int print(char *stream, uint_t length)
- {
- return _syscall(SYS_PRINT, (u32)stream, length, 0, 0, 0);
- }
-
- int read_input(uint_t *key, uint_t *state)
- {
- return _syscall(SYS_READINPUT, (u32)key,
- (u32)state, 0, 0, 0);
- }
-
- int open(char *path, uint_t state, uint_t *fd)
- {
- return _syscall(SYS_OPEN, (u32)path, state,
- (u32)fd, 0, 0);
- }
-
- int change_state(uint_t fid, uint_t new_state)
- {
- return _syscall(SYS_CHANGESTATE, fid, new_state, 0, 0, 0);
- }
-
- int get_child(uint_t fid, uint_t *child_fid)
- {
- return _syscall(SYS_GETCHILD, fid, (u32)child_fid,
- 0, 0, 0);
- }
-
- int next_child(uint_t fid)
- {
- return _syscall(SYS_NEXTCHILD, fid, 0, 0, 0, 0);
- }
-
- /*
- * This requires syscall_try to be set, or this will fail, if the child
- * was not found.
- */
- int find_child(uint_t fid, uint_t *child_fid, char *name)
- {
- uint_t child;
- int err = get_child(fid, &child);
- while(!err) {
- struct sys_info info;
- get_info(child, &info);
- if(string_equals(info.name, name)) {
- *child_fid = child;
- return 0;
- }
- err = next_child(child);
- }
- return ENOENT;
- }
-
- int get_parent(uint_t fid, uint_t *parent_fid)
- {
- return _syscall(SYS_GETPARENT, fid, (u32)parent_fid,
- 0, 0, 0);
- }
-
- int close(uint_t fid)
- {
- return _syscall(SYS_CLOSE, fid, 0, 0, 0, 0);
- }
-
- int read(uint_t fid, void *buf, uint_t offset,
- uint_t count)
- {
- return _syscall(SYS_READ, fid, (u32)buf, offset, count, 0);
- }
-
- int write(uint_t fid, void *buf, uint_t offset,
- uint_t count)
- {
- return _syscall(SYS_WRITE, fid, (u32)buf, offset, count, 0);
- }
-
- int create(uint_t fid, char *name)
- {
- return _syscall(SYS_CREATE, fid, (u32)name, 0, 0, 0);
- }
-
- int get_info(uint_t fid, struct sys_info *info)
- {
- return _syscall(SYS_GETINFO, fid, (u32)info, 0, 0, 0);
- }
-
- int create_process(uint_t *pid, char *path, char *arguments)
- {
- return _syscall(SYS_CREATEPROCESS, (u32)pid, (u32)path, (u32)arguments,
- 0, 0);
- }
-
-
- int pause_process(uint_t pid)
- {
- return _syscall(SYS_PAUSEPROCESS, pid, 0, 0, 0, 0);
- }
-
- int resume_process(uint_t pid)
- {
- return _syscall(SYS_RESUMEPROCESS, pid, 0, 0, 0, 0);
- }
-
- int printf(const char *fmt, ...)
- {
- char buf[512];
- uint_t sz = 512;
- va_list args;
- uint_t ret_val;
- va_start(args, fmt);
- ret_val = vsnprintf(buf,sz,fmt,args);
- print(buf, ret_val);
- va_end(args);
- return ret_val;
- }
-
- int insane(int code, const char *fmt, ...)
- {
- char buf[512];
- uint_t sz = 512;
- va_list args;
- uint_t ret_val;
- va_start(args, fmt);
- printf("[%d][APIMOD insanity]: ", code);
- ret_val = vsnprintf(buf,sz,fmt,args);
- print(buf, ret_val);
- va_end(args);
- exit_process();
- return 0;
- }
-
-
-
- void read_line(char *buf, uint_t buf_len)
- {
- uint_t i = 0, key;
- uint_t state;
- while(1) {
- read_input(&key, &state);
- if(state == KEYSTATE_DOWN) {
- char c;
- if(key < KEY_NONASCII) {
- c = key;
- } else {
- if(key == KEY_SPACE)
- c = ' ';
- else if(key == KEY_ENTER) {
- buf[i] = '\0';
- printf("\n");
- break;
- } else if(key == KEY_TAB)
- c = '\t';
- else if(key == KEY_BACKSPACE) {
- //Clear one character
- if(i > 0) {
- i--;
- buf[i] = '\0';
- printf("\n%s", buf);
- }
- continue;
- } else
- continue;
- }
- if(i < (buf_len - 1)) {
- printf("%c", c);
- buf[i] = c;
- i++;
- }
- }
- }
- }
-
- static char *skip_initial(char *str, char delimiter)
- {
- while((*str) != '\0') {
- if((*str) == delimiter)
- str++;
- else
- break;
- }
- return str;
- }
-
- char *separate(char *out, char *_str, char delimiter)
- {
- char *str = skip_initial(_str, delimiter);
- while((*str) != '\0') {
- if((*str) == delimiter) {
- break;
- } else {
- *out++ = *str;
- }
- str++;
- }
- *out = '\0';
- return str;
- }
-
- char **get_children(char *path, uint_t *nr_children)
- {
- uint_t fd, child_fd;
- int err = open(path, STATE_READ, &fd);
- if(err)
- return null;
- struct sys_info info;
- get_info(fd, &info);
- char **arr = (char **)malloc(info.child_count * sizeof(char *));
- uint_t i = 0;
- err = get_child(fd, &child_fd);
- while(err != 0) {
- arr[i] = (char *)malloc(VFS_NAME_LEN);
- get_info(child_fd, &info);
- string_copy(arr[i], info.name, VFS_NAME_LEN);
- i++;
- err = next_child(child_fd);
- }
- close(fd);
- *nr_children = info.child_count;
- return arr;
- }
-
- void free_children(char **arr, uint_t nr_children)
- {
- uint_t i;
- for(i = 0; i < nr_children; i++)
- free(arr[i], VFS_NAME_LEN);
- free(arr, sizeof(char *));
- }
-
- int delete_file(char *path)
- {
- uint_t fd_child, fd_parent;
- int err = open(path, STATE_WRITE, &fd_child);
- if(err)
- return err;
- err = get_parent(fd_child, &fd_parent);
- if(err) {
- close(fd_child);
- return err;
- }
- err = change_state(fd_parent, STATE_WRITE);
- if(err) {
- close(fd_child);
- close(fd_parent);
- return err;
- }
- err = delete(fd_child, fd_parent);
- close(fd_parent);
- if(err) {
- close(fd_child);
- return err;
- }
- return 0;
- }
-
- char *read_all_file(uint_t *length, char *path)
- {
- uint_t fd;
- int err = open(path, STATE_READ, &fd);
- if(err)
- return null;
- struct sys_info info;
- get_info(fd, &info);
- char *data = (char *)malloc(info.length);
- err = read(fd, data, 0, info.length);
- close(fd);
- if(err) {
- free(data, info.length);
- return null;
- }
- *length = info.length;
- return data;
- }
-
- int write_all_file(char *path, char *data, uint_t length)
- {
- uint_t fd;
- int err = open(path, STATE_WRITE, &fd);
- if(err)
- return err;
- err = write(fd, data, 0, length);
- if(err) {
- close(fd);
- return err;
- }
- err = close(fd);
- return err;
- }
-
- int create_file(char *path, char *name)
- {
- uint_t fd;
- int err = open(path, STATE_WRITE, &fd);
- if(err)
- return err;
- err = create(fd, name);
- close(fd);
- return err;
- }
-
- int get_info1(uint_t fid, struct sys_info1 *info)
- {
- return _syscall(SYS_GETINFO1, fid, (u32)info, 0, 0, 0);
- }
-
- int delete(uint_t fid, uint_t parent_fid)
- {
- return _syscall(SYS_DELETE, fid, parent_fid, 0, 0, 0);
- }
-
- int get_current(uint_t *fid)
- {
- return _syscall(SYS_GETCURRENT, (u32)fid, 0, 0, 0, 0);
- }
-
- int set_current(uint_t fid)
- {
- return _syscall(SYS_SETCURRENT, fid, 0, 0, 0, 0);
- }
-
- int exit_process()
- {
- return _syscall(SYS_EXITPROCESS, 0, 0, 0, 0, 0);
- }
-
- int string_starts_with(char *str, char *with)
- {
- while((*with) != '\0') {
- if((*str) != (*with))
- return 0;
- str++;
- with++;
- }
- return 1;
- }
-
- void string_to_lower(char *src)
- {
- while((*src) != '\0') {
- char c = *src;
- if(c >= 'A' && c <= 'Z')
- *src = c - 'A' + 'a';
- src++;
- }
- }
-
- void string_to_higher(char *src)
- {
- while((*src) != '\0') {
- char c = *src;
- if(c >= 'a' && c <= 'a')
- *src = c - 'a' + 'A';
- src++;
- }
- }
-
- int string_ends_with(char *str, char *with)
- {
- str += string_length(str) - 1;
- uint_t len = string_length(with) - 1;
- with += len;
- while(len--) {
- if((*str) != (*with))
- return 0;
- str--;
- with--;
- }
- return 1;
- }
-
- char *string_cat(char *dst, uint_t dst_buf_len, char *src)
- {
- char *dst_max = dst + dst_buf_len;
- dst += string_length(dst);
- while((*src) != '\0' && dst < (dst_max - 1)) {
- *dst++ = *src++;
- }
- *dst = '\0';
- return dst;
- }
-
- char *string_replace(char *out, size_t out_len, char *str, char *what, char *with)
- {
- size_t with_len = string_length(with);
- size_t what_len = string_length(what);
- while((*str) != '\0' && out_len > 1) {
- if(string_equals(str, what)) {
- if(out_len > with_len) {
- string_copy(out, with, out_len);
- out_len -= with_len;
- out += with_len;
- str += what_len;
- continue;
- }
- }
- *out = *str;
- out_len--;
- out++;
- str++;
- }
- *out = '\0';
- return out;
- }
-
- char *get_arguments(uint_t *len)
- {
- int err = _syscall(SYS_ARGS, 0, (u32)len, 0, 0, 0);
- if(err || (*len) == 0)
- return null;
- char *args = (char *)malloc(*len);
- err = _syscall(SYS_ARGS, (u32)args, (u32)len, 0, 0, 0);
- if(err) {
- free(args, *len);
- return null;
- }
- return args;
- }
-
-
- int get_device(uint_t *fid)
- {
- return _syscall(SYS_GETDEV, (u32)fid, 0, 0, 0, 0);
- }
-
- int next_device(uint_t fid)
- {
- return _syscall(SYS_NEXTDEV, fid, 0, 0, 0, 0);
- }
-
- void *get_pages(uint_t count)
- {
- void *pages;
- int err = _syscall(SYS_GETPAGES, (u32)(&pages), count, 0, 0, 0);
- if(!err)
- return pages;
- return null;
- }
-
- int free_pages(void *pages, uint_t count)
- {
- return _syscall(SYS_FREEPAGES, (u32)pages, count, 0, 0, 0);
- }
-
- #define MAX_MULTIPLIER 1000000000
- #define MAX_HEX_MULTIPLIER 0x10000000
-
- uint_t dec_string(char *_str)
- {
- uint_t len = string_length(_str);
- char *str = _str + len - 1;
- uint_t number = 0, multiplier = 1;
- while(str >= _str && multiplier < MAX_MULTIPLIER) {
- if((*str) >= '0' && (*str) <= '9') {
- number += ((*str) - '0') * multiplier;
- multiplier *= 10;
- }
- str--;
- }
- return number;
- }
-
- /*
- * Note that the string will include a '0' and 'x' at the beginning
- */
- uint_t hex_string(char *_str)
- {
- //Move past the '0x'
- _str += 2;
- uint_t len = string_length(_str);
- char *str = _str + len - 1;
- uint_t number = 0, multiplier = 1;
- while(str >= _str && multiplier <= MAX_HEX_MULTIPLIER) {
- if((*str) >= '0' && (*str) <= '9') {
- number += ((*str) - '0') * multiplier;
- multiplier *= 16;
- } else if((*str) >= 'a' && (*str) <= 'f') {
- number += ((*str) - 'a' + 10) * multiplier;
- multiplier *= 16;
- } else if((*str) >= 'A' && (*str) <= 'F') {
- number += ((*str) - 'A' + 10) * multiplier;
- multiplier *= 16;
- }
- str--;
- }
- return number;
- }
-
- int wait_for_process(uint_t pid)
- {
- return _syscall(SYS_WAITFORPROCESS, pid, 0, 0, 0, 0);
- }
-
- int kill_process(uint_t pid)
- {
- return _syscall(SYS_KILLPROCESS, pid, 0, 0, 0, 0);
- }
-
- int redirect_out(uint_t pid, uint_t fid)
- {
- return _syscall(SYS_REDIRECTOUT, pid, fid, 0, 0, 0);
- }
-
- int foo()
- {
- return _syscall(SYS_FOO, 0, 0, 0, 0, 0);
- }
-
- int foo_enter()
- {
- return _syscall(SYS_FOO_ENTER, 0, 0, 0, 0, 0);
- }
-
- int foo_leave()
- {
- return _syscall(SYS_FOO_LEAVE, 0, 0, 0, 0, 0);
- }
-
- int try()
- {
- return _syscall(SYS_TRY, 0, 0, 0, 0, 0);
- }
-
- int exit_try()
- {
- return _syscall(SYS_EXITTRY, 0, 0, 0, 0, 0);
- }
-
- static struct apimod_base apimod_base = {
- .try = try,
- .exit_try = exit_try,
- .foo = foo,
- .foo_enter = foo_enter,
- .foo_leave = foo_leave,
- .get_version = get_version,
- .exit_process = exit_process,
- .release = release,
- .create_process = create_process,
- .get_current = get_current,
- .set_current = set_current,
- .get_arguments = get_arguments,
- .pause_process = pause_process,
- .resume_process = resume_process,
- .get_pages = get_pages,
- .free_pages = free_pages,
- .wait_for_process = wait_for_process,
- .kill_process = kill_process,
- .redirect_out = redirect_out,
- };
-
- static struct apimod_console apimod_console = {
- .printf = printf,
- .print = print,
- .read_input = read_input,
- .read_line = read_line,
- };
-
- static struct apimod_lib_string apimod_lib_string = {
- .length = string_length,
- .equals = string_equals,
- .copy = string_copy,
- .cat = string_cat,
- .separate = separate,
- .starts_with = string_starts_with,
- .ends_with = string_ends_with,
- .replace = string_replace,
- .vsnprintf = vsnprintf,
- .snprintf = snprintf,
- .to_lower = string_to_lower,
- .to_higher = string_to_higher,
- .dec_string = dec_string,
- .hex_string = hex_string,
- };
-
- static struct apimod_lib_memory apimod_memory = {
- .copy = memory_copy,
- .set = memory_set,
- .malloc = malloc,
- .free = free,
- .equals = memory_equals,
- };
-
- static struct apimod_fs apimod_fs = {
- .open = open,
- .close = close,
- .read = read,
- .write = write,
- .get_info = get_info,
- .change_state = change_state,
- .get_child = get_child,
- .next_child = next_child,
- .find_child = find_child,
- .get_parent = get_parent,
- .get_info1 = get_info1,
- .create = create,
- .delete = delete,
- .get_device = get_device,
- .next_device = next_device,
- };
-
- static struct apimod_fs1 apimod_fs1 = {
- .get_children = get_children,
- .free_children = free_children,
- .read_all_file = read_all_file,
- .write_all_file = write_all_file,
- .create_file = create_file,
- .delete_file = delete_file,
- };
-
- static struct apimod_ini apimod_ini = {
- .read = ini_read,
- .dispose = ini_dispose,
- .get_value = ini_get_value,
- .get_class = ini_get_class,
- };
-
- static struct apimod_string apimod_string = {
- .init = string_init,
- .append_char = string_append_char,
- .append = string_append,
- .init_from = string_init_from,
- .new = string_new,
- .deinit = string_deinit,
- .delete = string_delete,
- };
-
-
- /*
- * This is called by a user mode application to get any of the interfaces
- * defined above
- */
- int apimod_get_interface(char *name, void **interface)
- {
- if(string_equals(name, "console")) {
- *interface = &apimod_console;
- } else if(string_equals(name, "base")) {
- *interface = &apimod_base;
- } else if(string_equals(name, "lib_string")) {
- *interface = &apimod_lib_string;
- } else if(string_equals(name, "fs")) {
- *interface = &apimod_fs;
- } else if(string_equals(name, "memory")) {
- *interface = &apimod_memory;
- } else if(string_equals(name, "ini")) {
- *interface = &apimod_ini;
- } else if(string_equals(name, "fs1")) {
- *interface = &apimod_fs1;
- } else if(string_equals(name, "string")) {
- *interface = &apimod_string;
- } else {
- insane(EPARAM, "apimod_get_interface: Invalid interface requested: %s\n", name);
- }
- return 0;
- }