static int db_set_value(const char *db_path, char *tag, char *name, char *type, char *value, int val_len)
{
int ret;
+ char key_internal[KEY_MAX];
+ size_t key_internal_len;
char file_path[PATH_MAX];
+ char file_path_new[PATH_MAX * 2];
+ char buf[PATH_MAX];
char *ptr;
FILE *fp = NULL;
+ FILE *fp_new = NULL;
+ int key_idx;
if (!db_path || !tag || !name || !type || !value)
return -EINVAL;
if (name == strstr(name, KEY_PREFIX))
- snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name + strlen(KEY_PREFIX), type);
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name + strlen(KEY_PREFIX), type);
else
- snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name, type);
-
- // Make directory recursively
- for (ptr = file_path + 1; *ptr != '\0'; ptr++) {
- if (*ptr == '/') {
- *ptr = '\0';
- ret = mkdir(file_path, 0555);
- if (ret != 0 && errno != EEXIST) {
- _E("mkdir for %s failed (%d)", file_path, errno);
- return -errno;
- }
- *ptr = '/';
- }
- }
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name, type);
+ snprintf(file_path, sizeof(file_path), "%s/%lu", db_path, simple_hash(key_internal));
- fp = fopen(file_path, "w");
+ fp = fopen(file_path, "r+");
if (!fp) {
_E("fopen for %s failed (%d)", file_path, errno);
return -errno;
}
- ret = fwrite(value, val_len, 1, fp);
- fclose(fp);
+ key_internal_len = strlen(key_internal);
+ key_idx = 0;
+ while ((ptr = fgets(buf, sizeof(buf), fp))) {
+ if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ')
+ break;
+ key_idx++;
+ }
- if (ret < 1) {
- _E("fwrite for %s failed", file_path);
- return -errno;
+ // 1. Insert new value
+ if (!ptr) {
+ ret = fprintf(fp, "%s %s\n", key_internal, value);
+ fclose(fp);
+
+ if (ret < 2) {
+ _E("fprintf for %s failed (%d)", file_path, errno);
+ return -errno;
+ }
+
+ _I("DB: value (key:%s,value:%s) is stored", name, value);
+ return 0;
+ }
+
+ // 2. Make new file to update value
+ snprintf(file_path_new, sizeof(file_path_new), "%s_tmp", file_path);
+ fp_new = fopen(file_path_new, "w");
+ if (!fp_new) {
+ _E("fopen for %s failed (%d)", file_path_new, errno);
+ ret = -errno;
+ goto clean;
}
- _I("DB: value (key:%s,value:%s) is stored", name, value);
+ // 2-1. Copy prefix
+ rewind(fp);
+ for (int i = 0; i < key_idx; i++) {
+ if (!fgets(buf, sizeof(buf), fp)) {
+ _E("fgets for %s failed", file_path);
+ ret = -EIO;
+ goto clean;
+ }
+ if (fputs(buf, fp_new) == EOF) {
+ _E("fputs for %s failed", file_path_new);
+ ret = -EIO;
+ goto clean;
+ }
+ }
- return 0;
+ // 2-2. Insert new value
+ ret = fprintf(fp_new, "%s %s\n", key_internal, value);
+ if (ret < 2) {
+ _E("fprintf for %s failed (%d)", file_path_new, errno);
+ ret = -errno;
+ goto clean;
+ }
+
+ // To move position indicator
+ if (!fgets(buf, sizeof(buf), fp)) {
+ _E("fgets for %s failed", file_path);
+ ret = -EIO;
+ goto clean;
+ }
+
+ // 2-3. Copy suffix
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (fputs(buf, fp_new) == EOF) {
+ _E("fputs for %s failed", file_path_new);
+ ret = -EIO;
+ goto clean;
+ }
+ }
+
+ // 2-4. Overwrite file
+ ret = rename(file_path_new, file_path);
+ if (ret != 0) {
+ _E("rename for %s failed (%d)", file_path_new, errno);
+ ret = -errno;
+ goto clean;
+ }
+
+ _I("DB: value (key:%s,value:%s) is updated", name, value);
+ ret = 0;
+
+clean:
+ if (fp_new)
+ fclose(fp_new);
+ if (fp)
+ fclose(fp);
+
+ return ret;
}
static int db_get_value(const char *db_path, char *tag, char *name, char *type, char *value, int val_len)
{
- int ret;
- char file_path[PATH_MAX];
+ char key_internal[KEY_MAX];
+ size_t key_internal_len;
+ char buf[PATH_MAX];
+ char *ptr;
FILE *fp = NULL;
if (!db_path || !tag || !name || !type || !value)
return -EINVAL;
if (name == strstr(name, KEY_PREFIX))
- snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name + strlen(KEY_PREFIX), type);
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name + strlen(KEY_PREFIX), type);
else
- snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name, type);
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name, type);
+ snprintf(buf, sizeof(buf), "%s/%lu", db_path, simple_hash(key_internal));
- fp = fopen(file_path, "r");
+ fp = fopen(buf, "r");
if (!fp) {
- _E("fopen for %s failed (%d)", file_path, errno);
+ _E("fopen for %s failed (%d)", buf, errno);
return -errno;
}
- ret = fread(value, val_len, 1, fp);
+ key_internal_len = strlen(key_internal);
+ while ((ptr = fgets(buf, sizeof(buf), fp))) {
+ if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ') {
+ sscanf(buf, "%*s %[^\n]s", value);
+ break;
+ }
+ }
fclose(fp);
- if (ret < 1) {
- _E("fread for %s failed", file_path);
+ if (!ptr) {
+ _E("fgets for %s failed", key_internal);
return -EIO;
}
static int system_info_create_db(const char *conf_path, char *db_path)
{
int ret;
+ char file_path[PATH_MAX];
+ FILE *fp = NULL;
if (conf_path == NULL)
conf_path = MODEL_CONFIG_RO_PATH;
if (db_path == NULL)
db_path = SYSTEM_INFO_DB_RO_PATH;
+ ret = mkdir(db_path, 0555);
+ if (ret != 0 && errno != EEXIST) {
+ _E("mkdir for %s failed (%d)", db_path, errno);
+ return -errno;
+ }
+
+ for (int i = 0; i < NUM_HASH_FILE; i++) {
+ snprintf(file_path, sizeof(file_path), "%s/%d", db_path, i);
+ fp = fopen(file_path, "w");
+ if (!fp) {
+ _E("fopen for %s failed (%d)", file_path, errno);
+ return -errno;
+ }
+ fclose(fp);
+ }
+
ret = system_info_get_values_config_xml(db_path, conf_path);
if (ret < 0)
_E("Failed to get keys and values from xml(%d)", ret);
static int db_get_value(enum tag_type tag, const char *key,
const char *type, char *value, size_t len)
{
- char *db_path;
char key_internal[KEY_MAX];
- char file_path[PATH_MAX];
+ size_t key_internal_len;
+ char buf[PATH_MAX]; // buffer size should be larger than KEY_MAX
FILE *fp = NULL;
int ret;
char *tag_s;
}
if (strstr(key, KEY_PREFIX) == key)
- snprintf(key_internal, sizeof(key_internal), "%s/%s:%s", tag_s, key + strlen(KEY_PREFIX), type);
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag_s, key + strlen(KEY_PREFIX), type);
else
- snprintf(key_internal, sizeof(key_internal), "%s/%s:%s", tag_s, key, type);
+ snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag_s, key, type);
pthread_mutex_lock(&fmutex);
if (!hashtable) {
}
if (access(SYSTEM_INFO_DB_RW_PATH, R_OK) == 0)
- db_path = SYSTEM_INFO_DB_RW_PATH;
+ snprintf(buf, sizeof(buf), SYSTEM_INFO_DB_RW_PATH"/%lu", simple_hash(key_internal));
else
- db_path = SYSTEM_INFO_DB_RO_PATH;
+ snprintf(buf, sizeof(buf), SYSTEM_INFO_DB_RO_PATH"/%lu", simple_hash(key_internal));
- snprintf(file_path, sizeof(file_path), "%s/%s", db_path, key_internal);
- fp = fopen(file_path, "r");
+ fp = fopen(buf, "r");
if (!fp) {
if (errno == ENOENT)
_D("Failed to find key in DB (%s, %s)", key, type);
else
- _E("fopen for %s failed (%d)", file_path, errno); //LCOV_EXCL_LINE
+ _E("fopen for %s failed (%d)", buf, errno); //LCOV_EXCL_LINE
ret = SYSTEM_INFO_ERROR_IO_ERROR; //LCOV_EXCL_LINE
goto out;
}
- temp = fgets(value, len, fp);
+ key_internal_len = strlen(key_internal);
+ while ((temp = fgets(buf, sizeof(buf), fp))) {
+ if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ') {
+ sscanf(buf, "%*s %[^\n]s", value);
+ break;
+ }
+ }
+
if (!temp) {
- _E("fgets for %s failed", file_path);
+ _D("Failed to find key in DB (%s)", key_internal);
ret = SYSTEM_INFO_ERROR_IO_ERROR;
goto out;
}