2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
29 #include <system_info.h>
30 #include <iniparser.h>
31 #include <libxml/xmlmemory.h>
32 #include <libxml/parser.h>
33 #include <libxml/tree.h>
35 #include "system_info_private.h"
41 #define LOG_TAG "SYSTEM_INFO"
42 #define _D(fmt, args...) SLOGD(fmt, ##args)
43 #define _E(fmt, args...) SLOGE(fmt, ##args)
44 #define _I(fmt, args...) SLOGI(fmt, ##args)
46 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
50 #define MODEL_CONFIG_TAG "model-config"
51 #define KEY_PREFIX "http://"
53 extern const struct runtime runtime[LANG_MAX];
55 static int db_set_value(const char *db_path, char *tag, char *name, char *type, char *value, int val_len)
58 char key_internal[KEY_MAX];
59 size_t key_internal_len;
60 char file_path[PATH_MAX];
61 char file_path_new[PATH_MAX * 2];
68 if (!db_path || !tag || !name || !type || !value)
71 if (name == strstr(name, KEY_PREFIX))
72 snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name + strlen(KEY_PREFIX), type);
74 snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name, type);
75 snprintf(file_path, sizeof(file_path), "%s/%lu", db_path, simple_hash(key_internal));
77 fp = fopen(file_path, "r+");
79 _E("fopen for %s failed (%d)", file_path, errno);
83 key_internal_len = strlen(key_internal);
85 while ((ptr = fgets(buf, sizeof(buf), fp))) {
86 if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ')
91 // 1. Insert new value
93 ret = fprintf(fp, "%s %s\n", key_internal, value);
97 _E("fprintf for %s failed (%d)", file_path, errno);
101 _I("DB: value (key:%s,value:%s) is stored", name, value);
105 // 2. Make new file to update value
106 snprintf(file_path_new, sizeof(file_path_new), "%s_tmp", file_path);
107 fp_new = fopen(file_path_new, "w");
109 _E("fopen for %s failed (%d)", file_path_new, errno);
116 for (int i = 0; i < key_idx; i++) {
117 if (!fgets(buf, sizeof(buf), fp)) {
118 _E("fgets for %s failed", file_path);
122 if (fputs(buf, fp_new) == EOF) {
123 _E("fputs for %s failed", file_path_new);
129 // 2-2. Insert new value
130 ret = fprintf(fp_new, "%s %s\n", key_internal, value);
132 _E("fprintf for %s failed (%d)", file_path_new, errno);
137 // To move position indicator
138 if (!fgets(buf, sizeof(buf), fp)) {
139 _E("fgets for %s failed", file_path);
145 while (fgets(buf, sizeof(buf), fp)) {
146 if (fputs(buf, fp_new) == EOF) {
147 _E("fputs for %s failed", file_path_new);
153 // 2-4. Overwrite file
154 ret = rename(file_path_new, file_path);
156 _E("rename for %s failed (%d)", file_path_new, errno);
161 _I("DB: value (key:%s,value:%s) is updated", name, value);
173 static int db_get_value(const char *db_path, char *tag, char *name, char *type, char *value, int val_len)
175 char key_internal[KEY_MAX];
176 size_t key_internal_len;
178 size_t value_internal_len;
182 if (!db_path || !tag || !name || !type || !value)
185 if (name == strstr(name, KEY_PREFIX))
186 snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name + strlen(KEY_PREFIX), type);
188 snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name, type);
189 snprintf(buf, sizeof(buf), "%s/%lu", db_path, simple_hash(key_internal));
191 fp = fopen(buf, "r");
193 _E("fopen for %s failed (%d)", buf, errno);
197 key_internal_len = strlen(key_internal);
198 while ((ptr = fgets(buf, sizeof(buf), fp))) {
199 if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ') {
200 value_internal_len = strcspn(buf + key_internal_len + 1, "\n") + 1;
201 snprintf(value, val_len < value_internal_len ? val_len : value_internal_len,
202 "%s", buf + key_internal_len + 1);
209 _E("fgets for %s failed", key_internal);
213 _I("DB: value (key:%s,value:%s) is fetched", name, value);
218 static int db_set_value_specific_runtime(const char *db_path, char *tag, char *name, char *type, char *value, int lang)
220 char value_intg[LANG_MAX + 1] = {0};
223 ret = db_get_value(db_path, tag, name, type, value_intg, LANG_MAX + 1);
227 value_intg[lang] = (value[0] == 't' ? 'T' : 'F');
228 ret = db_set_value(db_path, tag, name, type, value_intg, LANG_MAX);
233 static int db_set_value_foreach_runtime(const char *db_path, xmlNode *node,
234 char *tag, char *name, char *type, char *value)
238 char value_intg[LANG_MAX + 1] = {0};
241 memset(value_intg, strncmp(value, "true", 4) ? 'F' : 'T', LANG_MAX);
243 for (rt = 0; rt < LANG_MAX; rt++) {
244 if (!runtime[rt].xml_prop)
247 prop_val = xmlGetProp(node, (xmlChar *)(runtime[rt].xml_prop));
251 value_intg[runtime[rt].lang] = xmlStrcmp(prop_val, (xmlChar *)"on") ? 'F' : 'T';
256 ret = db_set_value(db_path, tag, name, type, value_intg, LANG_MAX);
261 static int system_info_get_values_config_xml(const char *db_path, const char *path)
265 xmlNode *cur_node, *tag_node;
266 char *tag, *name, *type, *value;
272 doc = xmlParseFile(path);
274 _E("cannot file open %s file!!!", path);
275 return SYSTEM_INFO_ERROR_IO_ERROR;
278 cur = xmlDocGetRootElement(doc);
280 _E("empty document %s file!!!", path);
285 for (cur_node = cur; cur_node ; cur_node = cur_node->next) {
286 if (!xmlStrcmp(cur->name, (const xmlChar*)MODEL_CONFIG_TAG))
290 _E("cannot find %s root element file!!!", MODEL_CONFIG_TAG);
295 cur = cur_node->xmlChildrenNode;
296 for (tag_node = cur; tag_node; tag_node = tag_node->next) {
297 if (!xmlStrcmp(tag_node->name, (const xmlChar *)TAG_TYPE_PLATFORM_STR))
298 tag = TAG_TYPE_PLATFORM_STR;
299 else if (!xmlStrcmp(tag_node->name, (const xmlChar *)TAG_TYPE_CUSTOM_STR))
300 tag = TAG_TYPE_CUSTOM_STR;
304 cur = tag_node->xmlChildrenNode;
305 for (cur_node = cur; cur_node ; cur_node = cur_node->next) {
306 if (cur_node->type != XML_ELEMENT_NODE)
309 name = (char *)xmlGetProp(cur_node, (const xmlChar*)"name");
313 type = (char *)xmlGetProp(cur_node, (const xmlChar*)"type");
319 value = (char *)xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
326 if (!strncmp(type, "bool", 4))
327 ret = db_set_value_foreach_runtime(db_path, cur_node, tag, name, type, value);
329 ret = db_set_value(db_path, tag, name, type, value, strlen(value));
332 _E("Failed to set value (%d)", ret);
348 static struct build_ini_keys {
352 { "version:model", "http://tizen.org/system/build.model" },
353 { "version:build", "http://tizen.org/system/build.string" },
354 { "version:release", "http://tizen.org/system/build.release" },
355 { "build:type", "http://tizen.org/system/build.type" },
356 { "build:date", "http://tizen.org/system/build.date" },
357 { "build:time", "http://tizen.org/system/build.time" },
358 { "build:variant", "http://tizen.org/system/build.variant" },
359 { "build:id", "http://tizen.org/system/build.id" },
362 static int system_info_get_values_ini(const char *db_path)
371 ini = iniparser_load(INFO_FILE_PATH);
373 _E("cannot file open %s file!!!", INFO_FILE_PATH);
377 for (i = 0 ; i < ARRAY_SIZE(ini_keys) ; i++) {
378 value = iniparser_getstring(ini, ini_keys[i].info, NULL);
380 _E("NOT found %s", ini_keys[i].info);
384 ret = db_set_value(db_path, TAG_TYPE_PLATFORM_STR, ini_keys[i].key, STR_TYPE, value, strlen(value));
386 _E("Failed to set value (%d)", ret);
389 iniparser_freedict(ini);
394 static int system_info_create_db(const char *conf_path, char *db_path)
397 char file_path[PATH_MAX];
400 if (conf_path == NULL)
401 conf_path = MODEL_CONFIG_RO_PATH;
404 db_path = SYSTEM_INFO_DB_RO_PATH;
406 ret = mkdir(db_path, 0555);
407 if (ret != 0 && errno != EEXIST) {
408 _E("mkdir for %s failed (%d)", db_path, errno);
412 for (int i = 0; i < NUM_HASH_FILE; i++) {
413 snprintf(file_path, sizeof(file_path), "%s/%d", db_path, i);
414 fp = fopen(file_path, "w");
416 _E("fopen for %s failed (%d)", file_path, errno);
422 ret = system_info_get_values_config_xml(db_path, conf_path);
424 _E("Failed to get keys and values from xml(%d)", ret);
426 ret = system_info_get_values_ini(db_path);
428 _E("Failed to get keys and values from ini(%d)", ret);
433 static void show_help(void)
435 printf("system_info_init_db [OPTIONS]\n");
436 printf(" -h --help Show this help\n");
437 printf(" -k --key=KEY System info key to update\n");
438 printf(" -t --type=TYPE System info type to update (int/bool/double/string)\n");
439 printf(" -l --lang=LANG System info specific language target (capi/webapi/csapi)\n");
440 printf(" -g --tag=TAG System info tag to update (platform/custom)\n");
441 printf(" -v --value=VALUE System info value to update\n");
442 printf(" -i --input=PATH System info get input argument from several source\n");
443 printf(" -o --output=PATH System info get output argument from several source\n");
446 static int system_info_update_db(int argc, char *argv[])
451 char key[KEY_MAX] = {0};
452 char type[KEY_MAX] = {0};
453 char tag[KEY_MAX] = {0};
454 char value[KEY_MAX] = {0};
455 char value_bool[LANG_MAX + 1] = {0};
456 char conf_path[KEY_MAX] = {0};
457 char db_path[KEY_MAX] = {0};
458 enum language lang = LANG_MAX;
461 struct option long_options[] = {
462 { "key", required_argument, 0, 0 },
463 { "type", required_argument, 0, 0 },
464 { "tag", required_argument, 0, 0 },
465 { "value", required_argument, 0, 0 },
466 { "input", required_argument, 0, 0 },
467 { "output", required_argument, 0, 0 },
468 { "help", no_argument, 0, 0 },
473 opt = getopt_long(argc, argv, "k:t:g:v:l:i:o:h",
479 snprintf(key, sizeof(key), "%s", optarg);
482 snprintf(type, sizeof(type), "%s", optarg);
485 snprintf(tag, sizeof(tag), "%s", optarg);
488 snprintf(value, sizeof(value), "%s", optarg);
491 snprintf(conf_path, sizeof(conf_path), "%s", optarg);
494 snprintf(db_path, sizeof(db_path), "%s", optarg);
497 for (rt = 0; rt < LANG_MAX; rt++) {
498 if (!runtime[rt].xml_prop)
500 if (!strncmp(optarg, runtime[rt].xml_prop, RT_PREFIX)) {
501 lang = runtime[rt].lang;
505 if (rt == LANG_MAX || !runtime[rt].xml_prop) {
506 printf("Invalid language (%s)\n", optarg);
517 if (conf_path[0] != '\0' && db_path[0] != '\0') {
518 printf("Make system info db(%s) by %s\n", db_path, conf_path);
519 return system_info_create_db(conf_path, db_path);
523 if (key[0] == '\0') {
524 printf("Invalid Parameter: no key\n");
527 if (type[0] == '\0') {
528 printf("Invalid Parameter: no type\n");
531 if (tag[0] == '\0') {
532 printf("Invalid Parameter: no tag\n");
535 if (value[0] == '\0') {
536 printf("Invalid Parameter: no value\n");
539 if ((lang != LANG_MAX) && (strncmp(type, "bool", 4))) {
540 printf("Invalid Parameter: lang parameter supports for just bool type\n");
547 if (lang == LANG_MAX)
548 _I("Request to update: key(%s), type(%s), tag(%s), value(%s)",
549 key, type, tag, value);
551 _I("Request to update for specific lang(%s): key(%s), type(%s), tag(%s), value(%s)",
552 runtime[lang].xml_prop, key, type, tag, value);
554 if (!strncmp(type, "bool", 4)) {
555 if (lang == LANG_MAX) {
556 memset(value_bool, value[0] == 't' ? 'T' : 'F', LANG_MAX);
557 ret = db_set_value(SYSTEM_INFO_DB_RO_PATH, tag, key, type, value_bool, LANG_MAX);
559 ret = db_set_value_specific_runtime(SYSTEM_INFO_DB_RO_PATH, tag, key, type, value, lang);
561 ret = db_set_value(SYSTEM_INFO_DB_RO_PATH, tag, key, type, value, strlen(value));
564 _E("Failed to set value (%d)", ret);
569 int main(int argc, char *argv[])
574 return system_info_create_db(NULL, NULL);
576 return system_info_update_db(argc, argv);