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