Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdf1df6b

Browse files
committed
Cause pg_dumpall to include GRANT/REVOKE for database-level permissions
in its output. Make it work with server versions back to 7.0, too.
1 parentd24d75f commitdf1df6b

File tree

4 files changed

+405
-289
lines changed

4 files changed

+405
-289
lines changed

‎src/bin/pg_dump/dumputils.c

Lines changed: 304 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/*-------------------------------------------------------------------------
22
*
33
* Utility routines for SQL dumping
4+
*Basically this is stuff that is useful in both pg_dump and pg_dumpall.
5+
*
46
*
57
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
68
* Portions Copyright (c) 1994, Regents of the University of California
79
*
8-
*
9-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.3 2002/09/07 16:14:33 petere Exp $
10+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.4 2003/05/30 22:55:15 tgl Exp $
1011
*
1112
*-------------------------------------------------------------------------
1213
*/
@@ -18,6 +19,12 @@
1819
#include"parser/keywords.h"
1920

2021

22+
staticboolparseAclItem(constchar*item,constchar*type,constchar*name,
23+
intremoteVersion,
24+
PQExpBuffergrantee,PQExpBuffergrantor,
25+
PQExpBufferprivs,PQExpBufferprivswgo);
26+
staticvoidAddAcl(PQExpBufferaclbuf,constchar*keyword);
27+
2128

2229
/*
2330
*Quotes input string if it's not a legitimate SQL identifier as-is.
@@ -89,7 +96,6 @@ fmtId(const char *rawid)
8996
}
9097

9198

92-
9399
/*
94100
* Convert a string value to an SQL string literal and append it to
95101
* the given buffer.
@@ -133,7 +139,9 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
133139
}
134140

135141

136-
142+
/*
143+
* Convert backend's version string into a number.
144+
*/
137145
int
138146
parse_version(constchar*versionString)
139147
{
@@ -152,3 +160,295 @@ parse_version(const char *versionString)
152160

153161
return (100*vmaj+vmin)*100+vrev;
154162
}
163+
164+
165+
/*
166+
* Build GRANT/REVOKE command(s) for an object.
167+
*
168+
*name: the object name, in the form to use in the commands (already quoted)
169+
*type: the object type (as seen in GRANT command: must be one of
170+
*TABLE, FUNCTION, LANGUAGE, or SCHEMA, or DATABASE)
171+
*acls: the ACL string fetched from the database
172+
*owner: username of object owner (will be passed through fmtId), or NULL
173+
*remoteVersion: version of database
174+
*
175+
* Returns TRUE if okay, FALSE if could not parse the acl string.
176+
* The resulting commands (if any) are appended to the contents of 'sql'.
177+
*
178+
* Note: beware of passing fmtId() result as 'name', since this routine
179+
* uses fmtId() internally.
180+
*/
181+
bool
182+
buildACLCommands(constchar*name,constchar*type,
183+
constchar*acls,constchar*owner,
184+
intremoteVersion,
185+
PQExpBuffersql)
186+
{
187+
char*aclbuf,
188+
*tok;
189+
PQExpBuffergrantee,grantor,privs,privswgo;
190+
boolfound_owner_privs= false;
191+
192+
if (strlen(acls)==0)
193+
return true;/* object has default permissions */
194+
195+
grantee=createPQExpBuffer();
196+
grantor=createPQExpBuffer();
197+
privs=createPQExpBuffer();
198+
privswgo=createPQExpBuffer();
199+
200+
/*
201+
* Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
202+
* wire-in knowledge about the default public privileges for different
203+
* kinds of objects.
204+
*/
205+
appendPQExpBuffer(sql,"REVOKE ALL ON %s %s FROM PUBLIC;\n",
206+
type,name);
207+
208+
/* Make a working copy of acls so we can use strtok */
209+
aclbuf=strdup(acls);
210+
211+
/* Scan comma-separated ACL items */
212+
for (tok=strtok(aclbuf,",");tok!=NULL;tok=strtok(NULL,","))
213+
{
214+
size_ttoklen;
215+
216+
/*
217+
* Token may start with '{' and/or '"'. Actually only the start
218+
* of the string should have '{', but we don't verify that.
219+
*/
220+
if (*tok=='{')
221+
tok++;
222+
if (*tok=='"')
223+
tok++;
224+
toklen=strlen(tok);
225+
while (toklen >=0&& (tok[toklen-1]=='"'||tok[toklen-1]=='}'))
226+
tok[toklen---1]='\0';
227+
228+
if (!parseAclItem(tok,type,name,remoteVersion,
229+
grantee,grantor,privs,privswgo))
230+
return false;
231+
232+
if (grantor->len==0&&owner)
233+
printfPQExpBuffer(grantor,"%s",owner);
234+
235+
if (privs->len>0||privswgo->len>0)
236+
{
237+
if (owner&&strcmp(grantee->data,owner)==0)
238+
{
239+
/*
240+
* For the owner, the default privilege level is
241+
* ALL WITH GRANT OPTION.
242+
*/
243+
found_owner_privs= true;
244+
if (strcmp(privswgo->data,"ALL")!=0)
245+
{
246+
appendPQExpBuffer(sql,"REVOKE ALL ON %s %s FROM %s;\n",
247+
type,name,
248+
fmtId(grantee->data));
249+
if (privs->len>0)
250+
appendPQExpBuffer(sql,"GRANT %s ON %s %s TO %s;\n",
251+
privs->data,type,name,
252+
fmtId(grantee->data));
253+
if (privswgo->len>0)
254+
appendPQExpBuffer(sql,"GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
255+
privswgo->data,type,name,
256+
fmtId(grantee->data));
257+
}
258+
}
259+
else
260+
{
261+
/*
262+
* Otherwise can assume we are starting from no privs.
263+
*/
264+
if (privs->len>0)
265+
{
266+
appendPQExpBuffer(sql,"GRANT %s ON %s %s TO ",
267+
privs->data,type,name);
268+
if (grantee->len==0)
269+
appendPQExpBuffer(sql,"PUBLIC;\n");
270+
elseif (strncmp(grantee->data,"group ",
271+
strlen("group "))==0)
272+
appendPQExpBuffer(sql,"GROUP %s;\n",
273+
fmtId(grantee->data+strlen("group ")));
274+
else
275+
appendPQExpBuffer(sql,"%s;\n",fmtId(grantee->data));
276+
}
277+
if (privswgo->len>0)
278+
{
279+
appendPQExpBuffer(sql,"GRANT %s ON %s %s TO ",
280+
privswgo->data,type,name);
281+
if (grantee->len==0)
282+
appendPQExpBuffer(sql,"PUBLIC");
283+
elseif (strncmp(grantee->data,"group ",
284+
strlen("group "))==0)
285+
appendPQExpBuffer(sql,"GROUP %s",
286+
fmtId(grantee->data+strlen("group ")));
287+
else
288+
appendPQExpBuffer(sql,"%s",fmtId(grantee->data));
289+
appendPQExpBuffer(sql," WITH GRANT OPTION;\n");
290+
}
291+
}
292+
}
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+
elseif (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+
}
306+
}
307+
308+
/*
309+
* If we didn't find any owner privs, the owner must have revoked 'em
310+
* all
311+
*/
312+
if (!found_owner_privs&&owner)
313+
{
314+
appendPQExpBuffer(sql,"REVOKE ALL ON %s %s FROM %s;\n",
315+
type,name,fmtId(owner));
316+
}
317+
318+
free(aclbuf);
319+
destroyPQExpBuffer(grantee);
320+
destroyPQExpBuffer(grantor);
321+
destroyPQExpBuffer(privs);
322+
destroyPQExpBuffer(privswgo);
323+
324+
return true;
325+
}
326+
327+
328+
/*
329+
* This will take an aclitem string of privilege code letters and
330+
* parse it into grantee, grantor, and privilege information. The
331+
* privilege information is split between privileges with grant option
332+
* (privswgo) and without (privs).
333+
*
334+
* Note: for cross-version compatibility, it's important to use ALL when
335+
* appropriate.
336+
*/
337+
staticbool
338+
parseAclItem(constchar*item,constchar*type,constchar*name,
339+
intremoteVersion,
340+
PQExpBuffergrantee,PQExpBuffergrantor,
341+
PQExpBufferprivs,PQExpBufferprivswgo)
342+
{
343+
char*buf;
344+
boolall_with_go= true;
345+
boolall_without_go= true;
346+
char*eqpos;
347+
char*slpos;
348+
char*pos;
349+
350+
buf=strdup(item);
351+
352+
/* user name is string up to = */
353+
eqpos=strchr(buf,'=');
354+
if (!eqpos)
355+
return false;
356+
*eqpos='\0';
357+
printfPQExpBuffer(grantee,"%s",buf);
358+
359+
/* grantor may be listed after / */
360+
slpos=strchr(eqpos+1,'/');
361+
if (slpos)
362+
{
363+
*slpos='\0';
364+
printfPQExpBuffer(grantor,"%s",slpos+1);
365+
}
366+
else
367+
resetPQExpBuffer(grantor);
368+
369+
/* privilege codes */
370+
#defineCONVERT_PRIV(code,keywd) \
371+
if ((pos = strchr(eqpos + 1, code))) \
372+
{ \
373+
if (*(pos + 1) == '*') \
374+
{ \
375+
AddAcl(privswgo, keywd); \
376+
all_without_go = false; \
377+
} \
378+
else \
379+
{ \
380+
AddAcl(privs, keywd); \
381+
all_with_go = false; \
382+
} \
383+
} \
384+
else \
385+
all_with_go = all_without_go = false
386+
387+
resetPQExpBuffer(privs);
388+
resetPQExpBuffer(privswgo);
389+
390+
if (strcmp(type,"TABLE")==0)
391+
{
392+
CONVERT_PRIV('a',"INSERT");
393+
CONVERT_PRIV('r',"SELECT");
394+
CONVERT_PRIV('R',"RULE");
395+
396+
if (remoteVersion >=70200)
397+
{
398+
CONVERT_PRIV('w',"UPDATE");
399+
CONVERT_PRIV('d',"DELETE");
400+
CONVERT_PRIV('x',"REFERENCES");
401+
CONVERT_PRIV('t',"TRIGGER");
402+
}
403+
else
404+
{
405+
/* 7.0 and 7.1 have a simpler worldview */
406+
CONVERT_PRIV('w',"UPDATE,DELETE");
407+
}
408+
}
409+
elseif (strcmp(type,"FUNCTION")==0)
410+
CONVERT_PRIV('X',"EXECUTE");
411+
elseif (strcmp(type,"LANGUAGE")==0)
412+
CONVERT_PRIV('U',"USAGE");
413+
elseif (strcmp(type,"SCHEMA")==0)
414+
{
415+
CONVERT_PRIV('C',"CREATE");
416+
CONVERT_PRIV('U',"USAGE");
417+
}
418+
elseif (strcmp(type,"DATABASE")==0)
419+
{
420+
CONVERT_PRIV('C',"CREATE");
421+
CONVERT_PRIV('T',"TEMPORARY");
422+
}
423+
else
424+
abort();
425+
426+
#undef CONVERT_PRIV
427+
428+
if (all_with_go)
429+
{
430+
resetPQExpBuffer(privs);
431+
printfPQExpBuffer(privswgo,"ALL");
432+
}
433+
elseif (all_without_go)
434+
{
435+
resetPQExpBuffer(privswgo);
436+
printfPQExpBuffer(privs,"ALL");
437+
}
438+
439+
free(buf);
440+
441+
return true;
442+
}
443+
444+
445+
/*
446+
* Append a privilege keyword to a keyword list, inserting comma if needed.
447+
*/
448+
staticvoid
449+
AddAcl(PQExpBufferaclbuf,constchar*keyword)
450+
{
451+
if (aclbuf->len>0)
452+
appendPQExpBufferChar(aclbuf,',');
453+
appendPQExpBuffer(aclbuf,"%s",keyword);
454+
}

‎src/bin/pg_dump/dumputils.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
/*-------------------------------------------------------------------------
22
*
33
* Utility routines for SQL dumping
4+
*Basically this is stuff that is useful in both pg_dump and pg_dumpall.
5+
*
46
*
57
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
68
* Portions Copyright (c) 1994, Regents of the University of California
79
*
8-
*
9-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v 1.4 2002/09/07 16:14:33 petere Exp $
10+
* $Id: dumputils.h,v 1.5 2003/05/30 22:55:15 tgl Exp $
1011
*
1112
*-------------------------------------------------------------------------
1213
*/
1314

1415
#ifndefDUMPUTILS_H
1516
#defineDUMPUTILS_H
1617

17-
#include"postgres_fe.h"
18-
1918
#include"pqexpbuffer.h"
2019

20+
2121
externchar*simple_prompt(constchar*prompt,intmaxlen,boolecho);
2222

2323
externconstchar*fmtId(constchar*identifier);
24-
externvoidappendStringLiteral(PQExpBufferbuf,constchar*str,boolescapeAll);
24+
externvoidappendStringLiteral(PQExpBufferbuf,constchar*str,
25+
boolescapeAll);
2526
externintparse_version(constchar*versionString);
27+
externboolbuildACLCommands(constchar*name,constchar*type,
28+
constchar*acls,constchar*owner,
29+
intremoteVersion,
30+
PQExpBuffersql);
2631

2732
#endif/* DUMPUTILS_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp