* Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
*
* openGauss 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.
*---------------------------------------------------------------------------------------
*
* pg_guc.cpp
* the interface for user to set the guc parameters
*
* IDENTIFICATION
* src/bin/gs_guc/pg_guc.cpp
*
* ---------------------------------------------------------------------------------------
*/
#ifdef WIN32
* Need this to get defines for restricted tokens and jobs. And it
* has to be set before any header from the Win32 API is loaded.
*/
#define _WIN32_WINNT 0x0501
#endif
#include "postgres_fe.h"
#include <locale.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "libpq/libpq-fe.h"
#include "flock.h"
#include "libpq/hba.h"
#include "libpq/pqsignal.h"
#include "getopt_long.h"
#include "miscadmin.h"
#include "cipher.h"
#include "bin/elog.h"
#include "openssl/rand.h"
#include "replication/replicainternal.h"
#include "common/config/cm_config.h"
#if defined(__CYGWIN__)
#include <sys/cygwin.h>
#include <windows.h>
#undef WIN32
#endif
#undef _
#define _(x) x
#define TRY_TIMES 3
#define LARGE_INSTANCE_NUM 2
#ifdef ENABLE_UT
#define static
#endif
typedef long pgpid_t;
*@@GaussDB@@
*Brief :update or add config_parameter
*Description :
*/
typedef enum { UPDATE_PARAMETER = 0, ADD_PARAMETER } UpdateOrAddParameter;
*@@GaussDB@@
*Brief :the comand types
*Description :
*/
typedef enum {
NO_COMMAND = 0,
SET_CONF_COMMAND,
RELOAD_CONF_COMMAND,
ENCRYPT_KEY_COMMAND,
CHECK_CONF_COMMAND,
GENERATE_KEY_COMMAND
} CtlCommand;
typedef enum {
CODE_OK = 0,
CODE_UNKNOW_CONFFILE_PATH,
CODE_OPEN_CONFFILE_FAILED,
CODE_CLOSE_CONFFILE_FAILED,
CODE_READE_CONFFILE_ERROR,
CODE_WRITE_CONFFILE_ERROR,
CODE_LOCK_CONFFILE_FAILED,
CODE_UNLOCK_CONFFILE_FAILED,
CODE_UNKOWN_ERROR
} ErrCode;
typedef enum {
INSTANCE_ANY,
INSTANCE_DATANODE,
INSTANCE_COORDINATOR,
INSTANCE_GTM,
INSTANCE_GTM_PROXY,
INSTANCE_CMAGENT,
INSTANCE_CMSERVER,
} NodeType;
typedef struct {
FILE* fp;
size_t size;
} FileLock;
#define DEFAULT_WAIT 60
#define MAX_BUF_SIZE 4096
#define MAX_COMMAND_LEN 4096
#define MAX_CHILD_PATH 1024
static int sig = SIGHUP;
CtlCommand ctl_command = NO_COMMAND;
const char* progname;
char** config_param = {0};
char** hba_param = {0};
char** config_value = {0};
int node_type_value[5] = {0};
int config_param_number = 0;
int cndn_param_number = 0;
int cmserver_param_number = 0;
int cmagent_param_number = 0;
int gtm_param_number = 0;
int lc_param_number = 0;
int config_value_number = 0;
int node_type_number = 0;
int arraysize = 0;
char** cndn_param = {0};
char** gtm_param = {0};
char** cmserver_param = {0};
char** cmagent_param = {0};
char** lc_param = {0};
char** cndn_guc_info = {0};
char** gtm_guc_info = {0};
char** cmserver_guc_info = {0};
char** cmagent_guc_info = {0};
char** lc_guc_info = {0};
bool is_hba_conf = false;
char pid_file[MAXPGPATH];
char gucconf_file[MAXPGPATH] = {0x00};
char tempguc_file[MAXPGPATH] = {0x00};
char gucconf_lock_file[MAXPGPATH] = {0x00};
char gaussdb_state_file[MAXPGPATH] = {0};
const int MAX_PARAM_LEN = 1024;
const int MAX_VALUE_LEN = 1024;
#define INVALID_LINES_IDX (int)(~0)
const int EQUAL_MARK_LEN = 3;
#define MAX_CONFIG_ITEM 1024
#define PG_LOCKFILE_SIZE 1024
#define ADDPOINTER_SIZE 2
#define MAX_HOST_NAME_LENGTH 255
#define TEMP_PGCONF_FILE "postgresql.conf.guc.bak"
#define TEMP_CMAGENTCONF_FILE "cm_agent.conf.bak"
#define TEMP_CMSERVERCONF_FILE "cm_server.conf.bak"
#define TEMP_GTMCONF_FILE "gtm.conf.bak"
#define TEMP_PGHBACONF_FILE "pg_hba.conf.bak"
#define DB_PROCESS_NAME "postgres"
#define PROG_NAME "gs_guc"
#define GUC_OPT_CONF_FILE "cluster_guc.conf"
#define SUCCESS 0
#define FAILURE 1
#define GS_FREE(ptr) \
do { \
if (NULL != (ptr)) { \
free((char*)(ptr)); \
ptr = NULL; \
} \
} while (0)
#define IsIllegalCharacter(c) ((c) != '/' && !isdigit((c)) && !isalpha((c)) && (c) != '_' && (c) != '-')
NodeType nodetype = INSTANCE_ANY;
bool g_remote_connection_signal = true;
unsigned int g_remote_command_result = 0;
ErrCode retCode = CODE_OK;
KeyMode key_mode = UNKNOWN_KEY_MODE;
char* key_username = NULL;
char* g_plainkey = NULL;
char* g_cipherkey = NULL;
char* g_prefix = NULL;
bool g_need_changed = true;
char* g_local_instance_path = NULL;
typedef struct {
char** nodename_array;
uint32 num;
} nodeInfo;
nodeInfo* g_incorrect_nodeInfo = NULL;
nodeInfo* g_ignore_nodeInfo = NULL;
typedef struct {
char** nodename_array;
char** gucinfo_array;
char** paramname_array;
char** paramvalue_array;
uint32 nodename_num;
uint32 gucinfo_num;
uint32 paramname_num;
uint32 paramvalue_num;
} gucInfo;
gucInfo* g_real_gucInfo = NULL;
gucInfo* g_expect_gucInfo = NULL;
uint32 g_local_dn_idx = 0;
char* g_current_data_dir = NULL;
void* pg_malloc(size_t size);
void* pg_malloc_zero(size_t size);
char* xstrdup(const char* s);
static void do_help(void);
static void do_help_config_guc(void);
static void do_help_check_guc(void);
static void do_help_config_hba(void);
static void do_help_encrypt(void);
static void do_help_generate(void);
static void do_help_common_options(void);
static void do_help_set_reset_options(void);
static void do_help_encrypt_options(void);
static void do_help_generate_options(void);
static bool is_file_exist(const char* path);
static void check_build_status(const char* path);
static bool is_gs_build_pid(const char* pid_path);
void do_advice(void);
static pgpid_t get_pgpid(void);
static int find_gucoption(
char** optlines, const char* opt_name, int* name_offset, int* name_len, int* value_offset, int* value_len);
ErrCode writefile(char* path, char** lines, UpdateOrAddParameter isAddorUpdate);
void do_checkvalidate(int type);
int do_config_reload();
static int do_gucset(const char *action_type, const char *data_dir);
static char* do_guccheck(const char* param);
static void to_generatenewline(char* oldline, char* newline, const char* param, const char* value, int optvalue_len);
static int find_param_in_string(const char* name_string, const char* name_param, size_t param_len);
void free_space(char** optlines, int size);
void do_hba_analysis(const char* strcmd);
void free_hba_params();
static void checkArchivepath(const char* paraValue);
static bool isMatchOptionName(
char* optLine, const char* paraName, int paraLength, int* paraOffset, int* valueLength, int* valueOffset);
bool isOptLineCommented(const char* optLine);
void trimBlanksTwoEnds(char** strPtr);
static void check_key_mode(const char* mode);
static void check_encrypt_options(void);
extern int do_hba_set(const char *action_type);
void get_instance_configfile(const char* datadir);
void print_gucinfo(const char* paraname);
int find_first_paravalue_index(const char* paraname);
int find_same_paravalue_index(const char* paraname);
void print_check_result();
int print_guc_result(const char* nodename);
int check_config_file_status();
char** backup_config_file(const char* read_file, char* write_file, FileLock filelock, int reserve_num_lines);
int do_parameter_value_write(char** opt_lines, UpdateOrAddParameter updateoradd);
static void checkCMParameter(const char* dataDir, const char* nodeName, const char* instName);
#ifdef __cplusplus
extern "C" {
#endif
extern void freefile(char** lines);
extern char** readfile(const char* path, int reserve_num_lines);
extern int find_gucoption_available(
char** optlines, const char* opt_name, int* name_offset, int* name_len, int* value_offset, int* value_len);
void process_cluster_guc_option(char* nodename, int type, char* instance_name, char* indatadir);
int validate_cluster_guc_options(char* nodename, int type, char* instance_name, char* indatadir);
extern int check_parameter(int type);
extern int save_guc_para_info();
extern bool get_env_value(const char* env_val, char* output_env_value, size_t env_var_value_len);
extern void check_env_value(const char* input_env_value);
bool allocate_memory_list();
extern int init_gauss_cluster_config(void);
extern char* get_AZ_value(char* value, const char* data_dir);
extern bool get_hostname_or_ip(char* out_name, size_t name_len);
#ifdef __cplusplus
}
#endif
* @@GaussDB@@
* Brief : void *pg_malloc(size_t size)
* Description : malloc space
* Notes :
*/
void* pg_malloc(size_t size)
{
void* result = NULL;
if (size == 0) {
write_stderr(_("%s: malloc 0\n"), progname);
exit(1);
}
result = (void*)malloc(size);
if (NULL == result) {
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
* @@GaussDB@@
* Brief : void *pg_malloc_zero(size_t size)
* Description : malloc space, then set it to '\0'
* Notes :
*/
void* pg_malloc_zero(size_t size)
{
void* tmp = NULL;
errno_t rc = 0;
tmp = pg_malloc(size);
rc = memset_s(tmp, size, '\0', size);
securec_check_c(rc, "\0", "\0");
return tmp;
}
* @@GaussDB@@
* Brief : bool allocate_memory_list()
* Description :
* Notes : Allocate memory space
*/
bool allocate_memory_list()
{
FILE* fp = NULL;
int lines = 0;
char line_info[MAXPGPATH] = {0};
char gausshome[MAXPGPATH] = {0};
char guc_file[MAXPGPATH] = {0};
int rc = 0;
rc = memset_s(line_info, MAXPGPATH, 0, MAXPGPATH);
securec_check_c(rc, "\0", "\0");
if (!get_env_value("GAUSSHOME", gausshome, sizeof(gausshome) / sizeof(char)))
return false;
check_env_value(gausshome);
rc = snprintf_s(guc_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, GUC_OPT_CONF_FILE);
securec_check_ss_c(rc, "\0", "\0");
if (checkPath(guc_file) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), guc_file, strerror(errno));
return false;
}
fp = fopen(guc_file, "r");
if (fp == NULL) {
write_stderr("ERROR: Failed to open file\"%s\"\n", guc_file);
return false;
}
if (NULL == fgets(line_info, MAXPGPATH - 1, fp)) {
write_stderr("ERROR: Failed to read file\"%s\"\n", guc_file);
fclose(fp);
return false;
}
while ((fgets(line_info, MAXPGPATH - 1, fp)) != NULL) {
if ((int)strlen(line_info) > 0 && line_info[(int)strlen(line_info) - 1] == '\n')
lines++;
}
if (0 != lines) {
cndn_param = ((char**)pg_malloc_zero(lines * sizeof(char*)));
gtm_param = ((char**)pg_malloc_zero(lines * sizeof(char*)));
cmserver_param = ((char**)pg_malloc_zero(lines * sizeof(char*)));
cmagent_param = ((char**)pg_malloc_zero(lines * sizeof(char*)));
lc_param = ((char**)pg_malloc_zero(lines * sizeof(char*)));
cndn_guc_info = ((char**)pg_malloc_zero(lines * sizeof(char*)));
gtm_guc_info = ((char**)pg_malloc_zero(lines * sizeof(char*)));
cmserver_guc_info = ((char**)pg_malloc_zero(lines * sizeof(char*)));
cmagent_guc_info = ((char**)pg_malloc_zero(lines * sizeof(char*)));
lc_guc_info = ((char**)pg_malloc_zero(lines * sizeof(char*)));
}
fclose(fp);
return true;
}
* @@GaussDB@@
* Brief : char *xstrdup(const char *s)
* Description :
* Notes :
*/
char* xstrdup(const char* s)
{
char* result = NULL;
result = strdup(s);
if (NULL == result) {
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
* @@GaussDB@@
* Brief : char* skipspace(char *p)
* Description : Skip all the blanks at the begin of p
* Notes :
*/
static char* skipspace(char *p)
{
while (isspace((unsigned char)*p)) {
p++;
}
return p;
}
* @@GaussDB@@
* Brief : static pgpid_t get_pgpid(void)
* Description : get pid number from pid file
* Notes :
*/
static pgpid_t get_pgpid(void)
{
FILE* pidf = NULL;
long pid;
pidf = fopen(pid_file, "r");
if (pidf == NULL) {
if (errno == ENOENT)
return 0;
else {
write_stderr(_("%s: could not open PID file \"%s\": %s\n"), progname, pid_file, gs_strerror(errno));
exit(1);
}
}
if (fscanf_s(pidf, "%ld", &pid) != 1) {
write_stderr(_("%s: invalid data in PID file \"%s\"\n"), progname, pid_file);
exit(1);
}
fclose(pidf);
return (pgpid_t)pid;
}
static void check_path(const char *path_name)
{
const char* danger_character_list[] = {"|",
";",
"&",
"$",
"<",
">",
"`",
"\\",
"'",
"\"",
"{",
"}",
"(",
")",
"[",
"]",
"~",
"*",
"?",
"!",
"\n",
NULL};
int i = 0;
for (i = 0; danger_character_list[i] != NULL; i++) {
if (strstr(path_name, danger_character_list[i]) != NULL) {
fprintf(stderr, "invalid token \"%s\" in path name: (%s)\n", danger_character_list[i], path_name);
exit(1);
}
}
}
* @@GaussDB@@
* Brief : static ErrCode writefile(char *path, char **lines,
UpdateOrAddParameter isAddorUpdate)
* Description : write record to the file
* Notes : if failed, return the reason
*/
ErrCode writefile(char* path, char** lines, UpdateOrAddParameter isAddorUpdate)
{
FILE* out_file = NULL;
char** line = NULL;
int fd = -1;
if (UPDATE_PARAMETER == isAddorUpdate) {
canonicalize_path(path);
if ((out_file = fopen(path, "w")) == NULL) {
(void)write_stderr(
_("%s: could not open file \"%s\" for writing: %s\n"), progname, path, gs_strerror(errno));
return CODE_OPEN_CONFFILE_FAILED;
}
fd = fileno(out_file);
if ((fd >= 0) && (-1 == fchmod(fd, S_IRUSR | S_IWUSR))) {
(void)write_stderr(_("could not set permissions of file \"%s\"\n"), path);
}
rewind(out_file);
for (line = lines; *line != NULL; line++) {
if (fputs(*line, out_file) < 0) {
(void)write_stderr(_("%s: could not write file \"%s\": %s\n"), progname, path, gs_strerror(errno));
fclose(out_file);
return CODE_WRITE_CONFFILE_ERROR;
}
}
} else if (ADD_PARAMETER == isAddorUpdate) {
canonicalize_path(path);
out_file = fopen(path, "a+");
if (NULL == out_file) {
(void)write_stderr(
_("%s: could not open file \"%s\" for writing: %s\n"), progname, path, gs_strerror(errno));
return CODE_OPEN_CONFFILE_FAILED;
}
(void)fseek(out_file, 0, SEEK_END);
if (fputs(*lines, out_file) < 0) {
(void)write_stderr(_("%s: could not write file \"%s\": %s\n"), progname, path, gs_strerror(errno));
fclose(out_file);
return CODE_WRITE_CONFFILE_ERROR;
}
} else {
return CODE_UNKOWN_ERROR;
}
* We don't care about the result.
*/
if (fsync(fileno(out_file)) != 0) {
(void)fclose(out_file);
(void)write_stderr(_("could not fsync file \"%s\": %s\n"), path, gs_strerror(errno));
return CODE_WRITE_CONFFILE_ERROR;
}
if (fclose(out_file)) {
(void)write_stderr(_("could not write file \"%s\": %s\n"), path, gs_strerror(errno));
return CODE_CLOSE_CONFFILE_FAILED;
}
return CODE_OK;
}
* @@GaussDB@@
* Brief : find_param_in_string(char *name_string,const char* name_param,size_t param_len)
* Description : find the param in a line
* Notes :
*/
static int find_param_in_string(const char* name_string, const char* name_param, size_t param_len)
{
char name_pri_temp[MAX_PARAM_LEN * 2] = {0};
char name_new_temp[MAX_PARAM_LEN] = {0};
char* cha = NULL;
char* chb = NULL;
int nRet = 0;
nRet = snprintf_s(name_pri_temp, MAX_PARAM_LEN * 2, MAX_PARAM_LEN * 2 - 1, "%s", name_string);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(name_new_temp, MAX_PARAM_LEN, MAX_PARAM_LEN - 1, "%s", name_param);
securec_check_ss_c(nRet, "\0", "\0");
cha = name_pri_temp;
chb = name_new_temp;
while (*cha) {
if (*cha >= 'A' && *cha <= 'Z')
*cha += 'a' - 'A';
cha++;
}
while (*chb) {
if (*chb >= 'A' && *chb <= 'Z')
*chb += 'a' - 'A';
chb++;
}
return strncmp(name_pri_temp, name_new_temp, param_len);
}
* @@GaussDB@@
* Brief : static void to_generatenewline(char* oldline, char* newline,
const char* param, const char* value, int optvalue_len)
* Description : according to the value from config file, make the new information
* Notes :
*/
static void to_generatenewline(char* oldline, char* newline, const char* param, const char* value, int optvalue_len)
{
char* poldline = NULL;
char* pnewline = NULL;
size_t paramlen = 0;
size_t valuelen = 0;
size_t offsetlen = 0;
int rc = 0;
if (NULL == oldline) {
return;
}
poldline = oldline;
pnewline = newline;
paramlen = (size_t)strnlen(param, MAX_PARAM_LEN);
valuelen = strnlen(value, MAX_VALUE_LEN);
while (isspace((unsigned char)*poldline)) {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
}
if (*poldline == '#') {
poldline++;
}
while (isspace((unsigned char)*poldline)) {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
}
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, paramlen);
securec_check_c(rc, "\0", "\0");
poldline += paramlen;
pnewline += paramlen;
offsetlen += paramlen;
while (isspace((unsigned char)*poldline)) {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
}
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
while (isspace((unsigned char)*poldline) && (unsigned char)*poldline != '\n') {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
}
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, value, valuelen);
securec_check_c(rc, "\0", "\0");
pnewline += valuelen;
poldline += optvalue_len;
offsetlen += valuelen;
* Not copy them to pnewline, untill the alpha '#' appear .
* After this, don't forget the end signal '\0'.
*/
while (*poldline && ('#' != *poldline)) {
if (isspace((unsigned char)*poldline)) {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
} else {
poldline++;
}
}
if (*poldline == '#') {
while (*poldline) {
rc = strncpy_s(pnewline, MAX_VALUE_LEN * 2 - offsetlen, poldline, 1);
securec_check_c(rc, "\0", "\0");
poldline++;
pnewline++;
offsetlen++;
}
}
*pnewline = '\0';
}
* @@GaussDB@@
* Brief : static int find_gucoption(char** optlines, const char* opt_name,
int* name_offset, int* name_len,
int* value_offset, int* value_len)
* Description : find the line information where the guc parameter in
* Notes :
*/
static int find_gucoption(
char** optlines, const char* opt_name, int* name_offset, int* name_len, int* value_offset, int* value_len)
{
bool isMatched = false;
int targetLine = 0;
int matchTimes = 0;
int i = 0;
size_t paramlen = 0;
if (NULL == optlines || NULL == opt_name) {
return INVALID_LINES_IDX;
}
paramlen = (size_t)strnlen(opt_name, MAX_PARAM_LEN);
if (NULL != name_len) {
*name_len = (int)paramlen;
}
for (i = 0; optlines[i] != NULL; i++) {
if (!isOptLineCommented(optlines[i])) {
isMatched = isMatchOptionName(optlines[i], opt_name, paramlen, name_offset, value_len, value_offset);
if (isMatched) {
matchTimes++;
targetLine = i;
}
}
}
if (matchTimes > 0) {
if (matchTimes > 1) {
(void)write_stderr("WARNING: There are %d \'%s\' not commented in \"postgresql.conf\", and only the "
"last one in %dth line will be set and used.\n",
matchTimes,
opt_name,
(targetLine + 1));
}
return targetLine;
}
matchTimes = 0;
for (i = 0; optlines[i] != NULL; i++) {
if (isOptLineCommented(optlines[i])) {
isMatched = isMatchOptionName(optlines[i], opt_name, paramlen, name_offset, value_len, value_offset);
if (isMatched) {
matchTimes++;
targetLine = i;
}
}
}
if (matchTimes > 0) {
return targetLine;
}
return INVALID_LINES_IDX;
}
* @@GaussDB@@
* Brief : free the space
* Description :
* Notes :
*/
void free_space(char** optlines, int size)
{
int i = 0;
if (NULL == optlines) {
return;
}
for (i = 0; i < size; i++) {
if (optlines[i] != NULL) {
GS_FREE(optlines[i]);
}
}
GS_FREE(optlines);
}
* @@GaussDB@@
* Brief : get the file lock
* Description : lock postgresql.conf.lock file
* Notes :
*/
ErrCode get_file_lock(const char* path, FileLock* filelock)
{
FILE* fp = NULL;
struct stat statbuf;
char content[PG_LOCKFILE_SIZE] = {0};
int i = 0;
int ret = -1;
char newpath[MAXPGPATH] = {'\0'};
if ((nodetype == INSTANCE_CMSERVER) ||
(nodetype == INSTANCE_CMAGENT))
{
return CODE_OK;
}
if (NULL == path) {
(void)write_stderr(_("%s: can not lock file: invalid path <NULL>"), progname);
return CODE_UNKOWN_ERROR;
}
ret = strcpy_s(newpath, sizeof(newpath), path);
securec_check_c(ret, "\0", "\0");
canonicalize_path(newpath);
if (checkPath(newpath) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), newpath, strerror(errno));
}
if (lstat(newpath, &statbuf) != 0) {
fp = fopen(newpath, PG_BINARY_W);
if (NULL == fp) {
(void)write_stderr(
_("%s: can't open lock file for write\"%s\" : %s\n"), progname, path, gs_strerror(errno));
return CODE_OPEN_CONFFILE_FAILED;
} else {
if (fwrite(content, PG_LOCKFILE_SIZE, 1, fp) != 1) {
fclose(fp);
(void)write_stderr(_("%s: can't write lock file \"%s\" : %s\n"), progname, path, gs_strerror(errno));
return CODE_WRITE_CONFFILE_ERROR;
}
fclose(fp);
}
}
fp = fopen(newpath, PG_BINARY_RW);
if (NULL == fp) {
(void)write_stderr(_("could not open file or directory \"%s\", errormsg: %s\n"), path, gs_strerror(errno));
return CODE_OPEN_CONFFILE_FAILED;
}
while (i < TRY_TIMES) {
ret = flock(fileno(fp), LOCK_EX | LOCK_NB, 0, START_LOCATION, statbuf.st_size);
if (ret == -1) {
i++;
sleep(1);
if (i >= TRY_TIMES) {
(void)write_stderr(
_("could not lock file or directory \"%s\", errormsg: %s\n"), path, gs_strerror(errno));
(void)write_stderr(_("HINT: This is transient error, as gaussdb is reading the configuration file. "
"Please re-execute the command again.\n"));
fclose(fp);
return CODE_LOCK_CONFFILE_FAILED;
}
continue;
}
break;
}
filelock->fp = fp;
filelock->size = statbuf.st_size;
return CODE_OK;
}
* @@GaussDB@@
* Brief : release_file_lock(FileLock* filelock)
* Description : release file
* Notes :
*/
void release_file_lock(FileLock* filelock)
{
if ((nodetype == INSTANCE_CMSERVER) ||
(nodetype == INSTANCE_CMAGENT))
{
return;
}
(void)flock(fileno(filelock->fp), LOCK_UN, 0, START_LOCATION, filelock->size);
fclose(filelock->fp);
filelock->fp = NULL;
filelock->size = 0;
}
Function : check_config_file_status
Description : check the status of postgresql.conf and postgresql.conf.bak
Input : None
Output : None
Return : int
FAILURE - These two files are not present.
SUCCESS - At least one file exists.
*******************************************************************************/
int check_config_file_status()
{
struct stat statbuf;
if ((lstat(gucconf_file, &statbuf) != 0) && (lstat(tempguc_file, &statbuf) != 0)) {
char* pchBasename = strrchr(gucconf_file, '/');
if (NULL == pchBasename) {
pchBasename = gucconf_file;
} else {
pchBasename++;
}
write_stderr(_("%s: %s does not exist!\n"), progname, pchBasename);
return FAILURE;
}
return SUCCESS;
}
Function : backup_config_file
Description : backup the config file.
Input : read_file - read file name
write_file - write file name
filelock - gucconf_lock_file
reserve_num_lines - reserve num lines
Output : None
Return : opt_lines
NULL - read/write write_file failed
opt_lines - SUCCESS
*******************************************************************************/
char** backup_config_file(const char* read_file, char* write_file, FileLock filelock, int reserve_num_lines)
{
char** opt_lines = NULL;
ErrCode ret = CODE_OK;
opt_lines = readfile(read_file, reserve_num_lines);
if (NULL == opt_lines) {
(void)write_stderr(_("read file \"%s\" failed: %s\n"), gucconf_file, gs_strerror(errno));
release_file_lock(&filelock);
return NULL;
}
ret = writefile(write_file, opt_lines, UPDATE_PARAMETER);
if (ret != CODE_OK) {
(void)write_stderr(_("could not write file \"%s\": %s\n"), write_file, gs_strerror(errno));
release_file_lock(&filelock);
freefile(opt_lines);
return NULL;
}
return opt_lines;
}
Function : do_parameter_value_write
Description : write the changed value into tempguc_file,
then rename tempguc_file to gucconf_file
Input : opt_lines - value information
updateoradd - operation action
Output : None
Return : int
*******************************************************************************/
int do_parameter_value_write(char** opt_lines, UpdateOrAddParameter updateoradd)
{
ErrCode ret = CODE_OK;
int nRet = 0;
char** newlines = NULL;
FILE* fp = NULL;
char newtempfile[MAXPGPATH * 2] = {0x00};
nRet = snprintf_s(newtempfile, MAXPGPATH * 2, MAXPGPATH * 2 - 1, "%s_bak", tempguc_file);
securec_check_ss_c(nRet, "\0", "\0");
ret = writefile(tempguc_file, opt_lines, updateoradd);
if (ret != CODE_OK) {
write_stderr("write file %s failed, errmsg: %s", tempguc_file, strerror(errno));
return FAILURE;
}
newlines = readfile(tempguc_file, 0);
if (NULL == newlines) {
write_stderr(_("read file \"%s\" failed: %s\n"), tempguc_file, gs_strerror(errno));
return FAILURE;
}
ret = writefile(newtempfile, newlines, UPDATE_PARAMETER);
freefile(newlines);
if (ret != CODE_OK) {
write_stderr(_("could not write file \"%s\": %s\n"), newtempfile, gs_strerror(errno));
return FAILURE;
}
if (0 != rename(newtempfile, gucconf_file)) {
write_stderr("error while moving file (%s to %s) : %s.\n", newtempfile, gucconf_file, strerror(errno));
(void)unlink(newtempfile);
return FAILURE;
}
fp = fopen(gucconf_file, "r");
if (NULL == fp) {
write_stderr(_("could not open file \"%s\", errormsg: %s\n"), gucconf_file, gs_strerror(errno));
return FAILURE;
}
if (fsync(fileno(fp)) != 0) {
(void)fclose(fp);
write_stderr(_("could not fsync file \"%s\": %s\n"), gucconf_file, gs_strerror(errno));
return FAILURE;
}
if (fclose(fp)) {
write_stderr(_("could not write file \"%s\": %s\n"), gucconf_file, gs_strerror(errno));
return FAILURE;
}
return SUCCESS;
}
bool
get_global_local_node_name()
{
if (NULL == g_local_node_name || '\0' == g_local_node_name[0]) {
char hostname[MAX_HOST_NAME_LENGTH] = {0};
int nRet = 0;
nRet = memset_s(hostname, MAX_HOST_NAME_LENGTH, '\0', MAX_HOST_NAME_LENGTH);
securec_check_c(nRet, "\0", "\0");
(void)gethostname(hostname, MAX_HOST_NAME_LENGTH);
if ('\0' == hostname[0]) {
write_stderr("ERROR: Failed to get local hostname.\n");
return FAILURE;
}
g_local_node_name = xstrdup(hostname);
}
return SUCCESS;
}
char **
append_string_info(char **optLines, const char *newContext)
{
int n = 0;
errno_t ret = 0;
while (NULL != optLines[n]) {
n += 1;
}
char** optLinesResult = (char**)pg_malloc_zero(sizeof(char *) * (n + 2));
ret = memcpy_s(optLinesResult, sizeof(char *) * (n + 2), optLines, sizeof(char *) * (n + 1));
securec_check_c(ret, "\0", "\0");
GS_FREE(optLines);
optLinesResult[n] = xstrdup(newContext);
optLinesResult[n + 1] = NULL;
return optLinesResult;
}
#ifndef ENABLE_MULTIPLE_NODES
* For a line in the configuration file, skip current spaces.
*/
static void SkipSpace(char* &line)
{
while (line != NULL && isspace((unsigned char)*line)) {
++line;
}
}
* Handle commented lines in the configuration file.
* return:
* true - replconninfoX is commented
* false - replconninfoX is not in current line.
*/
static bool ProcessCommented(char* &line, char* replconninfoX)
{
++line;
SkipSpace(line);
if (line != NULL && strncmp(line, replconninfoX, strlen(replconninfoX)) == 0) {
return true;
}
return false;
}
* Handle lines which is not commented in the configuration file.
* notNullReplconninfoNums - the number of replconninfo which is not null
* matchReplconninfoX - whether replconninfoX is in current line.
* isReplconninfoXNull - whether replconninfoX is NULL.
*/
static void ProcessNotCommented(char* &line, char* replconninfoX,
int ¬NullReplconninfoNums, bool &isReplconninfoXNull, bool &matchReplconninfoX)
{
if (line != NULL && strncmp(line, "replconninfo", strlen("replconninfo")) == 0) {
if (strncmp(line, replconninfoX, strlen(replconninfoX)) == 0) {
matchReplconninfoX = true;
}
line += strlen(replconninfoX);
SkipSpace(line);
if (line != NULL && *line == '=') {
line++;
}
SkipSpace(line);
if (line != NULL && strncmp(line, "''", strlen("''")) != 0 &&
strncmp(line, "\"\"", strlen("\"\"")) != 0) {
++notNullReplconninfoNums;
if (matchReplconninfoX) {
isReplconninfoXNull = false;
}
}
}
}
Function : IsLastNotNullReplconninfo
Description : determine if replconninfoX which is being set is the last one valid replconninfo
Input : optLines - postgres.conf info before changing
replconninfoX - replconninfo param name which is being set, eg "replconninfo1"
Output : None
Return : bool
*******************************************************************************/
static bool IsLastNotNullReplconninfo(char** optLines, char* replconninfoX)
{
int notNullReplconninfoNums = 0;
bool isReplconninfoXNull = true;
bool matchReplconninfoX = false;
char* p = NULL;
for (int i = 0; optLines != NULL && optLines[i] != NULL; i++) {
p = optLines[i];
SkipSpace(p);
if (p == NULL) {
continue;
}
if (*p == '#') {
if(ProcessCommented(p, replconninfoX)) {
return false;
} else {
continue;
}
}
ProcessNotCommented(p, replconninfoX, notNullReplconninfoNums,
isReplconninfoXNull, matchReplconninfoX);
if (notNullReplconninfoNums > 1) {
return false;
}
}
if (notNullReplconninfoNums == 1 && !isReplconninfoXNull) {
return true;
}
return false;
}
static void CheckLastValidReplconninfo(char** opt_lines, int idx)
{
if (strncmp(config_param[idx], "replconninfo", strlen("replconninfo")) == 0 &&
config_value[idx] != NULL && (strlen(config_value[idx]) == 0 ||
strncmp(config_value[idx], "''", strlen("''")) == 0) &&
IsLastNotNullReplconninfo(opt_lines, config_param[idx])) {
write_stderr("\nWARNING: This is the last valid replConnInfo, once set to null, "
"the host role will be changed to Normal if the local_role is primary now.\n");
}
}
static void CheckKeepSyncWindow(char** opt_lines, int idx)
{
if (strcmp(config_param[idx], "keep_sync_window") == 0) {
write_stderr("\nWARNING: If the primary server fails during keep_sync_window, the transactions which "
"were blocked during keep_sync_window will be lost and can't get recovered. This will affect RPO.\n");
}
}
#endif
static void
parse_next_sync_groups(char **pgroup, char *result)
{
if (**pgroup == '\0') {
result[0] = '\0';
return;
}
char *this_group = *pgroup;
char *p = *pgroup;
while (*p != '\0' && *p != ')') p++;
while (*p != '\0' && *p != ',') p++;
if (*p == ',') {
*p = '\0';
p++;
}
*pgroup = p;
errno_t rc = snprintf_s(result, MAX_VALUE_LEN, MAX_VALUE_LEN - 1, "'%s'", this_group);
securec_check_ss_c(rc, "\0", "\0");
return;
}
static int
transform_az_name(char *config_value, char *allAZString, int allAZStringBufLen, const char *data_dir)
{
if (strcmp(config_value, "''") == 0) {
errno_t rc = strncpy_s(allAZString, allAZStringBufLen, config_value, strlen(config_value));
securec_check_c(rc, "\0", "\0");
return SUCCESS;
}
char *azString = NULL;
char *buf = allAZString;
int buflen = allAZStringBufLen;
char *allgroup = xstrdup(config_value);
char *pgrp = allgroup + 1;
char this_group[MAX_VALUE_LEN] = {0x00};
allgroup[strlen(allgroup) - 1] = '\0';
parse_next_sync_groups(&pgrp, this_group);
while (this_group[0] != '\0') {
azString = get_AZ_value(this_group, data_dir);
if (NULL == azString) {
GS_FREE(allgroup);
return FAILURE;
}
int azStringLen = strlen(azString);
azString[0] = ' ';
azString[azStringLen - 1] = ',';
errno_t rc = strncpy_s(buf, buflen, azString, azStringLen);
securec_check_c(rc, "\0", "\0");
buf += azStringLen;
buflen -= azStringLen;
GS_FREE(azString);
parse_next_sync_groups(&pgrp, this_group);
}
GS_FREE(allgroup);
allAZString[0] = allAZString[strlen(allAZString) - 1] = '\'';
return SUCCESS;
}
* @@GaussDB@@
* Brief :
* Description :
* Notes :
*/
static int
do_gucset(const char *action_type, const char *data_dir)
{
char** opt_lines = NULL;
int lines_index = 0;
char* new_option = NULL;
size_t new_optlen = 0;
size_t newvalue_len = 0;
int optvalue_off = 0;
int optvalue_len = 0;
int nRet = 0;
int rc = 0;
int i = 0;
char *tmpAZStr = NULL;
char optconf_line[MAX_PARAM_LEN * 2] = {0x00};
char newconf_line[MAX_PARAM_LEN * 2] = {0x00};
struct stat statbuf;
struct stat tempbuf;
int func_status = -1;
int result_status = SUCCESS;
int ss_lines_index = 0;
int ss_optvalue_off = 0;
int ss_optvalue_len = 0;
char ss_enable_dss[MAX_VALUE_LEN] = {0x00};
FileLock filelock = {NULL, 0};
UpdateOrAddParameter updateoradd = UPDATE_PARAMETER;
if (SUCCESS != check_config_file_status())
return FAILURE;
if (lstat(gucconf_file, &statbuf) == 0 && statbuf.st_size == 0 &&
lstat(tempguc_file, &tempbuf) == 0 && tempbuf.st_size != 0) {
write_stderr(_("%s: the last signal is now,waiting....\n"), progname);
return FAILURE;
}
if (get_file_lock(gucconf_lock_file, &filelock) != CODE_OK)
return FAILURE;
if (lstat(gucconf_file, &statbuf) != 0)
opt_lines = backup_config_file(tempguc_file, gucconf_file, filelock, 0);
else
opt_lines = backup_config_file(gucconf_file, tempguc_file, filelock, 0);
if (NULL == opt_lines)
return FAILURE;
ss_lines_index = find_gucoption(opt_lines, "ss_enable_dss", NULL, NULL, &ss_optvalue_off, &ss_optvalue_len);
if (INVALID_LINES_IDX != ss_lines_index) {
rc = strncpy_s(ss_enable_dss, MAX_VALUE_LEN,
(opt_lines[ss_lines_index] + ss_optvalue_off), (size_t)ss_optvalue_len);
securec_check_c(rc, "\0", "\0");
}
for (i = 0; i < config_param_number; i++)
{
if (NULL == config_param[i]) {
release_file_lock(&filelock);
freefile(opt_lines);
GS_FREE(tmpAZStr);
write_stderr( _("%s: invalid input parameters\n"), progname);
return FAILURE;
}
if (g_need_changed && 0 == strncmp(config_param[i], "synchronous_standby_names",
strlen(config_param[i]) > strlen("synchronous_standby_names") ? strlen(config_param[i]) : strlen("synchronous_standby_names"))) {
if (FAILURE == get_global_local_node_name()) {
release_file_lock(&filelock);
freefile(opt_lines);
GS_FREE(tmpAZStr);
return FAILURE;
}
if (NULL != config_value[i]) {
char allAZString[MAX_VALUE_LEN] = {0x00};
result_status = transform_az_name(config_value[i], allAZString, MAX_VALUE_LEN, data_dir);
if (result_status == FAILURE) {
continue;
}
tmpAZStr = xstrdup(config_value[i]);
GS_FREE(config_value[i]);
config_value[i] = xstrdup(allAZString);
}
}
#ifndef ENABLE_MULTIPLE_NODES
CheckLastValidReplconninfo(opt_lines, i);
CheckKeepSyncWindow(opt_lines, i);
#endif
lines_index = find_gucoption(opt_lines, config_param[i], NULL, NULL, &optvalue_off, &optvalue_len);
if (INVALID_LINES_IDX != lines_index) {
size_t line_len = 0;
line_len = strlen(opt_lines[lines_index]);
rc = strncpy_s(optconf_line, MAX_PARAM_LEN*2, opt_lines[lines_index], (size_t)Min(line_len, MAX_PARAM_LEN*2 - 1));
securec_check_c(rc, "\0", "\0");
if (NULL != config_value[i]) {
to_generatenewline(optconf_line, newconf_line, config_param[i], config_value[i], optvalue_len);
} else {
* if parameter as value is NULL; consider it as UNSET (i.e to default value)
* which means comment the configuration parameter
*/
if (isOptLineCommented(optconf_line)) {
rc = strncpy_s(newconf_line, MAX_PARAM_LEN*2, optconf_line, (size_t)Min(line_len, MAX_PARAM_LEN*2 - 1));
securec_check_c(rc, "\0", "\0");
} else {
nRet = snprintf_s(newconf_line, MAX_PARAM_LEN*2, MAX_PARAM_LEN*2 - 1, "#%s", optconf_line);
securec_check_ss_c(nRet, "\0", "\0");
}
}
updateoradd = UPDATE_PARAMETER;
} else {
* then add the guc parameter to the tail of config file
*/
updateoradd= ADD_PARAMETER;
}
if (UPDATE_PARAMETER == updateoradd) {
GS_FREE(opt_lines[lines_index]);
opt_lines[lines_index] = xstrdup(newconf_line);
} else {
* Total length = parameter_name_length + ' = ' + parameter_value_length + '\n'
*/
size_t param_len=0;
* if parameter not found and in case of default value skip the process.
* so that server takes anyway default value.
*/
if (NULL != config_value[i]) {
newvalue_len = strnlen(config_value[i], MAX_VALUE_LEN);
param_len = strnlen(config_param[i], MAX_VALUE_LEN);
new_optlen = Min(param_len + EQUAL_MARK_LEN + newvalue_len + 1,(size_t)(MAX_VALUE_LEN-1) );
new_option = (char *)pg_malloc_zero(new_optlen + 1);
nRet = snprintf_s(new_option, (new_optlen + 1), new_optlen, "%s = %s\n", config_param[i], config_value[i]);
securec_check_ss_c(nRet, "\0", "\0");
new_option[new_optlen] = '\0';
opt_lines = append_string_info(opt_lines, new_option);
GS_FREE(new_option);
}
}
}
func_status = do_parameter_value_write(opt_lines, UPDATE_PARAMETER);
if (SUCCESS == func_status) {
for (i = 0; i < config_param_number; i++) {
if (NULL != config_value[i]) {
write_stderr( "gs_guc %s: %s=%s: [%s]\n", action_type, config_param[i], config_value[i], gucconf_file);
} else {
write_stderr( "gs_guc %s: #%s: [%s]\n", action_type, config_param[i], gucconf_file);
}
}
} else {
result_status = FAILURE;
}
release_file_lock(&filelock);
freefile(opt_lines);
for (i = 0; i < config_param_number; i++) {
if (g_need_changed && 0 == strncmp(config_param[i], "synchronous_standby_names",
strlen(config_param[i]) > strlen("synchronous_standby_names") ?
strlen(config_param[i]) : strlen("synchronous_standby_names"))) {
if (NULL != config_value[i] && tmpAZStr != NULL) {
GS_FREE(config_value[i]);
config_value[i] = xstrdup(tmpAZStr);
GS_FREE(tmpAZStr);
}
}
}
if (SUCCESS == result_status) {
return SUCCESS;
} else {
return FAILURE;
}
}
Function: do_guccheck
Desc : do gs_guc check option
param - the parameter name
Return : char *
NULL it means that the guc file is not incorrect.
*************************************************************************************/
static char* do_guccheck(const char* param)
{
char** opt_lines = NULL;
struct stat statbuf;
int lines_index = 0;
int optvalue_off = 0;
int optvalue_len = 0;
char* guc_value = NULL;
int ret = 0;
if (NULL == param) {
write_stderr(_("%s: invalid input parameters\n"), progname);
return NULL;
}
if (SUCCESS != check_config_file_status())
return NULL;
if (lstat(gucconf_file, &statbuf) != 0)
opt_lines = readfile(tempguc_file, 0);
else
opt_lines = readfile(gucconf_file, 0);
if (NULL == opt_lines) {
write_stderr(_("read file \"%s\" failed: %s\n"), gucconf_file, gs_strerror(errno));
return NULL;
}
lines_index = find_gucoption(opt_lines, param, NULL, NULL, &optvalue_off, &optvalue_len);
guc_value = (char*)pg_malloc_zero(MAX_VALUE_LEN * sizeof(char));
* if the parameter is not found and the option line starts with '#', the value is NULL.
*/
if (INVALID_LINES_IDX != lines_index && !isOptLineCommented(opt_lines[lines_index])) {
ret = strncpy_s(guc_value,
MAX_VALUE_LEN,
(opt_lines[lines_index] + optvalue_off),
Min((size_t)optvalue_len, MAX_VALUE_LEN - 1));
} else {
ret = strncpy_s(guc_value, MAX_VALUE_LEN, "NoFound", strlen("NoFound"));
}
securec_check_c(ret, "\0", "\0");
freefile(opt_lines);
return guc_value;
}
void ReadDBStateFile(GaussState* state)
{
FILE* statef = NULL;
if (state == NULL) {
write_stderr(_(" Could not get information from gaussdb.state\n"));
return;
}
statef = fopen(gaussdb_state_file, "r");
if (statef == NULL) {
if (errno == ENOENT) {
write_stderr(_(" file \"%s\" is not exist\n"), gaussdb_state_file);
} else {
write_stderr(_(" open file \"%s\" failed : %s\n"), gaussdb_state_file, strerror(errno));
}
exit(1);
}
if (0 == fread(state, 1, sizeof(GaussState), statef)) {
write_stderr(_(" read file \"%s\" failed\n"), gaussdb_state_file);
}
(void)fclose(statef);
statef = NULL;
}
* @@GaussDB@@
* Brief : static void do_config_reload()
* Description : reload config file
* Notes :
*/
int do_config_reload()
{
pgpid_t pid;
GaussState state;
errno_t tnRet = 0;
pid = get_pgpid();
if (pid == 0) {
write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
write_stderr(_("Is server running?\n"));
return FAILURE;
} else if (pid < 0) {
pid = -pid;
write_stderr(_("%s: cannot reload server; "
"single-user server is running (PID: %ld)\n"),
progname, pid);
write_stderr(_("Please terminate the single-user server and try again.\n"));
return FAILURE;
}
if (kill(pid, 0) != 0) {
write_stderr(_("gaussdb is not alive.\n"));
return FAILURE;
}
tnRet = memset_s(&state, sizeof(state), 0, sizeof(state));
securec_check_c(tnRet, "\0", "\0");
ReadDBStateFile(&state);
switch (state.state) {
case NORMAL_STATE:
case NEEDREPAIR_STATE:
case WAITING_STATE:
case DEMOTING_STATE:
case PROMOTING_STATE:
case BUILDING_STATE:
case CATCHUP_STATE:
break;
case COREDUMP_STATE:
write_stderr(_("ERROR: gaussDB state is Coredump\n"));
return FAILURE;
case UNKNOWN_STATE:
case STARTING_STATE:
write_stderr(_("ERROR: gaussDB state is Unknown or Staring\n"));
return FAILURE;
default:
write_stderr(_("ERROR: gaussDB state is Invalid\n"));
return FAILURE;
}
if (kill((pid_t)pid, sig) != 0) {
write_stderr(
_("%s: could not send reload signal (PID: %ld sig=%d): %s\n"), progname, pid, sig, gs_strerror(errno));
return FAILURE;
}
write_stderr(_("server signaled\n"));
return SUCCESS;
}
* @@GaussDB@@
* Brief :
* Description :
* Notes :
*/
void do_advice(void)
{
printf(_("Try \"%s --help\" for more information.\n"), progname);
}
static void do_help(void)
{
(void)printf(_("%s is an inferface to modify config files or encrypt plain text to cipher text.\n"), progname);
do_help_check_guc();
do_help_config_guc();
do_help_config_hba();
do_help_encrypt();
do_help_generate();
do_help_common_options();
do_help_set_reset_options();
do_help_encrypt_options();
do_help_generate_options();
}
Function: do_help_check_guc
Desc : function to print the help information about "gs_guc check"
Return :
*************************************************************************************/
static void do_help_check_guc(void)
{
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(_("\nChecking GUC parameters:\n"));
(void)printf(_(" %s check -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} {-c \"parameter\", -c "
"\"parameter\", ...}\n"),
progname);
(void)printf(_(" %s check -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} {-c parameter, -c "
"parameter, ...}\n"),
progname);
(void)printf(_("\nOptions for check with -c parameter: \n"));
(void)printf(_(" -Z NODE-TYPE only can be \"coordinator\" or \"datanode\"\n"));
#else
#ifdef ENABLE_LITE_MODE
(void)printf(_("\nChecking GUC parameters:\n"));
(void)printf(_(" %s check [-Z NODE-TYPE] -D DATADIR {-c \"parameter\", -c "
"\"parameter\", ...}\n"), progname);
(void)printf(_(" %s check [-Z NODE-TYPE] -D DATADIR {-c parameter, -c "
"parameter, ...}\n"), progname);
#else
(void)printf(_("\nChecking GUC parameters:\n"));
(void)printf(_(" %s check [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} {-c \"parameter\", -c "
"\"parameter\", ...}\n"),
progname);
(void)printf(_(" %s check [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} {-c parameter, -c "
"parameter, ...}\n"),
progname);
#endif
#endif
}
static void do_help_config_guc(void)
{
(void)printf(_("\nConfiguring GUC parameters:\n"));
(void)printf(_(" Usage:\n"));
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(_(" NODE-TYPE is coordinator, datanode or gtm:\n"));
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = value\" -c \"parameter = value\" ...}\n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = value \" -c \" parameter = value \" ...}\n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = \'value\'\" -c \"parameter = \'value\'\" ...}\n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = \'value\' \" -c \" parameter = \'value\' \" ...}\n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] {-c \"parameter\" -c \"parameter\" ...}\n"),
progname);
(void)printf(_(" NODE-TYPE is cmserver or cmagent:\n"));
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N all -I all] "
"{-c \"parameter = value\" -c \"parameter = value\" ...}\n"), progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N all -I all] "
"{-c \" parameter = \'value\' \" -c \" parameter = \'value\' \" ...}\n"), progname);
(void)printf(_("\n If the parameter is a string variable, use the form: -c \"parameter = \'value\'\",\n"));
(void)printf(_(" and if there is \" in the value, please transfer it with \\ carefully.\n"));
(void)printf(
_(" e.g. %s set -Z coordinator -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s set -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s set -Z coordinator -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"),
progname);
(void)printf(
_(" e.g. %s reload -Z coordinator -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s reload -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(_(" e.g. %s reload -Z coordinator -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", "
"World\\!\'\".\n"),
progname);
(void)printf(
_(" e.g. %s set -Z cmserver -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(_(" e.g. %s set -Z cmserver -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s set -Z cmagent -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(_(" e.g. %s set -Z cmagent -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
#else
#ifdef ENABLE_LITE_MODE
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = value\" -c \"parameter = value\" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = value \" -c \" parameter = value \" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = \'value\'\" -c \"parameter = \'value\'\" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = \'value\' \" -c \" parameter = \'value\' \" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--lcname=LCNAME] [--ignore-node=NODES] {-c \"parameter\" -c \"parameter\" ...}\n"), progname);
(void)printf(
_(" e.g. %s set -Z datanode -D /datanode/data -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s reload -Z datanode -D /datanode/data -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
#else
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = value\" -c \"parameter = value\" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = value \" -c \" parameter = value \" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \"parameter = \'value\'\" -c \"parameter = \'value\'\" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] "
"{-c \" parameter = \'value\' \" -c \" parameter = \'value\' \" ...}\n"), progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--lcname=LCNAME] [--ignore-node=NODES] {-c \"parameter\" -c \"parameter\" ...}\n"), progname);
(void)printf(
_(" e.g. %s set -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
(void)printf(
_(" e.g. %s reload -Z datanode -N all -I all -c \"program = \'\\\"Hello\\\", World\\!\'\".\n"), progname);
#endif
#endif
(void)printf(_("\n If parameter value set or reload to DEFAULT OR COMMENT configuration parameter, use the form: "
"-c \"parameter\"\n"));
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(_(" and only \"coordinator\", \"datanode\" and \"gtm\" can be supported."));
#endif
(void)printf(_("\n You can choose Usage as you like, and perhaps the first one "));
(void)printf(_("will be more suitable for you!\n"));
}
static void do_help_config_hba(void)
{
(void)printf(_("\nConfiguring Authentication Policy:\n"));
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME HOSTNAME AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" If authentication policy need to set/reload DEFAULT OR COMMENT then provide without "
"authentication menthod, use the form: \n"));
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK\" \n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK \" \n"),
progname);
(void)printf(_(" %s {set | reload} -Z NODE-TYPE [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME HOSTNAME\" \n"),
progname);
#else
#ifdef ENABLE_LITE_MODE
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME HOSTNAME AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" If authentication policy need to set/reload DEFAULT OR COMMENT then provide without "
"authentication menthod, use the form: \n"));
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK \" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] -D DATADIR "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME HOSTNAME\" \n"),
progname);
#else
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] "
"-h \"HOSTTYPE DATABASE USERNAME HOSTNAME AUTHMEHOD authentication-options\" \n"),
progname);
(void)printf(_(" If authentication policy need to set/reload DEFAULT OR COMMENT then provide without "
"authentication menthod, use the form: \n"));
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR IPMASK\" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME IPADDR-WITH-IPMASK \" \n"),
progname);
(void)printf(_(" %s {set | reload} [-Z NODE-TYPE] [-N NODE-NAME] {-I INSTANCE-NAME | -D DATADIR} "
"[--ignore-node=NODES] -h \"HOSTTYPE DATABASE USERNAME HOSTNAME\" \n"),
progname);
#endif
#endif
}
static void do_help_encrypt(void)
{
(void)printf(_("\nEncrypt plain text to cipher text:\n"));
(void)printf(_(" %s encrypt [-M keymode] -K password [-U username] "
"{-D DATADIR | -R RANDFILEDIR -C CIPHERFILEDIR}\n"), progname);
}
static void do_help_generate(void)
{
(void)printf(_("\nGenerate plain cipher key to cipher text:\n"));
(void)printf(_(" %s generate [-o prefix] -S cipherkey -D DATADIR\n"), progname);
}
static void do_help_common_options(void)
{
(void)printf(_("\nCommon options:\n"));
#ifndef ENABLE_LITE_MODE
(void)printf(_(" -N nodename in which this command need to be executed\n"));
(void)printf(_(" -I instance name\n"));
#endif
(void)printf(_(" -D, --pgdata=DATADIR location of the database storage area\n"));
(void)printf(_(" -c parameter=value the parameter to set\n"));
(void)printf(_(" -c parameter the parameter value to DEFAULT (i.e comments in configuration file)\n"));
(void)printf(_(" --lcname=LCNAME logical cluter name. It only can be used with datanode\n"));
(void)printf(_(" --ignore-node=NODES Nodes which need to ignore. "
"It only can be used with set/reload operation,and CN/DN nodetype\n"));
(void)printf(_(" -h host-auth-policy to set authentication policy in HBA conf file\n"));
(void)printf(_(" -?, --help show this help, then exit\n"));
(void)printf(_(" -V, --version output version information, then exit\n"));
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(
_("If the -D option is omitted, the environment variable PGDATA or GTMDATA is used based on NODE-TYPE.\n"));
#endif
}
static void do_help_set_reset_options(void)
{
#ifdef ENABLE_MULTIPLE_NODES
(void)printf(_("\nOptions for set with -c parameter: \n"));
(void)printf(_(" -Z NODE-TYPE can be \"coordinator\", \"datanode\", \"cmserver\", \"cmagent\", or \"gtm\". "));
(void)printf(_("NODE-TYPE is used to identify configuration file (with -c parameter) in data directory\n"));
(void)printf(_(" \"coordinator\" or \"datanode\" -- postgresql.conf\n"));
(void)printf(_(" \"coordinator\" and \"datanode\" -- postgresql.conf\n"));
(void)printf(_(" \"cmserver\" -- cm_server.conf\n"));
(void)printf(_(" \"cmagent\" -- cm_agent.conf\n"));
(void)printf(_(" \"gtm\" -- gtm.conf\n"));
(void)printf(_("\nOptions for set and reload with -h host-auth-policy: \n"));
(void)printf(_(" -Z NODE-TYPE can be \"coordinator\", or \"datanode\"\n"));
#else
#ifdef ENABLE_LITE_MODE
(void)printf(_("\nOptions for set with -c parameter: \n"));
(void)printf(_(" -Z NODE-TYPE can only be \"datanode\", default is \"datanode\". "));
(void)printf(_("NODE-TYPE is used to identify configuration file (with -c parameter) in data directory\n"));
(void)printf(_(" \"datanode\" -- postgresql.conf\n"));
(void)printf(_("\nOptions for set and reload with -h host-auth-policy: \n"));
(void)printf(_(" -Z NODE-TYPE can only be \"datanode\", default is \"datanode\"\n"));
#else
(void)printf(_("\nOptions for set with -c parameter: \n"));
(void)printf(_(" -Z NODE-TYPE can be \"datanode\", \"cmserver\" or \"cmagent\". "));
(void)printf(_("NODE-TYPE is used to identify configuration file (with -c parameter) in data directory\n"));
(void)printf(_(" \"datanode\" -- postgresql.conf\n"));
(void)printf(_(" \"cmserver\" -- cm_server.conf\n"));
(void)printf(_(" \"cmagent\" -- cm_agent.conf\n"));
(void)printf(_("\nOptions for set and reload with -h host-auth-policy: \n"));
(void)printf(_(" -Z NODE-TYPE can only be \"datanode\"\n"));
#endif
#endif
}
static void do_help_encrypt_options(void)
{
(void)printf(_("\nOptions for encrypt: \n"));
(void)printf(_(" -M, --keymode=MODE the cipher files will be applies in server, client or source,default "
"value is server mode\n"));
(void)printf(_(" -K PASSWORD the plain password you want to encrypt, which length should between "
"8~15 and at least 3 different types of characters\n"));
(void)printf(_(" -U, --keyuser=USER if appointed, the cipher files will name with the user name\n"));
(void)printf(_(" -R RANDFILEDIR set the dir that put the rand file\n"));
(void)printf(_(" -C CIPHERFILEDIR set the dir that put the cipher file\n"));
(void)printf(_("\n"));
}
static void do_help_generate_options(void)
{
(void)printf(_("\nOptions for generate: \n"));
(void)printf(_(" -o PREFIX the cipher files prefix. default value is obsserver\n"));
(void)printf(_(" -S CIPHERKEY the plain password you want to encrypt, which length should between "
"8~15 and at least 3 different types of characters\n"));
}
* @@GaussDB@@
* Brief :
* Description :
* Notes :
*/
static void checkArchivepath(const char* paraValue)
{
char xlogarchpath[MAXPGPATH * 2] = {'\0'};
char* endsp = NULL;
int rc = 0;
if (paraValue == NULL || *paraValue == 0) {
write_stderr(_("%s:The archive command is empty.\n"), progname);
exit(1);
}
if ((int)strlen(paraValue) + 1 > MAX_VALUE_LEN) {
write_stderr(
_("%s: The value of parameter archive_command is too long. Please check and make sure it is correct.\n"),
progname);
exit(1);
}
rc = snprintf_s(xlogarchpath, MAXPGPATH * 2, MAXPGPATH * 2 - 1, "%s", paraValue);
securec_check_ss_c(rc, "\0", "\0");
if ((endsp = strstr(xlogarchpath, "%f")) == NULL) {
write_stderr(_("%s:The parameter \"archive_command\" should be set with \"%%f\".\n"), progname);
exit(1);
}
if ((endsp = strstr(xlogarchpath, "%p")) == NULL) {
write_stderr(_("%s:The parameter \"archive_command\" should be set with \"%%p\".\n"), progname);
exit(1);
}
}
static bool is_file_exist(const char* path)
{
struct stat statbuf;
bool isExist = true;
if (lstat(path, &statbuf) < 0) {
if (errno != ENOENT) {
write_stderr(_("could not stat file \"%s\": %s\n"), path, strerror(errno));
exit(1);
}
isExist = false;
}
return isExist;
}
static bool is_gs_build_pid(const char* pid_path)
{
FILE* pidf = NULL;
long pid = 0;
bool ret = false;
pidf = fopen(pid_path, "r");
if (pidf == NULL) {
if (errno != ENOENT) {
write_stderr(_("The file \"%s\" open failed: %s.\n"), pid_path, strerror(errno));
exit(1);
}
goto fun_exit;
}
if (fscanf_s(pidf, "%ld", &pid) != 1) {
goto fun_exit;
}
fun_exit:
if (pidf != NULL) {
fclose(pidf);
pidf = NULL;
}
if (pid != 0 && (kill(pid, 0) == 0)) {
ret = true;
}
return ret;
}
* @@GaussDB@@
* Brief : static void check_build_status(const char* path)
* Description : check whether the build is starting
* Notes :
*/
static void check_build_status(const char* path)
{
int ss_c = 0;
char tmpfilename1[MAXPGPATH];
char tmpfilename2[MAXPGPATH];
ss_c = snprintf_s(tmpfilename1, MAXPGPATH, MAXPGPATH - 1, "%s/%s", path, "build_completed.start");
securec_check_ss_c(ss_c, "", "");
ss_c = snprintf_s(tmpfilename2, MAXPGPATH, MAXPGPATH - 1, "%s/%s", path, "gs_build.pid");
securec_check_ss_c(ss_c, "", "");
if (is_file_exist(tmpfilename1) || is_gs_build_pid(tmpfilename2)) {
write_stderr(_("%s:The gs_ctl build is doing now, the gs_guc process should be stopped.\n"), progname);
exit(1);
}
}
* obtain_parameter_list_array
* During parameter parsing, the parameters with the same name will overwrite the previous parameters.
* key : the parameter name
* value : the parameter value
*/
void
obtain_parameter_list_array(const char *key, const char *value)
{
int i = 0;
for(i = 0; i < config_param_number; i++)
{
if (0 == strncmp(config_param[i], key,
strlen(config_param[i]) > strlen(key) ? strlen(config_param[i]) : strlen(key))) {
GS_FREE(config_param[i]);
GS_FREE(config_value[i]);
config_param[i] = xstrdup(key);
if (NULL != value) {
config_value[i] = xstrdup(value);
} else {
config_value[i] = NULL;
}
return;
}
}
config_param[config_param_number++] = xstrdup(key);
if (NULL != value) {
config_value[config_value_number++] = xstrdup(value);
} else {
config_value[config_value_number++] = NULL;
}
}
* @@GaussDB@@
* Brief : static void do_analysis(const char* strcmd)
* Description : save the parameter and value into array
* Notes :
*/
static void do_analysis(const char* strcmd)
{
char* tempcmd = NULL;
char* pcmd = NULL;
if (strcmd == NULL)
{
write_stderr(_("%s:the config command is wrong.\n"), progname);
do_advice();
exit(1);
}
if (config_param_number > arraysize || config_value_number > arraysize)
{
write_stderr(_("%s: The number of config parameters:%d exceed the arraysize:%d\n"),
progname,
config_param_number,
arraysize);
do_advice();
exit(1);
}
pcmd = (char*)strstr(strcmd, "=");
if (NULL == pcmd) {
trimBlanksTwoEnds((char**)&strcmd);
if ((int)strlen(strcmd) > MAX_PARAM_LEN) {
(void)write_stderr(
_("%s: The parameter %s is too long. Please check and make sure it is correct.\n"), progname, strcmd);
exit(1);
}
obtain_parameter_list_array(strcmd, NULL);
return;
}
*pcmd = '\0';
tempcmd = pcmd + 1;
if (0 == strncmp(strcmd, "archive_command", 15)) {
checkArchivepath(tempcmd);
}
trimBlanksTwoEnds((char**)&strcmd);
trimBlanksTwoEnds(&tempcmd);
if ((int)strlen(strcmd) > MAX_PARAM_LEN) {
(void)write_stderr(
_("%s: The parameter %s is too long. Please check and make sure it is correct.\n"), progname, strcmd);
exit(1);
}
if (NULL != tempcmd && (int)strlen(tempcmd) > MAX_VALUE_LEN) {
(void)write_stderr(_("%s: The value of parameter %s is too long. Please check and make sure it is correct.\n"),
progname,
strcmd);
exit(1);
}
obtain_parameter_list_array(strcmd, tempcmd);
}
Function : do_check_parameter_name_type
Description : check the type of parameter name
Input : None
Output : If the type is incorrect, do exit(1).
Return : void
*******************************************************************************/
void do_check_parameter_name_type()
{
int i = 0;
int j = 0;
int name_len = 0;
for (i = 0; i < config_param_number; i++) {
name_len = strnlen(config_param[i], MAX_PARAM_LEN);
if ((*(config_param[i] + 0)) == '_' || *(config_param[i] + name_len - 1) == '_')
{
write_stderr(_("The parameter(%s) exists illegal character:%c(or:%c)\n"),
config_param[i],
*(config_param[i] + 0),
*(config_param[i] + name_len - 1));
do_advice();
exit(1);
}
for (j = 0; j < (int)strnlen(config_param[i], MAX_PARAM_LEN); j++) {
if ((!isalpha((unsigned char)(*(config_param[i] + j)))) &&
(!isdigit((unsigned char)(*(config_param[i] + j))))) {
if ((*(config_param[i] + j)) != '_') {
write_stderr(
_("The parameter(%s)exists illegal character:%c\n"), config_param[i], *(config_param[i] + j));
do_advice();
exit(1);
}
}
}
}
}
Function : do_check_parameter_value_type
Description : check the type of parameter value
Input : None
Output : If the type is incorrect, do exit(1).
Return : void
*******************************************************************************/
void do_check_parameter_value_type()
{
int i = 0;
int j = 0;
int num = 0;
for (i = 0; i < config_value_number; i++) {
if (NULL == config_value[i]) {
continue;
}
if (ctl_command == CHECK_CONF_COMMAND) {
write_stderr(_("The value of the parameter '-c' is incorrect.\n"));
do_help_check_guc();
exit(1);
}
if ((!isdigit((unsigned char)(*(config_value[i] + 0)))) && (*(config_value[i] + 0) != '\'') &&
(!isalpha((unsigned char)(*(config_value[i] + 0)))) && (*(config_value[i] + 0) != '-')) {
write_stderr(_("The parameter(%s) exists illegal character:%c\n"), config_value[i], *(config_value[i] + 0));
do_advice();
exit(1);
}
for (j = 0; j < (int)strnlen(config_value[i], MAX_PARAM_LEN); j++) {
if (*(config_value[i] + j) == '\'') {
num++;
}
if (*(config_value[i] + j) == '#') {
write_stderr(
_("The parameter(%s) exists illegal character:%c \n"), config_value[i], *(config_value[i] + j));
do_advice();
exit(1);
}
}
if (num == 1) {
write_stderr(_("%s: the character '\'' can not make a pair or to many\n"), config_value[i]);
do_advice();
exit(1);
}
}
}
* @@GaussDB@@
* Brief : do_checkvalidate()
* Description : check the parameter name and value whether the style and value are both correct or not.
* Notes :
*/
void do_checkvalidate(int type)
{
if (is_hba_conf)
return;
do_check_parameter_name_type();
do_check_parameter_value_type();
save_guc_para_info();
if (0 != check_parameter(type)) {
do_advice();
exit(1);
}
}
* @@GaussDB@@
* Brief : IsLegalPreix()
* Input : prefixStr -> the input parameter value
* Description : check the parameter. It is only support digit/alpha/'-'/'_'
*/
bool IsLegalPreix(const char* prefixStr)
{
int NBytes = int(strlen(prefixStr));
for (int i = 0; i < NBytes; i++) {
if (IsIllegalCharacter(prefixStr[i])) {
return false;
}
}
return true;
}
* do input parameter checking
*/
void checkDataDir(const char* datadir)
{
if (NULL == datadir || 0 == strlen(datadir)) {
write_stderr(_("%s: The value of -D is incorrect \n"), progname);
exit(1);
}
if (-1 == access(datadir, R_OK | W_OK)) {
write_stderr(_("ERROR: Could not access the path %s\n"), datadir);
exit(1);
}
}
void checkCipherkey()
{
if (g_cipherkey == NULL) {
g_cipherkey = simple_prompt("Password: ", MAX_GUC_PASS_LEN + 1, false);
if (!check_input_password(g_cipherkey, MAX_GUC_PASS_LEN)) {
write_stderr(_("%s: The input key must be %d~%d bytes and "
"contain at least three kinds of characters!\n"),
progname, MIN_KEY_LEN, MAX_GUC_PASS_LEN);
do_advice();
exit(1);
}
}
}
* @@GaussDB@@
* Brief : doGenerateKey()
* Input : datadir -> cipher/random file directory
* Description : generate cipher/rand file or generate encrypt file
*/
void doGenerateOperation(const char* datadir, const char* loginfo)
{
checkDataDir(datadir);
checkCipherkey();
key_mode = OBS_MODE;
if (strcmp(g_cipherkey, "default") == 0) {
char init_rand[RANDOM_LEN + 1] = {0};
int retval = 0;
char* encodetext = NULL;
retval = RAND_bytes((unsigned char*)init_rand, RANDOM_LEN);
if (retval != 1)
{
(void)write_stderr(_("%s: generate random key failed, errcode:%d.\n"), progname, retval);
GS_FREE(g_cipherkey);
exit(1);
}
encodetext = SEC_encodeBase64((char*)init_rand, RANDOM_LEN + 1);
GS_FREE(g_cipherkey);
g_cipherkey = (char*)encodetext;
if (g_cipherkey == NULL) {
(void)write_stderr(_("%s: encode Base64 failed\n"), progname);
exit(1);
}
if (strlen(g_cipherkey) > RANDOM_LEN) {
g_cipherkey[RANDOM_LEN - 3] = '\0';
}
gen_cipher_rand_files(key_mode, g_cipherkey, key_username, datadir, g_prefix);
OPENSSL_free(g_cipherkey);
g_cipherkey = NULL;
} else {
if (!check_input_password(g_cipherkey, MAX_GUC_PASS_LEN)) {
write_stderr(_("%s: The input key must be %d~%d bytes and "
"contain at least three kinds of characters!\n"),
progname, MIN_KEY_LEN, MAX_GUC_PASS_LEN);
GS_FREE(g_cipherkey);
do_advice();
exit(1);
}
gen_cipher_rand_files(key_mode, g_cipherkey, key_username, datadir, g_prefix);
GS_FREE(g_cipherkey);
}
(void)write_log("gs_guc generate %s\n", loginfo);
}
void checkLcName(int nodeType)
{
if ((NULL != g_lcname) && (INSTANCE_DATANODE != nodeType)) {
write_stderr(_("%s: lcname only can be used with \"datanode\"\n"), progname);
do_help_common_options();
exit(1);
}
}
void
print_help(const char* infoStr)
{
if (strncmp(infoStr, "--help", sizeof("--help")) == 0 || strncmp(infoStr, "-?", sizeof("-?")) == 0) {
do_help();
exit(0);
} else if (strncmp(infoStr, "-V", sizeof("-V")) == 0 || strncmp(infoStr, "--version", sizeof("--version")) == 0) {
#ifdef ENABLE_MULTIPLE_NODES
puts("gs_guc " DEF_GS_VERSION);
#else
puts("gs_guc " DEF_GS_VERSION);
#endif
exit(0);
}
}
void
get_action_value(CtlCommand ctlCmd, const char* cmd)
{
if (ctlCmd != NO_COMMAND) {
write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, cmd);
do_advice();
exit(1);
} else if (strncmp(cmd, "set", sizeof("set")) == 0) {
ctl_command = SET_CONF_COMMAND ;
} else if (strncmp(cmd, "reload", sizeof("reload")) == 0) {
ctl_command = RELOAD_CONF_COMMAND;
} else if (strncmp(cmd, "encrypt", sizeof("encrypt")) == 0) {
ctl_command = ENCRYPT_KEY_COMMAND;
} else if (strncmp(cmd, "check", sizeof("check")) == 0) {
ctl_command = CHECK_CONF_COMMAND;
} else if (strncmp(cmd, "generate", sizeof("generate")) == 0) {
ctl_command = GENERATE_KEY_COMMAND;
} else {
write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, cmd);
do_advice();
exit(1);
}
}
void
get_node_type_info(const char *type)
{
if (node_type_number >= LARGE_INSTANCE_NUM) {
(void)write_stderr("ERROR: The number of -Z must be less than or equal to 2.\n");
do_advice();
exit(1);
}
if (0 == strncmp("coordinator", type, sizeof("coordinator"))) {
nodetype = INSTANCE_COORDINATOR;
node_type_value[node_type_number++] = INSTANCE_COORDINATOR;
} else if (0 == strncmp("datanode", type, sizeof("datanode"))) {
nodetype = INSTANCE_DATANODE;
node_type_value[node_type_number++] = INSTANCE_DATANODE;
} else if (0 == strncmp("cmserver", type, sizeof("cmserver"))) {
nodetype = INSTANCE_CMSERVER;
node_type_value[node_type_number++] = INSTANCE_CMSERVER;
} else if (0 == strncmp("cmagent", type, sizeof("cmagent"))) {
nodetype = INSTANCE_CMAGENT;
node_type_value[node_type_number++] = INSTANCE_CMAGENT;
} else if (0 == strncmp("gtm", type, sizeof("gtm"))) {
nodetype = INSTANCE_GTM;
node_type_value[node_type_number++] = INSTANCE_GTM;
} else {
write_stderr(_("%s: unrecognized node type \"%s\"\n"), progname, type);
do_advice();
exit(1);
}
}
void
check_ctl_command(CtlCommand ctlCmd, NodeType nodeType)
{
if ((CHECK_CONF_COMMAND == ctlCmd) && (nodeType != INSTANCE_COORDINATOR) && (nodeType != INSTANCE_DATANODE)) {
write_stderr(_("%s: check operation is only supported for \"coordinator\" and \"datanode\"\n"), progname);
do_help_check_guc();
exit(1);
}
}
void clear_g_incorrect_nodeInfo()
{
uint32 idx = 0;
if (NULL == g_incorrect_nodeInfo) {
return;
}
for (idx = 0; idx < g_incorrect_nodeInfo->num; idx++) {
GS_FREE(g_incorrect_nodeInfo->nodename_array[idx]);
}
GS_FREE(g_incorrect_nodeInfo->nodename_array);
GS_FREE(g_incorrect_nodeInfo);
}
static void clear_g_ignore_nodeInfo()
{
uint32 idx = 0;
if (g_ignore_nodeInfo == NULL) {
return;
}
for (idx = 0; idx < g_ignore_nodeInfo->num; idx++) {
GS_FREE(g_ignore_nodeInfo->nodename_array[idx]);
}
GS_FREE(g_ignore_nodeInfo->nodename_array);
GS_FREE(g_ignore_nodeInfo);
}
static int countIgnoreNodeElems(const char *input)
{
int cnt = 1;
for (; *input != '\0'; input++) {
if (*input == ',') {
cnt++;
}
}
return cnt;
}
static void saveIgnoreNodeElems(const char *input)
{
errno_t rc = 0;
int cnt = 0;
int strLen = 0;
char* node = NULL;
char* tmpStr = NULL;
char* saveStr = NULL;
const char* split = ",";
if ((input == NULL) || (input[0] == '\0')) {
write_stderr(_("%s: invalid ignore nodes,please check it\n"), progname);
exit(1);
}
strLen = strlen(input);
tmpStr = (char*)pg_malloc_zero(strLen + 1);
rc = memcpy_s(tmpStr, strLen, input, strLen);
securec_check_c(rc, "\0", "\0");
cnt = countIgnoreNodeElems(tmpStr);
g_ignore_nodeInfo = (nodeInfo*)pg_malloc(sizeof(nodeInfo));
g_ignore_nodeInfo->nodename_array = (char**)pg_malloc_zero(cnt * sizeof(char*));
g_ignore_nodeInfo->num = 0;
node = strtok_r(tmpStr, split, &saveStr);
g_ignore_nodeInfo->nodename_array[g_ignore_nodeInfo->num++] = xstrdup(node);
while (node != NULL) {
node = strtok_r(NULL, split, &saveStr);
if (node == NULL) {
break;
}
g_ignore_nodeInfo->nodename_array[g_ignore_nodeInfo->num++] = xstrdup(node);
}
free(tmpStr);
}
static void process_encrypt_cmd(const char* pgdata_D, const char* pgdata_C, const char* pgdata_R)
{
errno_t rc = 0;
if (pgdata_D && (pgdata_R || pgdata_C)) {
write_stderr(_("%s: encrypt cannot use -D, -R and -C same time!\n"), progname);
do_advice();
exit(1);
}
if (!pgdata_D && !(pgdata_R || pgdata_C)) {
write_stderr(_("%s: encrypt must use -D or <-R and -C> !\n"), progname);
do_advice();
exit(1);
}
if ((pgdata_R && !pgdata_C) || (!pgdata_R && pgdata_C)) {
write_stderr(_("%s: encrypt must use -R and -C same time!\n"), progname);
do_advice();
exit(1);
}
if (!pgdata_D) {
pgdata_D = (char *)pgdata_C;
}
checkDataDir(pgdata_D);
if (pgdata_R) {
checkDataDir(pgdata_R);
}
gen_cipher_rand_files(key_mode, g_plainkey, key_username, pgdata_D, NULL);
if (pgdata_R) {
FILE* cmd_fp = NULL;
char read_buf[MAX_CHILD_PATH] = {0};
char* mv_cmd = NULL;
mv_cmd = (char*)pg_malloc_zero(MAX_COMMAND_LEN + 1);
rc = snprintf_s(mv_cmd, MAX_COMMAND_LEN, MAX_COMMAND_LEN - 1, "mv %s/*.rand %s/",
pgdata_C, pgdata_R);
securec_check_ss_c(rc, "\0", "\0");
cmd_fp = popen(mv_cmd, "r");
if (NULL == cmd_fp) {
(void)write_stderr("could not open mv command.\n");
GS_FREE(mv_cmd);
exit(1);
}
while (fgets(read_buf, sizeof(read_buf) - 1, cmd_fp) != 0) {
printf("%s\n", read_buf);
rc = memset_s(read_buf, sizeof(read_buf), 0, sizeof(read_buf));
securec_check_c(rc, "\0", "\0");
}
pclose(cmd_fp);
GS_FREE(mv_cmd);
}
}
* @@GaussDB@@
* Brief :
* Description :
* Notes :
*/
int main(int argc, char** argv)
{
#define MAXLOGINFOLEN 1024
static struct option long_options[] = {{"help", no_argument, NULL, '?'},
{"version", no_argument, NULL, 'V'},
{"pgdata", required_argument, NULL, 'D'},
{"keyuser", required_argument, NULL, 'U'},
{"keymode", required_argument, NULL, 'M'},
{"lcname", required_argument, NULL, 1},
{"ignore-node", required_argument, NULL, 2},
{NULL, 0, NULL, 0}};
int option_index;
int c;
char* temp_config_parameter = NULL;
bool bhave_param = false;
bool bhave_nodetype = false;
char loginfo[MAXLOGINFOLEN] = {0};
#if defined(WIN32) || defined(__CYGWIN__)
(void)setvbuf(stderr, NULL, _IONBF, 0);
#endif
char* pgdata_D = NULL;
char* pgdata_R = NULL;
char* pgdata_C = NULL;
char* nodename = NULL;
char* instance_name = NULL;
int nodeNum = 0;
int instanceNum = 0;
int nRet = 0;
errno_t rc = 0;
progname = PROG_NAME;
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("gs_guc"));
arraysize = argc - 1;
#ifndef ENABLE_LITE_MODE
bool is_cluster_init = false;
#endif
if (0 != arraysize) {
config_param = ((char**)pg_malloc_zero(arraysize * sizeof(char*)));
hba_param = ((char**)pg_malloc_zero(arraysize * sizeof(char *)));
config_value = ((char**)pg_malloc_zero(arraysize * sizeof(char*)));
}
key_mode = SERVER_MODE;
* save argv[0] so do_setgucparameter can look for the postmaster if necessary. we
* don't look for postmaster here because in many cases we won't need it.
*/
(void)umask(S_IRWXG | S_IRWXO);
if (argc > 1) {
print_help(argv[1]);
}
#ifndef WIN32
if (geteuid() == 0) {
write_stderr(_("%s: cannot be run as root\n"
"Please log in (using, e.g., \"su\") as the "
"(unprivileged) user that will\n"
"own the server process.\n"),
progname);
exit(1);
}
#endif
optind = 1;
while (optind < argc) {
while ((c = getopt_long(argc, argv, "N:I:D:R:C:c:h:Z:U:M:K:S:o:", long_options, &option_index)) != -1) {
switch (c) {
case 'D': {
GS_FREE(pgdata_D);
pgdata_D = xstrdup(optarg);
canonicalize_path(pgdata_D);
break;
}
case 'R': {
GS_FREE(pgdata_R);
pgdata_R = xstrdup(optarg);
canonicalize_path(pgdata_R);
check_path(pgdata_R);
break;
}
case 'C': {
GS_FREE(pgdata_C);
pgdata_C = xstrdup(optarg);
canonicalize_path(pgdata_C);
check_path(pgdata_C);
break;
}
case 'o': {
if (!IsLegalPreix(optarg)) {
write_stderr(_("%s: -o only be formed of 'a~z', 'A~Z', '0~9', '-', '_'\n"), progname);
do_advice();
exit(1);
}
GS_FREE(g_prefix);
g_prefix = xstrdup(optarg);
break;
}
case 'c': {
if (is_hba_conf) {
write_stderr(_("%s: only one type of configuration can be changed at a time\n"
"HINT: use either -c or -h option"),
progname);
do_advice();
exit(1);
}
if (strstr((const char*)optarg, "\n") != NULL) {
write_stderr("Error: The command line contains line breaks\n");
exit(1);
}
bhave_param = true;
temp_config_parameter = xstrdup(optarg);
do_analysis(temp_config_parameter);
GS_FREE(temp_config_parameter);
break;
}
case 'h': {
if (bhave_param) {
write_stderr(_("%s: only one type of configuration can be changed at a time\n"
"HINT: use either -c or -h option"),
progname);
do_advice();
exit(1);
}
is_hba_conf = true;
temp_config_parameter = xstrdup(optarg);
#ifndef ENABLE_LITE_MODE
if (!is_cluster_init) {
init_gauss_cluster_config();
is_cluster_init = true;
}
#endif
do_hba_analysis(temp_config_parameter);
GS_FREE(temp_config_parameter);
break;
}
case 'Z': {
bhave_nodetype = true;
get_node_type_info(optarg);
break;
}
case 'N': {
GS_FREE(nodename);
nodename = xstrdup(optarg);
nodeNum++;
break;
}
case 'I': {
GS_FREE(instance_name);
instance_name = xstrdup(optarg);
instanceNum++;
break;
}
case 'M': {
size_t mlen = 0;
char* mode_str = NULL;
check_key_mode(optarg);
mlen = strlen("-M ") + strlen(optarg) + strlen(" ") + 1;
mode_str = (char*)pg_malloc_zero(mlen);
nRet = snprintf_s(mode_str, mlen, mlen - 1, "-M %s ", optarg);
securec_check_ss_c(nRet, mode_str, "\0");
rc = strncat_s(loginfo, MAXLOGINFOLEN, mode_str, mlen - 1);
securec_check_c(rc, "\0", "\0");
loginfo[MAXLOGINFOLEN - 1] = '\0';
GS_FREE(mode_str);
break;
}
case 'U': {
char name_str[MAX_KEY_LEN] = {0};
GS_FREE(key_username);
key_username = xstrdup(optarg);
nRet = snprintf_s(name_str, MAX_KEY_LEN, MAX_KEY_LEN - 1, "-U %s ", "***");
securec_check_ss_c(nRet, "\0", "\0");
rc = strncat_s(loginfo, MAXLOGINFOLEN, name_str, strlen(name_str));
securec_check_c(rc, "\0", "\0");
loginfo[MAXLOGINFOLEN - 1] = '\0';
break;
}
case 'K': {
char key_str[MAX_KEY_LEN] = {0};
if (!check_input_password(optarg, MAX_GUC_PASS_LEN)) {
do_advice();
exit(1);
}
GS_FREE(g_plainkey);
g_plainkey = xstrdup(optarg);
if (!mask_single_passwd(optarg)) {
(void)fprintf(
stderr, _("%s: mask passwd failed. optarg is null, or out of memory!\n"), progname);
do_advice();
exit(1);
}
nRet = snprintf_s(key_str, MAX_KEY_LEN, MAX_KEY_LEN - 1, "-K %s ", "***");
securec_check_ss_c(nRet, "\0", "\0");
rc = strncat_s(loginfo, MAXLOGINFOLEN, key_str, strlen(key_str));
securec_check_c(rc, "\0", "\0");
loginfo[MAXLOGINFOLEN - 1] = '\0';
break;
}
case 'S': {
char key_str[MAX_KEY_LEN] = {0};
GS_FREE(g_cipherkey);
g_cipherkey = xstrdup(optarg);
if (!mask_single_passwd(optarg)) {
(void)fprintf(
stderr, _("%s: mask passwd failed. optarg is null, or out of memory!\n"), progname);
do_advice();
exit(1);
}
nRet = snprintf_s(key_str, MAX_KEY_LEN, MAX_KEY_LEN - 1, "-S %s ", "***");
securec_check_ss_c(nRet, "\0", "\0");
rc = strncat_s(loginfo, MAXLOGINFOLEN, key_str, strlen(key_str));
securec_check_c(rc, "\0", "\0");
loginfo[MAXLOGINFOLEN - 1] = '\0';
break;
}
case 0:
break;
case 1:
GS_FREE(g_lcname);
check_env_value_c(optarg);
g_lcname = xstrdup(optarg);
break;
case 2:
clear_g_ignore_nodeInfo();
saveIgnoreNodeElems(optarg);
break;
default:
do_advice();
exit(1);
}
}
if (optind < argc) {
get_action_value(ctl_command, (const char*)argv[optind]);
optind++;
}
}
#ifndef ENABLE_MULTIPLE_NODES
if (!bhave_nodetype) {
bhave_nodetype = true;
nodetype = INSTANCE_DATANODE;
node_type_value[node_type_number++] = INSTANCE_DATANODE;
}
#endif
if (ctl_command == NO_COMMAND) {
write_stderr(_("%s: no operation specified\n"), progname);
do_advice();
exit(1);
}
char arguments[MAX_BUF_SIZE] = {0x00};
for (int i = 0; i < argc; i++) {
if ((strlen(arguments) + strlen(argv[i])) >= (MAX_BUF_SIZE - 2)) {
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
(void)write_log("The gs_guc run with the following arguments: [%s].\n", argv[i]);
rc = memset_s(arguments, MAX_BUF_SIZE, 0, MAX_BUF_SIZE - 1);
securec_check_c(rc, "\0", "\0");
continue;
}
errno_t rc = strcat_s(arguments, MAX_BUF_SIZE, argv[i]);
size_t len = strlen(arguments);
if (rc != EOK) {
break;
}
arguments[len] = ' ';
arguments[len + 1] = '\0';
}
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
check_encrypt_options();
if (ctl_command == ENCRYPT_KEY_COMMAND) {
process_encrypt_cmd(pgdata_D, pgdata_C, pgdata_R);
(void)write_log("gs_guc encrypt %s\n", loginfo);
} else if (ctl_command == GENERATE_KEY_COMMAND) {
doGenerateOperation(pgdata_D, loginfo);
}
if (ctl_command == ENCRYPT_KEY_COMMAND || ctl_command == GENERATE_KEY_COMMAND) {
GS_FREE(g_prefix);
GS_FREE(g_plainkey);
GS_FREE(g_cipherkey);
GS_FREE(key_username);
GS_FREE(pgdata_D);
GS_FREE(pgdata_R);
GS_FREE(pgdata_C);
return 0;
}
if (nodeNum > 1 || instanceNum > 1) {
write_stderr(_("ERROR: The number of -I or -N must less than 2.\n"));
exit(1);
}
if (false == allocate_memory_list()) {
write_stderr(_("ERROR: Failed to allocate memory to list.\n"));
exit(1);
}
if (ctl_command != ENCRYPT_KEY_COMMAND && ctl_command != GENERATE_KEY_COMMAND && (!bhave_param && !is_hba_conf)) {
write_stderr(_("%s: the form of this command is incorrect\n"), progname);
do_advice();
exit(1);
}
if (ctl_command != ENCRYPT_KEY_COMMAND && ctl_command != GENERATE_KEY_COMMAND && !bhave_nodetype) {
write_stderr(_("%s: the type of node is not specified\n"), progname);
do_advice();
exit(1);
}
if ((g_ignore_nodeInfo != NULL) &&
(ctl_command != SET_CONF_COMMAND) &&
(ctl_command != RELOAD_CONF_COMMAND)) {
write_stderr(_("%s: --ignore-node must be used with set/reload operation\n"), progname);
clear_g_ignore_nodeInfo();
exit(1);
}
if ((g_ignore_nodeInfo != NULL) &&
(nodetype != INSTANCE_DATANODE) &&
(nodetype != INSTANCE_COORDINATOR)) {
write_stderr(_("%s: --ignore-node must be used with DN/CN\n"), progname);
clear_g_ignore_nodeInfo();
exit(1);
}
if ((g_ignore_nodeInfo != NULL) &&
(pgdata_D != NULL)) {
write_stderr(_("%s: -D and -ignore-node cannot be used together\n"), progname);
clear_g_ignore_nodeInfo();
exit(1);
}
* set/reload: cn, dn, cma, cms and gtm
* check: cn and dn
*/
check_ctl_command(ctl_command, nodetype);
if ((nodetype == INSTANCE_CMAGENT) || (nodetype == INSTANCE_CMSERVER)) {
checkCMParameter(pgdata_D, nodename, instance_name);
}
if ((NULL == instance_name) && (NULL == pgdata_D) &&
((nodetype != INSTANCE_CMAGENT) && (nodetype != INSTANCE_CMSERVER))) {
char* env_value = NULL;
env_value = getenv("PGDATA");
if ((NULL != env_value) && ('\0' != env_value[0]) && (MAXPGPATH > strlen(env_value))) {
pgdata_D = xstrdup(env_value);
canonicalize_path(pgdata_D);
}
}
if (nodetype == INSTANCE_DATANODE || nodetype == INSTANCE_COORDINATOR) {
check_build_status(pgdata_D);
}
if (nodename == NULL &&
instance_name == NULL &&
pgdata_D == NULL &&
((nodetype == INSTANCE_CMAGENT) || (nodetype == INSTANCE_CMSERVER)))
{
nodename = xstrdup("all");
instance_name = xstrdup("all");
}
init_log(PROG_NAME);
if ((true == is_hba_conf) &&
((nodetype != INSTANCE_COORDINATOR) && (nodetype != INSTANCE_DATANODE))) {
write_stderr(_("%s: authentication operation (-h) is not supported for \"gtm\" or \"gtm_proxy\"\n"), progname);
do_advice();
exit(1);
}
if (node_type_number == LARGE_INSTANCE_NUM) {
if (node_type_value[0] == node_type_value[1]) {
(void)write_stderr("When the number of -Z is equal to 2, the value must be different.\n");
exit(1);
}
for (int index = 0; index < LARGE_INSTANCE_NUM; index++) {
if (node_type_value[index] != INSTANCE_COORDINATOR && node_type_value[index] != INSTANCE_DATANODE) {
(void)write_stderr("ERROR: When the number of -Z is equal to 2, the parameter value of -Z must be "
"coordinator or datanode.\n");
exit(1);
}
checkLcName(node_type_value[index]);
}
nodetype = INSTANCE_COORDINATOR;
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
} else {
checkLcName(nodetype);
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
}
GS_FREE(pgdata_D);
GS_FREE(instance_name);
nRet = print_guc_result((const char*)nodename);
GS_FREE(nodename);
clear_g_incorrect_nodeInfo();
clear_g_ignore_nodeInfo();
if (is_hba_conf) {
free_hba_params();
}
if (0 != g_remote_command_result) {
return 1;
}
if (0 != nRet)
return 1;
else
return 0;
}
static void checkCMParameter(const char *dataDir, const char *nodeName, const char *instName)
{
int i = 0;
* This branch is not support.
* 1. -D cm_path
* 2. -I xxx
* 3. -I all
* 4. -N xxx -I all
* 5. -N all -I xxx
*/
if (NULL != dataDir &&
0 != strncmp(dataDir, "cm_instance_data_path",
strlen(dataDir) > strlen("cm_instance_data_path") ? strlen(dataDir) : strlen("cm_instance_data_path"))) {
(void)write_stderr("ERROR: When the '-Z' parameter is cmserver or cmagent, the -D parameter must be NULL.\n");
exit(1);
} else if (instName != NULL && 0 != strncmp(instName, "all" , strlen("all"))) {
(void)write_stderr("ERROR: When the '-Z' parameter is cmserver or cmagent, -N parameter and -I parameter must be all or NULL at the same time.\n");
exit(1);
} else if (instName != NULL && 0 == strncmp(instName, "all" , strlen("all")) && nodeName == NULL) {
(void)write_stderr("ERROR: When the '-Z' parameter is cmserver or cmagent, -N parameter and -I parameter must be all or NULL at the same time.\n");
exit(1);
} else if (nodeName != NULL && instName != NULL
&& 0 != strncmp(instName, "all" , strlen("all")) && 0 == strncmp(nodeName, "all" , strlen("all"))) {
(void)write_stderr("ERROR: When the '-Z' parameter is cmserver or cmagent, -N parameter and -I parameter must be all or NULL at the same time.\n");
exit(1);
} else if (nodeName != NULL && instName != NULL
&& 0 == strncmp(instName, "all" , strlen("all")) && 0 != strncmp(nodeName, "all" , strlen("all"))) {
(void)write_stderr("ERROR: When the '-Z' parameter is cmserver or cmagent, -N parameter and -I parameter must be all or NULL at the same time.\n");
exit(1);
}
for (i = 0; i < config_value_number; i++)
{
if (NULL == config_value[i]) {
(void)write_stderr("ERROR: cmserver or cmagent does not support -c \"parameter\".\n");
exit(1);
}
}
}
Function: print_gucinfo
Desc : print the "gs_guc check" result.
Input : paraname - the parameter name
Return : void
*************************************************************************************/
void print_gucinfo(const char* paraname)
{
int32 i = 0;
(void)write_stderr("The details for %s:\n", paraname);
for (i = 0; i < (int32)g_real_gucInfo->paramname_num; i++) {
if (strcmp(g_real_gucInfo->paramname_array[i], paraname) == 0) {
char* guc_value = g_real_gucInfo->paramvalue_array[i];
int j = 0;
while (guc_value[j] != '\0' && guc_value[j] != '\n' && guc_value[j] != '\r')
j++;
guc_value[j] = '\0';
(void)write_stderr(" [%s] %s=%s [%s]\n",
g_real_gucInfo->nodename_array[i],
g_real_gucInfo->paramname_array[i],
g_real_gucInfo->paramvalue_array[i],
g_real_gucInfo->gucinfo_array[i]);
}
}
}
Function: find_first_paravalue_index
Desc : get the index of the parameter value which paraname we got from
g_real_gucInfo->paramname_num firstly
Input : paraname - the parameter name
Return : int
-1 It means the parameter name is not found in g_real_gucInfo->paramname_num.
This scene does not be occured.
i The index number
*************************************************************************************/
int find_first_paravalue_index(const char* paraname)
{
int32 i = 0;
for (i = 0; i < (int32)g_real_gucInfo->paramname_num; i++) {
if (strcmp(g_real_gucInfo->paramname_array[i], paraname) == 0)
return i;
else
continue;
}
return -1;
}
Function: find_same_paravalue_index
Desc : if the parameter values have "NULL" and the parameter values are not same, return -1;
else, return the first parameter value index number
Input : paraname - the parameter name
Return : int
-1 The parameter values have "NULL" and the parameter values are not same
i The index number
*************************************************************************************/
int find_same_paravalue_index(const char* paraname)
{
int32 i = 0;
int32 index = -1;
* g_real_gucInfo->paramname_array*/
index = find_first_paravalue_index(paraname);
for (i = 0; i < (int32)g_real_gucInfo->paramname_num; i++) {
if (strcmp(g_real_gucInfo->paramname_array[i], paraname) == 0) {
if (strncmp(g_real_gucInfo->paramvalue_array[i], "NULL", strlen("NULL")) == 0)
return -1;
if (strcmp(g_real_gucInfo->paramvalue_array[index], g_real_gucInfo->paramvalue_array[i]) != 0)
return -1;
} else {
continue;
}
}
return index;
}
Function : print_check_result
Description : print the "gs_guc check" result
Input : None
Output : None
Return : void
*******************************************************************************/
void print_check_result()
{
int i = 0;
int index = 0;
for (i = 0; i < config_param_number; i++) {
index = find_same_paravalue_index(config_param[i]);
if (-1 != index) {
(void)write_stderr("The value of parameter %s is same on all instances.\n", config_param[i]);
int j;
j = 0;
char* guc_value = g_real_gucInfo->paramvalue_array[index];
while (guc_value[j] != '\0' && guc_value[j] != '\n' && guc_value[j] != '\r')
j++;
guc_value[j] = '\0';
(void)write_stderr(" %s=%s\n", config_param[i], g_real_gucInfo->paramvalue_array[index]);
} else {
print_gucinfo(config_param[i]);
}
}
(void)write_stderr("\n");
}
Function : print_guc_result
Description : The output of the set/reload/check statistics
Input : None
Output : None
Return : int
0 - Success
1 - Failure
*******************************************************************************/
int print_guc_result(const char* nodename)
{
int* instance_status_array = NULL;
int32 i = 0;
int32 j = 0;
* If the command is set/reload , -N all and -I all for GTM/CN/DN/CN&DN/CMA/CMS
* there is no need to print message again.
*/
if ((CHECK_CONF_COMMAND != ctl_command) &&
nodename != NULL &&
0 == strncmp(nodename, "all" , strlen("all"))) {
(void)write_stderr("\n");
return 0;
}
if (!g_remote_connection_signal || g_remote_command_result != 0) {
(void)write_stderr("Failed node names:\n");
for (i = 0; i < (int32)g_incorrect_nodeInfo->num; i++)
(void)write_stderr(" [%s]\n", g_incorrect_nodeInfo->nodename_array[i]);
} else {
if (CHECK_CONF_COMMAND != ctl_command) {
(void)write_stderr("\nTotal instances: %d. Failed instances: %d.\n",
(int32)g_expect_gucInfo->gucinfo_num,
(int32)(g_expect_gucInfo->gucinfo_num - g_real_gucInfo->gucinfo_num));
} else {
(void)write_stderr("\nTotal GUC values: %d. Failed GUC values: %d.\n",
(int32)g_expect_gucInfo->gucinfo_num,
(int32)(g_expect_gucInfo->gucinfo_num - g_real_gucInfo->gucinfo_num));
}
if (0 == g_expect_gucInfo->gucinfo_num) {
if (CHECK_CONF_COMMAND == ctl_command)
(void)write_stderr("There is no instance.\n\n");
else
(void)write_stderr("Success to perform gs_guc!\n\n");
return 0;
}
}
if (g_expect_gucInfo->gucinfo_num > g_real_gucInfo->gucinfo_num) {
if (CHECK_CONF_COMMAND == ctl_command)
(void)write_stderr("Failed GUC values information:\n");
else
(void)write_stderr("Failed instance information:\n");
instance_status_array = (int*)pg_malloc_zero(g_expect_gucInfo->gucinfo_num * sizeof(int));
for (i = 0; i < (int32)g_expect_gucInfo->gucinfo_num; i++)
instance_status_array[i] = 0;
for (i = 0; i < (int32)g_expect_gucInfo->gucinfo_num; i++) {
for (j = 0; j < (int32)g_expect_gucInfo->gucinfo_num; j++) {
if ((NULL != g_expect_gucInfo->nodename_array[i] && NULL != g_real_gucInfo->nodename_array[j]) &&
(NULL != g_expect_gucInfo->gucinfo_array[i] && NULL != g_real_gucInfo->gucinfo_array[j])) {
if ((0 == strcmp(g_expect_gucInfo->nodename_array[i], g_real_gucInfo->nodename_array[j])) &&
(0 == strcmp(g_expect_gucInfo->gucinfo_array[i], g_real_gucInfo->gucinfo_array[j])))
instance_status_array[i] = 1;
}
}
}
for (i = 0; i < (int32)g_expect_gucInfo->gucinfo_num; i++) {
if (instance_status_array[i] == 0) {
if (CHECK_CONF_COMMAND == ctl_command) {
(void)write_stderr(" [%s] %s [%s]\n",
g_expect_gucInfo->nodename_array[i],
g_expect_gucInfo->paramname_array[i],
g_expect_gucInfo->gucinfo_array[i]);
} else {
(void)write_stderr(
" [%s] [%s]\n", g_expect_gucInfo->nodename_array[i], g_expect_gucInfo->gucinfo_array[i]);
}
}
}
(void)write_stderr("\n");
if (CHECK_CONF_COMMAND != ctl_command)
(void)write_stderr("Failure to perform gs_guc!\n\n");
GS_FREE(instance_status_array);
return 1;
} else {
if (g_remote_connection_signal && g_remote_command_result == 0) {
if (CHECK_CONF_COMMAND == ctl_command)
print_check_result();
else
(void)write_stderr("Success to perform gs_guc!\n\n");
return 0;
} else {
if (CHECK_CONF_COMMAND != ctl_command)
(void)write_stderr("Failure to perform gs_guc!\n\n");
return 1;
}
}
}
char* get_ctl_command_type()
{
switch (ctl_command) {
case SET_CONF_COMMAND:
return "set";
case RELOAD_CONF_COMMAND:
return "reload";
case CHECK_CONF_COMMAND:
return "check";
default:
break;
}
return "";
}
Function : get_instance_configfile
Description : get instance configration file by instance data directory
Input : datadir - instance data directory
Output :
Return : void
******************************************************************************/
void get_instance_configfile(const char* datadir)
{
int nRet = 0;
switch (nodetype) {
case INSTANCE_COORDINATOR:
case INSTANCE_DATANODE: {
if (is_hba_conf) {
nRet = snprintf_s(pid_file, MAXPGPATH, MAXPGPATH - 1, "%s/postmaster.pid", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_file, MAXPGPATH, MAXPGPATH - 1, "%s/pg_hba.conf", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(tempguc_file, MAXPGPATH, MAXPGPATH - 1, "%s/%s", datadir, TEMP_PGHBACONF_FILE);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_lock_file, MAXPGPATH, MAXPGPATH - 1, "%s/pg_hba.conf.lock", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gaussdb_state_file, MAXPGPATH, MAXPGPATH - 1, "%s/gaussdb.state", datadir);
securec_check_ss_c(nRet, "\0", "\0");
} else {
nRet = snprintf_s(pid_file, MAXPGPATH, MAXPGPATH - 1, "%s/postmaster.pid", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gaussdb_state_file, MAXPGPATH, MAXPGPATH - 1, "%s/gaussdb.state", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_file, MAXPGPATH, MAXPGPATH - 1, "%s/postgresql.conf", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(tempguc_file, MAXPGPATH, MAXPGPATH - 1, "%s/%s", datadir, TEMP_PGCONF_FILE);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_lock_file, MAXPGPATH, MAXPGPATH - 1, "%s/postgresql.conf.lock", datadir);
securec_check_ss_c(nRet, "\0", "\0");
}
break;
}
case INSTANCE_CMAGENT:
{
nRet = snprintf_s(pid_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_agent/cm_agent.pid", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_agent/cm_agent.conf", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(tempguc_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_agent/%s", datadir, TEMP_CMAGENTCONF_FILE);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_lock_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_agent/cm_agent.conf.lock", datadir);
securec_check_ss_c(nRet, "\0", "\0");
break;
}
case INSTANCE_CMSERVER:
{
nRet = snprintf_s(pid_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_server/cm_server.pid", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_server/cm_server.conf", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(tempguc_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_server/%s", datadir, TEMP_CMSERVERCONF_FILE);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_lock_file, MAXPGPATH, MAXPGPATH-1, "%s/cm_server/cm_server.conf.lock", datadir);
securec_check_ss_c(nRet, "\0", "\0");
break;
}
case INSTANCE_GTM: {
nRet = snprintf_s(pid_file, MAXPGPATH, MAXPGPATH - 1, "%s/gtm.pid", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_file, MAXPGPATH, MAXPGPATH - 1, "%s/gtm.conf", datadir);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(tempguc_file, MAXPGPATH, MAXPGPATH - 1, "%s/%s", datadir, TEMP_GTMCONF_FILE);
securec_check_ss_c(nRet, "\0", "\0");
nRet = snprintf_s(gucconf_lock_file, MAXPGPATH, MAXPGPATH - 1, "%s/gtm.conf.lock", datadir);
securec_check_ss_c(nRet, "\0", "\0");
break;
}
default:
break;
}
}
Function : do_guc_set_reload_for_each_parameter
Description : do gs_guc set/reload
Input : action_type - action type. set/reload
Output : None
Return : None
******************************************************************************/
void do_guc_set_reload_for_each_parameter(const char* action_type, const char* data_dir)
{
if (!is_hba_conf) {
if (SUCCESS != do_gucset(action_type, data_dir)) {
return ;
}
} else {
if (SUCCESS != do_hba_set(action_type))
return ;
}
if (0 == strncmp(action_type, "reload", sizeof("reload")))
{
if (SUCCESS != do_config_reload())
return ;
}
g_real_gucInfo->nodename_array[g_real_gucInfo->nodename_num++] = xstrdup(g_local_node_name);
g_real_gucInfo->gucinfo_array[g_real_gucInfo->gucinfo_num++] = xstrdup(gucconf_file);
}
Function : do_guc_check_for_each_parameter
Description : do gs_guc check
Input : action_type - action type: check
Output : None
Return : None
******************************************************************************/
void do_guc_check_for_each_parameter(const char* action_type)
{
int i = 0;
char* guc_value = NULL;
for (i = 0; i < config_param_number; i++) {
guc_value = do_guccheck(config_param[i]);
if (NULL == guc_value) {
return;
} else if (strncmp(guc_value, "NoFound", strlen("NoFound")) == 0) {
(void)write_stderr(
"gs_guc %s: %s: %s=NULL: [%s]\n", action_type, g_local_node_name, config_param[i], gucconf_file);
g_real_gucInfo->paramvalue_array[g_real_gucInfo->paramvalue_num++] = xstrdup("NULL");
} else {
int j;
j = 0;
while (guc_value[j] != '\0' && guc_value[j] != '\n' && guc_value[j] != '\r')
j++;
guc_value[j] = '\0';
(void)write_stderr("gs_guc %s: %s: %s=%s: [%s]\n",
action_type,
g_local_node_name,
config_param[i],
guc_value,
gucconf_file);
g_real_gucInfo->paramvalue_array[g_real_gucInfo->paramvalue_num++] = xstrdup(guc_value);
}
g_real_gucInfo->nodename_array[g_real_gucInfo->nodename_num++] = xstrdup(g_local_node_name);
g_real_gucInfo->gucinfo_array[g_real_gucInfo->gucinfo_num++] = xstrdup(gucconf_file);
g_real_gucInfo->paramname_array[g_real_gucInfo->paramname_num++] = xstrdup(config_param[i]);
GS_FREE(guc_value);
}
}
Function : process_guc_command
Description : do gs_guc set/reload
Input : datadir - instance data directory
Output :
Return : int
0 - success
******************************************************************************/
int process_guc_command(const char* datadir)
{
if (NULL == datadir || '\0' == datadir[0])
return 1;
get_instance_configfile(datadir);
switch (ctl_command) {
case SET_CONF_COMMAND:
do_guc_set_reload_for_each_parameter("set", datadir);
break;
case RELOAD_CONF_COMMAND:
do_guc_set_reload_for_each_parameter("reload", datadir);
break;
case CHECK_CONF_COMMAND:
do_guc_check_for_each_parameter("check");
break;
default:
break;
}
return 0;
}
* isMatchOptionName - Check wether the option name is in the configure file.
*
* Params:
* @optLine: Line in the configure file.
* @paraName: Paramater name.
* @paraLength: Paramater length.
* @paraOffset: Paramater offset int the optLine.
* @valueLength: Value length.
* @valueOffset: Value offset int the optLine.
*
* Returns:
* True, iff the option name is in the configure file; else false.
*/
static bool isMatchOptionName(
char* optLine, const char* paraName, int paraLength, int* paraOffset, int* valueLength, int* valueOffset)
{
char* p = NULL;
char* q = NULL;
char* tmp = NULL;
p = optLine;
p = skipspace(p);
if ('#' == *p) {
p++;
}
p = skipspace(p);
if (find_param_in_string(p, paraName, paraLength) != 0) {
return false;
}
if (NULL != paraOffset) {
*paraOffset = p - optLine;
}
p += paraLength;
p = skipspace(p);
if (*p != '=') {
return false;
}
p++;
p = skipspace(p);
if (strlen(p) != 0) {
q = p + 1;
tmp = q;
while (*q && !('\n' == *q || '#' == *q)) {
if (!isspace((unsigned char)*q)) {
if ('\'' == *q) {
tmp = ++q;
break;
} else {
tmp = ++q;
}
} else {
* If paraName is a string, the ' ' is considered to
* be part of the string.
*/
('\'' == *p) ? tmp = ++q : q++;
}
}
}
if (NULL != valueOffset) {
*valueOffset = p - optLine;
}
if (NULL != valueLength) {
*valueLength = (NULL == tmp) ? 0 : (tmp - p);
}
return true;
}
* isOptLineCommented - Check wether the option line is commented with '#'.
*
* Params:
* @optLine: Line in the configure file.
*
* Returns:
* True, iff the option line starts with '#'; else false.
*/
bool isOptLineCommented(const char* optLine)
{
char* tmp = NULL;
if (NULL == optLine) {
return false;
}
tmp = (char*)optLine;
while (isspace((unsigned char)*tmp)) {
tmp++;
}
if ('#' == *tmp) {
return true;
}
return false;
}
* trimBlanksTwoEnds - Clear out all the blanks at the begin and end of string.
*
* Params:
* @strPtr: A pointer to the string.
*
* Returns:
* void, and the strPtr will be the output.
*/
void trimBlanksTwoEnds(char** strPtr)
{
int strLen = 0;
char* tmpPtr = NULL;
if (NULL == strPtr) {
(void)write_stderr(_("strPtr should not be NULL.\n"));
return;
}
strLen = strnlen(*strPtr, MAX_PARAM_LEN);
tmpPtr = *strPtr + strLen - 1;
while (isspace((unsigned char)**strPtr)) {
(*strPtr)++;
}
while (isspace((unsigned char)*tmpPtr)) {
*tmpPtr = '\0';
tmpPtr--;
}
return;
}
static void check_key_mode(const char* mode)
{
int slen = strlen("server");
int clen = strlen("client");
int srclen = strlen("source");
if (NULL == mode || '\0' == mode[0])
{
(void)write_stderr(_("%s: invalid key mode,please check it\n"), progname);
do_advice();
exit(1);
}
if (0 == strncmp(mode, "server", slen) && '\0' == mode[slen]) {
key_mode = SERVER_MODE;
} else if (0 == strncmp(mode, "client", clen) && '\0' == mode[clen]) {
key_mode = CLIENT_MODE;
} else if (0 == strncmp(mode, "source", srclen) && '\0' == mode[srclen]) {
key_mode = SOURCE_MODE;
} else {
(void)write_stderr(_("%s: the options of -M is not recognized\n"), progname);
do_advice();
exit(1);
}
}
static void check_encrypt_options(void)
{
if (ENCRYPT_KEY_COMMAND != ctl_command) {
return;
}
if (g_plainkey == NULL) {
g_plainkey = simple_prompt("Password: ", MAX_GUC_PASS_LEN + 1, false);
if (!check_input_password(g_plainkey, MAX_GUC_PASS_LEN)) {
write_stderr(_("%s: The input key must be %d~%d bytes and "
"contain at least three kinds of characters!\n"),
progname, MIN_KEY_LEN, MAX_GUC_PASS_LEN);
do_advice();
exit(1);
}
}
if (key_mode == SERVER_MODE && key_username != NULL) {
(void)write_stderr(
_("%s: In server mode,the encrypt operation will ignore the specified user:%s\n"), progname, key_username);
}
if (key_mode == SOURCE_MODE && key_username != NULL) {
(void)write_stderr(
_("%s: In source mode,the encrypt operation will ignore the specified user:%s\n"), progname, key_username);
}
}