1 /* -*-pgsql-c-*- */
2 /*
3  * $Header$
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2018	PgPool Global Development Group
9  *
10  * Permission to use, copy, modify, and distribute this software and
11  * its documentation for any purpose and without fee is hereby
12  * granted, provided that the above copyright notice appear in all
13  * copies and that both that copyright notice and this permission
14  * notice appear in supporting documentation, and that the name of the
15  * author not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior
17  * permission. The author makes no representations about the
18  * suitability of this software for any purpose.  It is provided "as
19  * is" without express or implied warranty.
20  */
21 #include "pool.h"
22 #include "pool_config.h"
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 
28 
29 #ifdef HAVE_GETOPT_H
30 #include <getopt.h>
31 #else
32 #include "utils/getopt_long.h"
33 #endif
34 
35 #include <errno.h>
36 #include <string.h>
37 #include <libgen.h>
38 #include "utils/elog.h"
39 #include "utils/palloc.h"
40 #include "utils/memutils.h"
41 #include "utils/pool_path.h"
42 
43 #include "version.h"
44 #include "auth/pool_passwd.h"
45 #include "auth/pool_hba.h"
46 #include "query_cache/pool_memqcache.h"
47 #include "watchdog/wd_utils.h"
48 #include "pool_config_variables.h"
49 
50 
51 static bool get_pool_key_filename(char *poolKeyFile);
52 
53 static void daemonize(void);
54 static char *get_pid_file_path(void);
55 static int	read_pid_file(void);
56 static void write_pid_file(void);
57 static void usage(void);
58 static void show_version(void);
59 static void stop_me(void);
60 static void FileUnlink(int code, Datum path);
61 
62 char	   *pcp_conf_file = NULL;	/* absolute path of the pcp.conf */
63 char	   *conf_file = NULL;	/* absolute path of the pgpool.conf */
64 char	   *hba_file = NULL;	/* absolute path of the hba.conf */
65 char	   *base_dir = NULL;	/* The working dir from where pgpool was
66 								 * invoked from */
67 
68 static int	not_detach = 0;		/* non 0 if non detach option (-n) is given */
69 int			stop_sig = SIGTERM; /* stopping signal default value */
70 int			myargc;
71 char	  **myargv;
72 int			assert_enabled = 0;
73 char	   *pool_key = NULL;
74 int
main(int argc,char ** argv)75 main(int argc, char **argv)
76 {
77 	int			opt;
78 	int			debug_level = 0;
79 	int			optindex;
80 	bool		discard_status = false;
81 	bool		clear_memcache_oidmaps = false;
82 
83 	char		pcp_conf_file_path[POOLMAXPATHLEN + 1];
84 	char		conf_file_path[POOLMAXPATHLEN + 1];
85 	char		hba_file_path[POOLMAXPATHLEN + 1];
86 	char		pool_passwd_key_file_path[POOLMAXPATHLEN + 1 + sizeof(POOLKEYFILE) + 1];
87 
88 	static struct option long_options[] = {
89 		{"hba-file", required_argument, NULL, 'a'},
90 		{"debug", no_argument, NULL, 'd'},
91 		{"config-file", required_argument, NULL, 'f'},
92 		{"key-file", required_argument, NULL, 'k'},
93 		{"pcp-file", required_argument, NULL, 'F'},
94 		{"help", no_argument, NULL, 'h'},
95 		{"mode", required_argument, NULL, 'm'},
96 		{"dont-detach", no_argument, NULL, 'n'},
97 		{"discard-status", no_argument, NULL, 'D'},
98 		{"clear-oidmaps", no_argument, NULL, 'C'},
99 		{"debug-assertions", no_argument, NULL, 'x'},
100 		{"version", no_argument, NULL, 'v'},
101 		{NULL, 0, NULL, 0}
102 	};
103 
104 	myargc = argc;
105 	myargv = argv;
106 
107 	snprintf(conf_file_path, sizeof(conf_file_path), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);
108 	snprintf(pcp_conf_file_path, sizeof(pcp_conf_file_path), "%s/%s", DEFAULT_CONFIGDIR, PCP_PASSWD_FILE_NAME);
109 	snprintf(hba_file_path, sizeof(hba_file_path), "%s/%s", DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME);
110 	pool_passwd_key_file_path[0] = 0;
111 
112 	while ((opt = getopt_long(argc, argv, "a:df:k:F:hm:nDCxv", long_options, &optindex)) != -1)
113 	{
114 		switch (opt)
115 		{
116 			case 'a':			/* specify hba configuration file */
117 				if (!optarg)
118 				{
119 					usage();
120 					exit(1);
121 				}
122 				strlcpy(hba_file_path, optarg, sizeof(hba_file_path));
123 				break;
124 
125 			case 'x':			/* enable cassert */
126 				assert_enabled = 1;
127 				break;
128 
129 			case 'd':			/* debug option */
130 				debug_level = 1;
131 				break;
132 
133 			case 'f':			/* specify configuration file */
134 				if (!optarg)
135 				{
136 					usage();
137 					exit(1);
138 				}
139 				strlcpy(conf_file_path, optarg, sizeof(conf_file_path));
140 				break;
141 
142 			case 'F':			/* specify PCP password file */
143 				if (!optarg)
144 				{
145 					usage();
146 					exit(1);
147 				}
148 				strlcpy(pcp_conf_file_path, optarg, sizeof(pcp_conf_file_path));
149 				break;
150 
151 			case 'k':			/* specify key file for decrypt pool_password
152 								 * entries */
153 				if (!optarg)
154 				{
155 					usage();
156 					exit(1);
157 				}
158 				strlcpy(pool_passwd_key_file_path, optarg, sizeof(pool_passwd_key_file_path));
159 				break;
160 
161 			case 'h':
162 				usage();
163 				exit(0);
164 				break;
165 
166 			case 'm':			/* stop mode */
167 				if (!optarg)
168 				{
169 					usage();
170 					exit(1);
171 				}
172 				if (*optarg == 's' || !strcmp("smart", optarg))
173 					stop_sig = SIGTERM; /* smart shutdown */
174 				else if (*optarg == 'f' || !strcmp("fast", optarg))
175 					stop_sig = SIGINT;	/* fast shutdown */
176 				else if (*optarg == 'i' || !strcmp("immediate", optarg))
177 					stop_sig = SIGQUIT; /* immediate shutdown */
178 				else
179 				{
180 					usage();
181 					exit(1);
182 				}
183 				break;
184 
185 			case 'n':			/* no detaching control ttys */
186 				not_detach = 1;
187 				break;
188 
189 			case 'D':			/* discard pgpool_status */
190 				discard_status = true;
191 				break;
192 
193 			case 'C':			/* discard caches in memcached */
194 				clear_memcache_oidmaps = true;
195 				break;
196 
197 			case 'v':
198 				show_version();
199 				exit(0);
200 
201 			default:
202 				usage();
203 				exit(1);
204 		}
205 	}
206 
207 	myargv = save_ps_display_args(myargc, myargv);
208 	/* create MemoryContexts */
209 	MemoryContextInit();
210 
211 	/* load the CWD before it is changed */
212 	base_dir = get_current_working_dir();
213 	/* convert all the paths to absolute paths */
214 	conf_file = make_absolute_path(conf_file_path, base_dir);
215 	pcp_conf_file = make_absolute_path(pcp_conf_file_path, base_dir);
216 	hba_file = make_absolute_path(hba_file_path, base_dir);
217 
218 	mypid = getpid();
219 
220 	pool_init_config();
221 
222 	pool_get_config(conf_file, CFGCXT_INIT);
223 
224 	/*
225 	 * Override debug level if command line -d arg is given adjust the
226 	 * log_min_message config variable
227 	 */
228 	if (debug_level > 0 && pool_config->log_min_messages > DEBUG1)
229 		set_one_config_option("log_min_messages", "DEBUG1", CFGCXT_INIT, PGC_S_ARGV, INFO);
230 
231 	/*
232 	 * If a non-switch argument remains, then it should be either "reload" or
233 	 * "stop".
234 	 */
235 	if (optind == (argc - 1))
236 	{
237 		if (!strcmp(argv[optind], "reload"))
238 		{
239 			pid_t		pid;
240 
241 			pid = read_pid_file();
242 			if (pid < 0)
243 			{
244 				ereport(FATAL,
245 						(return_code(1),
246 						 errmsg("could not read pid file")));
247 			}
248 
249 			if (kill(pid, SIGHUP) == -1)
250 			{
251 				ereport(FATAL,
252 						(return_code(1),
253 						 errmsg("could not reload configuration file pid: %d", pid),
254 						 errdetail("%m")));
255 			}
256 			exit(0);
257 		}
258 		if (!strcmp(argv[optind], "stop"))
259 		{
260 			stop_me();
261 			exit(0);
262 		}
263 		else
264 		{
265 			usage();
266 			exit(1);
267 		}
268 	}
269 
270 	/*
271 	 * else if no non-switch argument remains, then it should be a start
272 	 * request
273 	 */
274 	else if (optind == argc)
275 	{
276 		int			pid = read_pid_file();
277 
278 		if (pid > 0)
279 		{
280 			if (kill(pid, 0) == 0)
281 			{
282 				fprintf(stderr, "ERROR: pid file found. is another pgpool(%d) is running?\n", pid);
283 				exit(EXIT_FAILURE);
284 			}
285 			else
286 				fprintf(stderr, "NOTICE: pid file found but it seems bogus. Trying to start pgpool anyway...\n");
287 		}
288 	}
289 
290 	/*
291 	 * otherwise an error...
292 	 */
293 	else
294 	{
295 		usage();
296 		exit(1);
297 	}
298 
299 	if (pool_config->enable_pool_hba)
300 		load_hba(hba_file);
301 
302 #ifdef USE_SSL
303 
304 	/*
305 	 * If ssl is enabled, initialize the SSL context
306 	 */
307 	if (pool_config->ssl)
308 		SSL_ServerSide_init();
309 #endif							/* USE_SSL */
310 
311 	/* check effective user id for watchdog */
312 	/* watchdog must be started under the privileged user */
313 	wd_check_network_command_configurations();
314 
315 	/* set signal masks */
316 	poolinitmask();
317 
318 	/* read the pool password key */
319 	if (strlen(pool_passwd_key_file_path) == 0)
320 	{
321 		get_pool_key_filename(pool_passwd_key_file_path);
322 	}
323 	pool_key = read_pool_key(pool_passwd_key_file_path);
324 
325 	if (not_detach)
326 		write_pid_file();
327 	else
328 		daemonize();
329 
330 	/*
331 	 * Locate pool_passwd The default file name "pool_passwd" can be changed
332 	 * by setting pgpool.conf's "pool_passwd" directive.
333 	 */
334 	if (strcmp("", pool_config->pool_passwd))
335 	{
336 		char		pool_passwd[POOLMAXPATHLEN + 1];
337 		char		dirnamebuf[POOLMAXPATHLEN + 1];
338 		char	   *dirp;
339 
340 		strlcpy(dirnamebuf, conf_file, sizeof(dirnamebuf));
341 		dirp = dirname(dirnamebuf);
342 		snprintf(pool_passwd, sizeof(pool_passwd), "%s/%s",
343 				 dirp, pool_config->pool_passwd);
344 		pool_init_pool_passwd(pool_passwd, POOL_PASSWD_R);
345 	}
346 
347 	pool_semaphore_create(MAX_NUM_SEMAPHORES);
348 
349 	PgpoolMain(discard_status, clear_memcache_oidmaps); /* this is an infinate
350 														 * loop */
351 
352 	exit(0);
353 
354 }
355 
356 static void
show_version(void)357 show_version(void)
358 {
359 	fprintf(stderr, "%s version %s (%s)\n", PACKAGE, VERSION, PGPOOLVERSION);
360 }
361 
362 static void
usage(void)363 usage(void)
364 {
365 	char		homedir[POOLMAXPATHLEN];
366 
367 	if (!get_home_directory(homedir, sizeof(homedir)))
368 		strncpy(homedir, "USER-HOME-DIR", POOLMAXPATHLEN);
369 
370 	fprintf(stderr, "%s version %s (%s),\n", PACKAGE, VERSION, PGPOOLVERSION);
371 	fprintf(stderr, "  A generic connection pool/replication/load balance server for PostgreSQL\n\n");
372 	fprintf(stderr, "Usage:\n");
373 	fprintf(stderr, "  pgpool [ -c] [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ]\n");
374 	fprintf(stderr, "         [ -n ] [ -D ] [ -d ]\n");
375 	fprintf(stderr, "  pgpool [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ]\n");
376 	fprintf(stderr, "         [ -m SHUTDOWN-MODE ] stop\n");
377 	fprintf(stderr, "  pgpool [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ] reload\n\n");
378 	fprintf(stderr, "Common options:\n");
379 	fprintf(stderr, "  -a, --hba-file=HBA_CONFIG_FILE\n");
380 	fprintf(stderr, "                      Set the path to the pool_hba.conf configuration file\n");
381 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME);
382 	fprintf(stderr, "  -f, --config-file=CONFIG_FILE\n");
383 	fprintf(stderr, "                      Set the path to the pgpool.conf configuration file\n");
384 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);
385 	fprintf(stderr, "  -k, --key-file=KEY_FILE\n");
386 	fprintf(stderr, "                      Set the path to the pgpool key file\n");
387 	fprintf(stderr, "                      (default: %s/%s)\n", homedir, POOLKEYFILE);
388 	fprintf(stderr, "                      can be over ridden by %s environment variable\n", POOLKEYFILEENV);
389 	fprintf(stderr, "  -F, --pcp-file=PCP_CONFIG_FILE\n");
390 	fprintf(stderr, "                      Set the path to the pcp.conf configuration file\n");
391 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, PCP_PASSWD_FILE_NAME);
392 	fprintf(stderr, "  -h, --help          Print this help\n\n");
393 	fprintf(stderr, "Start options:\n");
394 	fprintf(stderr, "  -C, --clear-oidmaps Clear query cache oidmaps when memqcache_method is memcached\n");
395 	fprintf(stderr, "                      (If shmem, discards whenever pgpool starts.)\n");
396 	fprintf(stderr, "  -n, --dont-detach   Don't run in daemon mode, does not detach control tty\n");
397 	fprintf(stderr, "  -x, --debug-assertions   Turns on various assertion checks, This is a debugging aid\n");
398 	fprintf(stderr, "  -D, --discard-status Discard pgpool_status file and do not restore previous status\n");
399 	fprintf(stderr, "  -d, --debug         Debug mode\n\n");
400 	fprintf(stderr, "Stop options:\n");
401 	fprintf(stderr, "  -m, --mode=SHUTDOWN-MODE\n");
402 	fprintf(stderr, "                      Can be \"smart\", \"fast\", or \"immediate\"\n\n");
403 	fprintf(stderr, "Shutdown modes are:\n");
404 	fprintf(stderr, "  smart       quit after all clients have disconnected\n");
405 	fprintf(stderr, "  fast        quit directly, with proper shutdown\n");
406 	fprintf(stderr, "  immediate   the same mode as fast\n");
407 }
408 
409 static bool
get_pool_key_filename(char * poolKeyFile)410 get_pool_key_filename(char *poolKeyFile)
411 {
412 	char	   *passfile_env;
413 
414 	if ((passfile_env = getenv(POOLKEYFILEENV)) != NULL)
415 	{
416 		/* use the literal path from the environment, if set */
417 		strlcpy(poolKeyFile, passfile_env, POOLMAXPATHLEN);
418 	}
419 	else
420 	{
421 		char		homedir[POOLMAXPATHLEN];
422 
423 		if (!get_home_directory(homedir, sizeof(homedir)))
424 			return false;
425 		snprintf(poolKeyFile, POOLMAXPATHLEN + sizeof(POOLKEYFILE) + 1, "%s/%s", homedir, POOLKEYFILE);
426 	}
427 	return true;
428 }
429 
430 
431 char *
get_pool_key(void)432 get_pool_key(void)
433 {
434 	return pool_key;
435 }
436 
437 /*
438 * detach control ttys
439 */
440 static void
daemonize(void)441 daemonize(void)
442 {
443 	int			i;
444 	pid_t		pid;
445 	int			fdlimit;
446 
447 	pid = fork();
448 	if (pid == (pid_t) -1)
449 	{
450 		ereport(FATAL,
451 				(errmsg("could not daemonize the pgpool-II"),
452 				 errdetail("fork() system call failed with reason: \"%m\"")));
453 	}
454 	else if (pid > 0)
455 	{							/* parent */
456 		exit(0);
457 	}
458 
459 #ifdef HAVE_SETSID
460 	if (setsid() < 0)
461 	{
462 		ereport(FATAL,
463 				(errmsg("could not daemonize the pgpool-II"),
464 				 errdetail("setsid() system call failed with reason: \"%m\"")));
465 	}
466 #endif
467 
468 	mypid = getpid();
469 	write_pid_file();
470 	if (chdir("/"))
471 		ereport(WARNING,
472 				(errmsg("change directory failed"),
473 				 errdetail("chdir() system call failed with reason: \"%m\"")));
474 
475 	/* redirect stdin, stdout and stderr to /dev/null */
476 	i = open("/dev/null", O_RDWR);
477 	if (i < 0)
478 	{
479 		ereport(WARNING,
480 				(errmsg("failed to open \"/dev/null\""),
481 				 errdetail("%m")));
482 	}
483 	else
484 	{
485 		dup2(i, 0);
486 		dup2(i, 1);
487 		dup2(i, 2);
488 		close(i);
489 	}
490 	/* close syslog connection for daemonizing */
491 	if (pool_config->log_destination & LOG_DESTINATION_SYSLOG)
492 	{
493 		closelog();
494 	}
495 
496 	/* close other file descriptors */
497 	fdlimit = sysconf(_SC_OPEN_MAX);
498 	for (i = 3; i < fdlimit; i++)
499 		close(i);
500 }
501 
502 /*
503 * stop myself
504 */
505 static void
stop_me(void)506 stop_me(void)
507 {
508 	pid_t		pid;
509 	char	   *pid_file;
510 
511 	pid = read_pid_file();
512 	if (pid < 0)
513 	{
514 		ereport(FATAL,
515 				(errmsg("could not read pid file")));
516 	}
517 
518 	if (kill(pid, stop_sig) == -1)
519 	{
520 		ereport(FATAL,
521 				(errmsg("could not stop process with pid: %d", pid),
522 				 errdetail("%m")));
523 	}
524 	ereport(LOG,
525 			(errmsg("stop request sent to pgpool. waiting for termination...")));
526 
527 	while (kill(pid, 0) == 0)
528 	{
529 		fprintf(stderr, ".");
530 		sleep(1);
531 	}
532 	fprintf(stderr, "done.\n");
533 	pid_file = get_pid_file_path();
534 	unlink(pid_file);
535 	pfree(pid_file);
536 }
537 
538 /*
539  * The function returns the palloc'd copy of pid_file_path,
540  * caller must free it after use
541  */
542 static char *
get_pid_file_path(void)543 get_pid_file_path(void)
544 {
545 	char	   *new = NULL;
546 
547 	if (!is_absolute_path(pool_config->pid_file_name))
548 	{
549 		/*
550 		 * some implementations of dirname() may modify the string argument
551 		 * passed to it, so do not use the original conf_file as an argument
552 		 */
553 		char	   *conf_file_copy = pstrdup(conf_file);
554 		char	   *conf_dir = dirname(conf_file_copy);
555 		size_t		path_size;
556 
557 		if (conf_dir == NULL)
558 		{
559 			ereport(LOG,
560 					(errmsg("failed to get the dirname of pid file:\"%s\"",
561 							pool_config->pid_file_name),
562 					 errdetail("%m")));
563 			return NULL;
564 		}
565 		path_size = strlen(conf_dir) + strlen(pool_config->pid_file_name) + 1 + 1;
566 		new = palloc(path_size);
567 		snprintf(new, path_size, "%s/%s", conf_dir, pool_config->pid_file_name);
568 
569 		ereport(DEBUG1,
570 				(errmsg("pid file location is \"%s\"",
571 						new)));
572 
573 		pfree(conf_file_copy);
574 	}
575 	else
576 	{
577 		new = pstrdup(pool_config->pid_file_name);
578 	}
579 
580 	return new;
581 }
582 
583 /*
584 * read the pid file
585 */
586 static int
read_pid_file(void)587 read_pid_file(void)
588 {
589 	int			fd;
590 	int			readlen;
591 	char		pidbuf[128];
592 	char	   *pid_file = get_pid_file_path();
593 
594 	if (pid_file == NULL)
595 	{
596 		ereport(FATAL,
597 				(errmsg("failed to read pid file"),
598 				 errdetail("failed to get pid file path from \"%s\"",
599 						   pool_config->pid_file_name)));
600 	}
601 	fd = open(pid_file, O_RDONLY);
602 	if (fd == -1)
603 	{
604 		pfree(pid_file);
605 		return -1;
606 	}
607 	if ((readlen = read(fd, pidbuf, sizeof(pidbuf))) == -1)
608 	{
609 		close(fd);
610 		pfree(pid_file);
611 		ereport(FATAL,
612 				(errmsg("could not read pid file \"%s\"",
613 						pool_config->pid_file_name),
614 				 errdetail("%m")));
615 	}
616 	else if (readlen == 0)
617 	{
618 		close(fd);
619 		pfree(pid_file);
620 		ereport(FATAL,
621 				(errmsg("EOF detected while reading pid file \"%s\"",
622 						pool_config->pid_file_name),
623 				 errdetail("%m")));
624 	}
625 	pfree(pid_file);
626 	close(fd);
627 	return (atoi(pidbuf));
628 }
629 
630 /*
631 * write the pid file
632 */
633 static void
write_pid_file(void)634 write_pid_file(void)
635 {
636 	int			fd;
637 	char		pidbuf[128];
638 	char	   *pid_file = get_pid_file_path();
639 
640 	if (pid_file == NULL)
641 	{
642 		ereport(FATAL,
643 				(errmsg("failed to write pid file"),
644 				 errdetail("failed to get pid file path from \"%s\"",
645 						   pool_config->pid_file_name)));
646 	}
647 
648 	fd = open(pid_file, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
649 	if (fd == -1)
650 	{
651 		ereport(FATAL,
652 				(errmsg("could not open pid file \"%s\"",
653 						pool_config->pid_file_name),
654 				 errdetail("%m")));
655 	}
656 	snprintf(pidbuf, sizeof(pidbuf), "%d", (int) getpid());
657 	if (write(fd, pidbuf, strlen(pidbuf) + 1) == -1)
658 	{
659 		close(fd);
660 		pfree(pid_file);
661 		ereport(FATAL,
662 				(errmsg("could not write pid file \"%s\"",
663 						pool_config->pid_file_name),
664 				 errdetail("%m")));
665 	}
666 	if (fsync(fd) == -1)
667 	{
668 		close(fd);
669 		pfree(pid_file);
670 		ereport(FATAL,
671 				(errmsg("could not fsync pid file \"%s\"",
672 						pool_config->pid_file_name),
673 				 errdetail("%m")));
674 	}
675 	if (close(fd) == -1)
676 	{
677 		pfree(pid_file);
678 		ereport(FATAL,
679 				(errmsg("could not close pid file \"%s\"",
680 						pool_config->pid_file_name),
681 				 errdetail("%m")));
682 	}
683 	/* register the call back to delete the pid file at system exit */
684 	on_proc_exit(FileUnlink, (Datum) pid_file);
685 }
686 
687 /*
688  * get_config_file_name: return full path of pgpool.conf.
689  */
690 char *
get_config_file_name(void)691 get_config_file_name(void)
692 {
693 	return conf_file;
694 }
695 
696 /*
697  * get_hba_file_name: return full path of pool_hba.conf.
698  */
699 char *
get_hba_file_name(void)700 get_hba_file_name(void)
701 {
702 	return hba_file;
703 }
704 
705 /*
706  * Call back function to unlink the file
707  */
708 static void
FileUnlink(int code,Datum path)709 FileUnlink(int code, Datum path)
710 {
711 	char	   *filePath = (char *) path;
712 
713 	if (unlink(filePath) == 0)
714 		return;
715 
716 	/*
717 	 * We are already exiting the system just produce a log entry to report an
718 	 * error
719 	 */
720 	ereport(LOG,
721 			(errmsg("unlink failed for file at path \"%s\"", filePath),
722 			 errdetail("%m")));
723 }
724