Ejemplo n.º 1
0
/*
 * the result is also available with the global variable 'connection'.
 */
void
reconnect(int elevel)
{
	StringInfoData	buf;
	char		   *new_password;

	disconnect();
	initStringInfo(&buf);
	if (dbname && dbname[0])
		appendStringInfo(&buf, "dbname=%s ", dbname);
	if (host && host[0])
		appendStringInfo(&buf, "host=%s ", host);
	if (port && port[0])
		appendStringInfo(&buf, "port=%s ", port);
	if (username && username[0])
		appendStringInfo(&buf, "user=%s ", username);
	if (password && password[0])
		appendStringInfo(&buf, "password=%s ", password);

	connection = pgut_connect(buf.data, prompt_password, elevel);

	/* update password */
	if (connection)
	{
		new_password = PQpass(connection);
		if (new_password && new_password[0] &&
			(password == NULL || strcmp(new_password, password) != 0))
		{
			free(password);
			password = pgut_strdup(new_password);
		}
	}

	termStringInfo(&buf);
}
Ejemplo n.º 2
0
void
pgut_putenv(const char *key, const char *value)
{
	char	buf[1024];

	snprintf(buf, lengthof(buf), "%s=%s", key, value);
	putenv(pgut_strdup(buf));	/* putenv requires malloc'ed buffer */
}
Ejemplo n.º 3
0
/*
 * load guc variables
 */
static void
reload_params(void)
{
	pgut_disconnect(writer_conn);
	writer_conn = NULL;

	if (my_repository_server != NULL &&
		strcmp(my_repository_server, repository_server) != 0)
	{
		free(my_repository_server);
		my_repository_server = pgut_strdup(repository_server);
		set_connect_privileges();
	}

	free(my_repository_server);
	my_repository_server = pgut_strdup(repository_server);
}
Ejemplo n.º 4
0
void
dir_list_file_internal(parray *files, const char *root, const char *exclude[],
			bool omit_symlink, bool add_root, parray *black_list)
{
	pgFile *file;

	file = pgFileNew(root, omit_symlink);
	if (file == NULL)
		return;

	/* skip if the file is in black_list defined by user */
	if (black_list && parray_bsearch(black_list, root, BlackListCompare))
	{
		/* found in black_list. skip this item */
		return;
	}

	if (add_root)
		parray_append(files, file);

	/* chase symbolic link chain and find regular file or directory */
	while (S_ISLNK(file->mode))
	{
		ssize_t	len;
		char	linked[MAXPGPATH];

		len = readlink(file->path, linked, sizeof(linked));
		if (len == -1)
		{
			ereport(ERROR,
				(errcode(ERROR_SYSTEM),
				 errmsg("could not read link \"%s\": %s", file->path, strerror(errno))));
		}
		linked[len] = '\0';
		file->linked = pgut_strdup(linked);

		/* make absolute path to read linked file */
		if (linked[0] != '/')
		{
			char	dname[MAXPGPATH];
			char	absolute[MAXPGPATH];

			strncpy(dname, file->path, lengthof(dname));
			join_path_components(absolute, dirname(dname), linked);
			file = pgFileNew(absolute, omit_symlink);
		}
		else
			file = pgFileNew(file->linked, omit_symlink);

		/* linked file is not found, stop following link chain */
		if (file == NULL)
			return;

		parray_append(files, file);
	}

	/*
	 * If the entry was a directory, add it to the list and add call this
	 * function recursivelly.
	 * If the directory name is in the exclude list, do not list the contents.
	 */
	while (S_ISDIR(file->mode))
	{
		int				i;
		bool			skip = false;
		DIR			    *dir;
		struct dirent   *dent;
		char		    *dirname;

		/* skip entry which matches exclude list */
	   	dirname = strrchr(file->path, '/');
		if (dirname == NULL)
			dirname = file->path;
		else
			dirname++;

		/*
		 * If the item in the exclude list starts with '/', compare to the
		 * absolute path of the directory. Otherwise compare to the directory
		 * name portion.
		 */
		for (i = 0; exclude && exclude[i]; i++)
		{
			if (exclude[i][0] == '/')
			{
				if (strcmp(file->path, exclude[i]) == 0)
				{
					skip = true;
					break;
				}
			}
			else
			{
				if (strcmp(dirname, exclude[i]) == 0)
				{
					skip = true;
					break;
				}
			}
		}
		if (skip)
			break;

		/* open directory and list contents */
		dir = opendir(file->path);
		if (dir == NULL)
		{
			if (errno == ENOENT)
			{
				/* maybe the direcotry was removed */
				return;
			}
			ereport(ERROR,
				(errcode(ERROR_SYSTEM),
				 errmsg("could not open directory \"%s\": %s",
					file->path, strerror(errno))));
		}

		errno = 0;
		while ((dent = readdir(dir)))
		{
			char child[MAXPGPATH];

			/* skip entries point current dir or parent dir */
			if (strcmp(dent->d_name, ".") == 0 ||
				strcmp(dent->d_name, "..") == 0)
				continue;

			join_path_components(child, file->path, dent->d_name);
			dir_list_file_internal(files, child, exclude, omit_symlink, true, black_list);
		}
		if (errno && errno != ENOENT)
		{
			int errno_tmp = errno;
			closedir(dir);
			ereport(ERROR,
				(errcode(ERROR_SYSTEM),
				 errmsg("could not read directory \"%s\": %s",
					file->path, strerror(errno_tmp))));
		}
		closedir(dir);

		break;	/* pseudo loop */
	}

	parray_qsort(files, pgFileComparePath);
}
Ejemplo n.º 5
0
void
pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
{
	const char	  *message;

	if (opt == NULL)
	{
		fprintf(stderr, "Try \"%s --help\" for more information.\n", PROGRAM_NAME);
		exit(EINVAL);
	}

	if (opt->source > src)
	{
		/* high prior value has been set already. */
		return;
	}
	else if (src >= SOURCE_CMDLINE && opt->source >= src)
	{
		/* duplicated option in command line */
		message = "specified only once";
	}
	else
	{
		/* can be overwritten if non-command line source */
		opt->source = src;

		switch (opt->type)
		{
			case 'b':
			case 'B':
				if (optarg == NULL)
				{
					*((bool *) opt->var) = (opt->type == 'b');
					return;
				}
				else if (parse_bool(optarg, (bool *) opt->var))
				{
					return;
				}
				message = "a boolean";
				break;
			case 'f':
				((pgut_optfn) opt->var)(opt, optarg);
				return;
			case 'i':
				if (parse_int32(optarg, opt->var))
					return;
				message = "a 32bit signed integer";
				break;
			case 'u':
				if (parse_uint32(optarg, opt->var))
					return;
				message = "a 32bit unsigned integer";
				break;
			case 'I':
				if (parse_int64(optarg, opt->var))
					return;
				message = "a 64bit signed integer";
				break;
			case 'U':
				if (parse_uint64(optarg, opt->var))
					return;
				message = "a 64bit unsigned integer";
				break;
			case 's':
				if (opt->source != SOURCE_DEFAULT)
					free(*(char **) opt->var);
				*(char **) opt->var = pgut_strdup(optarg);
				return;
			case 't':
				if (parse_time(optarg, opt->var))
					return;
				message = "a time";
				break;
			case 'y':
			case 'Y':
				if (optarg == NULL)
				{
					*(YesNo *) opt->var = (opt->type == 'y' ? YES : NO);
					return;
				}
				else
				{
					bool	value;
					if (parse_bool(optarg, &value))
					{
						*(YesNo *) opt->var = (value ? YES : NO);
						return;
					}
				}
				message = "a boolean";
				break;
			default:
				ereport(ERROR,
					(errcode(EINVAL),
					 errmsg("invalid option type: %c", opt->type)));
				return;	/* keep compiler quiet */
		}
	}

	if (isprint(opt->sname))
		ereport(ERROR,
			(errcode(EINVAL),
			 errmsg("option -%c, --%s should be %s: '%s'",
				opt->sname, opt->lname, message, optarg)));
	else
		ereport(ERROR,
			(errcode(EINVAL),
			 errmsg("option --%s should be %s: '%s'",
				opt->lname, message, optarg)));
}
Ejemplo n.º 6
0
/**
 * @brief Entry point for pg_bulkload command.
 *
 * Flow:
 * <ol>
 *	 <li> Parses command arguments. </li>
 *	 <li> Without -r option: Starts the loading. </li>
 *	 <li> With -r option: Starts the recovery. </li>
 * </ol>
 *
 * @param argc [in] Number of arguments.
 * @param argv [in] Argument list.
 * @return Returns zero if successful, 1 otherwise.
 */
int
main(int argc, char *argv[])
{
	char	cwd[MAXPGPATH];
	char	control_file[MAXPGPATH] = "";
	int		i;

	pgut_init(argc, argv);
	if (argc < 2)
	{
		help(false);
		return E_PG_OTHER;
	}

	if (getcwd(cwd, MAXPGPATH) == NULL)
		ereport(ERROR,
			(errcode(EXIT_FAILURE),
			 errmsg("cannot read current directory: ")));

	i = pgut_getopt(argc, argv, options);

	for (; i < argc; i++)
	{
		if (control_file[0])
			ereport(ERROR,
				(errcode(EXIT_FAILURE),
				 errmsg("too many arguments")));

		/* make absolute control file path */
		if (is_absolute_path(argv[i]))
			strlcpy(control_file, argv[i], MAXPGPATH);
		else
			join_path_components(control_file, cwd, argv[i]);
		canonicalize_path(control_file);
	}

	/*
	 * Determines data loading or recovery.
	 */
	if (recovery)
	{
		/* verify arguments */
		if (!DataDir && (DataDir = getenv("PGDATA")) == NULL)
			elog(ERROR, "no $PGDATA specified");
		if (strlen(DataDir) + MAX_LOADSTATUS_NAME >= MAXPGPATH)
			elog(ERROR, "too long $PGDATA path length");
		if (control_file[0] != '\0')
			elog(ERROR, "invalid argument 'control file' for recovery");

		return LoaderRecoveryMain();
	}
	else
	{
		/* verify arguments */
		if (DataDir)
			elog(ERROR, "invalid option '-D' for data load");

		if (control_file[0])
			bulkload_options = list_concat(
				ParseControlFile(control_file), bulkload_options);

		/* chdir control_file to the parent directory */
		get_parent_directory(control_file);

		/* add path options */
		for (i = 0; i < NUM_PATH_OPTIONS; i++)
		{
			const pgut_option  *opt = &options[i];
			const char		   *path = *(const char **) opt->var;
			char				abspath[MAXPGPATH];
			char				item[MAXPGPATH + 32];

			if (path == NULL)
				continue;

			if ((i == 0 || i == 1) &&
				(pg_strcasecmp(path, "stdin") == 0 || type_function))
			{
				/* special case for stdin and input from function */
				strlcpy(abspath, path, lengthof(abspath));
			}
			else if (is_absolute_path(path) || (i == 2 && !writer_binary))
			{
				/* absolute path */
				strlcpy(abspath, path, lengthof(abspath));
			}
			else if (opt->source == SOURCE_FILE)
			{
				/* control file relative path */
				join_path_components(abspath, control_file, path);
			}
			else
			{
				/* current working directory relative path */
				join_path_components(abspath, cwd, path);
			}

			canonicalize_path(abspath);
			snprintf(item, lengthof(item), "%s=%s", opt->lname, abspath);
			bulkload_options = lappend(bulkload_options, pgut_strdup(item));
		}

		return LoaderLoadMain(bulkload_options);
	}
}
Ejemplo n.º 7
0
/*
 * Initialize backup catalog.
 */
int
do_init(void)
{
	char	path[MAXPGPATH];
	char   *log_directory = NULL;
	char   *archive_command = NULL;
	FILE   *fp;

	struct dirent **dp;
	int results;
	if (access(backup_path, F_OK) == 0){
		results = scandir(backup_path, &dp, selects, NULL);
		if(results != 0){
			elog(ERROR, _("backup catalog already exist. and it's not empty."));
		}
	}

	/* create backup catalog root directory */
	dir_create_dir(backup_path, DIR_PERMISSION);

	/* create directories for backup of online files */
	join_path_components(path, backup_path, RESTORE_WORK_DIR);
	dir_create_dir(path, DIR_PERMISSION);
	snprintf(path, lengthof(path), "%s/%s/%s", backup_path, RESTORE_WORK_DIR,
		PG_XLOG_DIR);
	dir_create_dir(path, DIR_PERMISSION);
	snprintf(path, lengthof(path), "%s/%s/%s", backup_path, RESTORE_WORK_DIR,
		SRVLOG_DIR);
	dir_create_dir(path, DIR_PERMISSION);

	/* create directory for timeline history files */
	join_path_components(path, backup_path, TIMELINE_HISTORY_DIR);
	dir_create_dir(path, DIR_PERMISSION);

	/* read postgresql.conf */
	if (pgdata)
	{
		join_path_components(path, pgdata, "postgresql.conf");
		parse_postgresql_conf(path, &log_directory, &archive_command);
	}

	/* create pg_rman.ini */
	join_path_components(path, backup_path, PG_RMAN_INI_FILE);
	fp = fopen(path, "wt");
	if (fp == NULL)
		elog(ERROR_SYSTEM, _("can't create pg_rman.ini: %s"), strerror(errno));

	/* set ARCLOG_PATH refered with log_directory */
	if (arclog_path == NULL && archive_command && archive_command[0])
	{
		char *command = pgut_strdup(archive_command);
		char *begin;
		char *end;
		char *fname;

		/* example: 'cp "%p" /path/to/arclog/"%f"' */
		for (begin = command; *begin;)
		{
			begin = begin + strspn(begin, " \n\r\t\v");
			end = begin + strcspn(begin, " \n\r\t\v");
			*end = '\0';

			if ((fname = strstr(begin, "%f")) != NULL)
			{
				while (strchr(" \n\r\t\v\"'", *begin))
					begin++;
				fname--;
				while (fname > begin && strchr(" \n\r\t\v\"'/", fname[-1]))
					fname--;
				*fname = '\0';

				if (is_absolute_path(begin))
					arclog_path = pgut_strdup(begin);
				break;
			}

			begin = end + 1;
		}

		free(command);
	}
	if (arclog_path)
	{
		fprintf(fp, "ARCLOG_PATH='%s'\n", arclog_path);
		elog(INFO, "ARCLOG_PATH is set to '%s'", arclog_path);
	}
	else if (archive_command && archive_command[0])
		elog(WARNING, "ARCLOG_PATH is not set because failed to parse archive_command '%s'."
				"Please set ARCLOG_PATH in pg_rman.ini or environmental variable", archive_command);
	else
		elog(WARNING, "ARCLOG_PATH is not set because archive_command is empty."
				"Please set ARCLOG_PATH in pg_rman.ini or environmental variable");

	/* set SRVLOG_PATH refered with log_directory */
	if (srvlog_path == NULL)
	{
		if (log_directory)
		{
			if (is_absolute_path(log_directory))
				srvlog_path = pgut_strdup(log_directory);
			else
			{
				srvlog_path = pgut_malloc(MAXPGPATH);
				join_path_components(srvlog_path, pgdata, log_directory);
			}
		}
		else if (pgdata)
		{
			/* default: log_directory = 'pg_log' */
			srvlog_path = pgut_malloc(MAXPGPATH);
			join_path_components(srvlog_path, pgdata, "pg_log");
		}
	}
	if (srvlog_path)
	{
		fprintf(fp, "SRVLOG_PATH='%s'\n", srvlog_path);
		elog(INFO, "SRVLOG_PATH is set to '%s'", srvlog_path);
	}

	fprintf(fp, "\n");
	fclose(fp);

	free(archive_command);
	free(log_directory);

	return 0;
}
Ejemplo n.º 8
0
/*
 * this tries to build all the elements of a path to a directory a la mkdir -p
 * we assume the path is in canonical form, i.e. uses / as the separator.
 */
bool
pgut_mkdir(const char *dirpath)
{
	struct stat sb;
	int			first,
				last,
				retval;
	char	   *path;
	char	   *p;

	Assert(dirpath != NULL);

	p = path = pgut_strdup(dirpath);
	retval = 0;

#ifdef WIN32
	/* skip network and drive specifiers for win32 */
	if (strlen(p) >= 2)
	{
		if (p[0] == '/' && p[1] == '/')
		{
			/* network drive */
			p = strstr(p + 2, "/");
			if (p == NULL)
			{
				free(path);
				ereport(ERROR,
					(errcode(EINVAL),
					 errmsg("invalid path \"%s\"", dirpath)));
				return false;
			}
		}
		else if (p[1] == ':' &&
				 ((p[0] >= 'a' && p[0] <= 'z') ||
				  (p[0] >= 'A' && p[0] <= 'Z')))
		{
			/* local drive */
			p += 2;
		}
	}
#endif

	if (p[0] == '/')			/* Skip leading '/'. */
		++p;
	for (first = 1, last = 0; !last; ++p)
	{
		if (p[0] == '\0')
			last = 1;
		else if (p[0] != '/')
			continue;
		*p = '\0';
		if (!last && p[1] == '\0')
			last = 1;
		if (first)
			first = 0;

retry:
		/* check for pre-existing directory; ok if it's a parent */
		if (stat(path, &sb) == 0)
		{
			if (!S_ISDIR(sb.st_mode))
			{
				if (last)
					errno = EEXIST;
				else
					errno = ENOTDIR;
				retval = 1;
				break;
			}
		}
		else if (mkdir(path, S_IRWXU) < 0)
		{
			if (errno == EEXIST)
				goto retry;	/* another thread might create the directory. */
			retval = 1;
			break;
		}
		if (!last)
			*p = '/';
	}
	free(path);

	if (retval == 0)
	{
		ereport(ERROR,
			(errcode_errno(),
			 errmsg("could not create directory \"%s\": ", dirpath)));
		return false;
	}

	return true;
}