* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "hitls_build.h"
#ifdef HITLS_BSL_CONF
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bsl_uio.h"
#include "bsl_sal.h"
#include "bsl_list.h"
#include "bsl_errno.h"
#include "bsl_err_internal.h"
#include "bsl_conf_def.h"
#define BREAK_FLAG 1
#define CONTINUE_FLAG 2
#define _BSL_STR(x) #x
#define BSL_STR(x) _BSL_STR(x)
static int32_t IsNameValid(const char *name)
{
const char table[128] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
};
uint32_t nameLen = (uint32_t)strlen(name);
char pos = 0;
for (uint32_t i = 0; i < nameLen; i++) {
pos = name[i];
if (pos < 0 || table[(uint32_t)pos] != 1) {
return 0;
}
}
return 1;
}
static int32_t IsEscapeValid(char c)
{
char table[] = {
'#', ';', '$', '\\', '\"', '\''
};
uint32_t tableSize = (uint32_t)(sizeof(table) / sizeof(table[0]));
for (uint32_t i = 0; i < tableSize; i++) {
if (c == table[i]) {
return 1;
}
}
return 0;
}
static int32_t RemoveSpace(char *str)
{
int32_t strLen = (int32_t)strlen(str);
if (strLen == 0) {
return 0;
}
int32_t head = 0;
int32_t tail = strLen - 1;
while (head <= tail) {
if (isspace((unsigned char)str[head])) {
head++;
} else {
break;
}
}
while (head <= tail) {
if (isspace((unsigned char)str[tail])) {
tail--;
} else {
break;
}
}
int32_t realLen = tail - head + 1;
if (realLen > 0) {
memmove(str, str + head, (size_t)realLen);
}
str[realLen] = '\0';
return realLen;
}
static int32_t ParseQuote(char *str, char quote)
{
int32_t cnt = 0;
int32_t strLen = (int32_t)strlen(str);
int32_t i = 0;
while (i < strLen) {
if (str[i] == quote) {
break;
}
if (str[i] == '\\') {
if (IsEscapeValid(str[i + 1]) == 0 && str[i + 1] != 'n') {
return BSL_CONF_CONTEXT_ERR;
}
i++;
if (i >= strLen) {
return BSL_CONF_CONTEXT_ERR;
}
if (str[i] == 'n') {
str[i] = '\n';
}
}
str[cnt] = str[i];
cnt++;
i++;
}
str[cnt] = '\0';
return BSL_SUCCESS;
}
static int32_t RemoveEscapeAndComments(char *buff)
{
bool isValue = false;
int32_t flag = 0;
int32_t cnt = 0;
int32_t len = (int32_t)strlen(buff);
int32_t i = 0;
while (i < len) {
if (buff[i] == '=') {
isValue = true;
}
if (buff[i] == ';' || buff[i] == '#') {
if (isValue) {
break;
}
}
if (buff[i] == '\\') {
if (isValue == false) {
return -1;
}
if (IsEscapeValid(buff[i + 1]) == 0 && buff[i + 1] != 'n') {
return -1;
}
flag++;
i++;
if (i >= len) {
return -1;
}
if (buff[i] == 'n') {
buff[i] = '\n';
}
}
buff[cnt] = buff[i];
cnt++;
i++;
}
buff[cnt] = '\0';
return flag;
}
static void FreeSectionNames(char **names, int32_t namesSize)
{
if (names == NULL) {
return;
}
for (int32_t i = 0; i < namesSize; i++) {
BSL_SAL_FREE(names[i]);
}
BSL_SAL_FREE(names);
}
char **DefaultGetSectionNames(BslList *sectionList, uint32_t *namesSize)
{
if (sectionList == NULL || namesSize == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return NULL;
}
int32_t cnt = 0;
int32_t num = BSL_LIST_COUNT(sectionList);
char **names = (char **)BSL_SAL_Calloc(num, sizeof(char *));
if (names == NULL) {
BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
return NULL;
}
BSL_CONF_Section *secData = NULL;
BslListNode *node = BSL_LIST_FirstNode(sectionList);
while (node != NULL && cnt < num) {
secData = BSL_LIST_GetData(node);
if (secData == NULL) {
FreeSectionNames(names, num);
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return NULL;
}
names[cnt] = BSL_SAL_Calloc(secData->sectionLen + 1, 1);
if (names[cnt] == NULL) {
FreeSectionNames(names, num);
BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
return NULL;
}
memcpy(names[cnt], secData->section, secData->sectionLen);
cnt++;
node = BSL_LIST_GetNextNode(sectionList, node);
}
if (cnt != num) {
FreeSectionNames(names, num);
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return NULL;
}
*namesSize = (uint32_t)num;
return names;
}
static int32_t CmpSectionFunc(const void *a, const void *b)
{
const BSL_CONF_Section *aData = (const BSL_CONF_Section *)a;
const char *bData = (const char *)b;
if (aData != NULL && aData->section != NULL && bData != NULL) {
if (strcmp(aData->section, bData) == 0) {
return 0;
}
}
return 1;
}
static int32_t CmpKeyFunc(const void *a, const void *b)
{
const BSL_CONF_KeyValue *aData = (const BSL_CONF_KeyValue *)a;
const char *bData = (const char *)b;
if (aData != NULL && aData->key != NULL && bData != NULL) {
if (strcmp(aData->key, bData) == 0) {
return 0;
}
}
return 1;
}
void DeleteKeyValueNodeFunc(void *data)
{
if (data == NULL) {
return;
}
BSL_CONF_KeyValue *keyValueNode = (BSL_CONF_KeyValue *)data;
BSL_SAL_FREE(keyValueNode->key);
BSL_SAL_FREE(keyValueNode->value);
BSL_SAL_FREE(keyValueNode);
}
void DeleteSectionNodeFunc(void *data)
{
if (data == NULL) {
return;
}
BSL_CONF_Section *sectionNode = (BSL_CONF_Section *)data;
BSL_LIST_FREE(sectionNode->keyValueList, DeleteKeyValueNodeFunc);
BSL_SAL_FREE(sectionNode->section);
BSL_SAL_FREE(sectionNode);
}
static int32_t UpdateKeyValue(BSL_CONF_KeyValue *keyValue, const char *value)
{
uint32_t newValueLen = (uint32_t)strlen(value);
char *newValue = (char *)BSL_SAL_Calloc(1, newValueLen + 1);
if (newValue == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
return BSL_CONF_MEM_ALLOC_FAIL;
}
memcpy(newValue, value, newValueLen);
BSL_SAL_FREE(keyValue->value);
keyValue->value = newValue;
keyValue->valueLen = newValueLen;
return BSL_SUCCESS;
}
static int32_t AddKeyValue(BslList *keyValueList, const char * key, const char *value)
{
int32_t ret = BSL_SUCCESS;
if (IsNameValid(key) == 0) {
BSL_ERR_PUSH_ERROR(BSL_CONF_INVALID_NAME);
return BSL_CONF_INVALID_NAME;
}
BSL_CONF_KeyValue *keyValue = (BSL_CONF_KeyValue *)BSL_SAL_Calloc(1, sizeof(BSL_CONF_KeyValue));
if (keyValue == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
return BSL_CONF_MEM_ALLOC_FAIL;
}
keyValue->keyLen = (uint32_t)strlen(key);
keyValue->key = (char *)BSL_SAL_Calloc(1, keyValue->keyLen + 1);
if (keyValue->key == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
ret = BSL_CONF_MEM_ALLOC_FAIL;
goto EXIT;
}
keyValue->valueLen = (uint32_t)strlen(value);
keyValue->value = (char *)BSL_SAL_Calloc(1, keyValue->valueLen + 1);
if (keyValue->value == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
ret = BSL_CONF_MEM_ALLOC_FAIL;
goto EXIT;
}
memcpy(keyValue->key, key, keyValue->keyLen);
memcpy(keyValue->value, value, keyValue->valueLen);
ret = BSL_LIST_AddElement(keyValueList, keyValue, BSL_LIST_POS_END);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
goto EXIT;
}
return BSL_SUCCESS;
EXIT:
DeleteKeyValueNodeFunc(keyValue);
return ret;
}
static int32_t AddSection(BslList *sectionList, const char *section, const char *key, const char *value)
{
int32_t ret = BSL_SUCCESS;
if (IsNameValid(section) == 0) {
BSL_ERR_PUSH_ERROR(BSL_CONF_INVALID_NAME);
return BSL_CONF_INVALID_NAME;
}
BSL_CONF_Section *sectionNode = (BSL_CONF_Section *)BSL_SAL_Calloc(1, sizeof(BSL_CONF_Section));
if (sectionNode == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
return BSL_CONF_MEM_ALLOC_FAIL;
}
sectionNode->sectionLen = (uint32_t)strlen(section);
sectionNode->section = (char *)BSL_SAL_Calloc(1, sectionNode->sectionLen + 1);
if (sectionNode->section == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
ret = BSL_CONF_MEM_ALLOC_FAIL;
goto EXIT;
}
memcpy(sectionNode->section, section, sectionNode->sectionLen);
sectionNode->keyValueList = BSL_LIST_New(sizeof(BslList));
if (sectionNode->keyValueList == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
ret = BSL_CONF_MEM_ALLOC_FAIL;
goto EXIT;
}
if (strlen(key) != 0) {
ret = AddKeyValue(sectionNode->keyValueList, key, value);
if (ret != BSL_SUCCESS) {
goto EXIT;
}
}
ret = BSL_LIST_AddElement(sectionList, sectionNode, BSL_LIST_POS_END);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
goto EXIT;
}
return BSL_SUCCESS;
EXIT:
DeleteSectionNodeFunc(sectionNode);
return ret;
}
BslList *DefaultGetSectionNode(BslList *sectionList, const char *section)
{
if (sectionList == NULL || section == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return NULL;
}
BSL_CONF_Section *sectionNode = BSL_LIST_SearchDataConst(sectionList, section, CmpSectionFunc, NULL);
if (sectionNode == NULL || sectionNode->keyValueList == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return NULL;
}
return sectionNode->keyValueList;
}
int32_t DefaultGetString(BslList *sectionList, const char *section, const char *key, char *str, uint32_t *strLen)
{
if (sectionList == NULL || section == NULL || key == NULL || str == NULL || strLen == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
BSL_CONF_Section *secCtx = BSL_LIST_SearchDataConst(sectionList, section, CmpSectionFunc, NULL);
if (secCtx == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
BSL_CONF_KeyValue *keyValue = BSL_LIST_SearchDataConst(secCtx->keyValueList, key, CmpKeyFunc, NULL);
if (keyValue == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_VALUE_NOT_FOUND);
return BSL_CONF_VALUE_NOT_FOUND;
}
if (*strLen < keyValue->valueLen + 1) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
memcpy(str, keyValue->value, keyValue->valueLen);
str[keyValue->valueLen] = '\0';
*strLen = keyValue->valueLen;
return BSL_SUCCESS;
}
int32_t DefaultGetNumber(BslList *sectionList, const char *section, const char *key, long int *num)
{
char str[BSL_CONF_LINE_SIZE + 1] = {0};
uint32_t strLen = BSL_CONF_LINE_SIZE + 1;
int32_t ret = DefaultGetString(sectionList, section, key, str, &strLen);
if (ret != BSL_SUCCESS) {
return ret;
}
char *endPtr = NULL;
errno = 0;
long int tmpNum = strtol(str, &endPtr, 0);
if (strlen(endPtr) > 0 || endPtr == str || (tmpNum == LONG_MAX || tmpNum == LONG_MIN) || errno == ERANGE ||
(tmpNum == 0 && errno != 0)) {
BSL_ERR_PUSH_ERROR(BSL_CONF_CONTEXT_ERR);
return BSL_CONF_CONTEXT_ERR;
}
*num = tmpNum;
return BSL_SUCCESS;
}
BslList *DefaultCreate(void)
{
BslList *sectionList = BSL_LIST_New(sizeof(BslList));
if (sectionList == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_MEM_ALLOC_FAIL);
return NULL;
}
int32_t ret = AddSection(sectionList, "default", "", "");
if (ret != BSL_SUCCESS) {
BSL_LIST_FREE(sectionList, NULL);
return NULL;
}
return sectionList;
}
void DefaultDestroy(BslList *sectionList)
{
if (sectionList == NULL) {
return;
}
BSL_LIST_FREE(sectionList, DeleteSectionNodeFunc);
}
static int32_t SetSection(BslList *sectionList, const char *section, const char * key, const char *value)
{
BSL_CONF_Section *secCtx = NULL;
BSL_CONF_KeyValue *keyValue = NULL;
if (strlen(section) == 0) {
if (strlen(key) == 0) {
BSL_ERR_PUSH_ERROR(BSL_CONF_CONTEXT_ERR);
return BSL_CONF_CONTEXT_ERR;
}
secCtx = BSL_LIST_SearchDataConst(sectionList, "default", CmpSectionFunc, NULL);
if (secCtx == NULL || secCtx->keyValueList == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
keyValue = BSL_LIST_SearchDataConst(secCtx->keyValueList, key, CmpKeyFunc, NULL);
if (keyValue == NULL) {
return AddKeyValue(secCtx->keyValueList, key, value);
} else {
return UpdateKeyValue(keyValue, value);
}
} else {
secCtx = BSL_LIST_SearchDataConst(sectionList, section, CmpSectionFunc, NULL);
if (secCtx == NULL) {
return AddSection(sectionList, section, key, value);
}
if (strlen(key) == 0) {
return BSL_SUCCESS;
}
if (secCtx->keyValueList == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
keyValue = BSL_LIST_SearchDataConst(secCtx->keyValueList, key, CmpKeyFunc, NULL);
if (keyValue == NULL) {
return AddKeyValue(secCtx->keyValueList, key, value);
} else {
return UpdateKeyValue(keyValue, value);
}
}
}
static int32_t ConfGetLine(BSL_UIO *uio, char *buff, int32_t buffSize, int32_t *offset, int32_t *flag)
{
int32_t tmpOffset = *offset;
int32_t buffLen = buffSize - tmpOffset;
if (buffLen <= 0) {
BSL_ERR_PUSH_ERROR(BSL_CONF_BUFF_OVERFLOW);
return BSL_CONF_BUFF_OVERFLOW;
}
int32_t ret = BSL_UIO_Gets(uio, buff + tmpOffset, (uint32_t *)&buffLen);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
buffLen += tmpOffset;
if (buffLen == 0) {
*flag = BREAK_FLAG;
return BSL_SUCCESS;
}
bool isEof = false;
if (buff[buffLen - 1] != '\n') {
ret = BSL_UIO_Ctrl(uio, BSL_UIO_FILE_GET_EOF, 1, &isEof);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
if (isEof != true) {
BSL_ERR_PUSH_ERROR(BSL_CONF_BUFF_OVERFLOW);
return BSL_CONF_BUFF_OVERFLOW;
}
(void)RemoveSpace(buff);
return BSL_SUCCESS;
}
buffLen = RemoveSpace(buff);
if (buffLen > 0) {
buffLen--;
}
if (buff[buffLen] == '\\') {
if (buffLen > 0 && buff[buffLen - 1] == '\\') {
tmpOffset = 0;
} else {
tmpOffset = buffLen;
*flag = CONTINUE_FLAG;
}
} else {
tmpOffset = 0;
}
*offset = tmpOffset;
return BSL_SUCCESS;
}
static int32_t ConfParseLine(BslList *sectionList, char *buff, char *section, char *key, char *value)
{
int32_t ret = BSL_SUCCESS;
size_t len = strlen(buff);
int32_t n = 2;
if (len < 1 || buff[0] == '#' || buff[0] == ';') {
return BSL_SUCCESS;
} else if (buff[0] == '[' && buff[len - 1] == ']') {
len -= 2;
if (len > BSL_CONF_SEC_SIZE) {
BSL_ERR_PUSH_ERROR(BSL_CONF_BUFF_OVERFLOW);
return BSL_CONF_BUFF_OVERFLOW;
}
memcpy(section, &buff[1], len);
section[len] = '\0';
} else if (sscanf(buff, "%" BSL_STR(BSL_CONF_LINE_SIZE) "[^=] = \"%" BSL_STR(BSL_CONF_LINE_SIZE) "[^\n]", key, value) == n) {
ret = ParseQuote(value, '\"');
} else if (sscanf(buff, "%" BSL_STR(BSL_CONF_LINE_SIZE) "[^=] = \'%" BSL_STR(BSL_CONF_LINE_SIZE) "[^\n]", key, value) == n) {
ret = ParseQuote(value, '\'');
} else if (RemoveEscapeAndComments(buff) < 0) {
BSL_ERR_PUSH_ERROR(BSL_CONF_CONTEXT_ERR);
return BSL_CONF_CONTEXT_ERR;
} else if (sscanf(buff, "%" BSL_STR(BSL_CONF_LINE_SIZE) "[^=]%" BSL_STR(BSL_CONF_LINE_SIZE) "[=]", key, value) == n) {
char *valPtr = strchr(buff, '=');
valPtr++;
len = strlen(valPtr);
memcpy(value, valPtr, len);
value[len] = '\0';
} else {
BSL_ERR_PUSH_ERROR(BSL_CONF_CONTEXT_ERR);
return BSL_CONF_CONTEXT_ERR;
}
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
(void)RemoveSpace(section);
(void)RemoveSpace(key);
(void)RemoveSpace(value);
return SetSection(sectionList, section, key, value);
}
int32_t DefaultLoadUio(BslList *sectionList, BSL_UIO *uio)
{
if (sectionList == NULL || uio == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
int32_t ret;
int32_t offset = 0;
int32_t flag;
char *buff = (char *)BSL_SAL_Calloc(4, (BSL_CONF_LINE_SIZE + 1));
if (buff == NULL) {
BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
return BSL_MALLOC_FAIL;
}
char *section = (char *)(buff + BSL_CONF_LINE_SIZE + 1);
char *key = (char *)(section + BSL_CONF_LINE_SIZE + 1);
char *value = (char *)(key + BSL_CONF_LINE_SIZE + 1);
while (true) {
flag = 0;
ret = ConfGetLine(uio, buff, BSL_CONF_LINE_SIZE + 1, &offset, &flag);
if (ret != BSL_SUCCESS || flag == BREAK_FLAG) {
break;
}
if (flag == CONTINUE_FLAG) {
continue;
}
ret = ConfParseLine(sectionList, buff, section, key, value);
if (ret != BSL_SUCCESS) {
break;
}
memset(buff, 0, BSL_CONF_LINE_SIZE + 1);
memset(key, 0, BSL_CONF_LINE_SIZE + 1);
memset(value, 0, BSL_CONF_LINE_SIZE + 1);
offset = 0;
}
BSL_SAL_Free(buff);
return ret;
}
int32_t DefaultLoad(BslList *sectionList, const char *file)
{
if (sectionList == NULL || file == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
BSL_UIO *in = BSL_UIO_New(BSL_UIO_FileMethod());
if (in == NULL) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
int32_t ret = BSL_UIO_Ctrl(in, BSL_UIO_FILE_OPEN, BSL_UIO_FILE_READ, (void *)(uintptr_t)file);
if (ret != BSL_SUCCESS) {
BSL_UIO_Free(in);
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
ret = DefaultLoadUio(sectionList, in);
BSL_UIO_Free(in);
return ret;
}
static int32_t DumpSection(BSL_UIO *uio, const BSL_CONF_Section *secData)
{
uint32_t strLen = secData->sectionLen + 4;
char *str = (char *)BSL_SAL_Calloc(1, strLen + 1);
if (str == NULL) {
BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
return BSL_MALLOC_FAIL;
}
int usedLen = snprintf(str, strLen + 1, "[%s]\n", secData->section);
if (usedLen < 0 || usedLen > BSL_CONF_LINE_SIZE) {
BSL_SAL_FREE(str);
BSL_ERR_PUSH_ERROR(BSL_CONF_BUFF_OVERFLOW);
return BSL_CONF_BUFF_OVERFLOW;
}
int32_t ret = BSL_UIO_Puts(uio, str, (uint32_t *)&usedLen);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
}
BSL_SAL_FREE(str);
return ret;
}
static int32_t DumpKeyValue(BSL_UIO *uio, const BSL_CONF_KeyValue *keyValue)
{
uint32_t strLen = keyValue->keyLen + keyValue->valueLen * 2 + 3;
char *str = (char *)BSL_SAL_Calloc(1, strLen + 1);
if (str == NULL) {
BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
return BSL_MALLOC_FAIL;
}
int usedLen = snprintf(str, strLen + 1, "%s=", keyValue->key);
if (usedLen < 0 || usedLen > BSL_CONF_LINE_SIZE) {
BSL_SAL_FREE(str);
BSL_ERR_PUSH_ERROR(BSL_CONF_DUMP_FAIL);
return BSL_CONF_DUMP_FAIL;
}
for (uint32_t i = 0; i < keyValue->valueLen; i++) {
if (IsEscapeValid(keyValue->value[i]) == 1) {
str[usedLen] = '\\';
usedLen++;
}
if (keyValue->value[i] == '\n') {
str[usedLen] = '\\';
usedLen++;
str[usedLen] = 'n';
usedLen++;
continue;
}
str[usedLen] = keyValue->value[i];
usedLen++;
}
str[usedLen] = '\n';
usedLen++;
if (usedLen > BSL_CONF_LINE_SIZE) {
BSL_SAL_FREE(str);
BSL_ERR_PUSH_ERROR(BSL_CONF_BUFF_OVERFLOW);
return BSL_CONF_BUFF_OVERFLOW;
}
int32_t ret = BSL_UIO_Puts(uio, str, (uint32_t *)&usedLen);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
}
BSL_SAL_FREE(str);
return ret;
}
int32_t DefaultDumpUio(BslList *sectionList, BSL_UIO *uio)
{
if (sectionList == NULL || uio == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
int32_t ret = BSL_SUCCESS;
BSL_CONF_Section *secData = NULL;
BSL_CONF_KeyValue *keyValue = NULL;
BslListNode *keyValueNode = NULL;
BslListNode *node = BSL_LIST_FirstNode(sectionList);
while (node != NULL) {
secData = BSL_LIST_GetData(node);
if (secData == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
ret = DumpSection(uio, secData);
if (ret != BSL_SUCCESS) {
return ret;
}
keyValueNode = BSL_LIST_FirstNode(secData->keyValueList);
while (keyValueNode != NULL) {
keyValue = BSL_LIST_GetData(keyValueNode);
if (keyValue == NULL) {
BSL_ERR_PUSH_ERROR(BSL_CONF_GET_FAIL);
return BSL_CONF_GET_FAIL;
}
ret = DumpKeyValue(uio, keyValue);
if (ret != BSL_SUCCESS) {
return ret;
}
keyValueNode = BSL_LIST_GetNextNode(secData->keyValueList, keyValueNode);
}
node = BSL_LIST_GetNextNode(sectionList, node);
}
return BSL_SUCCESS;
}
int32_t DefaultDump(BslList *sectionList, const char *file)
{
if (sectionList == NULL || file == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
BSL_UIO *out = BSL_UIO_New(BSL_UIO_FileMethod());
if (out == NULL) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
int32_t ret = BSL_UIO_Ctrl(out, BSL_UIO_FILE_OPEN, BSL_UIO_FILE_WRITE, (void *)(uintptr_t)file);
if (ret != BSL_SUCCESS) {
BSL_UIO_Free(out);
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
ret = DefaultDumpUio(sectionList, out);
BSL_UIO_SetIsUnderlyingClosedByUio(out, true);
BSL_UIO_Free(out);
return ret;
}
const BSL_CONF_Method *BSL_CONF_DefaultMethod(void)
{
static const BSL_CONF_Method DEFAULT_METHOD = {
DefaultCreate,
DefaultDestroy,
DefaultLoad,
DefaultLoadUio,
DefaultDump,
DefaultDumpUio,
DefaultGetSectionNode,
DefaultGetString,
DefaultGetNumber,
DefaultGetSectionNames,
};
return &DEFAULT_METHOD;
}
#endif