mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
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
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -141,12 +143,12 @@ usage(const char *progname)
|
||||
"\t -s \t\t dump out only the schema, no data\n");
|
||||
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");
|
||||
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user