Exemplo n.º 1
0
/*
 * Verify that the given directory exists and is empty. If it does not
 * exist, it is created. If it exists but is not empty, an error will
 * be give and the process ended.
 */
static void
verify_dir_is_empty_or_create(char *dirname)
{
	switch (pg_check_dir(dirname))
	{
		case 0:

			/*
			 * Does not exist, so create
			 */
			if (pg_mkdir_p(dirname, S_IRWXU) == -1)
			{
				fprintf(stderr,
						_("%s: could not create directory \"%s\": %s\n"),
						progname, dirname, strerror(errno));
				disconnect_and_exit(1);
			}
			return;
		case 1:

			/*
			 * Exists, empty
			 */
			return;
		case 2:
		case 3:
		case 4:

			/*
			 * Exists, not empty
			 */
			fprintf(stderr,
					_("%s: directory \"%s\" exists but is not empty\n"),
					progname, dirname);
			disconnect_and_exit(1);
		case -1:

			/*
			 * Access problem
			 */
			fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
					progname, dirname, strerror(errno));
			disconnect_and_exit(1);
	}
}
Exemplo n.º 2
0
int
main(int argc, char *argv[])
{
	/*
	 * options with no short version return a low integer, the rest return
	 * their short version value
	 */
	static struct option long_options[] = {
		{"pgdata", required_argument, NULL, 'D'},
		{"help", no_argument, NULL, '?'},
		{"version", no_argument, NULL, 'V'},
		{"debug", no_argument, NULL, 'd'},
		{"show", no_argument, NULL, 's'},
		{"noclean", no_argument, NULL, 'n'},
		{NULL, 0, NULL, 0}
	};

	int			c, ret;
	int			option_index;
	char	   *effective_user;
	char		bin_dir[MAXPGPATH];
	char	   *pg_data_native;
	bool		node_type_specified = false;

	progname = get_progname(argv[0]);
	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("initgtm"));

	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
		usage(progname);
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("initgtm (Postgres-XL) " PGXC_VERSION);
			exit(0);
		}
	}

	/* process command-line options */

	while ((c = getopt_long(argc, argv, "dD:nsZ:", long_options, &option_index)) != -1)
	{
		switch (c)
		{
			case 'D':
				pg_data = xstrdup(optarg);
				break;
			case 'd':
				debug = true;
				printf(_("Running in debug mode.\n"));
				break;
			case 'n':
				noclean = true;
				printf(_("Running in noclean mode.  Mistakes will not be cleaned up.\n"));
				break;
			case 's':
				show_setting = true;
				break;
			case 'Z':
				if (strcmp(xstrdup(optarg), "gtm") == 0)
					is_gtm = true;
				else if (strcmp(xstrdup(optarg), "gtm_proxy") == 0)
					is_gtm = false;
				else
				{
					fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
							progname);
					exit(1);
				}
				node_type_specified = true;
				break;
			default:
				/* getopt_long already emitted a complaint */
				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
						progname);
				exit(1);
		}
	}

	/* Non-option argument specifies data directory */
	if (optind < argc)
	{
		pg_data = xstrdup(argv[optind]);
		optind++;
	}

	if (optind < argc)
	{
		fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
				progname, argv[optind + 1]);
		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
				progname);
		exit(1);
	}

	/* Check on definition of GTM data folder */
	if (strlen(pg_data) == 0)
	{
		fprintf(stderr,
				_("%s: no data directory specified\n"
				  "You must identify the directory where the data for this GTM system\n"
				  "will reside.  Do this with either the invocation option -D or the\n"
				  "environment variable PGDATA.\n"),
				progname);
		exit(1);
	}

	if (!node_type_specified)
	{
		fprintf(stderr,
				_("%s: no node type specified\n"
				  "You must identify the node type chosen for initialization.\n"
				  "Do this with the invocation option -Z by choosing \"gtm\" or"
				  "\"gtm_proxy\"\n"),
				progname);
		exit(1);
	}

	pg_data_native = pg_data;
	canonicalize_path(pg_data);

#ifdef WIN32

	/*
	 * Before we execute another program, make sure that we are running with a
	 * restricted token. If not, re-execute ourselves with one.
	 */

	if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
		|| strcmp(restrict_env, "1") != 0)
	{
		PROCESS_INFORMATION pi;
		char	   *cmdline;

		ZeroMemory(&pi, sizeof(pi));

		cmdline = xstrdup(GetCommandLine());

		putenv("PG_RESTRICT_EXEC=1");

		if (!CreateRestrictedProcess(cmdline, &pi))
		{
			fprintf(stderr, "Failed to re-exec with restricted token: %lu.\n", GetLastError());
		}
		else
		{
			/*
			 * Successfully re-execed. Now wait for child process to capture
			 * exitcode.
			 */
			DWORD		x;

			CloseHandle(pi.hThread);
			WaitForSingleObject(pi.hProcess, INFINITE);

			if (!GetExitCodeProcess(pi.hProcess, &x))
			{
				fprintf(stderr, "Failed to get exit code from subprocess: %lu\n", GetLastError());
				exit(1);
			}
			exit(x);
		}
	}
#endif

	/* Like for initdb, check if a valid version of Postgres is running */
	if ((ret = find_other_exec(argv[0], "postgres", PG_BACKEND_VERSIONSTR,
							   backend_exec)) < 0)
	{
		char        full_path[MAXPGPATH];

		if (find_my_exec(argv[0], full_path) < 0)
			strlcpy(full_path, progname, sizeof(full_path));

		if (ret == -1)
			fprintf(stderr,
					_("The program \"postgres\" is needed by %s "
					  "but was not found in the\n"
					  "same directory as \"%s\".\n"
					  "Check your installation.\n"),
					progname, full_path);
		else
			fprintf(stderr,
					_("The program \"postgres\" was found by \"%s\"\n"
					  "but was not the same version as %s.\n"
					  "Check your installation.\n"),
					full_path, progname);
		exit(1);
	}

	/* store binary directory */
	strcpy(bin_path, backend_exec);
	*last_dir_separator(bin_path) = '\0';
	canonicalize_path(bin_path);

	if (!share_path)
	{
		share_path = pg_malloc(MAXPGPATH);
		get_share_path(backend_exec, share_path);
	}
	else if (!is_absolute_path(share_path))
	{
		fprintf(stderr, _("%s: input file location must be an absolute path\n"), progname);
		exit(1);
	}

	canonicalize_path(share_path);

	effective_user = get_id();

	/* Take into account GTM and GTM-proxy cases */
	if (is_gtm)
		set_input(&conf_file, "gtm.conf.sample");
	else
		set_input(&conf_file, "gtm_proxy.conf.sample");

	if (show_setting || debug)
	{
		fprintf(stderr,
				"VERSION=%s\n"
				"GTMDATA=%s\nshare_path=%s\nGTMPATH=%s\n"
				"GTM_CONF_SAMPLE=%s\n",
				PGXC_VERSION,
				pg_data, share_path, bin_path,
				conf_file);
		if (show_setting)
			exit(0);
	}

	check_input(conf_file);

	printf(_("The files belonging to this GTM system will be owned "
			 "by user \"%s\".\n"
			 "This user must also own the server process.\n\n"),
		   effective_user);

	printf("\n");

	umask(S_IRWXG | S_IRWXO);

	/*
	 * now we are starting to do real work, trap signals so we can clean up
	 */

	/* some of these are not valid on Windows */
#ifdef SIGHUP
	pqsignal(SIGHUP, trapsig);
#endif
#ifdef SIGINT
	pqsignal(SIGINT, trapsig);
#endif
#ifdef SIGQUIT
	pqsignal(SIGQUIT, trapsig);
#endif
#ifdef SIGTERM
	pqsignal(SIGTERM, trapsig);
#endif

	/* Ignore SIGPIPE when writing to backend, so we can clean up */
#ifdef SIGPIPE
	pqsignal(SIGPIPE, SIG_IGN);
#endif

	switch (pg_check_dir(pg_data))
	{
		case 0:
			/* PGDATA not there, must create it */
			printf(_("creating directory %s ... "),
				   pg_data);
			fflush(stdout);

			if (!mkdatadir(NULL))
				exit_nicely();
			else
				check_ok();

			made_new_pgdata = true;
			break;

		case 1:
			/* Present but empty, fix permissions and use it */
			printf(_("fixing permissions on existing directory %s ... "),
				   pg_data);
			fflush(stdout);

			if (chmod(pg_data, S_IRWXU) != 0)
			{
				fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
						progname, pg_data, strerror(errno));
				exit_nicely();
			}
			else
				check_ok();

			found_existing_pgdata = true;
			break;

		case 2:
			/* Present and not empty */
			fprintf(stderr,
					_("%s: directory \"%s\" exists but is not empty\n"),
					progname, pg_data);
			fprintf(stderr,
					_("If you want to create a new GTM system, either remove or empty\n"
					  "the directory \"%s\" or run %s\n"
					  "with an argument other than \"%s\".\n"),
					pg_data, progname, pg_data);
			exit(1);			/* no further message needed */

		default:
			/* Trouble accessing directory */
			fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
					progname, pg_data, strerror(errno));
			exit_nicely();
	}

	/* Select suitable configuration settings */
	set_null_conf();

	/* Now create all the text config files */
	setup_config();

	/* Get directory specification used to start this executable */
	strcpy(bin_dir, argv[0]);
	get_parent_directory(bin_dir);

	if (is_gtm)
		printf(_("\nSuccess. You can now start the GTM server using:\n\n"
				 "    %s%s%sgtm%s -D %s%s%s\n"
				 "or\n"
				 "    %s%s%sgtm_ctl%s -Z gtm -D %s%s%s -l logfile start\n\n"),
		   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
			   QUOTE_PATH, pg_data_native, QUOTE_PATH,
		   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
			   QUOTE_PATH, pg_data_native, QUOTE_PATH);
	else
		printf(_("\nSuccess. You can now start the GTM proxy server using:\n\n"
				 "    %s%s%sgtm_proxy%s -D %s%s%s\n"
				 "or\n"
				 "    %s%s%sgtm_ctl%s -Z gtm_proxy -D %s%s%s -l logfile start\n\n"),
		   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
			   QUOTE_PATH, pg_data_native, QUOTE_PATH,
		   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
			   QUOTE_PATH, pg_data_native, QUOTE_PATH);

	return 0;
}