]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/util.c
Have pg_upgrade use strtoul(), not strtol().
[postgresql] / contrib / pg_upgrade / util.c
1 /*
2  *      util.c
3  *
4  *      utility functions
5  *
6  *      Copyright (c) 2010, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/util.c
8  */
9
10 #include "pg_upgrade.h"
11
12 #include <signal.h>
13
14
15 /*
16  * report_status()
17  *
18  *      Displays the result of an operation (ok, failed, error message,...)
19  */
20 void
21 report_status(migratorContext *ctx, eLogType type, const char *fmt,...)
22 {
23         va_list         args;
24         char            message[MAX_STRING];
25
26         va_start(args, fmt);
27         vsnprintf(message, sizeof(message), fmt, args);
28         va_end(args);
29
30         pg_log(ctx, type, "%s\n", message);
31 }
32
33
34 /*
35  * prep_status(&ctx, )
36  *
37  *      Displays a message that describes an operation we are about to begin.
38  *      We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
39  *      "failed" indicators line up nicely.
40  *
41  *      A typical sequence would look like this:
42  *              prep_status(&ctx,  "about to flarb the next %d files", fileCount );
43  *
44  *              if(( message = flarbFiles(fileCount)) == NULL)
45  *                report_status(ctx, PG_REPORT, "ok" );
46  *              else
47  *                pg_log(ctx, PG_FATAL, "failed - %s", message );
48  */
49 void
50 prep_status(migratorContext *ctx, const char *fmt,...)
51 {
52         va_list         args;
53         char            message[MAX_STRING];
54
55         va_start(args, fmt);
56         vsnprintf(message, sizeof(message), fmt, args);
57         va_end(args);
58
59         if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
60                 pg_log(ctx, PG_REPORT, "%s", message);
61         else
62                 pg_log(ctx, PG_REPORT, "%-" MESSAGE_WIDTH "s", message);
63 }
64
65
66 void
67 pg_log(migratorContext *ctx, eLogType type, char *fmt,...)
68 {
69         va_list         args;
70         char            message[MAX_STRING];
71
72         va_start(args, fmt);
73         vsnprintf(message, sizeof(message), fmt, args);
74         va_end(args);
75
76         if (ctx->log_fd != NULL)
77         {
78                 fwrite(message, strlen(message), 1, ctx->log_fd);
79                 /* if we are using OVERWRITE_MESSAGE, add newline */
80                 if (strchr(message, '\r') != NULL)
81                         fwrite("\n", 1, 1, ctx->log_fd);
82                 fflush(ctx->log_fd);
83         }
84
85         switch (type)
86         {
87                 case PG_INFO:
88                         if (ctx->verbose)
89                                 printf("%s", _(message));
90                         break;
91
92                 case PG_REPORT:
93                 case PG_WARNING:
94                         printf("%s", _(message));
95                         break;
96
97                 case PG_FATAL:
98                         printf("%s", "\n");
99                         printf("%s", _(message));
100                         exit_nicely(ctx, true);
101                         break;
102
103                 case PG_DEBUG:
104                         if (ctx->debug)
105                                 fprintf(ctx->debug_fd, "%s\n", _(message));
106                         break;
107
108                 default:
109                         break;
110         }
111         fflush(stdout);
112 }
113
114
115 void
116 check_ok(migratorContext *ctx)
117 {
118         /* all seems well */
119         report_status(ctx, PG_REPORT, "ok");
120         fflush(stdout);
121 }
122
123
124 /*
125  * quote_identifier()
126  *              Properly double-quote a SQL identifier.
127  *
128  * The result should be pg_free'd, but most callers don't bother because
129  * memory leakage is not a big deal in this program.
130  */
131 char *
132 quote_identifier(migratorContext *ctx, const char *s)
133 {
134         char       *result = pg_malloc(ctx, strlen(s) * 2 + 3);
135         char       *r = result;
136
137         *r++ = '"';
138         while (*s)
139         {
140                 if (*s == '"')
141                         *r++ = *s;
142                 *r++ = *s;
143                 s++;
144         }
145         *r++ = '"';
146         *r++ = '\0';
147
148         return result;
149 }
150
151
152 /*
153  * get_user_info()
154  * (copied from initdb.c) find the current user
155  */
156 int
157 get_user_info(migratorContext *ctx, char **user_name)
158 {
159         int                     user_id;
160
161 #ifndef WIN32
162         struct passwd *pw = getpwuid(geteuid());
163
164         user_id = geteuid();
165 #else                                                   /* the windows code */
166         struct passwd_win32
167         {
168                 int                     pw_uid;
169                 char            pw_name[128];
170         }                       pass_win32;
171         struct passwd_win32 *pw = &pass_win32;
172         DWORD           pwname_size = sizeof(pass_win32.pw_name) - 1;
173
174         GetUserName(pw->pw_name, &pwname_size);
175
176         user_id = 1;
177 #endif
178
179         *user_name = pg_strdup(ctx, pw->pw_name);
180
181         return user_id;
182 }
183
184
185 void
186 exit_nicely(migratorContext *ctx, bool need_cleanup)
187 {
188         stop_postmaster(ctx, true, true);
189
190         pg_free(ctx->logfile);
191
192         if (ctx->log_fd)
193                 fclose(ctx->log_fd);
194
195         if (ctx->debug_fd)
196                 fclose(ctx->debug_fd);
197
198         /* terminate any running instance of postmaster */
199         if (ctx->postmasterPID != 0)
200                 kill(ctx->postmasterPID, SIGTERM);
201
202         if (need_cleanup)
203         {
204                 /*
205                  * FIXME must delete intermediate files
206                  */
207                 exit(1);
208         }
209         else
210                 exit(0);
211 }
212
213
214 void *
215 pg_malloc(migratorContext *ctx, int n)
216 {
217         void       *p = malloc(n);
218
219         if (p == NULL)
220                 pg_log(ctx, PG_FATAL, "%s: out of memory\n", ctx->progname);
221
222         return p;
223 }
224
225
226 void
227 pg_free(void *p)
228 {
229         if (p != NULL)
230                 free(p);
231 }
232
233
234 char *
235 pg_strdup(migratorContext *ctx, const char *s)
236 {
237         char       *result = strdup(s);
238
239         if (result == NULL)
240                 pg_log(ctx, PG_FATAL, "%s: out of memory\n", ctx->progname);
241
242         return result;
243 }
244
245
246 /*
247  * getErrorText()
248  *
249  *      Returns the text of the error message for the given error number
250  *
251  *      This feature is factored into a separate function because it is
252  *      system-dependent.
253  */
254 const char *
255 getErrorText(int errNum)
256 {
257 #ifdef WIN32
258         _dosmaperr(GetLastError());
259 #endif
260         return strdup(strerror(errNum));
261 }
262
263
264 /*
265  *      str2uint()
266  *
267  *      convert string to oid
268  */
269 unsigned int
270 str2uint(const char *str)
271 {
272         return strtoul(str, NULL, 10);
273 }