PageRenderTime 55ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/pg_upgrade/util.c

https://bitbucket.org/adunstan/pgdevel
C | 280 lines | 195 code | 36 blank | 49 comment | 14 complexity | 5bb0349d25b8f0168b02e9cac3dc94a9 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * util.c
  3. *
  4. * utility functions
  5. *
  6. * Copyright (c) 2010-2018, PostgreSQL Global Development Group
  7. * src/bin/pg_upgrade/util.c
  8. */
  9. #include "postgres_fe.h"
  10. #include "common/username.h"
  11. #include "pg_upgrade.h"
  12. #include <signal.h>
  13. LogOpts log_opts;
  14. static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2, 0);
  15. /*
  16. * report_status()
  17. *
  18. * Displays the result of an operation (ok, failed, error message,...)
  19. */
  20. void
  21. report_status(eLogType type, const char *fmt,...)
  22. {
  23. va_list args;
  24. char message[MAX_STRING];
  25. va_start(args, fmt);
  26. vsnprintf(message, sizeof(message), fmt, args);
  27. va_end(args);
  28. pg_log(type, "%s\n", message);
  29. }
  30. /* force blank output for progress display */
  31. void
  32. end_progress_output(void)
  33. {
  34. /*
  35. * In case nothing printed; pass a space so gcc doesn't complain about
  36. * empty format string.
  37. */
  38. prep_status(" ");
  39. }
  40. /*
  41. * prep_status
  42. *
  43. * Displays a message that describes an operation we are about to begin.
  44. * We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
  45. * "failed" indicators line up nicely.
  46. *
  47. * A typical sequence would look like this:
  48. * prep_status("about to flarb the next %d files", fileCount );
  49. *
  50. * if(( message = flarbFiles(fileCount)) == NULL)
  51. * report_status(PG_REPORT, "ok" );
  52. * else
  53. * pg_log(PG_FATAL, "failed - %s\n", message );
  54. */
  55. void
  56. prep_status(const char *fmt,...)
  57. {
  58. va_list args;
  59. char message[MAX_STRING];
  60. va_start(args, fmt);
  61. vsnprintf(message, sizeof(message), fmt, args);
  62. va_end(args);
  63. if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
  64. pg_log(PG_REPORT, "%s", message);
  65. else
  66. /* trim strings that don't end in a newline */
  67. pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
  68. }
  69. static void
  70. pg_log_v(eLogType type, const char *fmt, va_list ap)
  71. {
  72. char message[QUERY_ALLOC];
  73. vsnprintf(message, sizeof(message), _(fmt), ap);
  74. /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
  75. /* fopen() on log_opts.internal might have failed, so check it */
  76. if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
  77. log_opts.internal != NULL)
  78. {
  79. if (type == PG_STATUS)
  80. /* status messages need two leading spaces and a newline */
  81. fprintf(log_opts.internal, " %s\n", message);
  82. else
  83. fprintf(log_opts.internal, "%s", message);
  84. fflush(log_opts.internal);
  85. }
  86. switch (type)
  87. {
  88. case PG_VERBOSE:
  89. if (log_opts.verbose)
  90. printf("%s", message);
  91. break;
  92. case PG_STATUS:
  93. /* for output to a display, do leading truncation and append \r */
  94. if (isatty(fileno(stdout)))
  95. /* -2 because we use a 2-space indent */
  96. printf(" %s%-*.*s\r",
  97. /* prefix with "..." if we do leading truncation */
  98. strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
  99. MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
  100. /* optional leading truncation */
  101. strlen(message) <= MESSAGE_WIDTH - 2 ? message :
  102. message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
  103. else
  104. printf(" %s\n", message);
  105. break;
  106. case PG_REPORT:
  107. case PG_WARNING:
  108. printf("%s", message);
  109. break;
  110. case PG_FATAL:
  111. printf("\n%s", message);
  112. printf(_("Failure, exiting\n"));
  113. exit(1);
  114. break;
  115. default:
  116. break;
  117. }
  118. fflush(stdout);
  119. }
  120. void
  121. pg_log(eLogType type, const char *fmt,...)
  122. {
  123. va_list args;
  124. va_start(args, fmt);
  125. pg_log_v(type, fmt, args);
  126. va_end(args);
  127. }
  128. void
  129. pg_fatal(const char *fmt,...)
  130. {
  131. va_list args;
  132. va_start(args, fmt);
  133. pg_log_v(PG_FATAL, fmt, args);
  134. va_end(args);
  135. printf(_("Failure, exiting\n"));
  136. exit(1);
  137. }
  138. void
  139. check_ok(void)
  140. {
  141. /* all seems well */
  142. report_status(PG_REPORT, "ok");
  143. fflush(stdout);
  144. }
  145. /*
  146. * quote_identifier()
  147. * Properly double-quote a SQL identifier.
  148. *
  149. * The result should be pg_free'd, but most callers don't bother because
  150. * memory leakage is not a big deal in this program.
  151. */
  152. char *
  153. quote_identifier(const char *s)
  154. {
  155. char *result = pg_malloc(strlen(s) * 2 + 3);
  156. char *r = result;
  157. *r++ = '"';
  158. while (*s)
  159. {
  160. if (*s == '"')
  161. *r++ = *s;
  162. *r++ = *s;
  163. s++;
  164. }
  165. *r++ = '"';
  166. *r++ = '\0';
  167. return result;
  168. }
  169. /*
  170. * get_user_info()
  171. */
  172. int
  173. get_user_info(char **user_name_p)
  174. {
  175. int user_id;
  176. const char *user_name;
  177. char *errstr;
  178. #ifndef WIN32
  179. user_id = geteuid();
  180. #else
  181. user_id = 1;
  182. #endif
  183. user_name = get_user_name(&errstr);
  184. if (!user_name)
  185. pg_fatal("%s\n", errstr);
  186. /* make a copy */
  187. *user_name_p = pg_strdup(user_name);
  188. return user_id;
  189. }
  190. /*
  191. * str2uint()
  192. *
  193. * convert string to oid
  194. */
  195. unsigned int
  196. str2uint(const char *str)
  197. {
  198. return strtoul(str, NULL, 10);
  199. }
  200. /*
  201. * pg_putenv()
  202. *
  203. * This is like putenv(), but takes two arguments.
  204. * It also does unsetenv() if val is NULL.
  205. */
  206. void
  207. pg_putenv(const char *var, const char *val)
  208. {
  209. if (val)
  210. {
  211. #ifndef WIN32
  212. char *envstr;
  213. envstr = psprintf("%s=%s", var, val);
  214. putenv(envstr);
  215. /*
  216. * Do not free envstr because it becomes part of the environment on
  217. * some operating systems. See port/unsetenv.c::unsetenv.
  218. */
  219. #else
  220. SetEnvironmentVariableA(var, val);
  221. #endif
  222. }
  223. else
  224. {
  225. #ifndef WIN32
  226. unsetenv(var);
  227. #else
  228. SetEnvironmentVariableA(var, "");
  229. #endif
  230. }
  231. }