예제 #1
0
파일: dir.c 프로젝트: jamexu98918/pg_rman
static pgFile *
pgFileNew(const char *path, bool omit_symlink)
{
	struct stat		st;
	pgFile		   *file;

	/* stat the file */
	if ((omit_symlink ? stat(path, &st) : lstat(path, &st)) == -1)
	{
		/* file not found is not an error case */
		if (errno == ENOENT)
			return NULL;
		ereport(ERROR,
			(errcode(ERROR_SYSTEM),
			 errmsg("could not stat file \"%s\": %s", path, strerror(errno))));
	}

	file = (pgFile *) pgut_malloc(offsetof(pgFile, path) + strlen(path) + 1);

	file->mtime = st.st_mtime;
	file->size = st.st_size;
	file->read_size = 0;
	file->write_size = 0;
	file->mode = st.st_mode;
	file->crc = 0;
	file->is_datafile = false;
	file->linked = NULL;
	strcpy(file->path, path);		/* enough buffer size guaranteed */

	return file;
}
예제 #2
0
static List *
ParseControlFile(const char *path)
{
#define LINEBUF 1024
	char	buf[LINEBUF];
	int		lineno;
	FILE   *file;
	List   *items = NIL;

	file = pgut_fopen(path, "rt");

	for (lineno = 1; fgets(buf, LINEBUF, file); lineno++)
	{
		char   *keyword;
		char   *value;
		int		i;

		if (!ParseControlFileLine(buf, &keyword, &value))
			continue;

		/* PATH_OPTIONS */
		for (i = 0; i < NUM_PATH_OPTIONS; i++)
		{
			pgut_option *opt = &options[i];

			if (pgut_keyeq(keyword, opt->lname))
			{
				pgut_setopt(opt, value, SOURCE_FILE);
				break;
			}
		}

		/* Other options */
		if (i >= NUM_PATH_OPTIONS)
		{
			size_t	len;
			char   *item;

			len = strlen(keyword) + strlen(value) + 2;
			item = pgut_malloc(len);
			snprintf(item, len, "%s=%s", keyword, value);
			items = lappend(items, item);

			if (pg_strcasecmp(item, "TYPE=FUNCTION") == 0)
				type_function = true;

			if (pg_strcasecmp(item, "TYPE=BINARY") == 0 ||
				pg_strcasecmp(item, "TYPE=FIXED") == 0)
				type_binary = true;

			if (pg_strcasecmp(item, "WRITER=BINARY") == 0)
				writer_binary = true;
		}
	}

	fclose(file);

	return items;
}
예제 #3
0
파일: pgut.c 프로젝트: jamexu98918/pg_rman
char *
strdup_with_len(const char *str, size_t len)
{
	char *r;

	if (str == NULL)
		return NULL;

	r = pgut_malloc(len + 1);
	memcpy(r, str, len);
	r[len] = '\0';
	return r;
}
예제 #4
0
파일: pgut.c 프로젝트: jamexu98918/pg_rman
/*
 * Convert ISO-8601 format string to time_t value.
 */
bool
parse_time(const char *value, time_t *time)
{
	size_t		len;
	char	   *tmp;
	int			i;
	struct tm	tm;
	char		junk[2];

	/* tmp = replace( value, !isalnum, ' ' ) */
	tmp = pgut_malloc(strlen(value) + + 1);
	len = 0;
	for (i = 0; value[i]; i++)
		tmp[len++] = (IsAlnum(value[i]) ? value[i] : ' ');
	tmp[len] = '\0';

	/* parse for "YYYY-MM-DD HH:MI:SS" */
	memset(&tm, 0, sizeof(tm));
	tm.tm_year = 0;		/* tm_year is year - 1900 */
	tm.tm_mon = 0;		/* tm_mon is 0 - 11 */
	tm.tm_mday = 1;		/* tm_mday is 1 - 31 */
	tm.tm_hour = 0;
	tm.tm_min = 0;
	tm.tm_sec = 0;
	i = sscanf(tmp, "%04d %02d %02d %02d %02d %02d%1s",
		&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
		&tm.tm_hour, &tm.tm_min, &tm.tm_sec, junk);
	free(tmp);

	if (i < 1 || 6 < i)
		return false;

	/* adjust year */
	if (tm.tm_year < 100)
		tm.tm_year += 2000 - 1900;
	else if (tm.tm_year >= 1900)
		tm.tm_year -= 1900;

	/* adjust month */
	if (i > 1)
		tm.tm_mon -= 1;

	/* determine whether Daylight Saving Time is in effect */
	tm.tm_isdst = -1;

	*time = mktime(&tm);

	return true;
}
예제 #5
0
파일: pgut.c 프로젝트: kotsachin/pg_repack
/* Append the given string `val` to the `list` */
void
simple_string_list_append(SimpleStringList *list, const char *val)
{
	SimpleStringListCell *cell;

	/* this calculation correctly accounts for the null trailing byte */
	cell = (SimpleStringListCell *)
		pgut_malloc(sizeof(SimpleStringListCell) + strlen(val));
	cell->next = NULL;
	strcpy(cell->val, val);

	if (list->tail)
		list->tail->next = cell;
	else
		list->head = cell;
	list->tail = cell;
}
예제 #6
0
파일: pgut-fe.c 프로젝트: bwtakacy/pg_reorg
static char *
longopts_to_optstring(const struct option opts[])
{
	size_t	len;
	char   *result;
	char   *s;

	for (len = 0; opts[len].name; len++) { }
	result = pgut_malloc(len * 2 + 1);

	s = result;
	for (len = 0; opts[len].name; len++)
	{
		if (!isprint(opts[len].val))
			continue;
		*s++ = opts[len].val;
		if (opts[len].has_arg != no_argument)
			*s++ = ':';
	}
	*s = '\0';

	return result;
}
예제 #7
0
파일: dir.c 프로젝트: jamexu98918/pg_rman
/*
 * Construct parray of pgFile from the file list.
 * If root is not NULL, path will be absolute path.
 */
parray *
dir_read_file_list(const char *root, const char *file_txt)
{
	FILE   *fp;
	parray *files;
	char	buf[MAXPGPATH * 2];

	fp = fopen(file_txt, "rt");
	if (fp == NULL)
		ereport(ERROR,
			((errno == ENOENT ? errcode(ERROR_CORRUPTED) : errcode(ERROR_SYSTEM)),
			 errmsg("could not open \"%s\": %s", file_txt, strerror(errno))));

	files = parray_new();

	while (fgets(buf, lengthof(buf), fp))
	{
		char			path[MAXPGPATH];
		char			type;
		unsigned long	write_size;
		pg_crc32c		crc;
		unsigned int	mode;	/* bit length of mode_t depends on platforms */
		struct tm		tm;
		pgFile		   *file;

		memset(&tm, 0, sizeof(tm));
		if (sscanf(buf, "%s %c %lu %u %o %d-%d-%d %d:%d:%d",
			path, &type, &write_size, &crc, &mode,
			&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
			&tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 11)
		{
			ereport(ERROR,
				(errcode(ERROR_CORRUPTED),
				 errmsg("invalid format found in \"%s\"", file_txt)));
		}
		if (type != 'f' && type != 'F' && type != 'd' && type != 'l')
		{
			ereport(ERROR,
				(errcode(ERROR_CORRUPTED),
				 errmsg("invalid type '%c' found in \"%s\"", type, file_txt)));
		}
		tm.tm_isdst = -1;

		file = (pgFile *) pgut_malloc(offsetof(pgFile, path) +
					(root ? strlen(root) + 1 : 0) + strlen(path) + 1);

		tm.tm_year -= 1900;
		tm.tm_mon -= 1;
		file->mtime = mktime(&tm);
		file->mode = mode |
			((type == 'f' || type == 'F') ? S_IFREG :
			 type == 'd' ? S_IFDIR : type == 'l' ? S_IFLNK : 0);
		file->size = 0;
		file->read_size = 0;
		file->write_size = write_size;
		file->crc = crc;
		file->is_datafile = (type == 'F' ? true : false);
		file->linked = NULL;
		if (root)
			sprintf(file->path, "%s/%s", root, path);
		else
			strcpy(file->path, path);

		parray_append(files, file);
	}

	fclose(fp);

	/* file.txt is sorted, so this qsort is redundant */
	parray_qsort(files, pgFileComparePath);

	return files;
}
예제 #8
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;
}
예제 #9
0
/*
 * Create range object from one or two arguments.
 * All not-digit characters in the argument(s) are ignored.
 * Both arg1 and arg2 must be valid pointer.
 */
static void
parse_range(pgBackupRange *range, const char *arg1, const char *arg2)
{
	size_t		len = strlen(arg1) + strlen(arg2) + 1;
	char	   *tmp;
	int			num;
	struct tm	tm;

	tmp = pgut_malloc(len);
	tmp[0] = '\0';
	if (arg1 != NULL)
		remove_not_digit(tmp, len, arg1);
	if (arg2 != NULL)
		remove_not_digit(tmp + strlen(tmp), len - strlen(tmp), arg2);

	memset(&tm, 0, sizeof(tm));
	tm.tm_year = 0;		/* tm_year is year - 1900 */
	tm.tm_mon = 0;		/* tm_mon is 0 - 11 */
	tm.tm_mday = 1;		/* tm_mday is 1 - 31 */
	tm.tm_hour = 0;
	tm.tm_min = 0;
	tm.tm_sec = 0;
	num = sscanf(tmp, "%04d %02d %02d %02d %02d %02d",
		&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
		&tm.tm_hour, &tm.tm_min, &tm.tm_sec);

	if (num < 1)
	{
		if (strcmp(tmp,"") != 0)
			elog(ERROR, "supplied id(%s) is invalid", tmp);
		else
			elog(ERROR, "arguments are invalid. near \"%s\"", arg1);
	}

	free(tmp);

	/* adjust year and month to convert to time_t */
	tm.tm_year -= 1900;
	if (num > 1)
		tm.tm_mon -= 1;
	tm.tm_isdst = -1;

	if (!IsValidTime(tm))
		elog(ERROR, "supplied time(%s) is invalid.", arg1);

	range->begin = mktime(&tm);

	switch (num)
	{
		case 1:
			tm.tm_year++;
			break;
		case 2:
			tm.tm_mon++;
			break;
		case 3:
			tm.tm_mday++;
			break;
		case 4:
			tm.tm_hour++;
			break;
		case 5:
			tm.tm_min++;
			break;
		case 6:
			tm.tm_sec++;
			break;
	}
	range->end = mktime(&tm);
	range->end--;
}