/* * 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); }
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 */ }
/* * 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); }
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); }
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))); }
/** * @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); } }
/* * 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; }
/* * 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; }