]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/util.c
Prevent pg_upgrade from crashing if it can't write to the current
[postgresql] / contrib / pg_upgrade / util.c
1 /*
2  *      util.c
3  *
4  *      utility functions
5  *
6  *      Copyright (c) 2010-2012, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/util.c
8  */
9
10 #include "postgres.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 /*
39  * prep_status
40  *
41  *      Displays a message that describes an operation we are about to begin.
42  *      We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
43  *      "failed" indicators line up nicely.
44  *
45  *      A typical sequence would look like this:
46  *              prep_status("about to flarb the next %d files", fileCount );
47  *
48  *              if(( message = flarbFiles(fileCount)) == NULL)
49  *                report_status(PG_REPORT, "ok" );
50  *              else
51  *                pg_log(PG_FATAL, "failed - %s\n", message );
52  */
53 void
54 prep_status(const char *fmt,...)
55 {
56         va_list         args;
57         char            message[MAX_STRING];
58
59         va_start(args, fmt);
60         vsnprintf(message, sizeof(message), fmt, args);
61         va_end(args);
62
63         if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
64                 pg_log(PG_REPORT, "%s", message);
65         else
66                 pg_log(PG_REPORT, "%-" MESSAGE_WIDTH "s", message);
67 }
68
69
70 void
71 pg_log(eLogType type, char *fmt,...)
72 {
73         va_list         args;
74         char            message[MAX_STRING];
75
76         va_start(args, fmt);
77         vsnprintf(message, sizeof(message), fmt, args);
78         va_end(args);
79
80         /* PG_VERBOSE is only output in verbose mode */
81         /* fopen() on log_opts.internal might have failed, so check it */
82         if ((type != PG_VERBOSE || log_opts.verbose) && log_opts.internal != NULL)
83         {
84                 fwrite(message, strlen(message), 1, log_opts.internal);
85                 /* if we are using OVERWRITE_MESSAGE, add newline to log file */
86                 if (strchr(message, '\r') != NULL)
87                         fwrite("\n", 1, 1, log_opts.internal);
88                 fflush(log_opts.internal);
89         }
90
91         switch (type)
92         {
93                 case PG_VERBOSE:
94                         if (log_opts.verbose)
95                                 printf("%s", _(message));
96                         break;
97
98                 case PG_REPORT:
99                 case PG_WARNING:
100                         printf("%s", _(message));
101                         break;
102
103                 case PG_FATAL:
104                         printf("\n%s", _(message));
105                         printf("Failure, exiting\n");
106                         exit(1);
107                         break;
108
109                 default:
110                         break;
111         }
112         fflush(stdout);
113 }
114
115
116 void
117 check_ok(void)
118 {
119         /* all seems well */
120         report_status(PG_REPORT, "ok");
121         fflush(stdout);
122 }
123
124
125 /*
126  * quote_identifier()
127  *              Properly double-quote a SQL identifier.
128  *
129  * The result should be pg_free'd, but most callers don't bother because
130  * memory leakage is not a big deal in this program.
131  */
132 char *
133 quote_identifier(const char *s)
134 {
135         char       *result = pg_malloc(strlen(s) * 2 + 3);
136         char       *r = result;
137
138         *r++ = '"';
139         while (*s)
140         {
141                 if (*s == '"')
142                         *r++ = *s;
143                 *r++ = *s;
144                 s++;
145         }
146         *r++ = '"';
147         *r++ = '\0';
148
149         return result;
150 }
151
152
153 /*
154  * get_user_info()
155  * (copied from initdb.c) find the current user
156  */
157 int
158 get_user_info(char **user_name)
159 {
160         int                     user_id;
161
162 #ifndef WIN32
163         struct passwd *pw = getpwuid(geteuid());
164
165         user_id = geteuid();
166 #else                                                   /* the windows code */
167         struct passwd_win32
168         {
169                 int                     pw_uid;
170                 char            pw_name[128];
171         }                       pass_win32;
172         struct passwd_win32 *pw = &pass_win32;
173         DWORD           pwname_size = sizeof(pass_win32.pw_name) - 1;
174
175         GetUserName(pw->pw_name, &pwname_size);
176
177         user_id = 1;
178 #endif
179
180         *user_name = pg_strdup(pw->pw_name);
181
182         return user_id;
183 }
184
185
186 void *
187 pg_malloc(size_t n)
188 {
189         void       *p = malloc(n);
190
191         if (p == NULL)
192                 pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
193
194         return p;
195 }
196
197 void *
198 pg_realloc(void *ptr, size_t n)
199 {
200         void       *p = realloc(ptr, n);
201
202         if (p == NULL)
203                 pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
204
205         return p;
206 }
207
208
209 void
210 pg_free(void *p)
211 {
212         if (p != NULL)
213                 free(p);
214 }
215
216
217 char *
218 pg_strdup(const char *s)
219 {
220         char       *result = strdup(s);
221
222         if (result == NULL)
223                 pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
224
225         return result;
226 }
227
228
229 /*
230  * getErrorText()
231  *
232  *      Returns the text of the error message for the given error number
233  *
234  *      This feature is factored into a separate function because it is
235  *      system-dependent.
236  */
237 const char *
238 getErrorText(int errNum)
239 {
240 #ifdef WIN32
241         _dosmaperr(GetLastError());
242 #endif
243         return pg_strdup(strerror(errNum));
244 }
245
246
247 /*
248  *      str2uint()
249  *
250  *      convert string to oid
251  */
252 unsigned int
253 str2uint(const char *str)
254 {
255         return strtoul(str, NULL, 10);
256 }
257
258
259 /*
260  *      pg_putenv()
261  *
262  *      This is like putenv(), but takes two arguments.
263  *      It also does unsetenv() if val is NULL.
264  */
265 void
266 pg_putenv(const char *var, const char *val)
267 {
268         if (val)
269         {
270 #ifndef WIN32
271                 char       *envstr = (char *) pg_malloc(strlen(var) +
272                                                                                                 strlen(val) + 2);
273
274                 sprintf(envstr, "%s=%s", var, val);
275                 putenv(envstr);
276
277                 /*
278                  * Do not free envstr because it becomes part of the environment on
279                  * some operating systems.      See port/unsetenv.c::unsetenv.
280                  */
281 #else
282                 SetEnvironmentVariableA(var, val);
283 #endif
284         }
285         else
286         {
287 #ifndef WIN32
288                 unsetenv(var);
289 #else
290                 SetEnvironmentVariableA(var, "");
291 #endif
292         }
293 }