Add a -w/--no-password option that prevents all password prompts to all
[PostgreSQL.git] / src / bin / pg_dump / pg_dumpall.c
blob2f8b2c3ac0526d549dbeaafde199c63e59a91b76
1 /*-------------------------------------------------------------------------
3 * pg_dumpall.c
5 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
9 * $PostgreSQL$
11 *-------------------------------------------------------------------------
14 #include "postgres_fe.h"
16 #include <time.h>
17 #include <unistd.h>
19 #ifdef ENABLE_NLS
20 #include <locale.h>
21 #endif
23 #include "getopt_long.h"
25 #ifndef HAVE_INT_OPTRESET
26 int optreset;
27 #endif
29 #include "dumputils.h"
30 #include "pg_backup.h"
32 /* version string we expect back from pg_dump */
33 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
36 static const char *progname;
38 static void help(void);
40 static void dumpRoles(PGconn *conn);
41 static void dumpRoleMembership(PGconn *conn);
42 static void dumpGroups(PGconn *conn);
43 static void dumpTablespaces(PGconn *conn);
44 static void dumpCreateDB(PGconn *conn);
45 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
46 static void dumpUserConfig(PGconn *conn, const char *username);
47 static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
48 const char *type, const char *name);
49 static void dumpDatabases(PGconn *conn);
50 static void dumpTimestamp(char *msg);
51 static void doShellQuoting(PQExpBuffer buf, const char *str);
53 static int runPgDump(const char *dbname);
54 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
55 const char *pguser, enum trivalue prompt_password, bool fail_on_error);
56 static PGresult *executeQuery(PGconn *conn, const char *query);
57 static void executeCommand(PGconn *conn, const char *query);
59 static char pg_dump_bin[MAXPGPATH];
60 static PQExpBuffer pgdumpopts;
61 static bool output_clean = false;
62 static bool skip_acls = false;
63 static bool verbose = false;
65 static int disable_dollar_quoting = 0;
66 static int disable_triggers = 0;
67 static int no_tablespaces = 0;
68 static int use_setsessauth = 0;
69 static int server_version;
71 static FILE *OPF;
72 static char *filename = NULL;
74 static int binary_upgrade = 0;
76 int
77 main(int argc, char *argv[])
79 char *pghost = NULL;
80 char *pgport = NULL;
81 char *pguser = NULL;
82 char *pgdb = NULL;
83 char *use_role = NULL;
84 enum trivalue prompt_password = TRI_DEFAULT;
85 bool data_only = false;
86 bool globals_only = false;
87 bool roles_only = false;
88 bool tablespaces_only = false;
89 bool schema_only = false;
90 PGconn *conn;
91 int encoding;
92 const char *std_strings;
93 int c,
94 ret;
96 struct option long_options[] = {
97 {"binary-upgrade", no_argument, &binary_upgrade, 1}, /* not documented */
98 {"data-only", no_argument, NULL, 'a'},
99 {"clean", no_argument, NULL, 'c'},
100 {"inserts", no_argument, NULL, 'd'},
101 {"attribute-inserts", no_argument, NULL, 'D'},
102 {"column-inserts", no_argument, NULL, 'D'},
103 {"file", required_argument, NULL, 'f'},
104 {"globals-only", no_argument, NULL, 'g'},
105 {"host", required_argument, NULL, 'h'},
106 {"ignore-version", no_argument, NULL, 'i'},
107 {"database", required_argument, NULL, 'l'},
108 {"oids", no_argument, NULL, 'o'},
109 {"no-owner", no_argument, NULL, 'O'},
110 {"port", required_argument, NULL, 'p'},
111 {"roles-only", no_argument, NULL, 'r'},
112 {"schema-only", no_argument, NULL, 's'},
113 {"superuser", required_argument, NULL, 'S'},
114 {"tablespaces-only", no_argument, NULL, 't'},
115 {"username", required_argument, NULL, 'U'},
116 {"verbose", no_argument, NULL, 'v'},
117 {"no-password", no_argument, NULL, 'w'},
118 {"password", no_argument, NULL, 'W'},
119 {"no-privileges", no_argument, NULL, 'x'},
120 {"no-acl", no_argument, NULL, 'x'},
123 * the following options don't have an equivalent short option letter
125 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
126 {"disable-triggers", no_argument, &disable_triggers, 1},
127 {"lock-wait-timeout", required_argument, NULL, 2},
128 {"no-tablespaces", no_argument, &no_tablespaces, 1},
129 {"role", required_argument, NULL, 3},
130 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
132 {NULL, 0, NULL, 0}
135 int optindex;
137 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
139 progname = get_progname(argv[0]);
141 if (argc > 1)
143 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
145 help();
146 exit(0);
148 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
150 puts("pg_dumpall (PostgreSQL) " PG_VERSION);
151 exit(0);
155 if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
156 pg_dump_bin)) < 0)
158 char full_path[MAXPGPATH];
160 if (find_my_exec(argv[0], full_path) < 0)
161 strlcpy(full_path, progname, sizeof(full_path));
163 if (ret == -1)
164 fprintf(stderr,
165 _("The program \"pg_dump\" is needed by %s "
166 "but was not found in the\n"
167 "same directory as \"%s\".\n"
168 "Check your installation.\n"),
169 progname, full_path);
170 else
171 fprintf(stderr,
172 _("The program \"pg_dump\" was found by \"%s\"\n"
173 "but was not the same version as %s.\n"
174 "Check your installation.\n"),
175 full_path, progname);
176 exit(1);
179 pgdumpopts = createPQExpBuffer();
181 while ((c = getopt_long(argc, argv, "acdDf:gh:il:oOp:rsS:tU:vwWxX:", long_options, &optindex)) != -1)
183 switch (c)
185 case 'a':
186 data_only = true;
187 appendPQExpBuffer(pgdumpopts, " -a");
188 break;
190 case 'c':
191 output_clean = true;
192 break;
194 case 'd':
195 case 'D':
196 appendPQExpBuffer(pgdumpopts, " -%c", c);
197 break;
199 case 'f':
200 filename = optarg;
201 appendPQExpBuffer(pgdumpopts, " -f ");
202 doShellQuoting(pgdumpopts, filename);
203 break;
205 case 'g':
206 globals_only = true;
207 break;
209 case 'h':
210 pghost = optarg;
211 appendPQExpBuffer(pgdumpopts, " -h ");
212 doShellQuoting(pgdumpopts, pghost);
213 break;
215 case 'i':
216 /* ignored, deprecated option */
217 break;
219 case 'l':
220 pgdb = optarg;
221 break;
223 case 'o':
224 appendPQExpBuffer(pgdumpopts, " -o");
225 break;
227 case 'O':
228 appendPQExpBuffer(pgdumpopts, " -O");
229 break;
231 case 'p':
232 pgport = optarg;
233 appendPQExpBuffer(pgdumpopts, " -p ");
234 doShellQuoting(pgdumpopts, pgport);
235 break;
237 case 'r':
238 roles_only = true;
239 break;
241 case 's':
242 schema_only = true;
243 appendPQExpBuffer(pgdumpopts, " -s");
244 break;
246 case 'S':
247 appendPQExpBuffer(pgdumpopts, " -S ");
248 doShellQuoting(pgdumpopts, optarg);
249 break;
251 case 't':
252 tablespaces_only = true;
253 break;
255 case 'U':
256 pguser = optarg;
257 appendPQExpBuffer(pgdumpopts, " -U ");
258 doShellQuoting(pgdumpopts, pguser);
259 break;
261 case 'v':
262 verbose = true;
263 appendPQExpBuffer(pgdumpopts, " -v");
264 break;
266 case 'w':
267 prompt_password = TRI_NO;
268 appendPQExpBuffer(pgdumpopts, " -w");
269 break;
271 case 'W':
272 prompt_password = TRI_YES;
273 appendPQExpBuffer(pgdumpopts, " -W");
274 break;
276 case 'x':
277 skip_acls = true;
278 appendPQExpBuffer(pgdumpopts, " -x");
279 break;
281 case 'X':
282 /* -X is a deprecated alternative to long options */
283 if (strcmp(optarg, "disable-dollar-quoting") == 0)
284 disable_dollar_quoting = 1;
285 else if (strcmp(optarg, "disable-triggers") == 0)
286 disable_triggers = 1;
287 else if (strcmp(optarg, "no-tablespaces") == 0)
288 no_tablespaces = 1;
289 else if (strcmp(optarg, "use-set-session-authorization") == 0)
290 use_setsessauth = 1;
291 else
293 fprintf(stderr,
294 _("%s: invalid -X option -- %s\n"),
295 progname, optarg);
296 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
297 exit(1);
299 break;
301 case 0:
302 break;
304 case 2:
305 appendPQExpBuffer(pgdumpopts, " --lock-wait-timeout ");
306 doShellQuoting(pgdumpopts, optarg);
307 break;
309 case 3:
310 use_role = optarg;
311 appendPQExpBuffer(pgdumpopts, " --role ");
312 doShellQuoting(pgdumpopts, use_role);
313 break;
315 default:
316 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
317 exit(1);
321 /* Add long options to the pg_dump argument list */
322 if (binary_upgrade)
323 appendPQExpBuffer(pgdumpopts, " --binary-upgrade");
324 if (disable_dollar_quoting)
325 appendPQExpBuffer(pgdumpopts, " --disable-dollar-quoting");
326 if (disable_triggers)
327 appendPQExpBuffer(pgdumpopts, " --disable-triggers");
328 if (no_tablespaces)
329 appendPQExpBuffer(pgdumpopts, " --no-tablespaces");
330 if (use_setsessauth)
331 appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization");
333 if (optind < argc)
335 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
336 progname, argv[optind]);
337 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
338 progname);
339 exit(1);
342 /* Make sure the user hasn't specified a mix of globals-only options */
343 if (globals_only && roles_only)
345 fprintf(stderr, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
346 progname);
347 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
348 progname);
349 exit(1);
352 if (globals_only && tablespaces_only)
354 fprintf(stderr, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
355 progname);
356 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
357 progname);
358 exit(1);
361 if (roles_only && tablespaces_only)
363 fprintf(stderr, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
364 progname);
365 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
366 progname);
367 exit(1);
371 * If there was a database specified on the command line, use that,
372 * otherwise try to connect to database "postgres", and failing that
373 * "template1". "postgres" is the preferred choice for 8.1 and later
374 * servers, but it usually will not exist on older ones.
376 if (pgdb)
378 conn = connectDatabase(pgdb, pghost, pgport, pguser,
379 prompt_password, false);
381 if (!conn)
383 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
384 progname, pgdb);
385 exit(1);
388 else
390 conn = connectDatabase("postgres", pghost, pgport, pguser,
391 prompt_password, false);
392 if (!conn)
393 conn = connectDatabase("template1", pghost, pgport, pguser,
394 prompt_password, true);
396 if (!conn)
398 fprintf(stderr, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
399 "Please specify an alternative database.\n"),
400 progname);
401 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
402 progname);
403 exit(1);
408 * Open the output file if required, otherwise use stdout
410 if (filename)
412 OPF = fopen(filename, PG_BINARY_W);
413 if (!OPF)
415 fprintf(stderr, _("%s: could not open the output file \"%s\": %s\n"),
416 progname, filename, strerror(errno));
417 exit(1);
420 else
421 OPF = stdout;
424 * Get the active encoding and the standard_conforming_strings setting, so
425 * we know how to escape strings.
427 encoding = PQclientEncoding(conn);
428 std_strings = PQparameterStatus(conn, "standard_conforming_strings");
429 if (!std_strings)
430 std_strings = "off";
432 /* Set the role if requested */
433 if (use_role && server_version >= 80100)
435 PQExpBuffer query = createPQExpBuffer();
437 appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
438 executeCommand(conn, query->data);
439 destroyPQExpBuffer(query);
442 fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
443 if (verbose)
444 dumpTimestamp("Started on");
446 fprintf(OPF, "\\connect postgres\n\n");
448 if (!data_only)
450 /* Replicate encoding and std_strings in output */
451 fprintf(OPF, "SET client_encoding = '%s';\n",
452 pg_encoding_to_char(encoding));
453 fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
454 if (strcmp(std_strings, "off") == 0)
455 fprintf(OPF, "SET escape_string_warning = 'off';\n");
456 fprintf(OPF, "\n");
458 if (!tablespaces_only)
460 /* Dump roles (users) */
461 dumpRoles(conn);
463 /* Dump role memberships --- need different method for pre-8.1 */
464 if (server_version >= 80100)
465 dumpRoleMembership(conn);
466 else
467 dumpGroups(conn);
470 if (!roles_only && !no_tablespaces)
472 /* Dump tablespaces */
473 if (server_version >= 80000)
474 dumpTablespaces(conn);
477 /* Dump CREATE DATABASE commands */
478 if (!globals_only && !roles_only && !tablespaces_only)
479 dumpCreateDB(conn);
482 if (!globals_only && !roles_only && !tablespaces_only)
483 dumpDatabases(conn);
485 PQfinish(conn);
487 if (verbose)
488 dumpTimestamp("Completed on");
489 fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
491 if (filename)
492 fclose(OPF);
494 exit(0);
499 static void
500 help(void)
502 printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
503 printf(_("Usage:\n"));
504 printf(_(" %s [OPTION]...\n"), progname);
506 printf(_("\nGeneral options:\n"));
507 printf(_(" -f, --file=FILENAME output file name\n"));
508 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
509 printf(_(" --help show this help, then exit\n"));
510 printf(_(" --version output version information, then exit\n"));
511 printf(_("\nOptions controlling the output content:\n"));
512 printf(_(" -a, --data-only dump only the data, not the schema\n"));
513 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
514 printf(_(" -d, --inserts dump data as INSERT commands, rather than COPY\n"));
515 printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
516 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
517 printf(_(" -o, --oids include OIDs in dump\n"));
518 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
519 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
520 printf(_(" -s, --schema-only dump only the schema, no data\n"));
521 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
522 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
523 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
524 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
525 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
526 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
527 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
528 printf(_(" --use-set-session-authorization\n"
529 " use SET SESSION AUTHORIZATION commands instead of\n"
530 " ALTER OWNER commands to set ownership\n"));
532 printf(_("\nConnection options:\n"));
533 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
534 printf(_(" -l, --database=DBNAME alternative default database\n"));
535 printf(_(" -p, --port=PORT database server port number\n"));
536 printf(_(" -U, --username=NAME connect as specified database user\n"));
537 printf(_(" -w, --no-password never prompt for password\n"));
538 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
540 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
541 "output.\n\n"));
542 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
548 * Dump roles
550 static void
551 dumpRoles(PGconn *conn)
553 PQExpBuffer buf = createPQExpBuffer();
554 PGresult *res;
555 int i_rolname,
556 i_rolsuper,
557 i_rolinherit,
558 i_rolcreaterole,
559 i_rolcreatedb,
560 i_rolcatupdate,
561 i_rolcanlogin,
562 i_rolconnlimit,
563 i_rolpassword,
564 i_rolvaliduntil,
565 i_rolcomment;
566 int i;
568 /* note: rolconfig is dumped later */
569 if (server_version >= 80200)
570 printfPQExpBuffer(buf,
571 "SELECT rolname, rolsuper, rolinherit, "
572 "rolcreaterole, rolcreatedb, rolcatupdate, "
573 "rolcanlogin, rolconnlimit, rolpassword, "
574 "rolvaliduntil, "
575 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment "
576 "FROM pg_authid "
577 "ORDER BY 1");
578 else if (server_version >= 80100)
579 printfPQExpBuffer(buf,
580 "SELECT rolname, rolsuper, rolinherit, "
581 "rolcreaterole, rolcreatedb, rolcatupdate, "
582 "rolcanlogin, rolconnlimit, rolpassword, "
583 "rolvaliduntil, null as rolcomment "
584 "FROM pg_authid "
585 "ORDER BY 1");
586 else
587 printfPQExpBuffer(buf,
588 "SELECT usename as rolname, "
589 "usesuper as rolsuper, "
590 "true as rolinherit, "
591 "usesuper as rolcreaterole, "
592 "usecreatedb as rolcreatedb, "
593 "usecatupd as rolcatupdate, "
594 "true as rolcanlogin, "
595 "-1 as rolconnlimit, "
596 "passwd as rolpassword, "
597 "valuntil as rolvaliduntil, "
598 "null as rolcomment "
599 "FROM pg_shadow "
600 "UNION ALL "
601 "SELECT groname as rolname, "
602 "false as rolsuper, "
603 "true as rolinherit, "
604 "false as rolcreaterole, "
605 "false as rolcreatedb, "
606 "false as rolcatupdate, "
607 "false as rolcanlogin, "
608 "-1 as rolconnlimit, "
609 "null::text as rolpassword, "
610 "null::abstime as rolvaliduntil, "
611 "null as rolcomment "
612 "FROM pg_group "
613 "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
614 " WHERE usename = groname) "
615 "ORDER BY 1");
617 res = executeQuery(conn, buf->data);
619 i_rolname = PQfnumber(res, "rolname");
620 i_rolsuper = PQfnumber(res, "rolsuper");
621 i_rolinherit = PQfnumber(res, "rolinherit");
622 i_rolcreaterole = PQfnumber(res, "rolcreaterole");
623 i_rolcreatedb = PQfnumber(res, "rolcreatedb");
624 i_rolcatupdate = PQfnumber(res, "rolcatupdate");
625 i_rolcanlogin = PQfnumber(res, "rolcanlogin");
626 i_rolconnlimit = PQfnumber(res, "rolconnlimit");
627 i_rolpassword = PQfnumber(res, "rolpassword");
628 i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
629 i_rolcomment = PQfnumber(res, "rolcomment");
631 if (PQntuples(res) > 0)
632 fprintf(OPF, "--\n-- Roles\n--\n\n");
634 for (i = 0; i < PQntuples(res); i++)
636 const char *rolename;
638 rolename = PQgetvalue(res, i, i_rolname);
640 resetPQExpBuffer(buf);
642 if (output_clean)
643 appendPQExpBuffer(buf, "DROP ROLE %s;\n", fmtId(rolename));
646 * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
647 * will acquire the right properties even if it already exists. (The
648 * above DROP may therefore seem redundant, but it isn't really,
649 * because this technique doesn't get rid of role memberships.)
651 appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
652 appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
654 if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
655 appendPQExpBuffer(buf, " SUPERUSER");
656 else
657 appendPQExpBuffer(buf, " NOSUPERUSER");
659 if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
660 appendPQExpBuffer(buf, " INHERIT");
661 else
662 appendPQExpBuffer(buf, " NOINHERIT");
664 if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
665 appendPQExpBuffer(buf, " CREATEROLE");
666 else
667 appendPQExpBuffer(buf, " NOCREATEROLE");
669 if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
670 appendPQExpBuffer(buf, " CREATEDB");
671 else
672 appendPQExpBuffer(buf, " NOCREATEDB");
674 if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
675 appendPQExpBuffer(buf, " LOGIN");
676 else
677 appendPQExpBuffer(buf, " NOLOGIN");
679 if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
680 appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
681 PQgetvalue(res, i, i_rolconnlimit));
683 if (!PQgetisnull(res, i, i_rolpassword))
685 appendPQExpBuffer(buf, " PASSWORD ");
686 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
689 if (!PQgetisnull(res, i, i_rolvaliduntil))
690 appendPQExpBuffer(buf, " VALID UNTIL '%s'",
691 PQgetvalue(res, i, i_rolvaliduntil));
693 appendPQExpBuffer(buf, ";\n");
695 if (!PQgetisnull(res, i, i_rolcomment))
697 appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
698 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
699 appendPQExpBuffer(buf, ";\n");
702 fprintf(OPF, "%s", buf->data);
704 if (server_version >= 70300)
705 dumpUserConfig(conn, rolename);
708 PQclear(res);
710 fprintf(OPF, "\n\n");
712 destroyPQExpBuffer(buf);
717 * Dump role memberships. This code is used for 8.1 and later servers.
719 * Note: we expect dumpRoles already created all the roles, but there is
720 * no membership yet.
722 static void
723 dumpRoleMembership(PGconn *conn)
725 PGresult *res;
726 int i;
728 res = executeQuery(conn, "SELECT ur.rolname AS roleid, "
729 "um.rolname AS member, "
730 "a.admin_option, "
731 "ug.rolname AS grantor "
732 "FROM pg_auth_members a "
733 "LEFT JOIN pg_authid ur on ur.oid = a.roleid "
734 "LEFT JOIN pg_authid um on um.oid = a.member "
735 "LEFT JOIN pg_authid ug on ug.oid = a.grantor "
736 "ORDER BY 1,2,3");
738 if (PQntuples(res) > 0)
739 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
741 for (i = 0; i < PQntuples(res); i++)
743 char *roleid = PQgetvalue(res, i, 0);
744 char *member = PQgetvalue(res, i, 1);
745 char *option = PQgetvalue(res, i, 2);
747 fprintf(OPF, "GRANT %s", fmtId(roleid));
748 fprintf(OPF, " TO %s", fmtId(member));
749 if (*option == 't')
750 fprintf(OPF, " WITH ADMIN OPTION");
753 * We don't track the grantor very carefully in the backend, so cope
754 * with the possibility that it has been dropped.
756 if (!PQgetisnull(res, i, 3))
758 char *grantor = PQgetvalue(res, i, 3);
760 fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
762 fprintf(OPF, ";\n");
765 PQclear(res);
767 fprintf(OPF, "\n\n");
771 * Dump group memberships from a pre-8.1 server. It's annoying that we
772 * can't share any useful amount of code with the post-8.1 case, but
773 * the catalog representations are too different.
775 * Note: we expect dumpRoles already created all the roles, but there is
776 * no membership yet.
778 static void
779 dumpGroups(PGconn *conn)
781 PQExpBuffer buf = createPQExpBuffer();
782 PGresult *res;
783 int i;
785 res = executeQuery(conn,
786 "SELECT groname, grolist FROM pg_group ORDER BY 1");
788 if (PQntuples(res) > 0)
789 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
791 for (i = 0; i < PQntuples(res); i++)
793 char *groname = PQgetvalue(res, i, 0);
794 char *grolist = PQgetvalue(res, i, 1);
795 PGresult *res2;
796 int j;
799 * Array representation is {1,2,3} ... convert to (1,2,3)
801 if (strlen(grolist) < 3)
802 continue;
804 grolist = strdup(grolist);
805 grolist[0] = '(';
806 grolist[strlen(grolist) - 1] = ')';
807 printfPQExpBuffer(buf,
808 "SELECT usename FROM pg_shadow "
809 "WHERE usesysid IN %s ORDER BY 1",
810 grolist);
811 free(grolist);
813 res2 = executeQuery(conn, buf->data);
815 for (j = 0; j < PQntuples(res2); j++)
817 char *usename = PQgetvalue(res2, j, 0);
820 * Don't try to grant a role to itself; can happen if old
821 * installation has identically named user and group.
823 if (strcmp(groname, usename) == 0)
824 continue;
826 fprintf(OPF, "GRANT %s", fmtId(groname));
827 fprintf(OPF, " TO %s;\n", fmtId(usename));
830 PQclear(res2);
833 PQclear(res);
834 destroyPQExpBuffer(buf);
836 fprintf(OPF, "\n\n");
840 * Dump tablespaces.
842 static void
843 dumpTablespaces(PGconn *conn)
845 PGresult *res;
846 int i;
849 * Get all tablespaces except built-in ones (which we assume are named
850 * pg_xxx)
852 if (server_version >= 80200)
853 res = executeQuery(conn, "SELECT spcname, "
854 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
855 "spclocation, spcacl, "
856 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
857 "FROM pg_catalog.pg_tablespace "
858 "WHERE spcname !~ '^pg_' "
859 "ORDER BY 1");
860 else
861 res = executeQuery(conn, "SELECT spcname, "
862 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
863 "spclocation, spcacl, "
864 "null "
865 "FROM pg_catalog.pg_tablespace "
866 "WHERE spcname !~ '^pg_' "
867 "ORDER BY 1");
869 if (PQntuples(res) > 0)
870 fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
872 for (i = 0; i < PQntuples(res); i++)
874 PQExpBuffer buf = createPQExpBuffer();
875 char *spcname = PQgetvalue(res, i, 0);
876 char *spcowner = PQgetvalue(res, i, 1);
877 char *spclocation = PQgetvalue(res, i, 2);
878 char *spcacl = PQgetvalue(res, i, 3);
879 char *spccomment = PQgetvalue(res, i, 4);
880 char *fspcname;
882 /* needed for buildACLCommands() */
883 fspcname = strdup(fmtId(spcname));
885 if (output_clean)
886 appendPQExpBuffer(buf, "DROP TABLESPACE %s;\n", fspcname);
888 appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
889 appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
891 appendPQExpBuffer(buf, " LOCATION ");
892 appendStringLiteralConn(buf, spclocation, conn);
893 appendPQExpBuffer(buf, ";\n");
895 if (!skip_acls &&
896 !buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner,
897 server_version, buf))
899 fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
900 progname, spcacl, fspcname);
901 PQfinish(conn);
902 exit(1);
905 if (spccomment && strlen(spccomment))
907 appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
908 appendStringLiteralConn(buf, spccomment, conn);
909 appendPQExpBuffer(buf, ";\n");
912 fprintf(OPF, "%s", buf->data);
914 free(fspcname);
915 destroyPQExpBuffer(buf);
918 PQclear(res);
919 fprintf(OPF, "\n\n");
923 * Dump commands to create each database.
925 * To minimize the number of reconnections (and possibly ensuing
926 * password prompts) required by the output script, we emit all CREATE
927 * DATABASE commands during the initial phase of the script, and then
928 * run pg_dump for each database to dump the contents of that
929 * database. We skip databases marked not datallowconn, since we'd be
930 * unable to connect to them anyway (and besides, we don't want to
931 * dump template0).
933 static void
934 dumpCreateDB(PGconn *conn)
936 PQExpBuffer buf = createPQExpBuffer();
937 PGresult *res;
938 int i;
940 fprintf(OPF, "--\n-- Database creation\n--\n\n");
942 if (server_version >= 80400)
943 res = executeQuery(conn,
944 "SELECT datname, "
945 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
946 "pg_encoding_to_char(d.encoding), "
947 "datcollate, datctype, datfrozenxid, "
948 "datistemplate, datacl, datconnlimit, "
949 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
950 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
951 "WHERE datallowconn ORDER BY 1");
952 else if (server_version >= 80100)
953 res = executeQuery(conn,
954 "SELECT datname, "
955 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
956 "pg_encoding_to_char(d.encoding), "
957 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
958 "datistemplate, datacl, datconnlimit, "
959 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
960 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
961 "WHERE datallowconn ORDER BY 1");
962 else if (server_version >= 80000)
963 res = executeQuery(conn,
964 "SELECT datname, "
965 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
966 "pg_encoding_to_char(d.encoding), "
967 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
968 "datistemplate, datacl, -1 as datconnlimit, "
969 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
970 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
971 "WHERE datallowconn ORDER BY 1");
972 else if (server_version >= 70300)
973 res = executeQuery(conn,
974 "SELECT datname, "
975 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
976 "pg_encoding_to_char(d.encoding), "
977 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
978 "datistemplate, datacl, -1 as datconnlimit, "
979 "'pg_default' AS dattablespace "
980 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
981 "WHERE datallowconn ORDER BY 1");
982 else if (server_version >= 70100)
983 res = executeQuery(conn,
984 "SELECT datname, "
985 "coalesce("
986 "(select usename from pg_shadow where usesysid=datdba), "
987 "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
988 "pg_encoding_to_char(d.encoding), "
989 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
990 "datistemplate, '' as datacl, -1 as datconnlimit, "
991 "'pg_default' AS dattablespace "
992 "FROM pg_database d "
993 "WHERE datallowconn ORDER BY 1");
994 else
997 * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal
998 * with getting a NULL by not printing any OWNER clause.
1000 res = executeQuery(conn,
1001 "SELECT datname, "
1002 "(select usename from pg_shadow where usesysid=datdba), "
1003 "pg_encoding_to_char(d.encoding), "
1004 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
1005 "'f' as datistemplate, "
1006 "'' as datacl, -1 as datconnlimit, "
1007 "'pg_default' AS dattablespace "
1008 "FROM pg_database d "
1009 "ORDER BY 1");
1012 for (i = 0; i < PQntuples(res); i++)
1014 char *dbname = PQgetvalue(res, i, 0);
1015 char *dbowner = PQgetvalue(res, i, 1);
1016 char *dbencoding = PQgetvalue(res, i, 2);
1017 char *dbcollate = PQgetvalue(res, i, 3);
1018 char *dbctype = PQgetvalue(res, i, 4);
1019 uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5));
1020 char *dbistemplate = PQgetvalue(res, i, 6);
1021 char *dbacl = PQgetvalue(res, i, 7);
1022 char *dbconnlimit = PQgetvalue(res, i, 8);
1023 char *dbtablespace = PQgetvalue(res, i, 9);
1024 char *fdbname;
1026 fdbname = strdup(fmtId(dbname));
1028 resetPQExpBuffer(buf);
1031 * Skip the CREATE DATABASE commands for "template1" and "postgres",
1032 * since they are presumably already there in the destination cluster.
1033 * We do want to emit their ACLs and config options if any, however.
1035 if (strcmp(dbname, "template1") != 0 &&
1036 strcmp(dbname, "postgres") != 0)
1038 if (output_clean)
1039 appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
1041 appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
1043 appendPQExpBuffer(buf, " WITH TEMPLATE = template0");
1045 if (strlen(dbowner) != 0)
1046 appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
1048 appendPQExpBuffer(buf, " ENCODING = ");
1049 appendStringLiteralConn(buf, dbencoding, conn);
1051 if (strlen(dbcollate) != 0)
1053 appendPQExpBuffer(buf, " COLLATE = ");
1054 appendStringLiteralConn(buf, dbcollate, conn);
1057 if (strlen(dbctype) != 0)
1059 appendPQExpBuffer(buf, " CTYPE = ");
1060 appendStringLiteralConn(buf, dbctype, conn);
1064 * Output tablespace if it isn't the default. For default, it
1065 * uses the default from the template database. If tablespace is
1066 * specified and tablespace creation failed earlier, (e.g. no such
1067 * directory), the database creation will fail too. One solution
1068 * would be to use 'SET default_tablespace' like we do in pg_dump
1069 * for setting non-default database locations.
1071 if (strcmp(dbtablespace, "pg_default") != 0 && !no_tablespaces)
1072 appendPQExpBuffer(buf, " TABLESPACE = %s",
1073 fmtId(dbtablespace));
1075 if (strcmp(dbconnlimit, "-1") != 0)
1076 appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
1077 dbconnlimit);
1079 appendPQExpBuffer(buf, ";\n");
1081 if (strcmp(dbistemplate, "t") == 0)
1083 appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
1084 appendStringLiteralConn(buf, dbname, conn);
1085 appendPQExpBuffer(buf, ";\n");
1088 if (binary_upgrade)
1090 appendPQExpBuffer(buf, "\n-- For binary upgrade, set datfrozenxid.\n");
1091 appendPQExpBuffer(buf, "UPDATE pg_database\n"
1092 "SET datfrozenxid = '%u'\n"
1093 "WHERE datname = '%s';\n",
1094 dbfrozenxid, fdbname);
1098 if (!skip_acls &&
1099 !buildACLCommands(fdbname, NULL, "DATABASE", dbacl, dbowner,
1100 server_version, buf))
1102 fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
1103 progname, dbacl, fdbname);
1104 PQfinish(conn);
1105 exit(1);
1108 fprintf(OPF, "%s", buf->data);
1110 if (server_version >= 70300)
1111 dumpDatabaseConfig(conn, dbname);
1113 free(fdbname);
1116 PQclear(res);
1117 destroyPQExpBuffer(buf);
1119 fprintf(OPF, "\n\n");
1125 * Dump database-specific configuration
1127 static void
1128 dumpDatabaseConfig(PGconn *conn, const char *dbname)
1130 PQExpBuffer buf = createPQExpBuffer();
1131 int count = 1;
1133 for (;;)
1135 PGresult *res;
1137 printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
1138 appendStringLiteralConn(buf, dbname, conn);
1139 appendPQExpBuffer(buf, ";");
1141 res = executeQuery(conn, buf->data);
1142 if (!PQgetisnull(res, 0, 0))
1144 makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
1145 "DATABASE", dbname);
1146 PQclear(res);
1147 count++;
1149 else
1151 PQclear(res);
1152 break;
1156 destroyPQExpBuffer(buf);
1162 * Dump user-specific configuration
1164 static void
1165 dumpUserConfig(PGconn *conn, const char *username)
1167 PQExpBuffer buf = createPQExpBuffer();
1168 int count = 1;
1170 for (;;)
1172 PGresult *res;
1174 if (server_version >= 80100)
1175 printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
1176 else
1177 printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
1178 appendStringLiteralConn(buf, username, conn);
1180 res = executeQuery(conn, buf->data);
1181 if (PQntuples(res) == 1 &&
1182 !PQgetisnull(res, 0, 0))
1184 makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
1185 "ROLE", username);
1186 PQclear(res);
1187 count++;
1189 else
1191 PQclear(res);
1192 break;
1196 destroyPQExpBuffer(buf);
1202 * Helper function for dumpXXXConfig().
1204 static void
1205 makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
1206 const char *type, const char *name)
1208 char *pos;
1209 char *mine;
1210 PQExpBuffer buf = createPQExpBuffer();
1212 mine = strdup(arrayitem);
1213 pos = strchr(mine, '=');
1214 if (pos == NULL)
1215 return;
1217 *pos = 0;
1218 appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
1219 appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
1222 * Some GUC variable names are 'LIST' type and hence must not be quoted.
1224 if (pg_strcasecmp(mine, "DateStyle") == 0
1225 || pg_strcasecmp(mine, "search_path") == 0)
1226 appendPQExpBuffer(buf, "%s", pos + 1);
1227 else
1228 appendStringLiteralConn(buf, pos + 1, conn);
1229 appendPQExpBuffer(buf, ";\n");
1231 fprintf(OPF, "%s", buf->data);
1232 destroyPQExpBuffer(buf);
1233 free(mine);
1239 * Dump contents of databases.
1241 static void
1242 dumpDatabases(PGconn *conn)
1244 PGresult *res;
1245 int i;
1247 if (server_version >= 70100)
1248 res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
1249 else
1250 res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
1252 for (i = 0; i < PQntuples(res); i++)
1254 int ret;
1256 char *dbname = PQgetvalue(res, i, 0);
1258 if (verbose)
1259 fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
1261 fprintf(OPF, "\\connect %s\n\n", fmtId(dbname));
1263 if (filename)
1264 fclose(OPF);
1266 ret = runPgDump(dbname);
1267 if (ret != 0)
1269 fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
1270 exit(1);
1273 if (filename)
1275 OPF = fopen(filename, PG_BINARY_A);
1276 if (!OPF)
1278 fprintf(stderr, _("%s: could not re-open the output file \"%s\": %s\n"),
1279 progname, filename, strerror(errno));
1280 exit(1);
1286 PQclear(res);
1292 * Run pg_dump on dbname.
1294 static int
1295 runPgDump(const char *dbname)
1297 PQExpBuffer cmd = createPQExpBuffer();
1298 int ret;
1300 appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin,
1301 pgdumpopts->data);
1304 * If we have a filename, use the undocumented plain-append pg_dump
1305 * format.
1307 if (filename)
1308 appendPQExpBuffer(cmd, " -Fa ");
1309 else
1310 appendPQExpBuffer(cmd, " -Fp ");
1312 doShellQuoting(cmd, dbname);
1314 appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
1316 if (verbose)
1317 fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
1319 fflush(stdout);
1320 fflush(stderr);
1322 ret = system(cmd->data);
1324 destroyPQExpBuffer(cmd);
1326 return ret;
1331 * Make a database connection with the given parameters. An
1332 * interactive password prompt is automatically issued if required.
1334 * If fail_on_error is false, we return NULL without printing any message
1335 * on failure, but preserve any prompted password for the next try.
1337 static PGconn *
1338 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
1339 const char *pguser, enum trivalue prompt_password, bool fail_on_error)
1341 PGconn *conn;
1342 bool new_pass;
1343 const char *remoteversion_str;
1344 int my_version;
1345 static char *password = NULL;
1347 if (prompt_password == TRI_YES && !password)
1348 password = simple_prompt("Password: ", 100, false);
1351 * Start the connection. Loop until we have a password if requested by
1352 * backend.
1356 new_pass = false;
1357 conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
1359 if (!conn)
1361 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
1362 progname, dbname);
1363 exit(1);
1366 if (PQstatus(conn) == CONNECTION_BAD &&
1367 PQconnectionNeedsPassword(conn) &&
1368 password == NULL &&
1369 prompt_password != TRI_NO)
1371 PQfinish(conn);
1372 password = simple_prompt("Password: ", 100, false);
1373 new_pass = true;
1375 } while (new_pass);
1377 /* check to see that the backend connection was successfully made */
1378 if (PQstatus(conn) == CONNECTION_BAD)
1380 if (fail_on_error)
1382 fprintf(stderr,
1383 _("%s: could not connect to database \"%s\": %s\n"),
1384 progname, dbname, PQerrorMessage(conn));
1385 exit(1);
1387 else
1389 PQfinish(conn);
1390 return NULL;
1394 remoteversion_str = PQparameterStatus(conn, "server_version");
1395 if (!remoteversion_str)
1397 fprintf(stderr, _("%s: could not get server version\n"), progname);
1398 exit(1);
1400 server_version = parse_version(remoteversion_str);
1401 if (server_version < 0)
1403 fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
1404 progname, remoteversion_str);
1405 exit(1);
1408 my_version = parse_version(PG_VERSION);
1409 if (my_version < 0)
1411 fprintf(stderr, _("%s: could not parse version \"%s\"\n"),
1412 progname, PG_VERSION);
1413 exit(1);
1417 * We allow the server to be back to 7.0, and up to any minor release
1418 * of our own major version. (See also version check in pg_dump.c.)
1420 if (my_version != server_version
1421 && (server_version < 70000 ||
1422 (server_version / 100) > (my_version / 100)))
1424 fprintf(stderr, _("server version: %s; %s version: %s\n"),
1425 remoteversion_str, progname, PG_VERSION);
1426 fprintf(stderr, _("aborting because of server version mismatch\n"));
1427 exit(1);
1431 * On 7.3 and later, make sure we are not fooled by non-system schemas in
1432 * the search path.
1434 if (server_version >= 70300)
1435 executeCommand(conn, "SET search_path = pg_catalog");
1437 return conn;
1442 * Run a query, return the results, exit program on failure.
1444 static PGresult *
1445 executeQuery(PGconn *conn, const char *query)
1447 PGresult *res;
1449 if (verbose)
1450 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1452 res = PQexec(conn, query);
1453 if (!res ||
1454 PQresultStatus(res) != PGRES_TUPLES_OK)
1456 fprintf(stderr, _("%s: query failed: %s"),
1457 progname, PQerrorMessage(conn));
1458 fprintf(stderr, _("%s: query was: %s\n"),
1459 progname, query);
1460 PQfinish(conn);
1461 exit(1);
1464 return res;
1468 * As above for a SQL command (which returns nothing).
1470 static void
1471 executeCommand(PGconn *conn, const char *query)
1473 PGresult *res;
1475 if (verbose)
1476 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1478 res = PQexec(conn, query);
1479 if (!res ||
1480 PQresultStatus(res) != PGRES_COMMAND_OK)
1482 fprintf(stderr, _("%s: query failed: %s"),
1483 progname, PQerrorMessage(conn));
1484 fprintf(stderr, _("%s: query was: %s\n"),
1485 progname, query);
1486 PQfinish(conn);
1487 exit(1);
1490 PQclear(res);
1495 * dumpTimestamp
1497 static void
1498 dumpTimestamp(char *msg)
1500 char buf[256];
1501 time_t now = time(NULL);
1504 * We don't print the timezone on Win32, because the names are long and
1505 * localized, which means they may contain characters in various random
1506 * encodings; this has been seen to cause encoding errors when reading the
1507 * dump script.
1509 if (strftime(buf, sizeof(buf),
1510 #ifndef WIN32
1511 "%Y-%m-%d %H:%M:%S %Z",
1512 #else
1513 "%Y-%m-%d %H:%M:%S",
1514 #endif
1515 localtime(&now)) != 0)
1516 fprintf(OPF, "-- %s %s\n\n", msg, buf);
1521 * Append the given string to the shell command being built in the buffer,
1522 * with suitable shell-style quoting.
1524 static void
1525 doShellQuoting(PQExpBuffer buf, const char *str)
1527 const char *p;
1529 #ifndef WIN32
1530 appendPQExpBufferChar(buf, '\'');
1531 for (p = str; *p; p++)
1533 if (*p == '\'')
1534 appendPQExpBuffer(buf, "'\"'\"'");
1535 else
1536 appendPQExpBufferChar(buf, *p);
1538 appendPQExpBufferChar(buf, '\'');
1540 #else /* WIN32 */
1542 appendPQExpBufferChar(buf, '"');
1543 for (p = str; *p; p++)
1545 if (*p == '"')
1546 appendPQExpBuffer(buf, "\\\"");
1547 else
1548 appendPQExpBufferChar(buf, *p);
1550 appendPQExpBufferChar(buf, '"');
1551 #endif /* WIN32 */