aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/acl.c734
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c5
-rw-r--r--src/backend/utils/adt/ri_triggers.c6
-rw-r--r--src/backend/utils/adt/ruleutils.c30
-rw-r--r--src/backend/utils/cache/lsyscache.c73
-rw-r--r--src/backend/utils/cache/syscache.c86
-rw-r--r--src/backend/utils/fmgr/fmgr.c6
-rw-r--r--src/backend/utils/init/flatfiles.c544
-rw-r--r--src/backend/utils/init/miscinit.c95
-rw-r--r--src/backend/utils/init/postinit.c32
-rw-r--r--src/backend/utils/misc/guc.c6
-rw-r--r--src/backend/utils/misc/superuser.c62
12 files changed, 817 insertions, 862 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 68b34f3dce5..4d5904b7690 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.114 2005/05/27 00:57:49 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.115 2005/06/28 05:09:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,20 +17,33 @@
#include <ctype.h>
#include "catalog/namespace.h"
-#include "catalog/pg_group.h"
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_auth_members.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/inval.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
#include "utils/syscache.h"
-#define ACL_IDTYPE_GID_KEYWORD "group"
-#define ACL_IDTYPE_UID_KEYWORD "user"
+#define ACL_IDTYPE_ROLE_KEYWORD "role"
+
+/* The rolmemcache is a possibly-empty list of role OIDs.
+ * rolmemRole is the Role for which the cache was generated.
+ * In the event of a Role change the cache will be regenerated.
+ */
+static List *rolmemcache = NIL;
+static Oid rolmemRole = InvalidOid;
+
+/* rolmemcache and rolmemRole only valid when
+ * rolmemcacheValid is true */
+static bool rolmemcacheValid = false;
static const char *getid(const char *s, char *n);
static void putid(char *p, const char *s);
@@ -38,10 +51,9 @@ static Acl *allocacl(int n);
static const char *aclparse(const char *s, AclItem *aip);
static bool aclitem_match(const AclItem *a1, const AclItem *a2);
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
- AclId ownerid);
-static Acl *recursive_revoke(Acl *acl, AclId grantee, AclMode revoke_privs,
- AclId ownerid, DropBehavior behavior);
-static bool in_group(AclId uid, AclId gid);
+ Oid ownerId);
+static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
+ Oid ownerId, DropBehavior behavior);
static AclMode convert_priv_string(text *priv_type_text);
@@ -58,6 +70,9 @@ static AclMode convert_schema_priv_string(text *priv_type_text);
static Oid convert_tablespace_name(text *tablespacename);
static AclMode convert_tablespace_priv_string(text *priv_type_text);
+static void RolMemCacheCallback(Datum arg, Oid relid);
+static void recomputeRolMemCache(Oid roleid);
+
/*
* getid
@@ -175,7 +190,6 @@ aclparse(const char *s, AclItem *aip)
AclMode privs,
goption,
read;
- uint32 idtype;
char name[NAMEDATALEN];
char name2[NAMEDATALEN];
@@ -184,27 +198,22 @@ aclparse(const char *s, AclItem *aip)
#ifdef ACLDEBUG
elog(LOG, "aclparse: input = \"%s\"", s);
#endif
- idtype = ACL_IDTYPE_UID;
s = getid(s, name);
if (*s != '=')
{
/* we just read a keyword, not a name */
- if (strcmp(name, ACL_IDTYPE_GID_KEYWORD) == 0)
- idtype = ACL_IDTYPE_GID;
- else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD) != 0)
+ if (strcmp(name, ACL_IDTYPE_ROLE_KEYWORD) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("unrecognized key word: \"%s\"", name),
- errhint("ACL key word must be \"group\" or \"user\".")));
+ errhint("ACL key word must be \"role\".")));
s = getid(s, name); /* move s to the name beyond the keyword */
if (name[0] == '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing name"),
- errhint("A name must follow the \"group\" or \"user\" key word.")));
+ errhint("A name must follow the \"role\" key word.")));
}
- if (name[0] == '\0')
- idtype = ACL_IDTYPE_WORLD;
if (*s != '=')
ereport(ERROR,
@@ -263,18 +272,10 @@ aclparse(const char *s, AclItem *aip)
privs |= read;
}
- switch (idtype)
- {
- case ACL_IDTYPE_UID:
- aip->ai_grantee = get_usesysid(name);
- break;
- case ACL_IDTYPE_GID:
- aip->ai_grantee = get_grosysid(name);
- break;
- case ACL_IDTYPE_WORLD:
- aip->ai_grantee = ACL_ID_WORLD;
- break;
- }
+ if (name[0] == '\0')
+ aip->ai_grantee = ACL_ID_PUBLIC;
+ else
+ aip->ai_grantee = get_roleid_checked(name);
/*
* XXX Allow a degree of backward compatibility by defaulting the
@@ -287,23 +288,24 @@ aclparse(const char *s, AclItem *aip)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("a name must follow the \"/\" sign")));
-
- aip->ai_grantor = get_usesysid(name2);
+ aip->ai_grantor = get_roleid_checked(name2);
}
else
{
- aip->ai_grantor = BOOTSTRAP_USESYSID;
+ aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
ereport(WARNING,
(errcode(ERRCODE_INVALID_GRANTOR),
- errmsg("defaulting grantor to user ID %u", BOOTSTRAP_USESYSID)));
+ errmsg("defaulting grantor to user ID %u",
+ BOOTSTRAP_SUPERUSERID)));
}
- ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, goption, idtype);
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, privs, goption);
#ifdef ACLDEBUG
- elog(LOG, "aclparse: correctly read [%x %d %x]",
- idtype, aip->ai_grantee, privs);
+ elog(LOG, "aclparse: correctly read [%u %x %x]",
+ aip->ai_grantee, privs, goption);
#endif
+
return s;
}
@@ -375,7 +377,6 @@ aclitemout(PG_FUNCTION_ARGS)
char *out;
HeapTuple htup;
unsigned i;
- char *tmpname;
out = palloc(strlen("group =/") +
2 * N_ACL_RIGHTS +
@@ -385,41 +386,21 @@ aclitemout(PG_FUNCTION_ARGS)
p = out;
*p = '\0';
- switch (ACLITEM_GET_IDTYPE(*aip))
+ if (aip->ai_grantee != ACL_ID_PUBLIC)
{
- case ACL_IDTYPE_UID:
- htup = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(aip->ai_grantee),
- 0, 0, 0);
- if (HeapTupleIsValid(htup))
- {
- putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
- ReleaseSysCache(htup);
- }
- else
- {
- /* Generate numeric UID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantee);
- }
- break;
- case ACL_IDTYPE_GID:
- strcpy(p, "group ");
- p += strlen(p);
- tmpname = get_groname(aip->ai_grantee);
- if (tmpname != NULL)
- putid(p, tmpname);
- else
- {
- /* Generate numeric GID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantee);
- }
- break;
- case ACL_IDTYPE_WORLD:
- break;
- default:
- elog(ERROR, "unrecognized idtype: %d",
- (int) ACLITEM_GET_IDTYPE(*aip));
- break;
+ htup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(aip->ai_grantee),
+ 0, 0, 0);
+ if (HeapTupleIsValid(htup))
+ {
+ putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
+ ReleaseSysCache(htup);
+ }
+ else
+ {
+ /* Generate numeric OID if we don't find an entry */
+ sprintf(p, "%u", aip->ai_grantee);
+ }
}
while (*p)
++p;
@@ -437,18 +418,18 @@ aclitemout(PG_FUNCTION_ARGS)
*p++ = '/';
*p = '\0';
- htup = SearchSysCache(SHADOWSYSID,
+ htup = SearchSysCache(AUTHOID,
ObjectIdGetDatum(aip->ai_grantor),
0, 0, 0);
if (HeapTupleIsValid(htup))
{
- putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
+ putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
ReleaseSysCache(htup);
}
else
{
- /* Generate numeric UID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantor);
+ /* Generate numeric OID if we don't find an entry */
+ sprintf(p, "%u", aip->ai_grantor);
}
while (*p)
@@ -466,8 +447,7 @@ aclitemout(PG_FUNCTION_ARGS)
static bool
aclitem_match(const AclItem *a1, const AclItem *a2)
{
- return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
- a1->ai_grantee == a2->ai_grantee &&
+ return a1->ai_grantee == a2->ai_grantee &&
a1->ai_grantor == a2->ai_grantor;
}
@@ -511,7 +491,7 @@ hash_aclitem(PG_FUNCTION_ARGS)
* newly-created objects (or any object with a NULL acl entry).
*/
Acl *
-acldefault(GrantObjectType objtype, AclId ownerid)
+acldefault(GrantObjectType objtype, Oid ownerId)
{
AclMode world_default;
AclMode owner_default;
@@ -558,10 +538,9 @@ acldefault(GrantObjectType objtype, AclId ownerid)
if (world_default != ACL_NO_RIGHTS)
{
- aip->ai_grantee = ACL_ID_WORLD;
- aip->ai_grantor = ownerid;
- ACLITEM_SET_PRIVS_IDTYPE(*aip, world_default, ACL_NO_RIGHTS,
- ACL_IDTYPE_WORLD);
+ aip->ai_grantee = ACL_ID_PUBLIC;
+ aip->ai_grantor = ownerId;
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
aip++;
}
@@ -575,10 +554,9 @@ acldefault(GrantObjectType objtype, AclId ownerid)
* without any explicit "_SYSTEM"-like ACL entry, by internally
* special-casing the owner whereever we are testing grant options.
*/
- aip->ai_grantee = ownerid;
- aip->ai_grantor = ownerid;
- ACLITEM_SET_PRIVS_IDTYPE(*aip, owner_default, ACL_NO_RIGHTS,
- ACL_IDTYPE_UID);
+ aip->ai_grantee = ownerId;
+ aip->ai_grantor = ownerId;
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
return acl;
}
@@ -590,7 +568,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
* old_acl: the input ACL array
* mod_aip: defines the privileges to be added, removed, or substituted
* modechg: ACL_MODECHG_ADD, ACL_MODECHG_DEL, or ACL_MODECHG_EQL
- * ownerid: AclId of object owner
+ * ownerId: Oid of object owner
* behavior: RESTRICT or CASCADE behavior for recursive removal
*
* ownerid and behavior are only relevant when the update operation specifies
@@ -602,7 +580,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
*/
Acl *
aclupdate(const Acl *old_acl, const AclItem *mod_aip,
- int modechg, AclId ownerid, DropBehavior behavior)
+ int modechg, Oid ownerId, DropBehavior behavior)
{
Acl *new_acl = NULL;
AclItem *old_aip,
@@ -627,7 +605,7 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/* If granting grant options, check for circularity */
if (modechg != ACL_MODECHG_DEL &&
ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
- check_circularity(old_acl, mod_aip, ownerid);
+ check_circularity(old_acl, mod_aip, ownerId);
num = ACL_NUM(old_acl);
old_aip = ACL_DAT(old_acl);
@@ -661,9 +639,8 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/* initialize the new entry with no permissions */
new_aip[dst].ai_grantee = mod_aip->ai_grantee;
new_aip[dst].ai_grantor = mod_aip->ai_grantor;
- ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
- ACL_NO_RIGHTS, ACL_NO_RIGHTS,
- ACLITEM_GET_IDTYPE(*mod_aip));
+ ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
+ ACL_NO_RIGHTS, ACL_NO_RIGHTS);
num++; /* set num to the size of new_acl */
}
@@ -704,14 +681,14 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/*
* Remove abandoned privileges (cascading revoke). Currently we can
- * only handle this when the grantee is a user.
+ * only handle this when the grantee is not PUBLIC.
*/
if ((old_goptions & ~new_goptions) != 0)
{
- Assert(ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID);
+ Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
(old_goptions & ~new_goptions),
- ownerid, behavior);
+ ownerId, behavior);
}
return new_acl;
@@ -721,15 +698,15 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
* Update an ACL array to reflect a change of owner to the parent object
*
* old_acl: the input ACL array (must not be NULL)
- * oldownerid: AclId of the old object owner
- * newownerid: AclId of the new object owner
+ * oldOwnerId: Oid of the old object owner
+ * newOwnerId: Oid of the new object owner
*
* The result is a modified copy; the input object is not changed.
*
* NB: caller is responsible for having detoasted the input ACL, if needed.
*/
Acl *
-aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
+aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
{
Acl *new_acl;
AclItem *new_aip;
@@ -755,18 +732,14 @@ aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
memcpy(new_aip, old_aip, num * sizeof(AclItem));
for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
{
- /* grantor is always a UID, but grantee might not be */
- if (dst_aip->ai_grantor == oldownerid)
- dst_aip->ai_grantor = newownerid;
- else if (dst_aip->ai_grantor == newownerid)
+ if (dst_aip->ai_grantor == oldOwnerId)
+ dst_aip->ai_grantor = newOwnerId;
+ else if (dst_aip->ai_grantor == newOwnerId)
+ newpresent = true;
+ if (dst_aip->ai_grantee == oldOwnerId)
+ dst_aip->ai_grantee = newOwnerId;
+ else if (dst_aip->ai_grantee == newOwnerId)
newpresent = true;
- if (ACLITEM_GET_IDTYPE(*dst_aip) == ACL_IDTYPE_UID)
- {
- if (dst_aip->ai_grantee == oldownerid)
- dst_aip->ai_grantee = newownerid;
- else if (dst_aip->ai_grantee == newownerid)
- newpresent = true;
- }
}
/*
@@ -836,7 +809,7 @@ aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
*/
static void
check_circularity(const Acl *old_acl, const AclItem *mod_aip,
- AclId ownerid)
+ Oid ownerId)
{
Acl *acl;
AclItem *aip;
@@ -845,13 +818,13 @@ check_circularity(const Acl *old_acl, const AclItem *mod_aip,
AclMode own_privs;
/*
- * For now, grant options can only be granted to users, not groups or
- * PUBLIC. Otherwise we'd have to work a bit harder here.
+ * For now, grant options can only be granted to roles, not PUBLIC.
+ * Otherwise we'd have to work a bit harder here.
*/
- Assert(ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID);
+ Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
/* The owner always has grant options, no need to check */
- if (mod_aip->ai_grantor == ownerid)
+ if (mod_aip->ai_grantor == ownerId)
return;
/* Make a working copy */
@@ -864,15 +837,14 @@ cc_restart:
aip = ACL_DAT(acl);
for (i = 0; i < num; i++)
{
- if (ACLITEM_GET_IDTYPE(aip[i]) == ACL_IDTYPE_UID &&
- aip[i].ai_grantee == mod_aip->ai_grantee &&
+ if (aip[i].ai_grantee == mod_aip->ai_grantee &&
ACLITEM_GET_GOPTIONS(aip[i]) != ACL_NO_RIGHTS)
{
Acl *new_acl;
/* We'll actually zap ordinary privs too, but no matter */
new_acl = aclupdate(acl, &aip[i], ACL_MODECHG_DEL,
- ownerid, DROP_CASCADE);
+ ownerId, DROP_CASCADE);
pfree(acl);
acl = new_acl;
@@ -884,7 +856,7 @@ cc_restart:
/* Now we can compute grantor's independently-derived privileges */
own_privs = aclmask(acl,
mod_aip->ai_grantor,
- ownerid,
+ ownerId,
ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
ACLMASK_ALL);
own_privs = ACL_OPTION_TO_PRIVS(own_privs);
@@ -908,16 +880,16 @@ cc_restart:
* acl: the input ACL list
* grantee: the user from whom some grant options have been revoked
* revoke_privs: the grant options being revoked
- * ownerid: AclId of object owner
+ * ownerId: Oid of object owner
* behavior: RESTRICT or CASCADE behavior for recursive removal
*
* The input Acl object is pfree'd if replaced.
*/
static Acl *
recursive_revoke(Acl *acl,
- AclId grantee,
+ Oid grantee,
AclMode revoke_privs,
- AclId ownerid,
+ Oid ownerId,
DropBehavior behavior)
{
AclMode still_has;
@@ -926,11 +898,11 @@ recursive_revoke(Acl *acl,
num;
/* The owner can never truly lose grant options, so short-circuit */
- if (grantee == ownerid)
+ if (grantee == ownerId)
return acl;
/* The grantee might still have the privileges via another grantor */
- still_has = aclmask(acl, grantee, ownerid,
+ still_has = aclmask(acl, grantee, ownerId,
ACL_GRANT_OPTION_FOR(revoke_privs),
ACLMASK_ALL);
revoke_privs &= ~still_has;
@@ -956,13 +928,12 @@ restart:
mod_acl.ai_grantor = grantee;
mod_acl.ai_grantee = aip[i].ai_grantee;
- ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
- revoke_privs,
- revoke_privs,
- ACLITEM_GET_IDTYPE(aip[i]));
+ ACLITEM_SET_PRIVS_GOPTIONS(mod_acl,
+ revoke_privs,
+ revoke_privs);
new_acl = aclupdate(acl, &mod_acl, ACL_MODECHG_DEL,
- ownerid, behavior);
+ ownerId, behavior);
pfree(acl);
acl = new_acl;
@@ -976,10 +947,10 @@ restart:
/*
- * aclmask --- compute bitmask of all privileges held by userid.
+ * aclmask --- compute bitmask of all privileges held by roleid.
*
* When 'how' = ACLMASK_ALL, this simply returns the privilege bits
- * held by the given userid according to the given ACL list, ANDed
+ * held by the given roleid according to the given ACL list, ANDed
* with 'mask'. (The point of passing 'mask' is to let the routine
* exit early if all privileges of interest have been found.)
*
@@ -990,20 +961,20 @@ restart:
* Usage patterns:
*
* To see if any of a set of privileges are held:
- * if (aclmask(acl, userid, ownerid, privs, ACLMASK_ANY) != 0)
+ * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ANY) != 0)
*
* To see if all of a set of privileges are held:
- * if (aclmask(acl, userid, ownerid, privs, ACLMASK_ALL) == privs)
+ * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL) == privs)
*
* To determine exactly which of a set of privileges are held:
- * heldprivs = aclmask(acl, userid, ownerid, privs, ACLMASK_ALL);
+ * heldprivs = aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL);
+ *
*/
AclMode
-aclmask(const Acl *acl, AclId userid, AclId ownerid,
+aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how)
{
AclMode result;
- AclMode remaining;
AclItem *aidat;
int i,
num;
@@ -1022,7 +993,7 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
result = 0;
/* Owner always implicitly has all grant options */
- if (userid == ownerid)
+ if (is_member_of_role(roleid,ownerId))
{
result = mask & ACLITEM_ALL_GOPTION_BITS;
if (result == mask)
@@ -1033,39 +1004,19 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
aidat = ACL_DAT(acl);
/*
- * Check privileges granted directly to user or to public
- */
- for (i = 0; i < num; i++)
- {
- AclItem *aidata = &aidat[i];
-
- if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_WORLD
- || (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_UID
- && aidata->ai_grantee == userid))
- {
- result |= (aidata->ai_privs & mask);
- if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
- return result;
- }
- }
-
- /*
- * Check privileges granted via groups. We do this in a separate pass
- * to minimize expensive lookups in pg_group.
+ * Check privileges granted directly to role, indirectly
+ * via role membership or to public
*/
- remaining = (mask & ~result);
for (i = 0; i < num; i++)
{
AclItem *aidata = &aidat[i];
- if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_GID
- && (aidata->ai_privs & remaining)
- && in_group(userid, aidata->ai_grantee))
+ if (aidata->ai_grantee == ACL_ID_PUBLIC ||
+ is_member_of_role(roleid, aidata->ai_grantee))
{
result |= (aidata->ai_privs & mask);
if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
return result;
- remaining = (mask & ~result);
}
}
@@ -1074,55 +1025,19 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
/*
- * Is user a member of group?
+ * Is member a member of role?
+ * relmemcache includes the role itself too
*/
-static bool
-in_group(AclId uid, AclId gid)
-{
- bool result = false;
- HeapTuple tuple;
- Datum att;
- bool isNull;
- IdList *glist;
- AclId *aidp;
- int i,
- num;
+bool
+is_member_of_role(Oid member, Oid role)
+{
+ /* Fast path for simple case */
+ if (member == role)
+ return true;
- tuple = SearchSysCache(GROSYSID,
- ObjectIdGetDatum(gid),
- 0, 0, 0);
- if (HeapTupleIsValid(tuple))
- {
- att = SysCacheGetAttr(GROSYSID,
- tuple,
- Anum_pg_group_grolist,
- &isNull);
- if (!isNull)
- {
- /* be sure the IdList is not toasted */
- glist = DatumGetIdListP(att);
- /* scan it */
- num = IDLIST_NUM(glist);
- aidp = IDLIST_DAT(glist);
- for (i = 0; i < num; ++i)
- {
- if (aidp[i] == uid)
- {
- result = true;
- break;
- }
- }
- /* if IdList was toasted, free detoasted copy */
- if ((Pointer) glist != DatumGetPointer(att))
- pfree(glist);
- }
- ReleaseSysCache(tuple);
- }
- else
- ereport(WARNING,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group with ID %u does not exist", gid)));
- return result;
+ recomputeRolMemCache(member);
+
+ return list_member_oid(rolmemcache, role);
}
@@ -1162,10 +1077,9 @@ aclcontains(PG_FUNCTION_ARGS)
aidat = ACL_DAT(acl);
for (i = 0; i < num; ++i)
{
- if (aip->ai_grantee == aidat[i].ai_grantee
- && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
- && aip->ai_grantor == aidat[i].ai_grantor
- && (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
+ if (aip->ai_grantee == aidat[i].ai_grantee &&
+ aip->ai_grantor == aidat[i].ai_grantor &&
+ (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
PG_RETURN_BOOL(true);
}
PG_RETURN_BOOL(false);
@@ -1174,51 +1088,22 @@ aclcontains(PG_FUNCTION_ARGS)
Datum
makeaclitem(PG_FUNCTION_ARGS)
{
- int32 u_grantee = PG_GETARG_INT32(0);
- int32 g_grantee = PG_GETARG_INT32(1);
- int32 grantor = PG_GETARG_INT32(2);
- text *privtext = PG_GETARG_TEXT_P(3);
- bool goption = PG_GETARG_BOOL(4);
+ Oid grantee = PG_GETARG_OID(0);
+ Oid grantor = PG_GETARG_OID(1);
+ text *privtext = PG_GETARG_TEXT_P(2);
+ bool goption = PG_GETARG_BOOL(3);
AclItem *aclitem;
AclMode priv;
priv = convert_priv_string(privtext);
- aclitem = (AclItem *) palloc(sizeof(*aclitem));
+ aclitem = (AclItem *) palloc(sizeof(AclItem));
- if (u_grantee == 0 && g_grantee == 0)
- {
- aclitem ->ai_grantee = ACL_ID_WORLD;
+ aclitem->ai_grantee = grantee;
+ aclitem->ai_grantor = grantor;
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
- }
- else if (u_grantee != 0 && g_grantee != 0)
- {
- ereport(ERROR,
- (errcode(ERRCODE_DATA_EXCEPTION),
- errmsg("cannot specify both user and group")));
- }
- else if (u_grantee != 0)
- {
- aclitem ->ai_grantee = u_grantee;
-
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
- }
- else
- /* (g_grantee != 0) */
- {
- aclitem ->ai_grantee = g_grantee;
-
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
- }
-
- aclitem ->ai_grantor = grantor;
-
- ACLITEM_SET_PRIVS(*aclitem, priv);
- if (goption)
- ACLITEM_SET_GOPTIONS(*aclitem, priv);
- else
- ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
+ ACLITEM_SET_PRIVS_GOPTIONS(*aclitem, priv,
+ (goption ? priv : ACL_NO_RIGHTS));
PG_RETURN_ACLITEM_P(aclitem);
}
@@ -1267,7 +1152,7 @@ convert_priv_string(text *priv_type_text)
* has_table_privilege variants
* These are all named "has_table_privilege" at the SQL level.
* They take various combinations of relation name, relation OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1281,19 +1166,20 @@ convert_priv_string(text *priv_type_text)
Datum
has_table_privilege_name_name(PG_FUNCTION_ARGS)
{
- Name username = PG_GETARG_NAME(0);
+ Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*rolename));
+
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1309,16 +1195,16 @@ has_table_privilege_name(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1334,14 +1220,15 @@ has_table_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1357,14 +1244,14 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
{
Oid tableoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1372,12 +1259,12 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
/*
* has_table_privilege_id_name
* Check user privileges on a table given
- * usesysid, text tablename, and text priv name.
+ * roleid, text tablename, and text priv name.
*/
Datum
has_table_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid tableoid;
@@ -1387,7 +1274,7 @@ has_table_privilege_id_name(PG_FUNCTION_ARGS)
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1395,12 +1282,12 @@ has_table_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_table_privilege_id_id
* Check user privileges on a table given
- * usesysid, table oid, and text priv name.
+ * roleid, table oid, and text priv name.
*/
Datum
has_table_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1408,7 +1295,7 @@ has_table_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1491,7 +1378,7 @@ convert_table_priv_string(text *priv_type_text)
* has_database_privilege variants
* These are all named "has_database_privilege" at the SQL level.
* They take various combinations of database name, database OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1508,16 +1395,17 @@ has_database_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *databasename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1533,16 +1421,16 @@ has_database_privilege_name(PG_FUNCTION_ARGS)
{
text *databasename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1558,14 +1446,15 @@ has_database_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid databaseoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1581,14 +1470,14 @@ has_database_privilege_id(PG_FUNCTION_ARGS)
{
Oid databaseoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1596,12 +1485,12 @@ has_database_privilege_id(PG_FUNCTION_ARGS)
/*
* has_database_privilege_id_name
* Check user privileges on a database given
- * usesysid, text databasename, and text priv name.
+ * roleid, text databasename, and text priv name.
*/
Datum
has_database_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *databasename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid databaseoid;
@@ -1611,7 +1500,7 @@ has_database_privilege_id_name(PG_FUNCTION_ARGS)
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1619,12 +1508,12 @@ has_database_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_database_privilege_id_id
* Check user privileges on a database given
- * usesysid, database oid, and text priv name.
+ * roleid, database oid, and text priv name.
*/
Datum
has_database_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid databaseoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1632,7 +1521,7 @@ has_database_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1703,7 +1592,7 @@ convert_database_priv_string(text *priv_type_text)
* has_function_privilege variants
* These are all named "has_function_privilege" at the SQL level.
* They take various combinations of function name, function OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1720,16 +1609,17 @@ has_function_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *functionname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1745,16 +1635,16 @@ has_function_privilege_name(PG_FUNCTION_ARGS)
{
text *functionname = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1770,14 +1660,15 @@ has_function_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid functionoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1793,14 +1684,14 @@ has_function_privilege_id(PG_FUNCTION_ARGS)
{
Oid functionoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1808,12 +1699,12 @@ has_function_privilege_id(PG_FUNCTION_ARGS)
/*
* has_function_privilege_id_name
* Check user privileges on a function given
- * usesysid, text functionname, and text priv name.
+ * roleid, text functionname, and text priv name.
*/
Datum
has_function_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *functionname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid functionoid;
@@ -1823,7 +1714,7 @@ has_function_privilege_id_name(PG_FUNCTION_ARGS)
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1831,12 +1722,12 @@ has_function_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_function_privilege_id_id
* Check user privileges on a function given
- * usesysid, function oid, and text priv name.
+ * roleid, function oid, and text priv name.
*/
Datum
has_function_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid functionoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1844,7 +1735,7 @@ has_function_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1907,7 +1798,7 @@ convert_function_priv_string(text *priv_type_text)
* has_language_privilege variants
* These are all named "has_language_privilege" at the SQL level.
* They take various combinations of language name, language OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1924,16 +1815,17 @@ has_language_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *languagename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1949,16 +1841,16 @@ has_language_privilege_name(PG_FUNCTION_ARGS)
{
text *languagename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1974,14 +1866,15 @@ has_language_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid languageoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1997,14 +1890,14 @@ has_language_privilege_id(PG_FUNCTION_ARGS)
{
Oid languageoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2012,12 +1905,12 @@ has_language_privilege_id(PG_FUNCTION_ARGS)
/*
* has_language_privilege_id_name
* Check user privileges on a language given
- * usesysid, text languagename, and text priv name.
+ * roleid, text languagename, and text priv name.
*/
Datum
has_language_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *languagename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid languageoid;
@@ -2027,7 +1920,7 @@ has_language_privilege_id_name(PG_FUNCTION_ARGS)
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2035,12 +1928,12 @@ has_language_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_language_privilege_id_id
* Check user privileges on a language given
- * usesysid, language oid, and text priv name.
+ * roleid, language oid, and text priv name.
*/
Datum
has_language_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid languageoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2048,7 +1941,7 @@ has_language_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2111,7 +2004,7 @@ convert_language_priv_string(text *priv_type_text)
* has_schema_privilege variants
* These are all named "has_schema_privilege" at the SQL level.
* They take various combinations of schema name, schema OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -2128,16 +2021,17 @@ has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *schemaname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2153,16 +2047,16 @@ has_schema_privilege_name(PG_FUNCTION_ARGS)
{
text *schemaname = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2178,14 +2072,15 @@ has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid schemaoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2201,14 +2096,14 @@ has_schema_privilege_id(PG_FUNCTION_ARGS)
{
Oid schemaoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2216,12 +2111,12 @@ has_schema_privilege_id(PG_FUNCTION_ARGS)
/*
* has_schema_privilege_id_name
* Check user privileges on a schema given
- * usesysid, text schemaname, and text priv name.
+ * roleid, text schemaname, and text priv name.
*/
Datum
has_schema_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *schemaname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid schemaoid;
@@ -2231,7 +2126,7 @@ has_schema_privilege_id_name(PG_FUNCTION_ARGS)
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2239,12 +2134,12 @@ has_schema_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_schema_privilege_id_id
* Check user privileges on a schema given
- * usesysid, schema oid, and text priv name.
+ * roleid, schema oid, and text priv name.
*/
Datum
has_schema_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid schemaoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2252,7 +2147,7 @@ has_schema_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2319,7 +2214,7 @@ convert_schema_priv_string(text *priv_type_text)
* has_tablespace_privilege variants
* These are all named "has_tablespace_privilege" at the SQL level.
* They take various combinations of tablespace name, tablespace OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -2336,16 +2231,17 @@ has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *tablespacename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2361,16 +2257,16 @@ has_tablespace_privilege_name(PG_FUNCTION_ARGS)
{
text *tablespacename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2386,14 +2282,15 @@ has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid tablespaceoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2409,14 +2306,14 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
{
Oid tablespaceoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2424,12 +2321,12 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
/*
* has_tablespace_privilege_id_name
* Check user privileges on a tablespace given
- * usesysid, text tablespacename, and text priv name.
+ * roleid, text tablespacename, and text priv name.
*/
Datum
has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *tablespacename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid tablespaceoid;
@@ -2439,7 +2336,7 @@ has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2447,12 +2344,12 @@ has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_tablespace_privilege_id_id
* Check user privileges on a tablespace given
- * usesysid, tablespace oid, and text priv name.
+ * roleid, tablespace oid, and text priv name.
*/
Datum
has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid tablespaceoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2460,7 +2357,7 @@ has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2515,3 +2412,110 @@ convert_tablespace_priv_string(text *priv_type_text)
errmsg("unrecognized privilege type: \"%s\"", priv_type)));
return ACL_NO_RIGHTS; /* keep compiler quiet */
}
+
+void
+InitializeAcl(void)
+{
+ if (!IsBootstrapProcessingMode())
+ {
+ /*
+ * In normal mode, set a callback on any syscache
+ * invalidation of pg_auth_members rows
+ */
+ CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
+ RolMemCacheCallback,
+ (Datum) 0);
+
+ /* Force role/member cache to be recomputed on next use */
+ rolmemcacheValid = false;
+ }
+}
+
+/*
+ * RolMemCacheCallback
+ * Syscache inval callback function
+ */
+static void
+RolMemCacheCallback(Datum arg, Oid relid)
+{
+ /* Force role/member cache to be recomputed on next use */
+ rolmemcacheValid = false;
+}
+
+
+/*
+ * recomputeRolMemCache - recompute the role/member cache if needed
+ */
+static void
+recomputeRolMemCache(Oid roleid)
+{
+ int i;
+ Oid memberOid;
+ List *roles_list_hunt = NIL;
+ List *roles_list = NIL;
+ List *newrolmemcache;
+ CatCList *memlist;
+ MemoryContext oldctx;
+
+ /* Do nothing if rolmemcache is already valid */
+ if (rolmemcacheValid && rolmemRole == roleid)
+ return;
+
+ if (rolmemRole != roleid)
+ rolmemcacheValid = false;
+
+ /*
+ * Find all the roles which this role is a member of,
+ * including multi-level recursion
+ */
+
+ /*
+ * Include the current role itself to simplify checks
+ * later on, also should be at the head so lookup should
+ * be fast.
+ */
+ roles_list = lappend_oid(roles_list, roleid);
+ roles_list_hunt = lappend_oid(roles_list_hunt, roleid);
+
+ while (roles_list_hunt)
+ {
+ memberOid = linitial_oid(roles_list_hunt);
+ memlist = SearchSysCacheList(AUTHMEMMEMROLE, 1,
+ ObjectIdGetDatum(memberOid),
+ 0, 0, 0);
+ for (i = 0; i < memlist->n_members; i++) {
+ HeapTuple roletup = &memlist->members[i]->tuple;
+ Form_pg_auth_members rolemem = (Form_pg_auth_members) GETSTRUCT(roletup);
+
+ if (!list_member_oid(roles_list,rolemem->roleid)) {
+ roles_list = lappend_oid(roles_list,rolemem->roleid);
+ roles_list_hunt = lappend_oid(roles_list_hunt,rolemem->roleid);
+ }
+ }
+ roles_list_hunt = list_delete_oid(roles_list_hunt, memberOid);
+ ReleaseSysCacheList(memlist);
+ }
+
+ /*
+ * Now that we've built the list of role Oids this
+ * role is a member of, save it in permanent storage
+ */
+ oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ newrolmemcache = list_copy(roles_list);
+ MemoryContextSwitchTo(oldctx);
+
+ /*
+ * Now safe to assign to state variable
+ */
+ list_free(rolmemcache);
+ rolmemcache = newrolmemcache;
+
+ /*
+ * Mark as valid
+ */
+ rolmemRole = roleid;
+ rolmemcacheValid = true;
+
+ /* Clean up */
+ list_free(roles_list);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 90c8ea695bb..870513fb9d5 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -8,14 +8,13 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.22 2005/05/11 01:41:41 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.23 2005/06/28 05:09:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xact.h"
-#include "catalog/pg_shadow.h"
#include "fmgr.h"
#include "funcapi.h"
#include "miscadmin.h"
@@ -306,7 +305,7 @@ pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
if (!OidIsValid(beentry->userid))
PG_RETURN_NULL();
- PG_RETURN_INT32(beentry->userid);
+ PG_RETURN_OID(beentry->userid);
}
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index a0d561f1f0f..8de31643a68 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.79 2005/05/30 07:20:58 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.80 2005/06/28 05:09:00 tgl Exp $
*
* ----------
*/
@@ -3036,7 +3036,7 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
{
void *qplan;
Relation query_rel;
- AclId save_uid;
+ Oid save_uid;
/*
* The query is always run against the FK table except when this is an
@@ -3089,7 +3089,7 @@ ri_PerformCheck(RI_QueryKey *qkey, void *qplan,
Snapshot crosscheck_snapshot;
int limit;
int spi_result;
- AclId save_uid;
+ Oid save_uid;
Datum vals[RI_MAX_NUMKEYS * 2];
char nulls[RI_MAX_NUMKEYS * 2];
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 0bd1d73eae1..cbebd5495c0 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.201 2005/06/26 22:05:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.202 2005/06/28 05:09:01 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -46,13 +46,13 @@
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_trigger.h"
#include "executor/spi.h"
#include "funcapi.h"
@@ -1194,17 +1194,17 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
/* ----------
- * get_userbyid - Get a user name by usesysid and
- * fallback to 'unknown (UID=n)'
+ * get_userbyid - Get a user name by roleid and
+ * fallback to 'unknown (OID=n)'
* ----------
*/
Datum
pg_get_userbyid(PG_FUNCTION_ARGS)
{
- int32 uid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Name result;
- HeapTuple usertup;
- Form_pg_shadow user_rec;
+ HeapTuple roletup;
+ Form_pg_authid role_rec;
/*
* Allocate space for the result
@@ -1213,19 +1213,19 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
memset(NameStr(*result), 0, NAMEDATALEN);
/*
- * Get the pg_shadow entry and print the result
+ * Get the pg_authid entry and print the result
*/
- usertup = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(uid),
+ roletup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
- if (HeapTupleIsValid(usertup))
+ if (HeapTupleIsValid(roletup))
{
- user_rec = (Form_pg_shadow) GETSTRUCT(usertup);
- StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);
- ReleaseSysCache(usertup);
+ role_rec = (Form_pg_authid) GETSTRUCT(roletup);
+ StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
+ ReleaseSysCache(roletup);
}
else
- sprintf(NameStr(*result), "unknown (UID=%d)", uid);
+ sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
PG_RETURN_NAME(result);
}
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 5390d94462a..ea10f8c8cd3 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.125 2005/05/01 18:56:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.126 2005/06/28 05:09:01 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -24,8 +24,6 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
-#include "catalog/pg_group.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
@@ -2010,66 +2008,35 @@ get_namespace_name(Oid nspid)
return NULL;
}
-/* ---------- PG_SHADOW CACHE ---------- */
+/* ---------- PG_AUTHID CACHE ---------- */
/*
- * get_usesysid
- *
- * Given a user name, look up the user's sysid.
- * Raises an error if no such user (rather than returning zero,
- * which might possibly be a valid usesysid).
- *
- * Note: the type of usesysid is currently int4, but may change to Oid
- * someday. It'd be reasonable to return zero on failure if we were
- * using Oid ...
+ * get_roleid
+ * Given a role name, look up the role's OID.
+ * Returns InvalidOid if no such role.
*/
-AclId
-get_usesysid(const char *username)
+Oid
+get_roleid(const char *rolname)
{
- AclId userId;
- HeapTuple userTup;
-
- userTup = SearchSysCache(SHADOWNAME,
- PointerGetDatum(username),
- 0, 0, 0);
- if (!HeapTupleIsValid(userTup))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", username)));
-
- userId = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
-
- ReleaseSysCache(userTup);
-
- return userId;
+ return GetSysCacheOid(AUTHNAME,
+ PointerGetDatum(rolname),
+ 0, 0, 0);
}
/*
- * get_grosysid
- *
- * Given a group name, look up the group's sysid.
- * Raises an error if no such group (rather than returning zero,
- * which might possibly be a valid grosysid).
- *
+ * get_roleid_checked
+ * Given a role name, look up the role's OID.
+ * ereports if no such role.
*/
-AclId
-get_grosysid(char *groname)
+Oid
+get_roleid_checked(const char *rolname)
{
- AclId groupId;
- HeapTuple groupTup;
+ Oid roleid;
- groupTup = SearchSysCache(GRONAME,
- PointerGetDatum(groname),
- 0, 0, 0);
- if (!HeapTupleIsValid(groupTup))
+ roleid = get_roleid(rolname);
+ if (!OidIsValid(roleid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group \"%s\" does not exist", groname)));
-
- groupId = ((Form_pg_group) GETSTRUCT(groupTup))->grosysid;
-
- ReleaseSysCache(groupTup);
-
- return groupId;
+ errmsg("role \"%s\" does not exist", rolname)));
+ return roleid;
}
-
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c6cfbc5be24..cd24460857f 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.99 2005/05/11 01:26:02 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.100 2005/06/28 05:09:01 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -27,9 +27,10 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_auth_members.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_conversion.h"
-#include "catalog/pg_group.h"
#include "catalog/pg_index.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_language.h"
@@ -38,7 +39,6 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "utils/catcache.h"
@@ -172,6 +172,46 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
+ {AuthMemRelationId, /* AUTHMEMMEMROLE */
+ AuthMemMemRoleIndexId,
+ 0,
+ 2,
+ {
+ Anum_pg_auth_members_member,
+ Anum_pg_auth_members_roleid,
+ 0,
+ 0
+ }},
+ {AuthMemRelationId, /* AUTHMEMROLEMEM */
+ AuthMemRoleMemIndexId,
+ 0,
+ 2,
+ {
+ Anum_pg_auth_members_roleid,
+ Anum_pg_auth_members_member,
+ 0,
+ 0
+ }},
+ {AuthIdRelationId, /* AUTHNAME */
+ AuthIdRolnameIndexId,
+ 0,
+ 1,
+ {
+ Anum_pg_authid_rolname,
+ 0,
+ 0,
+ 0
+ }},
+ {AuthIdRelationId, /* AUTHOID */
+ AuthIdOidIndexId,
+ 0,
+ 1,
+ {
+ ObjectIdAttributeNumber,
+ 0,
+ 0,
+ 0
+ }},
{
CastRelationId, /* CASTSOURCETARGET */
CastSourceTargetIndexId,
@@ -233,26 +273,6 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
- {GroupRelationId, /* GRONAME */
- GroupNameIndexId,
- 0,
- 1,
- {
- Anum_pg_group_groname,
- 0,
- 0,
- 0
- }},
- {GroupRelationId, /* GROSYSID */
- GroupSysidIndexId,
- 0,
- 1,
- {
- Anum_pg_group_grosysid,
- 0,
- 0,
- 0
- }},
{IndexRelationId, /* INDEXRELID */
IndexRelidIndexId,
Anum_pg_index_indrelid,
@@ -383,26 +403,6 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
- {ShadowRelationId, /* SHADOWNAME */
- ShadowNameIndexId,
- 0,
- 1,
- {
- Anum_pg_shadow_usename,
- 0,
- 0,
- 0
- }},
- {ShadowRelationId, /* SHADOWSYSID */
- ShadowSysidIndexId,
- 0,
- 1,
- {
- Anum_pg_shadow_usesysid,
- 0,
- 0,
- 0
- }},
{StatisticRelationId, /* STATRELATT */
StatisticRelidAttnumIndexId,
Anum_pg_statistic_starelid,
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 0733f190c2b..dd6134ccfd0 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.95 2005/05/29 04:23:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.96 2005/06/28 05:09:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -769,7 +769,7 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
struct fmgr_security_definer_cache
{
FmgrInfo flinfo;
- AclId userid;
+ Oid userid;
};
/*
@@ -786,7 +786,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
Datum result;
FmgrInfo *save_flinfo;
struct fmgr_security_definer_cache * volatile fcache;
- AclId save_userid;
+ Oid save_userid;
HeapTuple tuple;
if (!fcinfo->flinfo->fn_extra)
diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c
index fcbc99189ff..8b129692f45 100644
--- a/src/backend/utils/init/flatfiles.c
+++ b/src/backend/utils/init/flatfiles.c
@@ -4,9 +4,10 @@
* Routines for maintaining "flat file" images of the shared catalogs.
*
* We use flat files so that the postmaster and not-yet-fully-started
- * backends can look at the contents of pg_database, pg_shadow, and pg_group
- * for authentication purposes. This module is responsible for keeping the
- * flat-file images as nearly in sync with database reality as possible.
+ * backends can look at the contents of pg_database, pg_authid, and
+ * pg_auth_members for authentication purposes. This module is
+ * responsible for keeping the flat-file images as nearly in sync with
+ * database reality as possible.
*
* The tricky part of the write_xxx_file() routines in this module is that
* they need to be able to operate in the context of the database startup
@@ -22,7 +23,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.8 2005/06/17 22:32:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.9 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,12 +32,14 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "access/genam.h"
#include "access/heapam.h"
#include "access/twophase_rmgr.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_auth_members.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
-#include "catalog/pg_group.h"
#include "catalog/pg_namespace.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
#include "commands/trigger.h"
#include "miscadmin.h"
@@ -45,19 +48,18 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/flatfiles.h"
+#include "utils/fmgroids.h"
#include "utils/resowner.h"
#include "utils/syscache.h"
/* Actual names of the flat files (within $PGDATA/global/) */
#define DATABASE_FLAT_FILE "pg_database"
-#define GROUP_FLAT_FILE "pg_group"
-#define USER_FLAT_FILE "pg_pwd"
+#define AUTH_FLAT_FILE "pg_auth"
/* Info bits in a flatfiles 2PC record */
#define FF_BIT_DATABASE 1
-#define FF_BIT_GROUP 2
-#define FF_BIT_USER 4
+#define FF_BIT_AUTH 2
/*
@@ -73,8 +75,7 @@
* SubTransactionId is seen at top-level commit.
*/
static SubTransactionId database_file_update_subid = InvalidSubTransactionId;
-static SubTransactionId group_file_update_subid = InvalidSubTransactionId;
-static SubTransactionId user_file_update_subid = InvalidSubTransactionId;
+static SubTransactionId auth_file_update_subid = InvalidSubTransactionId;
/*
@@ -88,23 +89,13 @@ database_file_update_needed(void)
}
/*
- * Mark flat group file as needing an update (because pg_group changed)
+ * Mark flat auth file as needing an update (because pg_auth changed)
*/
void
-group_file_update_needed(void)
+auth_file_update_needed(void)
{
- if (group_file_update_subid == InvalidSubTransactionId)
- group_file_update_subid = GetCurrentSubTransactionId();
-}
-
-/*
- * Mark flat user file as needing an update (because pg_shadow changed)
- */
-void
-user_file_update_needed(void)
-{
- if (user_file_update_subid == InvalidSubTransactionId)
- user_file_update_subid = GetCurrentSubTransactionId();
+ if (auth_file_update_subid == InvalidSubTransactionId)
+ auth_file_update_subid = GetCurrentSubTransactionId();
}
@@ -128,39 +119,20 @@ database_getflatfilename(void)
}
/*
- * group_getflatfilename --- get full pathname of group file
- *
- * Note that result string is palloc'd, and should be freed by the caller.
- */
-char *
-group_getflatfilename(void)
-{
- int bufsize;
- char *pfnam;
-
- bufsize = strlen(DataDir) + strlen("/global/") +
- strlen(GROUP_FLAT_FILE) + 1;
- pfnam = (char *) palloc(bufsize);
- snprintf(pfnam, bufsize, "%s/global/%s", DataDir, GROUP_FLAT_FILE);
-
- return pfnam;
-}
-
-/*
- * Get full pathname of password file.
+ * Get full pathname of auth file.
*
* Note that result string is palloc'd, and should be freed by the caller.
*/
char *
-user_getflatfilename(void)
+auth_getflatfilename(void)
{
int bufsize;
char *pfnam;
bufsize = strlen(DataDir) + strlen("/global/") +
- strlen(USER_FLAT_FILE) + 1;
+ strlen(AUTH_FLAT_FILE) + 1;
pfnam = (char *) palloc(bufsize);
- snprintf(pfnam, bufsize, "%s/global/%s", DataDir, USER_FLAT_FILE);
+ snprintf(pfnam, bufsize, "%s/global/%s", DataDir, AUTH_FLAT_FILE);
return pfnam;
}
@@ -189,7 +161,7 @@ fputs_quote(const char *str, FILE *fp)
/*
* name_okay
*
- * We must disallow newlines in user and group names because
+ * We must disallow newlines in role names because
* hba.c's parser won't handle fields split across lines, even if quoted.
*/
static bool
@@ -322,165 +294,81 @@ write_database_file(Relation drel)
/*
- * write_group_file: update the flat group file
+ * Support for write_auth_file
*/
-static void
-write_group_file(Relation grel)
-{
- char *filename,
- *tempname;
- int bufsize;
- FILE *fp;
- mode_t oumask;
- HeapScanDesc scan;
- HeapTuple tuple;
-
- /*
- * Create a temporary filename to be renamed later. This prevents the
- * backend from clobbering the flat file while the postmaster
- * might be reading from it.
- */
- filename = group_getflatfilename();
- bufsize = strlen(filename) + 12;
- tempname = (char *) palloc(bufsize);
- snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
-
- oumask = umask((mode_t) 077);
- fp = AllocateFile(tempname, "w");
- umask(oumask);
- if (fp == NULL)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write to temporary file \"%s\": %m",
- tempname)));
-
- /*
- * Read pg_group and write the file.
- */
- scan = heap_beginscan(grel, SnapshotNow, 0, NULL);
- while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
- {
- Form_pg_group grpform = (Form_pg_group) GETSTRUCT(tuple);
- HeapTupleHeader tup = tuple->t_data;
- char *tp; /* ptr to tuple data */
- long off; /* offset in tuple data */
- bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */
- Datum datum;
- char *groname;
- IdList *grolist_p;
- AclId *aidp;
- int i,
- num;
-
- groname = NameStr(grpform->groname);
-
- /*
- * Check for illegal characters in the group name.
- */
- if (!name_okay(groname))
- {
- ereport(LOG,
- (errmsg("invalid group name \"%s\"", groname)));
- continue;
- }
-
- /*
- * We can't use heap_getattr() here because during startup we will
- * not have any tupdesc for pg_group. Fortunately it's not too
- * hard to work around this. grolist is the first possibly-null
- * field so we can compute its offset directly.
- */
- tp = (char *) tup + tup->t_hoff;
- off = offsetof(FormData_pg_group, grolist);
-
- if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_group_grolist - 1, bp))
- {
- /* grolist is null, so we can ignore this group */
- continue;
- }
-
- /* assume grolist is pass-by-ref */
- datum = PointerGetDatum(tp + off);
-
- /*
- * We can't currently support out-of-line toasted group lists in
- * startup mode (the tuptoaster won't work). This sucks, but it
- * should be something of a corner case. Live with it until we
- * can redesign pg_group.
- *
- * Detect startup mode by noting whether we got a tupdesc.
- */
- if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)) &&
- RelationGetDescr(grel) == NULL)
- continue;
- /* be sure the IdList is not toasted */
- grolist_p = DatumGetIdListP(datum);
+typedef struct {
+ Oid roleid;
+ char* rolname;
+ char* rolpassword;
+ char* rolvaliduntil;
+ List* roles_names;
+} auth_entry;
+
+typedef struct {
+ Oid roleid;
+ Oid memberid;
+} authmem_entry;
+
+static int
+oid_compar(const void *a, const void *b)
+{
+ const auth_entry *a_auth = (const auth_entry*) a;
+ const auth_entry *b_auth = (const auth_entry*) b;
- /*
- * The file format is: "groupname" usesysid1 usesysid2 ...
- *
- * We ignore groups that have no members.
- */
- aidp = IDLIST_DAT(grolist_p);
- num = IDLIST_NUM(grolist_p);
- if (num > 0)
- {
- fputs_quote(groname, fp);
- fprintf(fp, "\t%u", aidp[0]);
- for (i = 1; i < num; ++i)
- fprintf(fp, " %u", aidp[i]);
- fputs("\n", fp);
- }
+ if (a_auth->roleid < b_auth->roleid) return -1;
+ if (a_auth->roleid > b_auth->roleid) return 1;
+ return 0;
+}
- /* if IdList was toasted, free detoasted copy */
- if ((Pointer) grolist_p != DatumGetPointer(datum))
- pfree(grolist_p);
- }
- heap_endscan(scan);
+static int
+name_compar(const void *a, const void *b)
+{
+ const auth_entry *a_auth = (const auth_entry*) a;
+ const auth_entry *b_auth = (const auth_entry*) b;
- if (FreeFile(fp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write to temporary file \"%s\": %m",
- tempname)));
+ return strcmp(a_auth->rolname,b_auth->rolname);
+}
- /*
- * Rename the temp file to its final name, deleting the old flat file.
- * We expect that rename(2) is an atomic action.
- */
- if (rename(tempname, filename))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not rename file \"%s\" to \"%s\": %m",
- tempname, filename)));
+static int
+mem_compar(const void *a, const void *b)
+{
+ const authmem_entry *a_auth = (const authmem_entry*) a;
+ const authmem_entry *b_auth = (const authmem_entry*) b;
- pfree(tempname);
- pfree(filename);
+ if (a_auth->memberid < b_auth->memberid) return -1;
+ if (a_auth->memberid > b_auth->memberid) return 1;
+ return 0;
}
-
/*
- * write_user_file: update the flat password file
+ * write_auth_file: update the flat auth file
*/
static void
-write_user_file(Relation urel)
+write_auth_file(Relation rel_auth, Relation rel_authmem, bool startup)
{
char *filename,
*tempname;
int bufsize;
+ BlockNumber totalblocks;
FILE *fp;
mode_t oumask;
HeapScanDesc scan;
HeapTuple tuple;
+ int curr_role = 0;
+ int total_roles = 0;
+ int curr_mem = 0;
+ int total_mem = 0;
+ int est_rows;
+ auth_entry *auth_info;
+ authmem_entry *authmem_info = NULL;
/*
* Create a temporary filename to be renamed later. This prevents the
- * backend from clobbering the flat file while the postmaster might
+ * backend from clobbering the pg_auth file while the postmaster might
* be reading from it.
*/
- filename = user_getflatfilename();
+ filename = auth_getflatfilename();
bufsize = strlen(filename) + 12;
tempname = (char *) palloc(bufsize);
snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
@@ -495,39 +383,41 @@ write_user_file(Relation urel)
tempname)));
/*
- * Read pg_shadow and write the file.
+ * Read pg_authid and fill temporary data structures.
*/
- scan = heap_beginscan(urel, SnapshotNow, 0, NULL);
+ totalblocks = RelationGetNumberOfBlocks(rel_auth);
+ totalblocks = totalblocks ? totalblocks : 1;
+ est_rows = totalblocks * (BLCKSZ / (sizeof(HeapTupleHeaderData)+sizeof(FormData_pg_authid)));
+ auth_info = (auth_entry*) palloc(est_rows*sizeof(auth_entry));
+
+ scan = heap_beginscan(rel_auth, SnapshotNow, 0, NULL);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- Form_pg_shadow pwform = (Form_pg_shadow) GETSTRUCT(tuple);
+ Form_pg_authid pwform = (Form_pg_authid) GETSTRUCT(tuple);
HeapTupleHeader tup = tuple->t_data;
char *tp; /* ptr to tuple data */
long off; /* offset in tuple data */
bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */
Datum datum;
- char *usename,
- *passwd,
- *valuntil;
- AclId usesysid;
- usename = NameStr(pwform->usename);
- usesysid = pwform->usesysid;
+ auth_info[curr_role].roleid = HeapTupleGetOid(tuple);
+ auth_info[curr_role].rolname = pstrdup(NameStr(pwform->rolname));
+ auth_info[curr_role].roles_names = NIL;
/*
* We can't use heap_getattr() here because during startup we will
- * not have any tupdesc for pg_shadow. Fortunately it's not too
- * hard to work around this. passwd is the first possibly-null
+ * not have any tupdesc for pg_authid. Fortunately it's not too
+ * hard to work around this. rolpassword is the first possibly-null
* field so we can compute its offset directly.
*/
tp = (char *) tup + tup->t_hoff;
- off = offsetof(FormData_pg_shadow, passwd);
+ off = offsetof(FormData_pg_authid, rolpassword);
if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_shadow_passwd - 1, bp))
+ att_isnull(Anum_pg_authid_rolpassword - 1, bp))
{
/* passwd is null, emit as an empty string */
- passwd = pstrdup("");
+ auth_info[curr_role].rolpassword = pstrdup("");
}
else
{
@@ -539,59 +429,175 @@ write_user_file(Relation urel)
* if it is, ignore it, since we can't handle that in startup mode.
*/
if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)))
- passwd = pstrdup("");
+ auth_info[curr_role].rolpassword = pstrdup("");
else
- passwd = DatumGetCString(DirectFunctionCall1(textout, datum));
+ auth_info[curr_role].rolpassword = DatumGetCString(DirectFunctionCall1(textout, datum));
/* assume passwd has attlen -1 */
off = att_addlength(off, -1, tp + off);
}
if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_shadow_valuntil - 1, bp))
+ att_isnull(Anum_pg_authid_rolvaliduntil - 1, bp))
{
- /* valuntil is null, emit as an empty string */
- valuntil = pstrdup("");
+ /* rolvaliduntil is null, emit as an empty string */
+ auth_info[curr_role].rolvaliduntil = pstrdup("");
}
else
{
- /* assume valuntil has attalign 'i' */
- off = att_align(off, 'i');
- /* assume valuntil is pass-by-value, integer size */
- datum = Int32GetDatum(*((int32 *) (tp + off)));
- valuntil = DatumGetCString(DirectFunctionCall1(abstimeout, datum));
+ /*
+ * rolvaliduntil is timestamptz, which we assume is double
+ * alignment and pass-by-reference.
+ */
+ off = att_align(off, 'd');
+ datum = PointerGetDatum(tp + off);
+ auth_info[curr_role].rolvaliduntil = DatumGetCString(DirectFunctionCall1(timestamptz_out, datum));
}
/*
* Check for illegal characters in the user name and password.
*/
- if (!name_okay(usename))
+ if (!name_okay(auth_info[curr_role].rolname))
{
ereport(LOG,
- (errmsg("invalid user name \"%s\"", usename)));
+ (errmsg("invalid role name \"%s\"",
+ auth_info[curr_role].rolname)));
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
continue;
}
- if (!name_okay(passwd))
+ if (!name_okay(auth_info[curr_role].rolpassword))
{
ereport(LOG,
- (errmsg("invalid user password \"%s\"", passwd)));
+ (errmsg("invalid role password \"%s\"",
+ auth_info[curr_role].rolpassword)));
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
continue;
}
- /*
- * The file format is: "usename" usesysid "passwd" "valuntil"
+ curr_role++;
+ total_roles++;
+ }
+ heap_endscan(scan);
+
+ Assert(total_roles <= est_rows);
+
+ qsort(auth_info, total_roles, sizeof(auth_entry), oid_compar);
+
+ /*
+ * Read pg_auth_members into temporary data structure, too
+ */
+ totalblocks = RelationGetNumberOfBlocks(rel_authmem);
+ totalblocks = totalblocks ? totalblocks : 1;
+ est_rows = totalblocks * (BLCKSZ / (sizeof(HeapTupleHeaderData)+sizeof(FormData_pg_auth_members)));
+ authmem_info = (authmem_entry*) palloc(est_rows*sizeof(authmem_entry));
+
+ scan = heap_beginscan(rel_authmem, SnapshotNow, 0, NULL);
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Form_pg_auth_members memform = (Form_pg_auth_members) GETSTRUCT(tuple);
+
+ authmem_info[curr_mem].roleid = memform->roleid;
+ authmem_info[curr_mem].memberid = memform->member;
+ curr_mem++;
+ total_mem++;
+ }
+ heap_endscan(scan);
+
+ Assert(total_mem <= est_rows);
+
+ qsort(authmem_info, total_mem, sizeof(authmem_entry), mem_compar);
+
+ for (curr_role = 0; curr_role < total_roles; curr_role++)
+ {
+ int first_found, last_found, curr_mem;
+ List *roles_list_hunt = NIL;
+ List *roles_list = NIL;
+ ListCell *mem = NULL;
+ auth_entry *found_role = NULL, key_auth;
+ authmem_entry key;
+ authmem_entry *found_mem = NULL;
+
+ roles_list_hunt = lappend_oid(roles_list_hunt,
+ auth_info[curr_role].roleid);
+
+ while (roles_list_hunt)
+ {
+ key.memberid = linitial_oid(roles_list_hunt);
+ roles_list_hunt = list_delete_first(roles_list_hunt);
+ if (total_mem)
+ found_mem = bsearch(&key, authmem_info, total_mem,
+ sizeof(authmem_entry), mem_compar);
+ if (found_mem)
+ {
+ /*
+ * bsearch found a match for us; but if there were multiple
+ * matches it could have found any one of them.
+ */
+ first_found = last_found = (found_mem - authmem_info);
+ while (first_found > 0 &&
+ mem_compar(&key, &authmem_info[first_found - 1]) == 0)
+ first_found--;
+ while (last_found + 1 < total_mem &&
+ mem_compar(&key, &authmem_info[last_found + 1]) == 0)
+ last_found++;
+
+ for (curr_mem = first_found; curr_mem <= last_found; curr_mem++)
+ {
+ Oid otherrole = authmem_info[curr_mem].roleid;
+
+ if (!list_member_oid(roles_list, otherrole))
+ {
+ roles_list = lappend_oid(roles_list,
+ otherrole);
+ roles_list_hunt = lappend_oid(roles_list_hunt,
+ otherrole);
+ }
+ }
+ }
+ }
+
+ foreach(mem, roles_list)
+ {
+ key_auth.roleid = lfirst_oid(mem);
+ found_role = bsearch(&key_auth, auth_info, total_roles, sizeof(auth_entry), oid_compar);
+ auth_info[curr_role].roles_names = lappend(auth_info[curr_role].roles_names,found_role->rolname);
+ }
+ }
+
+ qsort(auth_info, total_roles, sizeof(auth_entry), name_compar);
+
+ for (curr_role = 0; curr_role < total_roles; curr_role++)
+ {
+ ListCell *mem = NULL;
+
+ /*----------
+ * The file format is:
+ * "rolename" "password" "validuntil" "member" "member" ...
+ * where lines are expected to be in order by rolename
+ *----------
*/
- fputs_quote(usename, fp);
- fprintf(fp, " %u ", usesysid);
- fputs_quote(passwd, fp);
+ fputs_quote(auth_info[curr_role].rolname, fp);
+ fputs(" ", fp);
+ fputs_quote(auth_info[curr_role].rolpassword, fp);
fputs(" ", fp);
- fputs_quote(valuntil, fp);
+ fputs_quote(auth_info[curr_role].rolvaliduntil, fp);
+
+ foreach(mem, auth_info[curr_role].roles_names)
+ {
+ fputs(" ", fp);
+ fputs_quote(lfirst(mem), fp);
+ }
+
fputs("\n", fp);
- pfree(passwd);
- pfree(valuntil);
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
}
- heap_endscan(scan);
if (FreeFile(fp))
ereport(ERROR,
@@ -609,6 +615,8 @@ write_user_file(Relation urel)
errmsg("could not rename file \"%s\" to \"%s\": %m",
tempname, filename)));
+ pfree(auth_info);
+ pfree(authmem_info);
pfree(tempname);
pfree(filename);
}
@@ -634,7 +642,7 @@ BuildFlatFiles(bool database_only)
{
ResourceOwner owner;
RelFileNode rnode;
- Relation rel;
+ Relation rel, rel_auth, rel_authmem;
/*
* We don't have any hope of running a real relcache, but we can use
@@ -657,21 +665,16 @@ BuildFlatFiles(bool database_only)
if (!database_only)
{
- /* hard-wired path to pg_group */
+ /* hard-wired path to pg_auth */
rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0;
- rnode.relNode = GroupRelationId;
+ rnode.relNode = AuthIdRelationId;
+ rel_auth = XLogOpenRelation(rnode);
- rel = XLogOpenRelation(rnode);
- write_group_file(rel);
-
- /* hard-wired path to pg_shadow */
rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0;
- rnode.relNode = ShadowRelationId;
-
- rel = XLogOpenRelation(rnode);
- write_user_file(rel);
+ rnode.relNode = AuthMemRelationId;
+ rel_authmem = XLogOpenRelation(rnode);
}
CurrentResourceOwner = NULL;
@@ -699,19 +702,17 @@ void
AtEOXact_UpdateFlatFiles(bool isCommit)
{
Relation drel = NULL;
- Relation grel = NULL;
- Relation urel = NULL;
+ Relation arel = NULL;
+ Relation mrel = NULL;
if (database_file_update_subid == InvalidSubTransactionId &&
- group_file_update_subid == InvalidSubTransactionId &&
- user_file_update_subid == InvalidSubTransactionId)
+ auth_file_update_subid == InvalidSubTransactionId)
return; /* nothing to do */
if (!isCommit)
{
database_file_update_subid = InvalidSubTransactionId;
- group_file_update_subid = InvalidSubTransactionId;
- user_file_update_subid = InvalidSubTransactionId;
+ auth_file_update_subid = InvalidSubTransactionId;
return;
}
@@ -731,10 +732,10 @@ AtEOXact_UpdateFlatFiles(bool isCommit)
*/
if (database_file_update_subid != InvalidSubTransactionId)
drel = heap_open(DatabaseRelationId, ExclusiveLock);
- if (group_file_update_subid != InvalidSubTransactionId)
- grel = heap_open(GroupRelationId, ExclusiveLock);
- if (user_file_update_subid != InvalidSubTransactionId)
- urel = heap_open(ShadowRelationId, ExclusiveLock);
+ if (auth_file_update_subid != InvalidSubTransactionId) {
+ arel = heap_open(AuthIdRelationId, ExclusiveLock);
+ mrel = heap_open(AuthMemRelationId, ExclusiveLock);
+ }
/* Okay to write the files */
if (database_file_update_subid != InvalidSubTransactionId)
@@ -744,18 +745,12 @@ AtEOXact_UpdateFlatFiles(bool isCommit)
heap_close(drel, NoLock);
}
- if (group_file_update_subid != InvalidSubTransactionId)
- {
- group_file_update_subid = InvalidSubTransactionId;
- write_group_file(grel);
- heap_close(grel, NoLock);
- }
-
- if (user_file_update_subid != InvalidSubTransactionId)
+ if (auth_file_update_subid != InvalidSubTransactionId)
{
- user_file_update_subid = InvalidSubTransactionId;
- write_user_file(urel);
- heap_close(urel, NoLock);
+ auth_file_update_subid = InvalidSubTransactionId;
+ write_auth_file(arel, mrel, false);
+ heap_close(arel, NoLock);
+ heap_close(mrel, NoLock);
}
/*
@@ -785,15 +780,10 @@ AtPrepare_UpdateFlatFiles(void)
database_file_update_subid = InvalidSubTransactionId;
info |= FF_BIT_DATABASE;
}
- if (group_file_update_subid != InvalidSubTransactionId)
- {
- group_file_update_subid = InvalidSubTransactionId;
- info |= FF_BIT_GROUP;
- }
- if (user_file_update_subid != InvalidSubTransactionId)
+ if (auth_file_update_subid != InvalidSubTransactionId)
{
- user_file_update_subid = InvalidSubTransactionId;
- info |= FF_BIT_USER;
+ auth_file_update_subid = InvalidSubTransactionId;
+ info |= FF_BIT_AUTH;
}
if (info != 0)
RegisterTwoPhaseRecord(TWOPHASE_RM_FLATFILES_ID, info,
@@ -817,29 +807,23 @@ AtEOSubXact_UpdateFlatFiles(bool isCommit,
if (database_file_update_subid == mySubid)
database_file_update_subid = parentSubid;
- if (group_file_update_subid == mySubid)
- group_file_update_subid = parentSubid;
-
- if (user_file_update_subid == mySubid)
- user_file_update_subid = parentSubid;
+ if (auth_file_update_subid == mySubid)
+ auth_file_update_subid = parentSubid;
}
else
{
if (database_file_update_subid == mySubid)
database_file_update_subid = InvalidSubTransactionId;
- if (group_file_update_subid == mySubid)
- group_file_update_subid = InvalidSubTransactionId;
-
- if (user_file_update_subid == mySubid)
- user_file_update_subid = InvalidSubTransactionId;
+ if (auth_file_update_subid == mySubid)
+ auth_file_update_subid = InvalidSubTransactionId;
}
}
/*
- * This trigger is fired whenever someone modifies pg_database, pg_shadow
- * or pg_group via general-purpose INSERT/UPDATE/DELETE commands.
+ * This trigger is fired whenever someone modifies pg_database, pg_authid
+ * or pg_auth_members via general-purpose INSERT/UPDATE/DELETE commands.
*
* It is sufficient for this to be a STATEMENT trigger since we don't
* care which individual rows changed. It doesn't much matter whether
@@ -862,11 +846,11 @@ flatfile_update_trigger(PG_FUNCTION_ARGS)
case DatabaseRelationId:
database_file_update_needed();
break;
- case GroupRelationId:
- group_file_update_needed();
+ case AuthIdRelationId:
+ auth_file_update_needed();
break;
- case ShadowRelationId:
- user_file_update_needed();
+ case AuthMemRelationId:
+ auth_file_update_needed();
break;
default:
elog(ERROR, "flatfile_update_trigger was called for wrong table");
@@ -895,8 +879,6 @@ flatfile_twophase_postcommit(TransactionId xid, uint16 info,
*/
if (info & FF_BIT_DATABASE)
database_file_update_needed();
- if (info & FF_BIT_GROUP)
- group_file_update_needed();
- if (info & FF_BIT_USER)
- user_file_update_needed();
+ if (info & FF_BIT_AUTH)
+ auth_file_update_needed();
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 508c56e1e03..1db29928996 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.142 2005/06/20 02:17:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.143 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,7 +29,7 @@
#include <utime.h>
#endif
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h"
#include "storage/fd.h"
@@ -251,7 +251,7 @@ make_absolute_path(const char *path)
/* ----------------------------------------------------------------
- * User ID things
+ * Role ID things
*
* The authenticated user is determined at connection start and never
* changes. The session user can be changed only by SET SESSION
@@ -261,60 +261,60 @@ make_absolute_path(const char *path)
* restore the current user id if you need to change it.
* ----------------------------------------------------------------
*/
-static AclId AuthenticatedUserId = 0;
-static AclId SessionUserId = 0;
-static AclId CurrentUserId = 0;
+static Oid AuthenticatedUserId = InvalidOid;
+static Oid SessionUserId = InvalidOid;
+static Oid CurrentUserId = InvalidOid;
static bool AuthenticatedUserIsSuperuser = false;
/*
* This function is relevant for all privilege checks.
*/
-AclId
+Oid
GetUserId(void)
{
- AssertState(AclIdIsValid(CurrentUserId));
+ AssertState(OidIsValid(CurrentUserId));
return CurrentUserId;
}
void
-SetUserId(AclId newid)
+SetUserId(Oid roleid)
{
- AssertArg(AclIdIsValid(newid));
- CurrentUserId = newid;
+ AssertArg(OidIsValid(roleid));
+ CurrentUserId = roleid;
}
/*
* This value is only relevant for informational purposes.
*/
-AclId
+Oid
GetSessionUserId(void)
{
- AssertState(AclIdIsValid(SessionUserId));
+ AssertState(OidIsValid(SessionUserId));
return SessionUserId;
}
void
-SetSessionUserId(AclId newid)
+SetSessionUserId(Oid roleid)
{
- AssertArg(AclIdIsValid(newid));
- SessionUserId = newid;
+ AssertArg(OidIsValid(roleid));
+ SessionUserId = roleid;
/* Current user defaults to session user. */
- if (!AclIdIsValid(CurrentUserId))
- CurrentUserId = newid;
+ if (!OidIsValid(CurrentUserId))
+ CurrentUserId = roleid;
}
void
-InitializeSessionUserId(const char *username)
+InitializeSessionUserId(const char *rolename)
{
- HeapTuple userTup;
+ HeapTuple roleTup;
Datum datum;
bool isnull;
- AclId usesysid;
+ Oid roleid;
/*
* Don't do scans if we're bootstrapping, none of the system catalogs
@@ -325,23 +325,23 @@ InitializeSessionUserId(const char *username)
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
- userTup = SearchSysCache(SHADOWNAME,
- PointerGetDatum(username),
+ roleTup = SearchSysCache(AUTHNAME,
+ PointerGetDatum(rolename),
0, 0, 0);
- if (!HeapTupleIsValid(userTup))
+ if (!HeapTupleIsValid(roleTup))
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", username)));
+ errmsg("role \"%s\" does not exist", rolename)));
- usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
+ roleid = HeapTupleGetOid(roleTup);
- AuthenticatedUserId = usesysid;
- AuthenticatedUserIsSuperuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
+ AuthenticatedUserId = roleid;
+ AuthenticatedUserIsSuperuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
- SetSessionUserId(usesysid); /* sets CurrentUserId too */
+ SetSessionUserId(roleid); /* sets CurrentUserId too */
/* Record username and superuser status as GUC settings too */
- SetConfigOption("session_authorization", username,
+ SetConfigOption("session_authorization", rolename,
PGC_BACKEND, PGC_S_OVERRIDE);
SetConfigOption("is_superuser",
AuthenticatedUserIsSuperuser ? "on" : "off",
@@ -349,11 +349,11 @@ InitializeSessionUserId(const char *username)
/*
* Set up user-specific configuration variables. This is a good place
- * to do it so we don't have to read pg_shadow twice during session
+ * to do it so we don't have to read pg_authid twice during session
* startup.
*/
- datum = SysCacheGetAttr(SHADOWNAME, userTup,
- Anum_pg_shadow_useconfig, &isnull);
+ datum = SysCacheGetAttr(AUTHNAME, roleTup,
+ Anum_pg_authid_rolconfig, &isnull);
if (!isnull)
{
ArrayType *a = DatumGetArrayTypeP(datum);
@@ -361,7 +361,7 @@ InitializeSessionUserId(const char *username)
ProcessGUCArray(a, PGC_S_USER);
}
- ReleaseSysCache(userTup);
+ ReleaseSysCache(roleTup);
}
@@ -374,10 +374,10 @@ InitializeSessionUserIdStandalone(void)
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
- AuthenticatedUserId = BOOTSTRAP_USESYSID;
+ AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
AuthenticatedUserIsSuperuser = true;
- SetSessionUserId(BOOTSTRAP_USESYSID);
+ SetSessionUserId(BOOTSTRAP_SUPERUSERID);
}
@@ -390,19 +390,19 @@ InitializeSessionUserIdStandalone(void)
* to indicate whether the *current* session userid is a superuser.
*/
void
-SetSessionAuthorization(AclId userid, bool is_superuser)
+SetSessionAuthorization(Oid roleid, bool is_superuser)
{
/* Must have authenticated already, else can't make permission check */
- AssertState(AclIdIsValid(AuthenticatedUserId));
+ AssertState(OidIsValid(AuthenticatedUserId));
- if (userid != AuthenticatedUserId &&
+ if (roleid != AuthenticatedUserId &&
!AuthenticatedUserIsSuperuser)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set session authorization")));
- SetSessionUserId(userid);
- SetUserId(userid);
+ SetSessionUserId(roleid);
+ SetUserId(roleid);
SetConfigOption("is_superuser",
is_superuser ? "on" : "off",
@@ -411,30 +411,29 @@ SetSessionAuthorization(AclId userid, bool is_superuser)
/*
- * Get user name from user id
+ * Get user name from user oid
*/
char *
-GetUserNameFromId(AclId userid)
+GetUserNameFromId(Oid roleid)
{
HeapTuple tuple;
char *result;
- tuple = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(userid),
+ tuple = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("invalid user ID: %d", userid)));
+ errmsg("invalid role OID: %u", roleid)));
- result = pstrdup(NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename));
+ result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
ReleaseSysCache(tuple);
return result;
}
-
/*-------------------------------------------------------------------------
* Interlock-file support
*
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 1836aee81d7..9baacacfffd 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.149 2005/06/24 01:06:26 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.150 2005/06/28 05:09:02 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -20,11 +20,11 @@
#include <math.h>
#include <unistd.h>
-#include "catalog/catalog.h"
#include "access/heapam.h"
+#include "catalog/catalog.h"
#include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
#include "libpq/hba.h"
#include "mb/pg_wchar.h"
@@ -37,6 +37,7 @@
#include "storage/procarray.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "utils/acl.h"
#include "utils/flatfiles.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
@@ -49,7 +50,7 @@ static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
static void ReverifyMyDatabase(const char *name);
static void InitCommunication(void);
static void ShutdownPostgres(int code, Datum arg);
-static bool ThereIsAtLeastOneUser(void);
+static bool ThereIsAtLeastOneRole(void);
/*** InitPostgres support ***/
@@ -415,12 +416,12 @@ InitPostgres(const char *dbname, const char *username)
else if (!IsUnderPostmaster)
{
InitializeSessionUserIdStandalone();
- if (!ThereIsAtLeastOneUser())
+ if (!ThereIsAtLeastOneRole())
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("no users are defined in this database system"),
- errhint("You should immediately run CREATE USER \"%s\" WITH SYSID %d CREATEUSER;.",
- username, BOOTSTRAP_USESYSID)));
+ errmsg("no roles are defined in this database system"),
+ errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.",
+ username)));
}
else
{
@@ -469,6 +470,9 @@ InitPostgres(const char *dbname, const char *username)
/* set default namespace search path */
InitializeSearchPath();
+ /* set up ACL framework (currently just sets RolMemCache callback) */
+ InitializeAcl();
+
/* initialize client encoding */
InitializeClientEncoding();
@@ -530,22 +534,22 @@ ShutdownPostgres(int code, Datum arg)
/*
- * Returns true if at least one user is defined in this database cluster.
+ * Returns true if at least one role is defined in this database cluster.
*/
static bool
-ThereIsAtLeastOneUser(void)
+ThereIsAtLeastOneRole(void)
{
- Relation pg_shadow_rel;
+ Relation pg_authid_rel;
HeapScanDesc scan;
bool result;
- pg_shadow_rel = heap_open(ShadowRelationId, AccessExclusiveLock);
+ pg_authid_rel = heap_open(AuthIdRelationId, AccessExclusiveLock);
- scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
+ scan = heap_beginscan(pg_authid_rel, SnapshotNow, 0, NULL);
result = (heap_getnext(scan, ForwardScanDirection) != NULL);
heap_endscan(scan);
- heap_close(pg_shadow_rel, AccessExclusiveLock);
+ heap_close(pg_authid_rel, AccessExclusiveLock);
return result;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0ab8e742336..84d8085503a 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.270 2005/06/26 19:16:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.271 2005/06/28 05:09:02 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -5108,7 +5108,7 @@ ParseLongOption(const char *string, char **name, char **value)
/*
- * Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
+ * Handle options fetched from pg_database.datconfig or pg_authid.rolconfig.
* The array parameter must be an array of TEXT (it must not be NULL).
*/
void
@@ -5154,7 +5154,7 @@ ProcessGUCArray(ArrayType *array, GucSource source)
/*
* We process all these options at SUSET level. We assume that
- * the right to insert an option into pg_database or pg_shadow was
+ * the right to insert an option into pg_database or pg_authid was
* checked when it was inserted.
*/
SetConfigOption(name, value, PGC_SUSET, source);
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 520dc470cdc..9e965b8107f 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -14,29 +14,29 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.31 2005/05/29 20:38:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.32 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
#include "utils/inval.h"
#include "utils/syscache.h"
#include "miscadmin.h"
/*
- * In common cases the same userid (ie, the session or current ID) will
+ * In common cases the same roleid (ie, the session or current ID) will
* be queried repeatedly. So we maintain a simple one-entry cache for
- * the status of the last requested userid. The cache can be flushed
- * at need by watching for cache update events on pg_shadow.
+ * the status of the last requested roleid. The cache can be flushed
+ * at need by watching for cache update events on pg_authid.
*/
-static AclId last_userid = 0; /* 0 == cache not valid */
-static bool last_userid_is_super = false;
-static bool userid_callback_registered = false;
+static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
+static bool last_roleid_is_super = false;
+static bool roleid_callback_registered = false;
-static void UseridCallback(Datum arg, Oid relid);
+static void RoleidCallback(Datum arg, Oid relid);
/*
@@ -50,49 +50,49 @@ superuser(void)
/*
- * The specified userid has Postgres superuser privileges
+ * The specified role has Postgres superuser privileges
*/
bool
-superuser_arg(AclId userid)
+superuser_arg(Oid roleid)
{
bool result;
- HeapTuple utup;
+ HeapTuple rtup;
/* Quick out for cache hit */
- if (AclIdIsValid(last_userid) && last_userid == userid)
- return last_userid_is_super;
+ if (OidIsValid(last_roleid) && last_roleid == roleid)
+ return last_roleid_is_super;
/* Special escape path in case you deleted all your users. */
- if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
+ if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
return true;
- /* OK, look up the information in pg_shadow */
- utup = SearchSysCache(SHADOWSYSID,
- Int32GetDatum(userid),
+ /* OK, look up the information in pg_authid */
+ rtup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
- if (HeapTupleIsValid(utup))
+ if (HeapTupleIsValid(rtup))
{
- result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
- ReleaseSysCache(utup);
+ result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
+ ReleaseSysCache(rtup);
}
else
{
- /* Report "not superuser" for invalid userids */
+ /* Report "not superuser" for invalid roleids */
result = false;
}
/* If first time through, set up callback for cache flushes */
- if (!userid_callback_registered)
+ if (!roleid_callback_registered)
{
- CacheRegisterSyscacheCallback(SHADOWSYSID,
- UseridCallback,
+ CacheRegisterSyscacheCallback(AUTHOID,
+ RoleidCallback,
(Datum) 0);
- userid_callback_registered = true;
+ roleid_callback_registered = true;
}
/* Cache the result for next time */
- last_userid = userid;
- last_userid_is_super = result;
+ last_roleid = roleid;
+ last_roleid_is_super = result;
return result;
}
@@ -102,8 +102,8 @@ superuser_arg(AclId userid)
* Syscache inval callback function
*/
static void
-UseridCallback(Datum arg, Oid relid)
+RoleidCallback(Datum arg, Oid relid)
{
- /* Invalidate our local cache in case user's superuserness changed */
- last_userid = 0;
+ /* Invalidate our local cache in case role's superuserness changed */
+ last_roleid = InvalidOid;
}