ADD_SUBDIRECTORY(src/tizenid)
ADD_SUBDIRECTORY(src/init_db)
ADD_SUBDIRECTORY(test)
+ADD_SUBDIRECTORY(tool)
IF(UNIX)
};
#define NUM_HASH_FILE 10
-static inline unsigned long simple_hash(char *str)
+static inline unsigned long simple_hash(const char *str)
{
unsigned long ret = 0;
int c;
* @brief It is not decided if it should be opened to public.
*/
typedef enum {
- SYSTEM_INFO_BOOL,
+ SYSTEM_INFO_TYPE_MIN = 0,
+ SYSTEM_INFO_BOOL = SYSTEM_INFO_TYPE_MIN,
SYSTEM_INFO_INT,
SYSTEM_INFO_DOUBLE,
SYSTEM_INFO_STRING,
+ SYSTEM_INFO_TYPE_MAX,
} system_info_type_e;
-
/**
* @internal
* @brief Enumeration for system information key.
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(uuid)
+BuildRequires: pkgconfig(libsyscommon)
BuildRequires: glibc-devel-static
Requires: security-config
%description test
A System Information test tool
+%package tool
+Summary: System-info command line tool package
+Group: Development/System
+Requires: %{name}
+
+%description tool
+A System Information command line tool
+
%if 0%{?gcov:1}
%package -n system-info-gcov
Summary: A System Information gcov test file
%files -n system-info-gcov
%{_datadir}/gcov/obj/*
%endif
+
+%files tool
+%{_bindir}/system-info-tool
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(TOOL_REQUIRED REQUIRED libsyscommon)
+
+SET(SYSTEM_INFO_TOOL "system-info-tool")
+FILE(GLOB SRCS "*.c")
+
+ADD_EXECUTABLE(${SYSTEM_INFO_TOOL} ${SRCS})
+SET_TARGET_PROPERTIES(${SYSTEM_INFO_TOOL} PROPERTIES COMPILE_FLAGS "-fPIE")
+ADD_DEPENDENCIES(${SYSTEM_INFO_TOOL} capi-system-info)
+TARGET_LINK_LIBRARIES(${SYSTEM_INFO_TOOL} capi-system-info ${TOOL_REQUIRED_LDFLAGS} -pie)
+
+INSTALL(TARGETS ${SYSTEM_INFO_TOOL} DESTINATION bin)
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "system-info-tool.h"
+#include "system-info-tool-get.h"
+
+void system_info_tool_get_help(void)
+{
+ printf(" -l|--list-all List all system-info database entries\n");
+ printf(" -g|--get KEY [-v|--verbose] Get value of feature KEY\n");
+ printf(" If -v option is given, shows result in detail\n");
+ printf(" ex) system-info-tool -g tizen.org/feature/display\n");
+ printf(" system-info-tool -g tizen.org/system/manufacturer -v\n");
+}
+
+static void print_dbentry(struct dbentry *dbentry, bool found)
+{
+ const struct db *db;
+
+ if (!dbentry || !dbentry->db)
+ return;
+
+ db = dbentry->db;
+
+ if (found) {
+ printf("%s Key (%c) found: ", db->name, db->ticker);
+ } else {
+ printf("%s Key (%c) not found\n", db->name, db->ticker);
+ return;
+ }
+
+ print_value(dbentry->value);
+}
+
+int system_info_tool_get_raw(const char *searchkey, system_info_type_e searchtype,
+ enum db_e searchdb, struct dbentry *dbentry)
+{
+ char dbpath[BUFFER_MAX - 1];
+ char dbentry_format[BUFFER_MAX];
+ int retval;
+
+ if (!dbentry)
+ return -EINVAL;
+
+ if (searchdb < DB_START || searchdb >= DB_END)
+ return -EINVAL;
+
+ dbentry->db = &db[searchdb];
+
+ /* scanf format: "%127[^:]:%127[^:]:%127s %127s" */
+ snprintf(dbentry_format, sizeof(dbentry_format), "%%%d[^:]:%%%d[^:]:%%%ds %%%ds",
+ BUFFER_MAX - 1, BUFFER_MAX - 1, BUFFER_MAX - 1, BUFFER_MAX - 1);
+
+ for (int i = 0; i < NUM_HASH_FILE; ++i) {
+ __auto_fclose__ FILE *fp = NULL;
+ char line[BUFFER_MAX * 8] = {0, };
+ char tag[BUFFER_MAX - 1] = {0, };
+ char key[BUFFER_MAX - 1] = {0, };
+ char type[BUFFER_MAX - 1] = {0, };
+ char value[BUFFER_MAX - 1] = {0, };
+ const char *typestring;
+
+ snprintf(dbpath, sizeof(dbpath), "%s/%d", db[searchdb].path, i);
+ fp = fopen(dbpath, "r");
+ if (!fp)
+ continue;
+
+ while ((fgets(line, sizeof(line), fp))) {
+ retval = sscanf(line, dbentry_format, tag, key, type, value);
+ if (retval != 4)
+ continue;
+
+ if (strncmp(key, searchkey, strlen(key) + 1))
+ continue;
+
+ typestring = type_to_string(searchtype);
+ if (strncmp(type, typestring, strlen(type) + 1))
+ continue;
+
+ strncpy(dbentry->key, key, sizeof(dbentry->key) - 1);
+ strncpy(dbentry->tag, tag, sizeof(dbentry->tag) - 1);
+ dbentry->value.type = searchtype;
+ if (strncmp(type, "bool", sizeof("bool")) == 0)
+ dbentry->value.b = (value[runtime_env] == 'T');
+ else if (strncmp(type, "int", sizeof("int")) == 0)
+ dbentry->value.i = atoi(value);
+ else if (strncmp(type, "double", sizeof("double")) == 0)
+ dbentry->value.d = atof(value);
+ else if (strncmp(type, "string", sizeof("string")) == 0)
+ dbentry->value.s = strndup(value, sizeof(value));
+
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+static int system_info_tool_get_api(const char *key, struct value *value)
+{
+ int retval;
+ int ret;
+ int match = 0;
+ int select;
+ int i;
+
+ struct cache {
+ int match;
+ struct value value;
+ } cache[SYSTEM_INFO_TYPE_MAX] = {
+ { -1, { SYSTEM_INFO_BOOL, } },
+ { -1, { SYSTEM_INFO_INT, } },
+ { -1, { SYSTEM_INFO_DOUBLE, } },
+ { -1, { SYSTEM_INFO_STRING, } },
+ };
+
+ retval = system_info_get_platform_bool(key, &cache[SYSTEM_INFO_BOOL].value.b);
+ if (retval == 0)
+ cache[SYSTEM_INFO_BOOL].match = ++match;
+
+ retval = system_info_get_platform_int(key, &cache[SYSTEM_INFO_INT].value.i);
+ if (retval == 0)
+ cache[SYSTEM_INFO_INT].match = ++match;
+
+ retval = system_info_get_platform_double(key, &cache[SYSTEM_INFO_DOUBLE].value.d);
+ if (retval == 0)
+ cache[SYSTEM_INFO_DOUBLE].match = ++match;
+
+ retval = system_info_get_platform_string(key, &cache[SYSTEM_INFO_STRING].value.s);
+ if (retval == 0)
+ cache[SYSTEM_INFO_STRING].match = ++match;
+
+ if (match == 1) {
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i)
+ if (cache[i].match == match)
+ memcpy(value, &cache[i].value, sizeof(struct value));
+ return 0;
+ } else if (match > 1) {
+ printf("There is multiple same keys with different type. Which type to search?\n");
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i)
+ if (cache[i].match > 0) {
+ printf(" [%d] ", cache[i].match);
+ print_value(cache[i].value);
+ }
+
+ printf("Select: ");
+ retval = scanf("%d", &select);
+ if (retval != 1) {
+ printf("Invalid selection\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i) {
+ if (cache[i].match == select) {
+ memcpy(value, &cache[i].value, sizeof(struct value));
+ return 0;
+ }
+ }
+
+ if (i == SYSTEM_INFO_TYPE_MAX) {
+ printf("Invalid selection\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ printf("key=%s is not found\n", key);
+ ret = -ENOENT;
+
+out:
+ free(cache[SYSTEM_INFO_STRING].value.s);
+
+ return ret;
+}
+
+void system_info_tool_get(const char *key, bool verbose)
+{
+ struct value api;
+ int retval;
+
+ retval = system_info_tool_get_api(key, &api);
+ if (retval < 0)
+ return;
+
+ /* show each database if -v option is given */
+ if (verbose) {
+ int retplt;
+ int rethal;
+ int retusr;
+
+ /* set db to be searched */
+ __auto_free_dbentry__ struct dbentry plt = { 0, }; /* scan platform ro db */
+ __auto_free_dbentry__ struct dbentry hal = { 0, }; /* scan platform hal ro db */
+ __auto_free_dbentry__ struct dbentry usr = { 0, }; /* scan platform rw db */
+
+ retplt = system_info_tool_get_raw(key, api.type, DB_DEFAULT_RO, &plt);
+ print_dbentry(&plt, retplt == 0);
+
+ rethal = system_info_tool_get_raw(key, api.type, DB_HAL_RO, &hal);
+ print_dbentry(&hal, rethal == 0);
+
+ retusr = system_info_tool_get_raw(key, api.type, DB_DEFAULT_RW, &usr);
+ print_dbentry(&usr, retusr == 0);
+
+ /* print description how API have derived the result */
+ if (retusr == 0) {
+ printf("Result (=%c overrides %c,%c): ", usr.db->ticker, plt.db->ticker, hal.db->ticker);
+ } else if (retplt == 0 && rethal == 0) {
+ if (plt.value.type == SYSTEM_INFO_BOOL && hal.value.type == SYSTEM_INFO_BOOL)
+ printf("Result (=%c && %c): ", plt.db->ticker, hal.db->ticker);
+ else
+ printf("Result (=%c overrides %c): ", hal.db->ticker, plt.db->ticker);
+ } else if (retplt == 0) {
+ printf("Result (=%c): ", plt.db->ticker);
+ } else if (rethal == 0) {
+ printf("Result (=%c): ", hal.db->ticker);
+ } else {
+ printf("Result (error occured): ");
+ }
+ }
+
+ print_value(api);
+
+ return;
+}
+
+void system_info_tool_list_all(enum db_e dbtype)
+{
+ char dbpath[BUFFER_MAX - 1];
+ char dbentry_format[BUFFER_MAX];
+ int retval;
+
+ if (access(db[dbtype].path, F_OK) != 0)
+ return;
+
+ /* scanf format: "%127[^:]:%127[^:]:%127s %127s" */
+ snprintf(dbentry_format, sizeof(dbentry_format), "%%%d[^:]:%%%d[^:]:%%%ds %%%ds",
+ BUFFER_MAX - 1, BUFFER_MAX - 1, BUFFER_MAX - 1, BUFFER_MAX - 1);
+
+ for (int i = 0; i < NUM_HASH_FILE; ++i) {
+ __auto_fclose__ FILE *fp = NULL;
+ char line[BUFFER_MAX * 8] = {0, };
+ char tag[BUFFER_MAX - 1] = {0, };
+ char key[BUFFER_MAX - 1] = {0, };
+ char type[BUFFER_MAX - 1] = {0, };
+ char value[BUFFER_MAX - 1] = {0, };
+
+ snprintf(dbpath, sizeof(dbpath), "%s/%d", db[dbtype].path, i);
+ fp = fopen(dbpath, "r");
+ if (!fp)
+ continue;
+
+ while ((fgets(line, sizeof(line), fp))) {
+ retval = sscanf(line, dbentry_format, tag, key, type, value);
+ if (retval != 4)
+ continue;
+
+ printf("%s: ", db[dbtype].name);
+ printf("key=%s, ", key);
+ printf("type=%s, ", type);
+ if (strncmp(type, "bool", sizeof("bool")) == 0)
+ printf("value=%d, ", (value[runtime_env] == 'T'));
+ else
+ printf("value=%s, ", value);
+ printf("tag=%s\n", tag);
+ }
+ }
+}
--- /dev/null
+#ifndef __SYSTEM_INFO_TOOL_GET_H__
+#define __SYSTEM_INFO_TOOL_GET_H__
+
+#include <stdbool.h>
+
+void system_info_tool_get_help(void);
+void system_info_tool_get(const char *key, bool verbose);
+int system_info_tool_get_raw(const char *searchkey, system_info_type_e searchtype,
+ enum db_e searchdb, struct dbentry *dbentry);
+void system_info_tool_list_all(enum db_e dbtype);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <sys/file.h>
+
+#include "system-info-tool.h"
+#include "system-info-tool-get.h"
+#include "system-info-tool-set.h"
+
+void system_info_tool_set_help(void)
+{
+ printf(" -s|--set KEY TYPE VALUE Add or update user-defined KEY\n");
+ printf(" Available TYPE: bool, int, double, string\n");
+ printf(" ex) system-info-tool -a tizen.org/feature/display bool 1\n");
+ printf(" system-info-tool -a tizen.org/system/manufacturer string Tizen\n");
+ printf(" -c|--clear KEY Clear user-defined KEY. This cannot clear read-only system key\n");
+ printf(" -C|--clear-all Clear all user-defined keys\n");
+}
+
+static int convert_raw_optargs(const char *rawtype, const char *rawvalue, struct value *out)
+{
+ system_info_type_e type = string_to_type(rawtype);
+
+ if (type == SYSTEM_INFO_TYPE_MAX) {
+ printf("Invalid type \"%s\"\n", rawtype);
+ return -EINVAL;
+ }
+
+ out->type = type;
+
+ if (type == SYSTEM_INFO_BOOL) {
+ int tmpbool;
+ if (sscanf(rawvalue, "%d", &tmpbool) == 1) {
+ out->b = tmpbool;
+ return 0;
+ } else if (strncasecmp(rawvalue, "true", sizeof("true")) == 0) {
+ out->b = true;
+ return 0;
+ } else if (strncasecmp(rawvalue, "false", sizeof("false")) == 0) {
+ out->b = false;
+ return 0;
+ }
+ printf("Invalid bool value \"%s\"\n", rawvalue);
+ } else if (type == SYSTEM_INFO_INT) {
+ if (sscanf(rawvalue, "%d", &out->i) == 1)
+ return 0;
+ printf("Invalid int value \"%s\"\n", rawvalue);
+ } else if (type == SYSTEM_INFO_DOUBLE) {
+ if (sscanf(rawvalue, "%lf", &out->d) == 1)
+ return 0;
+ printf("Invalid double value \"%s\"\n", rawvalue);
+ } else if (type == SYSTEM_INFO_STRING) {
+ out->s = strndup(rawvalue, BUFFER_MAX);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int try_flock(FILE *fp, bool blocking)
+{
+ int fd = -1;
+ int retval;
+ int flags = LOCK_EX;
+
+ if (!fp)
+ return -EBADF;
+
+ fd = fileno(fp);
+ if (fd < 0)
+ return -errno;
+
+ if (blocking == false)
+ flags |= LOCK_NB;
+
+ retval = flock(fd, flags);
+ if (retval != 0) {
+ if (errno == EWOULDBLOCK)
+ printf("User-defined database is now being accessed by someone. Try again\n");
+ else
+ printf("Failed to acquire exclusive flock, %m\n");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int add_new_entry(const char *key, struct value value)
+{
+ char dbpath[BUFFER_MAX];
+ char internal_key[BUFFER_MAX] = {0, };
+ char internal_value[BUFFER_MAX] = {0, };
+ int retval;
+ __auto_fclose__ FILE *fp = NULL;
+
+ if (!key)
+ return -EINVAL;
+
+ /* make internal_key */
+ snprintf(internal_key, sizeof(internal_key), "platform:%s:%s", key, type_to_string(value.type));
+
+ /* make internal_value */
+ if (value.type == SYSTEM_INFO_BOOL) {
+ if (value.b == true)
+ snprintf(internal_value, sizeof(internal_value), "TTTTTTTT");
+ else
+ snprintf(internal_value, sizeof(internal_value), "FFFFFFFF");
+ } else if (value.type == SYSTEM_INFO_INT) {
+ snprintf(internal_value, sizeof(internal_value), "%d", value.i);
+ } else if (value.type == SYSTEM_INFO_DOUBLE) {
+ snprintf(internal_value, sizeof(internal_value), "%lf", value.d);
+ } else if (value.type == SYSTEM_INFO_STRING) {
+ snprintf(internal_value, sizeof(internal_value), "%s", value.s);
+ } else {
+ return -EINVAL;
+ }
+
+ snprintf(dbpath, sizeof(dbpath), "%s/%lu", SYSTEM_INFO_DB_RW_PATH, simple_hash(internal_key));
+ fp = fopen(dbpath, "a");
+ if (!fp)
+ return -errno;
+
+ retval = try_flock(fp, false);
+ if (retval < 0)
+ return retval;
+
+ retval = fprintf(fp, "%s %s\n", internal_key, internal_value);
+ if (retval < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int remove_entry(const char *key, system_info_type_e type)
+{
+ char dbpath[BUFFER_MAX];
+ char backup[BUFFER_MAX];
+ char internal_key[BUFFER_MAX];
+ char line[BUFFER_MAX * 8];
+ char readkey[BUFFER_MAX];
+ char readtype[BUFFER_MAX];
+ __auto_fclose__ FILE *fp1 = NULL;
+ __auto_fclose__ FILE *fp2 = NULL;
+ int retval;
+
+ if (!key)
+ return -EINVAL;
+
+ if (type < SYSTEM_INFO_TYPE_MIN || type >= SYSTEM_INFO_TYPE_MAX)
+ return -EINVAL;
+
+ /* make internal_key */
+ snprintf(internal_key, sizeof(internal_key), "platform:%s:%s", key, type_to_string(type));
+
+ snprintf(dbpath, sizeof(dbpath), "%s/%lu", SYSTEM_INFO_DB_RW_PATH, simple_hash(internal_key));
+ fp1 = fopen(dbpath, "r+");
+ if (!fp1)
+ return -errno;
+
+ retval = try_flock(fp1, false);
+ if (retval < 0)
+ return retval;
+
+ snprintf(backup, sizeof(backup), "%s/.backup.%lu", SYSTEM_INFO_DB_RW_PATH, simple_hash(internal_key));
+ fp2 = fopen(backup, "w+");
+ if (!fp2)
+ return -errno;
+
+ while ((fgets(line, sizeof(line), fp1))) {
+ retval = sscanf(line, "platform:%127s:%127s", readkey, readtype);
+ if (retval != 2)
+ continue;
+
+ if (strncmp(readkey, key, sizeof(readkey)) == 0
+ && string_to_type(readtype) == type)
+ continue;
+
+ fprintf(fp2, "%s", line);
+ }
+
+ if (truncate(dbpath, 0) < 0)
+ printf("Failed to reset database, %m\n");
+
+ rewind(fp1);
+ rewind(fp2);
+
+ while ((fgets(line, sizeof(line), fp2)))
+ fprintf(fp1, "%s", line);
+
+ unlink(backup);
+
+ return 0;
+}
+
+static int modify_entry(const char *key, struct value value)
+{
+ int ret;
+
+ ret = remove_entry(key, value.type);
+ if (ret < 0)
+ return ret;
+
+ return add_new_entry(key, value);
+}
+
+static int system_info_tool_set_entry(const char *key, struct value value)
+{
+ __auto_free_dbentry__ struct dbentry dbentry = {0, };
+ int retval;
+
+ if (!key)
+ return -EINVAL;
+
+ retval = system_info_tool_get_raw(key, value.type, DB_DEFAULT_RW, &dbentry);
+ if (retval == 0)
+ return modify_entry(key, value);
+ else
+ return add_new_entry(key, value);
+}
+
+static int system_info_tool_init_rw_database(void)
+{
+ return system("/usr/bin/mkdir -p "SYSTEM_INFO_DB_RW_PATH);
+}
+
+int system_info_tool_set(int argc, char *argv[])
+{
+ int ret;
+ char *key;
+ struct value value;
+
+ /* argv[optind] : key
+ * argv[optind + 1]: type
+ * argv[optind + 2]: value
+ * check if there is at least 3 arguments */
+ if (argc - optind < 3) {
+ printf("Need key, type, value\n");
+ return -EINVAL;
+ }
+
+ if (access(SYSTEM_INFO_DB_RW_PATH, F_OK) != 0) {
+ ret = system_info_tool_init_rw_database();
+ if (ret != 0)
+ return -ENOTSUP;
+ }
+
+ key = argv[optind];
+ ret = convert_raw_optargs(argv[optind + 1], argv[optind + 2], &value);
+ if (ret < 0)
+ return ret;
+
+ return system_info_tool_set_entry(key, value);
+}
+
+int system_info_tool_clear_key(const char *key)
+{
+ int retval;
+ int ret;
+ int match = 0;
+ int i;
+ int select;
+
+ struct cache {
+ int match;
+ struct dbentry dbentry;
+ } cache[SYSTEM_INFO_TYPE_MAX] = {
+ { -1, },
+ { -1, },
+ { -1, },
+ { -1, },
+ };
+
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i) {
+ retval = system_info_tool_get_raw(key, i, DB_DEFAULT_RW, &cache[i].dbentry);
+ if (retval == 0)
+ cache[i].match = ++match;
+ }
+
+ if (match == 1) {
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i) {
+ if (cache[i].match == match) {
+ ret = remove_entry(cache[i].dbentry.key, cache[i].dbentry.value.type);
+ goto out;
+ }
+ }
+ } else if (match > 1) {
+ printf("There is multiple same keys with different type. Which type to clear?\n");
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i)
+ if (cache[i].match > 0) {
+ printf(" [%d] ", cache[i].match);
+ print_value(cache[i].dbentry.value);
+ }
+
+ printf("Select: ");
+ retval = scanf("%d", &select);
+ if (retval != 1) {
+ printf("Invalid selection\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < SYSTEM_INFO_TYPE_MAX; ++i) {
+ if (cache[i].match == select) {
+ ret = remove_entry(cache[i].dbentry.key, cache[i].dbentry.value.type);
+ goto out;
+ }
+ }
+ }
+
+ printf("user-defined key=%s is not found\n", key);
+ ret = -ENOENT;
+
+out:
+ if (cache[SYSTEM_INFO_STRING].match > 0)
+ free(cache[SYSTEM_INFO_STRING].dbentry.value.s);
+
+ return ret;
+}
+
+void system_info_tool_clear_all(void)
+{
+ char dbpath[BUFFER_MAX];
+ int retval;
+
+ for (int i = 0; i < NUM_HASH_FILE; ++i) {
+ __auto_fclose__ FILE *fp = NULL;
+ snprintf(dbpath, sizeof(dbpath), "%s/%d", SYSTEM_INFO_DB_RW_PATH, i);
+ fp = fopen(dbpath, "r");
+ if (!fp)
+ continue;
+
+ retval = try_flock(fp, true);
+ if (retval < 0)
+ continue;
+
+ if (truncate(dbpath, 0) < 0)
+ printf("Failed to reset database, %m\n");
+ unlink(dbpath);
+ }
+}
--- /dev/null
+#ifndef __SYSTEM_INFO_TOOL_SET_H__
+#define __SYSTEM_INFO_TOOL_SET_H__
+
+void system_info_tool_set_help(void);
+int system_info_tool_set(int argc, char *argv[]);
+int system_info_tool_clear_key(const char *key);
+void system_info_tool_clear_all(void);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <libsyscommon/list.h>
+
+#include "system-info-tool.h"
+#include "system-info-tool-get.h"
+#include "system-info-tool-set.h"
+
+int runtime_env = C;
+const struct db db[DB_END] = {
+/* { dbpath, dbname, ticker } */
+ [DB_DEFAULT_RO] = { SYSTEM_INFO_DB_RO_PATH, "Platform", 'A' },
+ [DB_HAL_RO] = { SYSTEM_INFO_HAL_DB_RO_PATH, "HAL", 'B' },
+ [DB_DEFAULT_RW] = { SYSTEM_INFO_DB_RW_PATH, "User-defined", 'C' },
+};
+
+static const char *__type_to_string[SYSTEM_INFO_TYPE_MAX] = {
+ [SYSTEM_INFO_BOOL] = "bool",
+ [SYSTEM_INFO_INT] = "int",
+ [SYSTEM_INFO_DOUBLE] = "double",
+ [SYSTEM_INFO_STRING] = "string",
+};
+
+const char *type_to_string(system_info_type_e type)
+{
+ if (type < SYSTEM_INFO_TYPE_MIN || type >= SYSTEM_INFO_TYPE_MAX)
+ return NULL;
+
+ return __type_to_string[type];
+}
+
+system_info_type_e string_to_type(const char *type)
+{
+ if (strncasecmp(type, "bool", sizeof("bool")) == 0)
+ return SYSTEM_INFO_BOOL;
+ else if (strncasecmp(type, "int", sizeof("int")) == 0)
+ return SYSTEM_INFO_INT;
+ else if (strncasecmp(type, "double", sizeof("double")) == 0)
+ return SYSTEM_INFO_DOUBLE;
+ else if (strncasecmp(type, "string", sizeof("string")) == 0)
+ return SYSTEM_INFO_STRING;
+ else
+ return SYSTEM_INFO_TYPE_MAX;
+}
+
+void print_value(struct value value)
+{
+ if (value.type == SYSTEM_INFO_BOOL)
+ printf("type=bool, value=%d\n", value.b);
+ else if (value.type == SYSTEM_INFO_INT)
+ printf("type=int, value=%d\n", value.i);
+ else if (value.type == SYSTEM_INFO_DOUBLE)
+ printf("type=double, value=%f\n", value.d);
+ else if (value.type == SYSTEM_INFO_STRING)
+ printf("type=string, value=%s\n", value.s);
+ else
+ printf("type=inavlid, error\n");
+}
+
+static void system_info_tool_show_help(void)
+{
+ printf("USAGE\n");
+ printf(" system-into-tool [OPTION]\n\n");
+ printf("OPTION\n");
+ system_info_tool_get_help();
+ system_info_tool_set_help();
+ printf(" -h|--help Show this help\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ int retval;
+ char *runtime_str;
+ char *key;
+ bool verbose = false;
+ GList *keys = NULL;
+ GList *elem;
+
+ if (argc < 2) {
+ system_info_tool_show_help();
+ return 1;
+ }
+
+ runtime_str = getenv("RUNTIME_TYPE");
+ if (runtime_str) {
+ for (int i = 0; runtime[i].lang != LANG_MAX; ++i) {
+ if (strncmp(runtime[i].runtime_type, runtime_str, strlen(runtime_str) + 1) == 0) {
+ runtime_env = runtime[i].lang;
+ break;
+ }
+ }
+ }
+
+ const struct option long_option[] = {
+ { "get", required_argument, NULL, 'g' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "list-all", no_argument, NULL, 'l' },
+ { "set" , no_argument, NULL, 's' }, /* requires 3 arguments */
+ { "clear", required_argument, NULL, 'c' },
+ { "clear-all", no_argument, NULL, 'C' },
+ { "help", no_argument, NULL, 'h' },
+ { 0, 0, 0, 0 },
+ };
+
+ for (;;) {
+ opt = getopt_long(argc, argv, "g:vlsc:Ch", long_option, NULL);
+ if (opt < 0)
+ break;
+ switch (opt) {
+ case 'g':
+ SYS_G_LIST_APPEND(keys, strdup(optarg));
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'l':
+ for (int i = DB_START; i < DB_END; ++i)
+ system_info_tool_list_all(i);
+ break;
+ case 's':
+ retval = system_info_tool_set(argc, argv);
+ if (retval < 0) {
+ printf("Failed to set key\n");
+ system_info_tool_set_help();
+ return 1;
+ }
+ optind += 3; /* manually consume 3 arguments */
+ break;
+ case 'c':
+ system_info_tool_clear_key(optarg);
+ break;
+ case 'C':
+ system_info_tool_clear_all();
+ break;
+ case 'h':
+ system_info_tool_show_help();
+ break;
+ default:
+ system_info_tool_show_help();
+ break;
+ }
+ }
+
+ SYS_G_LIST_FOREACH(keys, elem, key) {
+ system_info_tool_get(key, verbose);
+ free(key);
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef __SYSTEM_INFO_TOOL_H__
+#define __SYSTEM_INFO_TOOL_H__
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <system_info.h>
+#include <system_info_type.h>
+#include <system_info_private.h>
+
+#define BUFFER_MAX 128
+
+enum db_e {
+ DB_START = 0,
+ DB_DEFAULT_RO = DB_START,
+ DB_HAL_RO,
+ DB_DEFAULT_RW,
+ DB_END,
+};
+
+struct db {
+ const char *path;
+ const char *name;
+ const char ticker;
+};
+extern const struct db db[DB_END];
+
+struct value {
+ system_info_type_e type;
+ union {
+ bool b;
+ int i;
+ double d;
+ char *s;
+ };
+};
+
+struct dbentry {
+ const struct db *db;
+ char tag[BUFFER_MAX];
+ char key[BUFFER_MAX];
+ struct value value;
+};
+
+extern int runtime_env;
+
+static inline void fclosep(FILE **fp)
+{
+ if (*fp)
+ fclose(*fp);
+}
+#define __auto_fclose__ __attribute__((cleanup(fclosep)))
+
+static inline void closep(int *fd)
+{
+ if (*fd >= 0)
+ close(*fd);
+}
+#define __auto_close__ __attribute__((cleanup(closep)))
+
+static inline void free_value(struct value *v)
+{
+ if (v->type == SYSTEM_INFO_STRING)
+ free(v->s);
+}
+#define __auto_free_value__ __attribute__((cleanup(free_value)))
+
+static inline void free_dbentry(struct dbentry *entry)
+{
+ if (entry->value.type == SYSTEM_INFO_STRING)
+ free(entry->value.s);
+}
+#define __auto_free_dbentry__ __attribute__((cleanup(free_dbentry)))
+
+
+const char *type_to_string(system_info_type_e type);
+system_info_type_e string_to_type(const char *type);
+void print_value(struct value value);
+
+#endif