diff options
Diffstat (limited to 'src/bin/pg_upgrade/util.c')
-rw-r--r-- | src/bin/pg_upgrade/util.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/bin/pg_upgrade/util.c b/src/bin/pg_upgrade/util.c new file mode 100644 index 0000000..fc20472 --- /dev/null +++ b/src/bin/pg_upgrade/util.c @@ -0,0 +1,243 @@ +/* + * util.c + * + * utility functions + * + * Copyright (c) 2010-2021, PostgreSQL Global Development Group + * src/bin/pg_upgrade/util.c + */ + +#include "postgres_fe.h" + +#include <signal.h> + +#include "common/username.h" +#include "pg_upgrade.h" + +LogOpts log_opts; + +static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2, 0); + + +/* + * report_status() + * + * Displays the result of an operation (ok, failed, error message,...) + */ +void +report_status(eLogType type, const char *fmt,...) +{ + va_list args; + char message[MAX_STRING]; + + va_start(args, fmt); + vsnprintf(message, sizeof(message), fmt, args); + va_end(args); + + pg_log(type, "%s\n", message); +} + + +/* force blank output for progress display */ +void +end_progress_output(void) +{ + /* + * In case nothing printed; pass a space so gcc doesn't complain about + * empty format string. + */ + prep_status(" "); +} + + +/* + * prep_status + * + * Displays a message that describes an operation we are about to begin. + * We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and + * "failed" indicators line up nicely. + * + * A typical sequence would look like this: + * prep_status("about to flarb the next %d files", fileCount ); + * + * if(( message = flarbFiles(fileCount)) == NULL) + * report_status(PG_REPORT, "ok" ); + * else + * pg_log(PG_FATAL, "failed - %s\n", message ); + */ +void +prep_status(const char *fmt,...) +{ + va_list args; + char message[MAX_STRING]; + + va_start(args, fmt); + vsnprintf(message, sizeof(message), fmt, args); + va_end(args); + + if (strlen(message) > 0 && message[strlen(message) - 1] == '\n') + pg_log(PG_REPORT, "%s", message); + else + /* trim strings that don't end in a newline */ + pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message); +} + + +static void +pg_log_v(eLogType type, const char *fmt, va_list ap) +{ + char message[QUERY_ALLOC]; + + vsnprintf(message, sizeof(message), _(fmt), ap); + + /* PG_VERBOSE and PG_STATUS are only output in verbose mode */ + /* fopen() on log_opts.internal might have failed, so check it */ + if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) && + log_opts.internal != NULL) + { + if (type == PG_STATUS) + /* status messages need two leading spaces and a newline */ + fprintf(log_opts.internal, " %s\n", message); + else + fprintf(log_opts.internal, "%s", message); + fflush(log_opts.internal); + } + + switch (type) + { + case PG_VERBOSE: + if (log_opts.verbose) + printf("%s", message); + break; + + case PG_STATUS: + /* for output to a display, do leading truncation and append \r */ + if (isatty(fileno(stdout))) + /* -2 because we use a 2-space indent */ + printf(" %s%-*.*s\r", + /* prefix with "..." if we do leading truncation */ + strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...", + MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2, + /* optional leading truncation */ + strlen(message) <= MESSAGE_WIDTH - 2 ? message : + message + strlen(message) - MESSAGE_WIDTH + 3 + 2); + else + printf(" %s\n", message); + break; + + case PG_REPORT: + case PG_WARNING: + printf("%s", message); + break; + + case PG_FATAL: + printf("\n%s", message); + printf(_("Failure, exiting\n")); + exit(1); + break; + + default: + break; + } + fflush(stdout); +} + + +void +pg_log(eLogType type, const char *fmt,...) +{ + va_list args; + + va_start(args, fmt); + pg_log_v(type, fmt, args); + va_end(args); +} + + +void +pg_fatal(const char *fmt,...) +{ + va_list args; + + va_start(args, fmt); + pg_log_v(PG_FATAL, fmt, args); + va_end(args); + printf(_("Failure, exiting\n")); + exit(1); +} + + +void +check_ok(void) +{ + /* all seems well */ + report_status(PG_REPORT, "ok"); + fflush(stdout); +} + + +/* + * quote_identifier() + * Properly double-quote a SQL identifier. + * + * The result should be pg_free'd, but most callers don't bother because + * memory leakage is not a big deal in this program. + */ +char * +quote_identifier(const char *s) +{ + char *result = pg_malloc(strlen(s) * 2 + 3); + char *r = result; + + *r++ = '"'; + while (*s) + { + if (*s == '"') + *r++ = *s; + *r++ = *s; + s++; + } + *r++ = '"'; + *r++ = '\0'; + + return result; +} + + +/* + * get_user_info() + */ +int +get_user_info(char **user_name_p) +{ + int user_id; + const char *user_name; + char *errstr; + +#ifndef WIN32 + user_id = geteuid(); +#else + user_id = 1; +#endif + + user_name = get_user_name(&errstr); + if (!user_name) + pg_fatal("%s\n", errstr); + + /* make a copy */ + *user_name_p = pg_strdup(user_name); + + return user_id; +} + + +/* + * str2uint() + * + * convert string to oid + */ +unsigned int +str2uint(const char *str) +{ + return strtoul(str, NULL, 10); +} |