From 916710fc914b94995438fee36f4480b17ce420ed Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sun, 19 Jul 1998 05:24:51 +0000 Subject: [PATCH] pg_dump -z has gotten rather thoroughly broken in the last couple of days --- it was emitting stuff like REVOKE ALL on 'table' from PUBLIC; GRANT ALL on "table" to "Public"; neither of which work. While I was at it I cleaned up a few other things: * \connect commands are issued only in -z mode. In this way, reloading a pg_dump script made without -z will generate a simple database wholly owned by the invoking user, rather than a mishmash of tables owned by various people but lacking in access rights. (Analogy: cp versus cp -p.) * \connect commands are issued just before COPY FROM stdin commands; without this, reloading a database containing non-world-writable tables tended to fail because the COPY was not necessarily attempted as the table owner. * Redundant \connect commands are suppressed (each one costs a backend launch, so...). * Man page updated (-z wasn't ever documented). The first two items were discussed in a pgsql-hackers thread around 6 May 98 ("An item for the TODO list: pg_dump and multiple table owners") but no one had bothered to deal with 'em yet. regards, tom lane --- src/bin/pg_dump/pg_dump.c | 84 ++++++++++++++++++++++++++++++++--------------- src/man/pg_dump.1 | 19 +++++++---- 2 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 45e9a8135d..ad68b9fcde 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -21,7 +21,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.77 1998/07/08 14:33:19 thomas Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.78 1998/07/19 05:24:49 momjian Exp $ * * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb * @@ -95,6 +95,7 @@ static void setMaxOid(FILE *fout); static char *AddAcl(char *s, const char *add); static char *GetPrivledges(char *s); static ACL *ParseACL(const char *acls, int *count); +static void becomeUser(FILE *fout, const char *username); extern char *optarg; extern int optind, @@ -110,6 +111,7 @@ int dumpData; /* dump data using proper insert strings */ int attrNames; /* put attr names into insert strings */ int schemaOnly; int dataOnly; +int aclsOption; char g_opaque_type[10]; /* name for the opaque type */ @@ -142,12 +144,12 @@ usage(const char *progname) fprintf(stderr, "\t -t table \t\t dump for this table only\n"); fprintf(stderr, + "\t -u \t\t use password authentication\n"); + fprintf(stderr, "\t -v \t\t verbose\n"); fprintf(stderr, "\t -z \t\t dump ACLs (grant/revoke)\n"); fprintf(stderr, - "\t -u \t\t use password authentication\n"); - fprintf(stderr, "\nIf dbname is not supplied, then the DATABASE environment " "variable value is used.\n"); fprintf(stderr, "\n"); @@ -435,7 +437,7 @@ dumpClasses(const TableInfo tblinfo[], const int numTables, FILE *fout, if (g_verbose) fprintf(stderr, "%s dumping out schema of sequence '%s' %s\n", g_comment_start, tblinfo[i].relname, g_comment_end); - fprintf(fout, "\\connect - %s\n", tblinfo[i].usename); + becomeUser(fout, tblinfo[i].usename); dumpSequence(fout, tblinfo[i]); } } @@ -458,6 +460,8 @@ dumpClasses(const TableInfo tblinfo[], const int numTables, FILE *fout, fprintf(stderr, "%s dumping out the contents of Table '%s' %s\n", g_comment_start, classname, g_comment_end); + becomeUser(fout, tblinfo[i].usename); + if (!dumpData) dumpClasses_nodumpData(fout, classname, oids); else @@ -534,8 +538,7 @@ main(int argc, char **argv) const char *pghost = NULL; const char *pgport = NULL; char *tablename = NULL; - int oids = 0, - acls = 0; + int oids = 0; TableInfo *tblinfo; int numTables; char connect_string[512] = ""; @@ -598,8 +601,8 @@ main(int argc, char **argv) case 'v': /* verbose */ g_verbose = true; break; - case 'z': /* Dump oids */ - acls = 1; + case 'z': /* Dump ACLs and table ownership info */ + aclsOption = 1; break; case 'u': use_password = 1; @@ -657,11 +660,11 @@ main(int argc, char **argv) strcat(connect_string, tmp_string); sprintf(tmp_string, "password=%s ", password); strcat(connect_string, tmp_string); - bzero(tmp_string, sizeof(tmp_string)); - bzero(password, sizeof(password)); + MemSet(tmp_string, 0, sizeof(tmp_string)); + MemSet(password, 0, sizeof(password)); } g_conn = PQconnectdb(connect_string); - bzero(connect_string, sizeof(connect_string)); + MemSet(connect_string, 0, sizeof(connect_string)); /* check to see that the backend connection was successfully made */ if (PQstatus(g_conn) == CONNECTION_BAD) { @@ -679,10 +682,10 @@ main(int argc, char **argv) if (g_verbose) fprintf(stderr, "%s last builtin oid is %d %s\n", g_comment_start, g_last_builtin_oid, g_comment_end); - tblinfo = dumpSchema(g_fout, &numTables, tablename, acls); + tblinfo = dumpSchema(g_fout, &numTables, tablename, aclsOption); } else - tblinfo = dumpSchema(NULL, &numTables, tablename, acls); + tblinfo = dumpSchema(NULL, &numTables, tablename, aclsOption); if (!schemaOnly) dumpClasses(tblinfo, numTables, g_fout, tablename, oids); @@ -1961,7 +1964,7 @@ dumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs, if (funcInd != -1) dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes); - fprintf(fout, "\\connect - %s\n", tinfo[i].usename); + becomeUser(fout, tinfo[i].usename); sprintf(q, "CREATE TYPE \"%s\" " @@ -2028,7 +2031,7 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i, else finfo[i].dumped = 1; - fprintf(fout, "\\connect - %s\n", finfo[i].usename); + becomeUser(fout, finfo[i].usename); sprintf(q, "CREATE FUNCTION \"%s\" (", finfo[i].proname); for (j = 0; j < finfo[i].nargs; j++) @@ -2143,7 +2146,7 @@ dumpOprs(FILE *fout, OprInfo *oprinfo, int numOperators, oprinfo[i].oprlsortop)); } - fprintf(fout, "\\connect - %s\n", oprinfo[i].usename); + becomeUser(fout, oprinfo[i].usename); sprintf(q, "CREATE OPERATOR %s " @@ -2238,7 +2241,7 @@ dumpAggs(FILE *fout, AggInfo *agginfo, int numAggs, else comma2[0] = '\0'; - fprintf(fout, "\\connect - %s\n", agginfo[i].usename); + becomeUser(fout, agginfo[i].usename); sprintf(q, "CREATE AGGREGATE %s ( %s %s%s %s%s %s );\n", agginfo[i].aggname, @@ -2349,7 +2352,7 @@ ParseACL(const char *acls, int *count) s = strdup(acls); /* Setup up public */ - ParsedAcl[0].user = strdup("Public"); + ParsedAcl[0].user = NULL; /* indicates PUBLIC */ tok = strtok(s, ","); ParsedAcl[0].privledges = GetPrivledges(strchr(tok, '=')); @@ -2397,16 +2400,23 @@ dumpACL(FILE *fout, TableInfo tbinfo) /* Revoke Default permissions for PUBLIC */ fprintf(fout, - "REVOKE ALL on '%s' from PUBLIC;\n", + "REVOKE ALL on \"%s\" from PUBLIC;\n", tbinfo.relname); for (k = 0; k < l; k++) { if (ACLlist[k].privledges != (char *) NULL) - fprintf(fout, - "GRANT %s on \"%s\" to \"%s\";\n", - ACLlist[k].privledges, tbinfo.relname, - ACLlist[k].user); + { + if (ACLlist[k].user == (char *) NULL) + fprintf(fout, + "GRANT %s on \"%s\" to PUBLIC;\n", + ACLlist[k].privledges, tbinfo.relname); + else + fprintf(fout, + "GRANT %s on \"%s\" to \"%s\";\n", + ACLlist[k].privledges, tbinfo.relname, + ACLlist[k].user); + } } } @@ -2437,7 +2447,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables, continue; if (!tablename || (!strcmp(tblinfo[i].relname, tablename))) { - fprintf(fout, "\\connect - %s\n", tblinfo[i].usename); + becomeUser(fout, tblinfo[i].usename); dumpSequence(fout, tblinfo[i]); if (acls) dumpACL(fout, tblinfo[i]); @@ -2459,7 +2469,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables, parentRels = tblinfo[i].parentRels; numParents = tblinfo[i].numParents; - fprintf(fout, "\\connect - %s\n", tblinfo[i].usename); + becomeUser(fout, tblinfo[i].usename); sprintf(q, "CREATE TABLE \"%s\" (", fmtId(tblinfo[i].relname)); actual_atts = 0; @@ -2954,8 +2964,30 @@ dumpTriggers(FILE *fout, const char *tablename, continue; for (j = 0; j < tblinfo[i].ntrig; j++) { - fprintf(fout, "\\connect - %s\n", tblinfo[i].usename); + becomeUser(fout, tblinfo[i].usename); fputs(tblinfo[i].triggers[j], fout); } } } + + +/* Issue a psql \connect command to become the specified user. + * We want to do this only if we are dumping ACLs, + * and only if the new username is different from the last one + * (to avoid the overhead of useless backend launches). + */ + +static void becomeUser(FILE *fout, const char *username) +{ + static const char *lastusername = ""; + + if (! aclsOption) + return; + + if (strcmp(lastusername, username) == 0) + return; + + fprintf(fout, "\\connect - %s\n", username); + + lastusername = username; +} diff --git a/src/man/pg_dump.1 b/src/man/pg_dump.1 index c34fe322a7..67f04e67c0 100644 --- a/src/man/pg_dump.1 +++ b/src/man/pg_dump.1 @@ -1,7 +1,7 @@ .\" This is -*-nroff-*- .\" XXX standard disclaimer belongs here.... -.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_dump.1,v 1.11 1998/06/24 13:21:28 momjian Exp $ -.TH PG_DUMP UNIX 1/20/96 PostgreSQL PostgreSQL +.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_dump.1,v 1.12 1998/07/19 05:24:51 momjian Exp $ +.TH PG_DUMP UNIX 7/15/98 PostgreSQL PostgreSQL .SH NAME pg_dump - dumps out a Postgres database into a script file .SH SYNOPSIS @@ -36,23 +36,27 @@ port] .BR "-t" table] [\c +.BR "-u" +] +[\c .BR "-v" ] [\c -.BR "-u"] +.BR "-z" +] dbname .in -5n .SH DESCRIPTION .IR "pg_dump" is a utility for dumping out a Postgres database into a script file containing query commands. The script -files are in a ASCII format and can be used to reconstruct the database, +files are in ASCII format and can be used to reconstruct the database, even on other machines and other architectures. .IR "pg_dump" will produce the queries necessary to re-generate all user-defined types, functions, tables, indices, aggregates, and operators. In addition, all the data is copied out in ASCII format so -that it can be readily copied in again, as well, as imported into tools +that it can be readily copied in again, as well as imported into tools for textual editing. .PP .IR "pg_dump" @@ -92,10 +96,13 @@ Dump out only the schema, no data Dump for this table only .TP .BR "-u" -Use password authentication. Prompts for username and password. +Use password authentication. Prompts for username and password .TP .BR "-v" "" Specifies verbose mode +.TP +.BR "-z" "" +Include ACLs (grant/revoke commands) and table ownership information .PP If dbname is not supplied, then the DATABASE environment variable value is used. .SH "CAVEATS AND LIMITATIONS" -- 2.11.0