/* * Copyright (c) 2006 Jakub Vana * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup generic * @{ */ /** @file */ #include #include #include #include sysinfo_item_t *_root = NULL; static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree) { if (subtree == NULL) return NULL; while (subtree != NULL) { int i = 0; char *a = (char *) name; char *b = subtree->name; while ((a[i] == b[i]) && (b[i])) i++; if ((!a[i]) && (!b[i])) /* Last name in path matches */ return subtree; if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) return sysinfo_find_item(a + i + 1, subtree->subinfo.table); //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ // return NULL; return NULL; /* No subinfo */ } /* No matches try next */ subtree = subtree->next; i = 0; } return NULL; } static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree) { sysinfo_item_t *subtree; subtree = *psubtree; if (subtree == NULL) { sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); int i = 0, j; ASSERT(item); *psubtree = item; item->next = NULL; item->val_type = SYSINFO_VAL_UNDEFINED; item->subinfo.table = NULL; while (name[i] && (name[i] != '.')) i++; item->name = malloc(i, 0); ASSERT(item->name); for (j = 0; j < i; j++) item->name[j] = name[j]; item->name[j] = 0; if (name[i]) { /* =='.' */ item->subinfo_type = SYSINFO_SUBINFO_TABLE; return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); } item->subinfo_type = SYSINFO_SUBINFO_NONE; return item; } while (subtree != NULL) { int i = 0, j; char *a = (char *) name; char *b = subtree->name; while ((a[i] == b[i]) && (b[i])) i++; if ((!a[i]) && (!b[i])) /* Last name in path matches */ return subtree; if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table)); if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) { subtree->subinfo_type = SYSINFO_SUBINFO_TABLE; return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table)); } //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ // return NULL; return NULL; } /* No matches try next or create new*/ if (subtree->next == NULL) { sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); ASSERT(item); subtree->next = item; item->next = NULL; item->val_type = SYSINFO_VAL_UNDEFINED; item->subinfo.table = NULL; i = 0; while (name[i] && (name[i] != '.')) i++; item->name = malloc(i, 0); ASSERT(item->name); for (j = 0; j < i; j++) item->name[j] = name[j]; item->name[j] = 0; if(name[i]) { /* =='.' */ item->subinfo_type = SYSINFO_SUBINFO_TABLE; return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); } item->subinfo_type = SYSINFO_SUBINFO_NONE; return item; } else { subtree = subtree->next; i = 0; } } panic("Not reached\n"); return NULL; } void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val) { if (root == NULL) root = &_root; /* If already created create only returns pointer If not, create it */ sysinfo_item_t *item = sysinfo_create_path(name, root); if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ item->val.val=val; item->val_type = SYSINFO_VAL_VAL; } } void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn) { if (root == NULL) root = &_root; /* If already created create only returns pointer If not, create it */ sysinfo_item_t *item = sysinfo_create_path(name, root); if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ item->val.fn=fn; item->val_type = SYSINFO_VAL_FUNCTION; } } void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) { if (root == NULL) root = &_root; /* If already created create only returns pointer If not, create it */ sysinfo_item_t *item = sysinfo_create_path(name, root); if (item != NULL) item->val_type = SYSINFO_VAL_UNDEFINED; } void sysinfo_dump(sysinfo_item_t **proot, int depth) { sysinfo_item_t *root; if (proot == NULL) proot = &_root; root = *proot; while (root != NULL) { int i; unative_t val = 0; char *vtype = NULL; for (i = 0; i < depth; i++) printf(" "); switch (root->val_type) { case SYSINFO_VAL_UNDEFINED: val = 0; vtype = "UND"; break; case SYSINFO_VAL_VAL: val = root->val.val; vtype = "VAL"; break; case SYSINFO_VAL_FUNCTION: val = ((sysinfo_val_fn_t) (root->val.fn)) (root); vtype = "FUN"; break; } printf("%s %s val:%d(%x) sub:%s\n", root->name, vtype, val, val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? "TAB" : "FUN")); if (root->subinfo_type == SYSINFO_SUBINFO_TABLE) sysinfo_dump(&(root -> subinfo.table), depth + 1); root = root->next; } } sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root) { // TODO: Implement Subsystem subinfo (by function implemented subinfo) sysinfo_rettype_t ret = {0, false}; if (root == NULL) root = &_root; sysinfo_item_t *item = sysinfo_find_item(name, *root); if (item != NULL) { if (item->val_type == SYSINFO_VAL_UNDEFINED) return ret; else ret.valid = true; if (item->val_type == SYSINFO_VAL_VAL) ret.val = item->val.val; else ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item); } return ret; } unative_t sys_sysinfo_valid(unative_t ptr, unative_t len) { char *str; sysinfo_rettype_t ret = {0, 0}; str = malloc(len + 1, 0); ASSERT(str); if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) ret = sysinfo_get_val(str, NULL); free(str); return ret.valid; } unative_t sys_sysinfo_value(unative_t ptr, unative_t len) { char *str; sysinfo_rettype_t ret = {0, 0}; str = malloc(len + 1, 0); ASSERT(str); if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) ret = sysinfo_get_val(str, NULL); free(str); return ret.val; } /** @} */