* Copyright (c) 2022 Huawei Technologies Co.,Ltd.
*
* DSS is licensed under 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.
* -------------------------------------------------------------------------
*
* dss_args_parse.c
*
*
* IDENTIFICATION
* src/common/dss_args_parse.c
*
* -------------------------------------------------------------------------
*/
#include "cm_base.h"
#include "cm_config.h"
#include "cm_dlock.h"
#include "cm_list.h"
#include "cm_system.h"
#include "cm_cipher.h"
#include "cm_encrypt.h"
#include "cm_utils.h"
#include "cm_signal.h"
#include "cm_sec_file.h"
#include "dss_log.h"
#include "dss_defs.h"
#include "dss_errno.h"
#include "dss_param.h"
#include "dss_file.h"
#include "dss_args_parse.h"
#ifdef __cplusplus
extern "C" {
#endif
status_t cmd_parse_check(dss_args_t *cmd_args_set, int set_size)
{
for (int i = 0; i < set_size; i++) {
if (cmd_args_set[i].required && !cmd_args_set[i].inputed) {
DSS_PRINT_ERROR(
"args [-%c|--%s] needs input value.\n", cmd_args_set[i].short_name, cmd_args_set[i].long_name);
return CM_ERROR;
}
}
return CM_SUCCESS;
}
static status_t cmd_parse_short_name_args(int argc, char **argv, int *argc_idx, dss_args_t *cmd_args_set, int set_size)
{
int i = *argc_idx;
int j;
for (j = 0; j < set_size; j++) {
if (cmd_args_set[j].short_name != argv[i][DSS_ARG_IDX_1]) {
continue;
}
if (cmd_args_set[j].inputed) {
DSS_PRINT_ERROR("%s repeat args.\n", argv[i]);
return CM_ERROR;
}
if (!cmd_args_set[j].required_args) {
if (argv[i][DSS_ARG_IDX_2] != 0x0) {
DSS_PRINT_ERROR("%s should not with args.\n", argv[i]);
return CM_ERROR;
}
} else {
if (argv[i][DSS_ARG_IDX_2] == 0x0 && (i + 1 >= argc)) {
DSS_PRINT_ERROR("%s should with args.\n", argv[i]);
return CM_ERROR;
}
if (argv[i][DSS_ARG_IDX_2] != 0x0) {
cmd_args_set[j].input_args = &argv[i][DSS_ARG_IDX_2];
} else {
i++;
cmd_args_set[j].input_args = argv[i];
}
if (cmd_args_set[j].check_args != NULL &&
cmd_args_set[j].check_args(cmd_args_set[j].input_args) != CM_SUCCESS) {
return CM_ERROR;
}
if (cmd_args_set[j].convert_args != NULL &&
cmd_args_set[j].convert_args(cmd_args_set[j].input_args, &cmd_args_set[j].convert_result,
&cmd_args_set[j].convert_result_size) != CM_SUCCESS) {
return CM_ERROR;
}
}
cmd_args_set[j].inputed = CM_TRUE;
break;
}
if (j == set_size) {
DSS_PRINT_ERROR("input %s hit no args.\n", argv[i]);
return CM_ERROR;
}
*argc_idx = i;
return CM_SUCCESS;
}
static status_t cmd_parse_long_name_args(int argc, char **argv, int *argc_idx, dss_args_t *cmd_args_set, int set_size)
{
int i = *argc_idx;
int j;
for (j = 0; j < set_size; j++) {
if (cmd_args_set[j].long_name == NULL || strcmp(cmd_args_set[j].long_name, &argv[i][DSS_ARG_IDX_2]) != 0) {
continue;
}
if (cmd_args_set[j].inputed) {
DSS_PRINT_ERROR("%s repeat args.\n", argv[i]);
return CM_ERROR;
}
if (cmd_args_set[j].required_args) {
if (i + 1 >= argc) {
DSS_PRINT_ERROR("%s should with args.\n", argv[i]);
return CM_ERROR;
}
i++;
cmd_args_set[j].input_args = argv[i];
if (cmd_args_set[j].check_args != NULL &&
cmd_args_set[j].check_args(cmd_args_set[j].input_args) != CM_SUCCESS) {
return CM_ERROR;
}
if (cmd_args_set[j].convert_args != NULL &&
cmd_args_set[j].convert_args(cmd_args_set[j].input_args, &cmd_args_set[j].convert_result,
&cmd_args_set[j].convert_result_size) != CM_SUCCESS) {
return CM_ERROR;
}
}
cmd_args_set[j].inputed = CM_TRUE;
break;
}
if (j == set_size) {
DSS_PRINT_ERROR("input %s hit no args.\n", argv[i]);
return CM_ERROR;
}
*argc_idx = i;
return CM_SUCCESS;
}
status_t cmd_parse_args(int argc, char **argv, dss_args_set_t *args_set)
{
if (argc < CMD_ARGS_AT_LEAST || (args_set->args_size == 0 && argc > CMD_ARGS_AT_LEAST)) {
DSS_PRINT_ERROR("args num %d error.\n", argc);
return CM_ERROR;
}
if (args_set->args_size == 0) {
return CM_SUCCESS;
}
for (int i = CMD_ARGS_AT_LEAST; i < argc; i++) {
if (argv[i][DSS_ARG_IDX_0] != '-') {
DSS_PRINT_ERROR("%s should begin with -.\n", argv[i]);
return CM_ERROR;
}
status_t status;
if (argv[i][DSS_ARG_IDX_1] != '-') {
status = cmd_parse_short_name_args(argc, argv, &i, args_set->cmd_args, args_set->args_size);
} else {
status = cmd_parse_long_name_args(argc, argv, &i, args_set->cmd_args, args_set->args_size);
}
if (status != CM_SUCCESS) {
return status;
}
}
if (args_set->args_check != NULL) {
return args_set->args_check(args_set->cmd_args, args_set->args_size);
}
return cmd_parse_check(args_set->cmd_args, args_set->args_size);
}
void cmd_parse_init(dss_args_t *cmd_args_set, int set_size)
{
for (int i = 0; i < set_size; i++) {
cmd_args_set[i].inputed = CM_FALSE;
cmd_args_set[i].input_args = NULL;
cmd_args_set[i].convert_result = NULL;
cmd_args_set[i].convert_result_size = 0;
}
}
void cmd_parse_clean(dss_args_t *cmd_args_set, int set_size)
{
for (int i = 0; i < set_size; i++) {
cmd_args_set[i].inputed = CM_FALSE;
cmd_args_set[i].input_args = NULL;
if (cmd_args_set[i].clean_convert_args != NULL) {
cmd_args_set[i].clean_convert_args(cmd_args_set[i].convert_result, cmd_args_set[i].convert_result_size);
}
cmd_args_set[i].convert_result = NULL;
cmd_args_set[i].convert_result_size = 0;
}
}
status_t cmd_check_au_size(const char *au_size_str)
{
uint32 min_multiple = DSS_MIN_AU_SIZE / SIZE_K(1);
uint32 max_multiple = DSS_MAX_AU_SIZE / SIZE_K(1);
uint32 au_size;
status_t ret = cm_str2uint32(au_size_str, &au_size);
if (ret != CM_SUCCESS) {
DSS_PRINT_ERROR("au_size %s is error!\n", au_size_str);
return CM_ERROR;
}
if (au_size == 0 || au_size < min_multiple || au_size > max_multiple) {
DSS_PRINT_ERROR(
"au_size %u is error, au_size cannot be 0, must greater than 2MB, smaller than 64MB!\n", au_size);
return CM_ERROR;
}
return CM_SUCCESS;
}
status_t cmd_check_dss_home(const char *dss_home)
{
return dss_check_path(dss_home);
}
status_t cmd_realpath_home(const char *input_args, char **convert_result, int *convert_size)
{
uint32 len = (uint32)strlen(input_args);
if (len == 0 || len >= CM_FILE_NAME_BUFFER_SIZE) {
DSS_PRINT_ERROR("the len of path is invalid.\n");
return CM_ERROR;
}
*convert_result = (char *)malloc(CM_FILE_NAME_BUFFER_SIZE);
if (*convert_result == NULL) {
DSS_PRINT_ERROR("Malloc failed.\n");
return CM_ERROR;
}
status_t status = realpath_file(input_args, *convert_result, CM_FILE_NAME_BUFFER_SIZE);
if (status != CM_SUCCESS) {
DSS_PRINT_ERROR("path is insecure, home: %s.\n", input_args);
free(*convert_result);
*convert_result = NULL;
return status;
}
*convert_size = (int)CM_FILE_NAME_BUFFER_SIZE;
return status;
}
status_t cmd_check_convert_dss_home(const char *input_args, void **convert_result, int *convert_size)
{
if (input_args == NULL) {
*convert_result = NULL;
*convert_size = 0;
return CM_SUCCESS;
}
status_t status = cmd_realpath_home(input_args, (char **)convert_result, convert_size);
if (status != CM_SUCCESS) {
DSS_PRINT_ERROR("home realpth failed, home: %s.\n", input_args);
return status;
}
return CM_SUCCESS;
}
void cmd_clean_check_convert(char *convert_result, int convert_size)
{
if (convert_result != NULL) {
CM_FREE_PTR(convert_result);
}
}
status_t cmd_check_uint64(const char *str)
{
uint64 num;
status_t status = cm_str2uint64(str, &num);
if (status == CM_ERROR) {
DSS_PRINT_ERROR("%s is not a valid uint64\n", str);
return CM_ERROR;
}
return CM_SUCCESS;
}
status_t set_config_info(char *home, dss_config_t *inst_cfg)
{
status_t status;
status = dss_set_cfg_dir(home, inst_cfg);
if (status != CM_SUCCESS) {
LOG_DEBUG_ERR("Environment variant DSS_HOME not found!\n");
return status;
}
status = dss_load_config(inst_cfg);
if (status != CM_SUCCESS) {
LOG_DEBUG_ERR("Failed to load parameters!\n");
return status;
}
return CM_SUCCESS;
}
status_t dss_get_vg_item(dss_vg_info_item_t **vg_item, const char *vg_name)
{
dss_vg_info_item_t *tmp_vg_item = dss_find_vg_item(vg_name);
if (tmp_vg_item == NULL) {
LOG_DEBUG_ERR("vg_name %s is not exist.\n", vg_name);
return CM_ERROR;
}
*vg_item = tmp_vg_item;
return CM_SUCCESS;
}
config_item_t g_dss_admin_parameters[] = {
{"LOG_HOME", CM_TRUE, ATTR_READONLY, "", NULL, NULL, "-", "-", "GS_TYPE_VARCHAR", NULL, 0, EFFECT_REBOOT, CFG_INS,
NULL, NULL},
#ifdef OPENGAUSS
{"_LOG_BACKUP_FILE_COUNT", CM_TRUE, ATTR_NONE, "20", NULL, NULL, "-", "[0,1024]", "GS_TYPE_INTEGER", NULL, 1,
EFFECT_REBOOT, CFG_INS, NULL, NULL},
#else
{"_LOG_BACKUP_FILE_COUNT", CM_TRUE, ATTR_NONE, "20", NULL, NULL, "-", "[0,128]", "GS_TYPE_INTEGER", NULL, 1,
EFFECT_REBOOT, CFG_INS, NULL, NULL},
#endif
{"_LOG_MAX_FILE_SIZE", CM_TRUE, ATTR_NONE, "256M", NULL, NULL, "-", "[1M,4G]", "GS_TYPE_INTEGER", NULL, 2,
EFFECT_REBOOT, CFG_INS, NULL, NULL},
{"_LOG_FILE_PERMISSIONS", CM_TRUE, ATTR_READONLY, "600", NULL, NULL, "-", "[600-777]", "GS_TYPE_INTEGER", NULL, 3,
EFFECT_REBOOT, CFG_INS, NULL, NULL},
{"_LOG_PATH_PERMISSIONS", CM_TRUE, ATTR_READONLY, "700", NULL, NULL, "-", "[700-777]", "GS_TYPE_INTEGER", NULL, 4,
EFFECT_REBOOT, CFG_INS, NULL, NULL},
{"_LOG_LEVEL", CM_TRUE, ATTR_NONE, "519", NULL, NULL, "-", "[0,4087]", "GS_TYPE_INTEGER", NULL, 5, EFFECT_REBOOT,
CFG_INS, NULL, NULL, NULL, NULL},
#ifdef OPENGAUSS
{"_AUDIT_BACKUP_FILE_COUNT", CM_TRUE, ATTR_NONE, "20", NULL, NULL, "-", "[0,1024]", "GS_TYPE_INTEGER", NULL, 6,
EFFECT_REBOOT, CFG_INS, NULL, NULL, NULL, NULL},
#else
{"_AUDIT_BACKUP_FILE_COUNT", CM_TRUE, ATTR_NONE, "20", NULL, NULL, "-", "[0,128]", "GS_TYPE_INTEGER", NULL, 6,
EFFECT_REBOOT, CFG_INS, NULL, NULL, NULL, NULL},
#endif
{"_AUDIT_MAX_FILE_SIZE", CM_TRUE, ATTR_NONE, "256M", NULL, NULL, "-", "[1M,4G]", "GS_TYPE_INTEGER", NULL, 7,
EFFECT_REBOOT, CFG_INS, NULL, NULL, NULL, NULL},
{"LSNR_PATH", CM_TRUE, ATTR_READONLY, "/tmp/", NULL, NULL, "-", "-", "GS_TYPE_VARCHAR", NULL, 8, EFFECT_REBOOT,
CFG_INS, NULL, NULL, NULL, NULL},
{"_AUDIT_LEVEL", CM_TRUE, ATTR_NONE, "1", NULL, NULL, "-", "-", "GS_TYPE_VARCHAR", NULL, 9, EFFECT_REBOOT, CFG_INS,
NULL, NULL, NULL, NULL},
{"CLUSTER_RUN_MODE", CM_TRUE, ATTR_NONE, "cluster_primary", NULL, NULL, "-", "-", "GS_TYPE_VARCHAR", NULL, 10,
EFFECT_REBOOT, CFG_INS, NULL, NULL, NULL, NULL},
{ "LOG_COMPRESSED", CM_TRUE, ATTR_READONLY, "FALSE", NULL, NULL, "-", "[FALSE,TRUE]", "GS_TYPE_BOOLEAN", NULL,
11, EFFECT_REBOOT, CFG_INS, NULL, NULL, NULL, NULL},
};
static status_t dss_load_local_server_config_core(
dss_config_t *inst_cfg, config_item_t *client_parameters, uint32 item_count)
{
char file_name[CM_MAX_PATH_LEN];
char *home = dss_get_cfg_dir(inst_cfg);
status_t res;
if (snprintf_s(file_name, CM_MAX_PATH_LEN, CM_MAX_PATH_LEN - 1, "%s/cfg/%s", home, DSS_CFG_NAME) == -1) {
cm_panic(0);
}
cm_init_config(client_parameters, item_count, &inst_cfg->config);
inst_cfg->config.ignore = CM_TRUE;
if (!cm_file_exist(file_name)) {
return CM_SUCCESS;
}
res = cm_read_config(file_name, &inst_cfg->config);
if (res != CM_SUCCESS) {
LOG_DEBUG_ERR("Read config from %s failed.\n", file_name);
}
return res;
}
status_t dss_load_local_server_config(dss_config_t *inst_cfg)
{
return dss_load_local_server_config_core(
inst_cfg, g_dss_admin_parameters, sizeof(g_dss_admin_parameters) / sizeof(config_item_t));
}
#ifdef __cplusplus
}
#endif