diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-07-07 20:40:02 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-07-07 20:40:02 +0000 |
commit | 59d1b3d99e690734fa2a2bd0fae12b0cb1084294 (patch) | |
tree | ff074126ccc1a6342de38737d79e218f22fb9be4 /src/backend/utils/adt/acl.c | |
parent | 442b59dd8bc4b0efa1d733690f6ba9dae3f61b1f (diff) | |
download | postgresql-59d1b3d99e690734fa2a2bd0fae12b0cb1084294.tar.gz postgresql-59d1b3d99e690734fa2a2bd0fae12b0cb1084294.zip |
Track dependencies on shared objects (which is to say, roles; we already
have adequate mechanisms for tracking the contents of databases and
tablespaces). This solves the longstanding problem that you can drop a
user who still owns objects and/or has access permissions.
Alvaro Herrera, with some kibitzing from Tom Lane.
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r-- | src/backend/utils/adt/acl.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 5b65099696e..a416def8155 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.117 2005/06/29 20:34:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.118 2005/07/07 20:39:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -59,6 +59,7 @@ static void check_circularity(const Acl *old_acl, const AclItem *mod_aip, Oid ownerId); static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs, Oid ownerId, DropBehavior behavior); +static int oidComparator(const void *arg1, const void *arg2); static AclMode convert_priv_string(text *priv_type_text); @@ -1053,6 +1054,86 @@ aclmask(const Acl *acl, Oid roleid, Oid ownerId, /* + * aclmembers + * Find out all the roleids mentioned in an Acl. + * Note that we do not distinguish grantors from grantees. + * + * *roleids is set to point to a palloc'd array containing distinct OIDs + * in sorted order. The length of the array is the function result. + */ +int +aclmembers(const Acl *acl, Oid **roleids) +{ + Oid *list; + const AclItem *acldat; + int i, + j, + k; + + if (acl == NULL || ACL_NUM(acl) == 0) + { + *roleids = NULL; + return 0; + } + + /* Allocate the worst-case space requirement */ + list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid)); + acldat = ACL_DAT(acl); + + /* + * Walk the ACL collecting mentioned RoleIds. + */ + j = 0; + for (i = 0; i < ACL_NUM(acl); i++) + { + const AclItem *ai = &acldat[i]; + + if (ai->ai_grantee != ACL_ID_PUBLIC) + list[j++] = ai->ai_grantee; + /* grantor is currently never PUBLIC, but let's check anyway */ + if (ai->ai_grantor != ACL_ID_PUBLIC) + list[j++] = ai->ai_grantor; + } + + /* Sort the array */ + qsort(list, j, sizeof(Oid), oidComparator); + + /* Remove duplicates from the array */ + k = 0; + for (i = 1; i < j; i++) + { + if (list[k] != list[i]) + list[++k] = list[i]; + } + + /* + * We could repalloc the array down to minimum size, but it's hardly + * worth it since it's only transient memory. + */ + *roleids = list; + + return k + 1; +} + +/* + * oidComparator + * qsort comparison function for Oids + */ +static int +oidComparator(const void *arg1, const void *arg2) +{ + Oid oid1 = * (const Oid *) arg1; + Oid oid2 = * (const Oid *) arg2; + + if (oid1 > oid2) + return 1; + if (oid1 < oid2) + return -1; + return 0; +} + + +/* * aclinsert (exported function) */ Datum |