aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r--src/bin/pg_dump/pg_dump.c242
1 files changed, 152 insertions, 90 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 809fe0216af..32b529b64e9 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.314 2003/01/06 18:53:24 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.315 2003/01/23 23:39:01 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -92,7 +92,7 @@ static void dumpFuncACL(Archive *fout, FuncInfo *finfo);
static void dumpAggACL(Archive *fout, AggInfo *finfo);
static void dumpACL(Archive *fout, const char *type, const char *name,
const char *tag, const char *nspname,
- const char *usename, const char *acl, const char *objoid);
+ const char *owner, const char *acl, const char *objoid);
static void dumpConstraints(Archive *fout, TableInfo *tblinfo, int numTables);
static void dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables);
@@ -114,8 +114,10 @@ static char *getFormattedTypeName(const char *oid, OidOptions opts);
static char *myFormatType(const char *typname, int32 typmod);
static const char *fmtQualifiedId(const char *schema, const char *id);
-static void AddAcl(char *aclbuf, const char *keyword);
-static char *GetPrivileges(Archive *AH, const char *s, const char *type);
+static void AddAcl(PQExpBuffer aclbuf, const char *keyword);
+static void
+parseAclItem(const char *item, const char *type, const char *name, int remoteVersion,
+ PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo);
static int dumpBlobs(Archive *AH, char *, void *);
static int dumpDatabase(Archive *AH);
@@ -4777,42 +4779,80 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
/*
- * These are some support functions to fix the acl problem of pg_dump
- *
- * Matthew C. Aycock 12/02/97
- */
-
-/* Append a keyword to a keyword list, inserting comma if needed.
- * Caller must make aclbuf big enough for all possible keywords.
+ * Append a privilege keyword to a keyword list, inserting comma if needed.
*/
static void
-AddAcl(char *aclbuf, const char *keyword)
+AddAcl(PQExpBuffer aclbuf, const char *keyword)
{
- if (*aclbuf)
- strcat(aclbuf, ",");
- strcat(aclbuf, keyword);
+ if (aclbuf->len > 0)
+ appendPQExpBufferChar(aclbuf, ',');
+ appendPQExpBuffer(aclbuf, "%s", keyword);
}
+
/*
- * This will take a string of privilege code letters and return a malloced,
- * comma delimited string of keywords for GRANT.
+ * This will take an aclitem string of privilege code letters and
+ * parse it into grantee, grantor, and privilege information. The
+ * privilege information is split between privileges with grant option
+ * (privswgo) and without (privs).
*
* Note: for cross-version compatibility, it's important to use ALL when
* appropriate.
*/
-static char *
-GetPrivileges(Archive *AH, const char *s, const char *type)
+static void
+parseAclItem(const char *item, const char *type, const char *name, int remoteVersion,
+ PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo)
{
- char aclbuf[100];
- bool all = true;
+ char *buf;
+ bool all_with_go = true;
+ bool all_without_go = true;
+ char *eqpos;
+ char *slpos;
+ char *pos;
+
+ buf = strdup(item);
- aclbuf[0] = '\0';
+ /* user name is string up to = */
+ eqpos = strchr(buf, '=');
+ if (!eqpos)
+ {
+ write_msg(NULL, "could not parse ACL list (%s) for object %s (%s)\n",
+ item, name, type);
+ exit_nicely();
+ }
+ *eqpos = '\0';
+ printfPQExpBuffer(grantee, "%s", buf);
-#define CONVERT_PRIV(code,keywd) \
- if (strchr(s, code)) \
- AddAcl(aclbuf, keywd); \
+ /* grantor may be listed after / */
+ slpos = strchr(eqpos + 1, '/');
+ if (slpos)
+ {
+ *slpos = '\0';
+ printfPQExpBuffer(grantor, "%s", slpos + 1);
+ }
+ else
+ resetPQExpBuffer(grantor);
+
+ /* privilege codes */
+#define CONVERT_PRIV(code, keywd) \
+ if ((pos = strchr(eqpos + 1, code))) \
+ { \
+ if (*(pos + 1) == '*') \
+ { \
+ AddAcl(privswgo, keywd); \
+ all_without_go = false; \
+ } \
+ else \
+ { \
+ AddAcl(privs, keywd); \
+ all_with_go = false; \
+ } \
+ } \
else \
- all = false
+ all_with_go = all_without_go = false
+
+ resetPQExpBuffer(privs);
+ resetPQExpBuffer(privswgo);
if (strcmp(type, "TABLE") == 0)
{
@@ -4820,7 +4860,7 @@ GetPrivileges(Archive *AH, const char *s, const char *type)
CONVERT_PRIV('r', "SELECT");
CONVERT_PRIV('R', "RULE");
- if (AH->remoteVersion >= 70200)
+ if (remoteVersion >= 70200)
{
CONVERT_PRIV('w', "UPDATE");
CONVERT_PRIV('d', "DELETE");
@@ -4847,10 +4887,16 @@ GetPrivileges(Archive *AH, const char *s, const char *type)
#undef CONVERT_PRIV
- if (all)
- return strdup("ALL");
- else
- return strdup(aclbuf);
+ if (all_with_go)
+ {
+ resetPQExpBuffer(privs);
+ printfPQExpBuffer(privswgo, "ALL");
+ }
+ else if (all_without_go)
+ {
+ resetPQExpBuffer(privswgo);
+ printfPQExpBuffer(privs, "ALL");
+ }
}
@@ -4861,7 +4907,7 @@ GetPrivileges(Archive *AH, const char *s, const char *type)
* 'name' is the formatted name of the object. Must be quoted etc. already.
* 'tag' is the tag for the archive entry (typ. unquoted name of object).
* 'nspname' is the namespace the object is in (NULL if none).
- * 'usename' is the owner, NULL if there is no owner (for languages).
+ * 'owner' is the owner, NULL if there is no owner (for languages).
* 'acls' is the string read out of the fooacl system catalog field;
* it will be parsed here.
* 'objoid' is the OID of the object for purposes of ordering.
@@ -4869,28 +4915,34 @@ GetPrivileges(Archive *AH, const char *s, const char *type)
*/
static void
dumpACL(Archive *fout, const char *type, const char *name,
- const char *tag, const char *nspname, const char *usename,
+ const char *tag, const char *nspname, const char *owner,
const char *acls, const char *objoid)
{
char *aclbuf,
- *tok,
- *eqpos,
- *priv;
- PQExpBuffer sql;
+ *tok;
+ PQExpBuffer sql, grantee, grantor, privs, privswgo;
bool found_owner_privs = false;
if (strlen(acls) == 0)
return; /* object has default permissions */
+#define MKENTRY(grantor, command) \
+ ArchiveEntry(fout, objoid, tag, nspname, grantor ? grantor : "", "ACL", NULL, command, "", NULL, NULL, NULL)
+
sql = createPQExpBuffer();
+ grantee = createPQExpBuffer();
+ grantor = createPQExpBuffer();
+ privs = createPQExpBuffer();
+ privswgo = createPQExpBuffer();
/*
* Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
* wire-in knowledge about the default public privileges for different
* kinds of objects.
*/
- appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM PUBLIC;\n",
+ printfPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM PUBLIC;\n",
type, name);
+ MKENTRY(owner, sql->data);
/* Make a working copy of acls so we can use strtok */
aclbuf = strdup(acls);
@@ -4898,6 +4950,10 @@ dumpACL(Archive *fout, const char *type, const char *name,
/* Scan comma-separated ACL items */
for (tok = strtok(aclbuf, ","); tok != NULL; tok = strtok(NULL, ","))
{
+ size_t toklen;
+
+ resetPQExpBuffer(sql);
+
/*
* Token may start with '{' and/or '"'. Actually only the start
* of the string should have '{', but we don't verify that.
@@ -4906,39 +4962,33 @@ dumpACL(Archive *fout, const char *type, const char *name,
tok++;
if (*tok == '"')
tok++;
+ toklen = strlen(tok);
+ while (toklen >=0 && (tok[toklen-1] == '"' || tok[toklen-1] == '}'))
+ tok[toklen-- - 1] = '\0';
- /* User name is string up to = in tok */
- eqpos = strchr(tok, '=');
- if (!eqpos)
- {
- write_msg(NULL, "could not parse ACL list (%s) for object %s (%s)\n",
- acls, name, type);
- exit_nicely();
- }
- *eqpos = '\0'; /* it's ok to clobber aclbuf */
-
- /*
- * Parse the privileges (right-hand side).
- */
- priv = GetPrivileges(fout, eqpos + 1, type);
+ parseAclItem(tok, type, name, fout->remoteVersion,
+ grantee, grantor, privs, privswgo);
+ if (grantor->len == 0 && owner)
+ printfPQExpBuffer(grantor, "%s", owner);
- if (*priv)
+ if (privs->len > 0 || privswgo->len > 0)
{
- if (usename && strcmp(tok, usename) == 0)
+ if (owner && strcmp(grantee->data, owner) == 0)
{
/*
- * For the owner, the default privilege level is ALL.
+ * For the owner, the default privilege level is ALL WITH GRANT OPTION.
*/
found_owner_privs = true;
- if (strcmp(priv, "ALL") != 0)
+ if (strcmp(privswgo->data, "ALL") != 0)
{
- /* NB: only one fmtId per appendPQExpBuffer! */
- appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM ",
- type, name);
- appendPQExpBuffer(sql, "%s;\n", fmtId(tok));
- appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
- priv, type, name);
- appendPQExpBuffer(sql, "%s;\n", fmtId(tok));
+ appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
+ type, name, fmtId(grantee->data));
+ if (privs->len > 0)
+ appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s;\n",
+ privs->data, type, name, fmtId(grantee->data));
+ if (privswgo->len > 0)
+ appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
+ privswgo->data, type, name, fmtId(grantee->data));
}
}
else
@@ -4946,57 +4996,69 @@ dumpACL(Archive *fout, const char *type, const char *name,
/*
* Otherwise can assume we are starting from no privs.
*/
- appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
- priv, type, name);
- if (eqpos == tok)
+ if (privs->len > 0)
{
- /* Empty left-hand side means "PUBLIC" */
- appendPQExpBuffer(sql, "PUBLIC;\n");
+ appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
+ privs->data, type, name);
+ if (grantee->len == 0)
+ appendPQExpBuffer(sql, "PUBLIC;\n");
+ else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
+ appendPQExpBuffer(sql, "GROUP %s;\n",
+ fmtId(grantee->data + strlen("group ")));
+ else
+ appendPQExpBuffer(sql, "%s;\n", fmtId(grantee->data));
+ }
+ if (privswgo->len > 0)
+ {
+ appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
+ privswgo->data, type, name);
+ if (grantee->len == 0)
+ appendPQExpBuffer(sql, "PUBLIC");
+ else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
+ appendPQExpBuffer(sql, "GROUP %s",
+ fmtId(grantee->data + strlen("group ")));
+ else
+ appendPQExpBuffer(sql, "%s", fmtId(grantee->data));
+ appendPQExpBuffer(sql, " WITH GRANT OPTION;\n");
}
- else if (strncmp(tok, "group ", strlen("group ")) == 0)
- appendPQExpBuffer(sql, "GROUP %s;\n",
- fmtId(tok + strlen("group ")));
- else
- appendPQExpBuffer(sql, "%s;\n", fmtId(tok));
}
}
else
{
/* No privileges. Issue explicit REVOKE for safety. */
- if (eqpos == tok)
- {
- /* Empty left-hand side means "PUBLIC"; already did it */
- }
- else if (strncmp(tok, "group ", strlen("group ")) == 0)
- {
+ if (grantee->len == 0)
+ ; /* Empty left-hand side means "PUBLIC"; already did it */
+ else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM GROUP %s;\n",
type, name,
- fmtId(tok + strlen("group ")));
- }
+ fmtId(grantee->data + strlen("group ")));
else
- {
appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
- type, name, fmtId(tok));
- }
+ type, name, fmtId(grantee->data));
}
- free(priv);
+
+ if (sql->len > 0)
+ MKENTRY(grantor->data, sql->data);
}
/*
* If we didn't find any owner privs, the owner must have revoked 'em
* all
*/
- if (!found_owner_privs && usename)
+ if (!found_owner_privs && owner)
{
appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
- type, name, fmtId(usename));
+ type, name, fmtId(owner));
+ MKENTRY(owner, sql->data);
}
- ArchiveEntry(fout, objoid, tag, nspname, usename ? usename : "",
- "ACL", NULL, sql->data, "", NULL, NULL, NULL);
-
free(aclbuf);
destroyPQExpBuffer(sql);
+ destroyPQExpBuffer(grantee);
+ destroyPQExpBuffer(grantor);
+ destroyPQExpBuffer(privs);
+ destroyPQExpBuffer(privswgo);
+#undef MKENTRY
}