77 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.4 2003/05/30 22:55:15 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.5 2003/07/24 15:52:53 petere Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -24,6 +24,7 @@ static bool parseAclItem(const char *item, const char *type, const char *name,
2424PQExpBuffer grantee ,PQExpBuffer grantor ,
2525PQExpBuffer privs ,PQExpBuffer privswgo );
2626static void AddAcl (PQExpBuffer aclbuf ,const char * keyword );
27+ #define supports_grant_options (version ) ((version) >= 70400)
2728
2829
2930/*
@@ -187,6 +188,7 @@ buildACLCommands(const char *name, const char *type,
187188char * aclbuf ,
188189* tok ;
189190PQExpBuffer grantee ,grantor ,privs ,privswgo ;
191+ PQExpBuffer firstsql ,secondsql ;
190192bool found_owner_privs = false;
191193
192194if (strlen (acls )== 0 )
@@ -196,13 +198,23 @@ buildACLCommands(const char *name, const char *type,
196198grantor = createPQExpBuffer ();
197199privs = createPQExpBuffer ();
198200privswgo = createPQExpBuffer ();
201+ /*
202+ * At the end, these two will be pasted together to form the
203+ * result. But the owner privileges need to go before the other
204+ * ones to keep the dependencies valid. In recent versions this
205+ * is normally the case, but in old versions they come after the
206+ * PUBLIC privileges and that results in problems if we need to
207+ * run REVOKE on the owner privileges.
208+ */
209+ firstsql = createPQExpBuffer ();
210+ secondsql = createPQExpBuffer ();
199211
200212/*
201213 * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
202214 * wire-in knowledge about the default public privileges for different
203215 * kinds of objects.
204216 */
205- appendPQExpBuffer (sql ,"REVOKE ALL ON %s %s FROM PUBLIC;\n" ,
217+ appendPQExpBuffer (firstsql ,"REVOKE ALL ON %s %s FROM PUBLIC;\n" ,
206218type ,name );
207219
208220/* Make a working copy of acls so we can use strtok */
@@ -234,24 +246,28 @@ buildACLCommands(const char *name, const char *type,
234246
235247if (privs -> len > 0 || privswgo -> len > 0 )
236248{
237- if (owner && strcmp (grantee -> data ,owner )== 0 )
249+ if (owner
250+ && strcmp (grantee -> data ,owner )== 0
251+ && strcmp (grantor -> data ,owner )== 0 )
238252{
253+ found_owner_privs = true;
239254/*
240- * For the owner, the default privilege level is
241- *ALL WITH GRANT OPTION.
255+ * For the owner, the default privilege level is ALL
256+ * WITH GRANT OPTION (only ALL prior to 7.4) .
242257 */
243- found_owner_privs = true;
244- if (strcmp (privswgo -> data ,"ALL" )!= 0 )
258+ if (supports_grant_options (remoteVersion )
259+ ?strcmp (privswgo -> data ,"ALL" )!= 0
260+ :strcmp (privs -> data ,"ALL" )!= 0 )
245261{
246- appendPQExpBuffer (sql ,"REVOKE ALL ON %s %s FROM %s;\n" ,
262+ appendPQExpBuffer (firstsql ,"REVOKE ALL ON %s %s FROM %s;\n" ,
247263type ,name ,
248264fmtId (grantee -> data ));
249265if (privs -> len > 0 )
250- appendPQExpBuffer (sql ,"GRANT %s ON %s %s TO %s;\n" ,
266+ appendPQExpBuffer (firstsql ,"GRANT %s ON %s %s TO %s;\n" ,
251267privs -> data ,type ,name ,
252268fmtId (grantee -> data ));
253269if (privswgo -> len > 0 )
254- appendPQExpBuffer (sql ,"GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n" ,
270+ appendPQExpBuffer (firstsql ,"GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n" ,
255271privswgo -> data ,type ,name ,
256272fmtId (grantee -> data ));
257273}
@@ -261,48 +277,44 @@ buildACLCommands(const char *name, const char *type,
261277/*
262278 * Otherwise can assume we are starting from no privs.
263279 */
280+ if (grantor -> len > 0
281+ && (!owner || strcmp (owner ,grantor -> data )!= 0 ))
282+ appendPQExpBuffer (secondsql ,"SET SESSION AUTHORIZATION %s;\n" ,
283+ fmtId (grantor -> data ));
284+
264285if (privs -> len > 0 )
265286{
266- appendPQExpBuffer (sql ,"GRANT %s ON %s %s TO " ,
287+ appendPQExpBuffer (secondsql ,"GRANT %s ON %s %s TO " ,
267288privs -> data ,type ,name );
268289if (grantee -> len == 0 )
269- appendPQExpBuffer (sql ,"PUBLIC;\n" );
290+ appendPQExpBuffer (secondsql ,"PUBLIC;\n" );
270291else if (strncmp (grantee -> data ,"group " ,
271292strlen ("group " ))== 0 )
272- appendPQExpBuffer (sql ,"GROUP %s;\n" ,
293+ appendPQExpBuffer (secondsql ,"GROUP %s;\n" ,
273294fmtId (grantee -> data + strlen ("group " )));
274295else
275- appendPQExpBuffer (sql ,"%s;\n" ,fmtId (grantee -> data ));
296+ appendPQExpBuffer (secondsql ,"%s;\n" ,fmtId (grantee -> data ));
276297}
277298if (privswgo -> len > 0 )
278299{
279- appendPQExpBuffer (sql ,"GRANT %s ON %s %s TO " ,
300+ appendPQExpBuffer (secondsql ,"GRANT %s ON %s %s TO " ,
280301privswgo -> data ,type ,name );
281302if (grantee -> len == 0 )
282- appendPQExpBuffer (sql ,"PUBLIC" );
303+ appendPQExpBuffer (secondsql ,"PUBLIC" );
283304else if (strncmp (grantee -> data ,"group " ,
284305strlen ("group " ))== 0 )
285- appendPQExpBuffer (sql ,"GROUP %s" ,
306+ appendPQExpBuffer (secondsql ,"GROUP %s" ,
286307fmtId (grantee -> data + strlen ("group " )));
287308else
288- appendPQExpBuffer (sql ,"%s" ,fmtId (grantee -> data ));
289- appendPQExpBuffer (sql ," WITH GRANT OPTION;\n" );
309+ appendPQExpBuffer (secondsql ,"%s" ,fmtId (grantee -> data ));
310+ appendPQExpBuffer (secondsql ," WITH GRANT OPTION;\n" );
290311}
312+
313+ if (grantor -> len > 0
314+ && (!owner || strcmp (owner ,grantor -> data )!= 0 ))
315+ appendPQExpBuffer (secondsql ,"RESET SESSION AUTHORIZATION;\n" );
291316}
292317}
293- else
294- {
295- /* No privileges. Issue explicit REVOKE for safety. */
296- if (grantee -> len == 0 )
297- ;/* Empty left-hand side means "PUBLIC"; already did it */
298- else if (strncmp (grantee -> data ,"group " ,strlen ("group " ))== 0 )
299- appendPQExpBuffer (sql ,"REVOKE ALL ON %s %s FROM GROUP %s;\n" ,
300- type ,name ,
301- fmtId (grantee -> data + strlen ("group " )));
302- else
303- appendPQExpBuffer (sql ,"REVOKE ALL ON %s %s FROM %s;\n" ,
304- type ,name ,fmtId (grantee -> data ));
305- }
306318}
307319
308320/*
@@ -311,7 +323,7 @@ buildACLCommands(const char *name, const char *type,
311323 */
312324if (!found_owner_privs && owner )
313325{
314- appendPQExpBuffer (sql ,"REVOKE ALL ON %s %s FROM %s;\n" ,
326+ appendPQExpBuffer (firstsql ,"REVOKE ALL ON %s %s FROM %s;\n" ,
315327type ,name ,fmtId (owner ));
316328}
317329
@@ -321,6 +333,10 @@ buildACLCommands(const char *name, const char *type,
321333destroyPQExpBuffer (privs );
322334destroyPQExpBuffer (privswgo );
323335
336+ appendPQExpBuffer (sql ,"%s%s" ,firstsql -> data ,secondsql -> data );
337+ destroyPQExpBuffer (firstsql );
338+ destroyPQExpBuffer (secondsql );
339+
324340return true;
325341}
326342