Make dumpACL behave more reasonably for case where owner has revoked
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 May 2002 18:33:45 +0000 (18:33 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 May 2002 18:33:45 +0000 (18:33 +0000)
some of his own privileges.

src/bin/pg_dump/pg_dump.c

index 7cb3ea430bb7968216befd4b58f83971a920a4af..20c847ea63c64d283434d3336b50a59595585f90 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.257 2002/04/29 17:30:18 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.258 2002/05/06 18:33:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,7 +79,7 @@ static void dumpComment(Archive *fout, const char *target, const char *oid,
            const char *((*deps)[]));
 static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
 static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly);
-static void dumpACL(Archive *fout, TableInfo tbinfo);
+static void dumpACL(Archive *fout, TableInfo *tbinfo);
 static void dumpTriggers(Archive *fout, const char *tablename,
             TableInfo *tblinfo, int numTables);
 static void dumpRules(Archive *fout, const char *tablename,
@@ -4129,58 +4129,27 @@ GetPrivileges(Archive *AH, const char *s)
        return strdup(aclbuf);
 }
 
-/*
- * The name says it all; a function to append a string if the dest
- * is big enough. If not, it does a realloc.
- */
-static void
-strcatalloc(char **dest, int *dSize, char *src)
-{
-   int         dLen = strlen(*dest);
-   int         sLen = strlen(src);
-
-   if ((dLen + sLen) >= *dSize)
-   {
-       *dSize = (dLen + sLen) * 2;
-       *dest = realloc(*dest, *dSize);
-   }
-   strcpy(*dest + dLen, src);
-}
-
 
 /*
  * dumpACL:
- *   Write out grant/revoke information
- *   Called for sequences and tables
+ *   Write out grant/revoke information for a table, view or sequence
  */
-
 static void
-dumpACL(Archive *fout, TableInfo tbinfo)
+dumpACL(Archive *fout, TableInfo *tbinfo)
 {
-   const char *acls = tbinfo.relacl;
+   const char *acls = tbinfo->relacl;
    char       *aclbuf,
               *tok,
               *eqpos,
               *priv;
    char       *objoid;
-   char       *sql;
-   char        tmp[1024];
-   int         sSize = 4096;
+   PQExpBuffer sql;
+   bool        found_owner_privs = false;
 
    if (strlen(acls) == 0)
        return;                 /* table has default permissions */
 
-   /*
-    * Allocate a larginsh buffer for the output SQL.
-    */
-   sql = (char *) malloc(sSize);
-
-   /*
-    * Revoke Default permissions for PUBLIC. Is this actually necessary,
-    * or is it just a waste of time?
-    */
-   sprintf(sql, "REVOKE ALL on %s from PUBLIC;\n",
-           fmtId(tbinfo.relname, force_quotes));
+   sql = createPQExpBuffer();
 
    /* Make a working copy of acls so we can use strtok */
    aclbuf = strdup(acls);
@@ -4202,9 +4171,10 @@ dumpACL(Archive *fout, TableInfo tbinfo)
        if (!eqpos)
        {
            write_msg(NULL, "could not parse ACL list ('%s') for relation %s\n",
-                     acls, tbinfo.relname);
+                     acls, tbinfo->relname);
            exit_nicely();
        }
+       *eqpos = '\0';          /* it's ok to clobber aclbuf */
 
        /*
         * Parse the privileges (right-hand side).  Skip if there are
@@ -4213,41 +4183,69 @@ dumpACL(Archive *fout, TableInfo tbinfo)
        priv = GetPrivileges(fout, eqpos + 1);
        if (*priv)
        {
-           sprintf(tmp, "GRANT %s on %s to ",
-                   priv, fmtId(tbinfo.relname, force_quotes));
-           strcatalloc(&sql, &sSize, tmp);
-
-           /*
-            * Note: fmtId() can only be called once per printf, so don't
-            * try to merge printing of username into the above printf.
-            */
-           if (eqpos == tok)
+           if (strcmp(tok, tbinfo->usename) == 0)
            {
-               /* Empty left-hand side means "PUBLIC" */
-               strcatalloc(&sql, &sSize, "PUBLIC;\n");
+               /*
+                * For the owner, the default privilege level is ALL.
+                */
+               found_owner_privs = true;
+               if (strcmp(priv, "ALL") != 0)
+               {
+                   /* NB: only one fmtId per appendPQExpBuffer! */
+                   appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ",
+                                     fmtId(tbinfo->relname, force_quotes));
+                   appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
+                   appendPQExpBuffer(sql, "GRANT %s ON %s TO ",
+                                     priv,
+                                     fmtId(tbinfo->relname, force_quotes));
+                   appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
+               }
            }
            else
            {
-               *eqpos = '\0';  /* it's ok to clobber aclbuf */
-               if (strncmp(tok, "group ", strlen("group ")) == 0)
-                   sprintf(tmp, "GROUP %s;\n",
-                           fmtId(tok + strlen("group "), force_quotes));
+               /*
+                * Otherwise can assume we are starting from no privs.
+                */
+               appendPQExpBuffer(sql, "GRANT %s ON %s TO ",
+                                 priv,
+                                 fmtId(tbinfo->relname, force_quotes));
+               if (eqpos == tok)
+               {
+                   /* Empty left-hand side means "PUBLIC" */
+                   appendPQExpBuffer(sql, "PUBLIC;\n");
+               }
+               else if (strncmp(tok, "group ", strlen("group ")) == 0)
+                   appendPQExpBuffer(sql, "GROUP %s;\n",
+                                     fmtId(tok + strlen("group "),
+                                           force_quotes));
                else
-                   sprintf(tmp, "%s;\n", fmtId(tok, force_quotes));
-               strcatalloc(&sql, &sSize, tmp);
+                   appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
            }
        }
        free(priv);
    }
 
+   /*
+    * If we didn't find any owner privs, the owner must have revoked 'em all
+    */
+   if (!found_owner_privs && *tbinfo->usename)
+   {
+       appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ",
+                         fmtId(tbinfo->relname, force_quotes));
+       appendPQExpBuffer(sql, "%s;\n", fmtId(tbinfo->usename, force_quotes));
+   }
+
    free(aclbuf);
 
-   if (tbinfo.viewdef != NULL)
-       objoid = tbinfo.viewoid;
+   if (tbinfo->viewdef != NULL)
+       objoid = tbinfo->viewoid;
    else
-       objoid = tbinfo.oid;
+       objoid = tbinfo->oid;
+
+   ArchiveEntry(fout, objoid, tbinfo->relname, "ACL",
+                NULL, sql->data, "", "", "", NULL, NULL);
 
-   ArchiveEntry(fout, objoid, tbinfo.relname, "ACL", NULL, sql, "", "", "", NULL, NULL);
+   destroyPQExpBuffer(sql);
 }
 
 static void
@@ -4350,7 +4348,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
            /* becomeUser(fout, tblinfo[i].usename); */
            dumpSequence(fout, tblinfo[i], schemaOnly, dataOnly);
            if (!aclsSkip)
-               dumpACL(fout, tblinfo[i]);
+               dumpACL(fout, &tblinfo[i]);
        }
    }
    if (serialSeq)
@@ -4486,7 +4484,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
                             NULL, NULL);
 
                if (!aclsSkip)
-                   dumpACL(fout, tblinfo[i]);
+                   dumpACL(fout, &tblinfo[i]);
 
            }