Commit 7d0c4188 authored by Tom Lane's avatar Tom Lane

Make acl-related functions safe for TOAST. Mark pg_class.relacl as

compressible but not externally storable (since we're not sure about
whether creating a toast relation for pg_class would work).
parent b7319d37
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.9 2000/07/22 11:18:46 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.10 2000/07/31 22:39:17 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -273,7 +273,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) ...@@ -273,7 +273,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
/* ---------- /* ----------
* If the old value is an external stored one, check if it * If the old value is an external stored one, check if it
* has changed so we have to detele it later. * has changed so we have to delete it later.
* ---------- * ----------
*/ */
if (!old_isnull && att[i]->attlen == -1 && if (!old_isnull && att[i]->attlen == -1 &&
...@@ -336,17 +336,16 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) ...@@ -336,17 +336,16 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (att[i]->attlen == -1) if (att[i]->attlen == -1)
{ {
/* ---------- /* ----------
* If the tables attribute say's PLAIN allways, we * If the table's attribute says PLAIN always, force it so.
* do so below.
* ---------- * ----------
*/ */
if (att[i]->attstorage == 'p') if (att[i]->attstorage == 'p')
toast_action[i] = 'p'; toast_action[i] = 'p';
/* ---------- /* ----------
* We're running for UPDATE, so any TOASTed value we find * We took care of UPDATE above, so any TOASTed value we find
* still in the tuple must be someone elses we cannot reuse. * still in the tuple must be someone else's we cannot reuse.
* Expand it to plain and eventually toast it again below. * Expand it to plain (and, probably, toast it again below).
* ---------- * ----------
*/ */
if (VARATT_IS_EXTENDED(DatumGetPointer(toast_values[i]))) if (VARATT_IS_EXTENDED(DatumGetPointer(toast_values[i])))
...@@ -367,7 +366,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) ...@@ -367,7 +366,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
else else
{ {
/* ---------- /* ----------
* Not a variable size attribute, plain storage allways * Not a variable size attribute, plain storage always
* ---------- * ----------
*/ */
toast_action[i] = 'p'; toast_action[i] = 'p';
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.38 2000/04/12 17:14:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.39 2000/07/31 22:39:13 tgl Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/syscache.h" #include "utils/syscache.h"
static int32 aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode); static int32 aclcheck(char *relname, Acl *acl, AclId id,
AclIdType idtype, AclMode mode);
/* /*
* Enable use of user relations in place of real system catalogs. * Enable use of user relations in place of real system catalogs.
...@@ -68,14 +69,16 @@ char *aclcheck_error_strings[] = { ...@@ -68,14 +69,16 @@ char *aclcheck_error_strings[] = {
static static
dumpacl(Acl *acl) dumpacl(Acl *acl)
{ {
unsigned i; int i;
AclItem *aip; AclItem *aip;
elog(DEBUG, "acl size = %d, # acls = %d", elog(DEBUG, "acl size = %d, # acls = %d",
ACL_SIZE(acl), ACL_NUM(acl)); ACL_SIZE(acl), ACL_NUM(acl));
aip = (AclItem *) ACL_DAT(acl); aip = ACL_DAT(acl);
for (i = 0; i < ACL_NUM(acl); ++i) for (i = 0; i < ACL_NUM(acl); ++i)
elog(DEBUG, " acl[%d]: %s", i, aclitemout(aip + i)); elog(DEBUG, " acl[%d]: %s", i,
DatumGetCString(DirectFunctionCall1(aclitemout,
PointerGetDatum(aip + i))));
} }
#endif #endif
...@@ -89,7 +92,7 @@ ChangeAcl(char *relname, ...@@ -89,7 +92,7 @@ ChangeAcl(char *relname,
unsigned modechg) unsigned modechg)
{ {
unsigned i; unsigned i;
Acl *old_acl = (Acl *) NULL, Acl *old_acl,
*new_acl; *new_acl;
Relation relation; Relation relation;
HeapTuple tuple; HeapTuple tuple;
...@@ -97,14 +100,12 @@ ChangeAcl(char *relname, ...@@ -97,14 +100,12 @@ ChangeAcl(char *relname,
char nulls[Natts_pg_class]; char nulls[Natts_pg_class];
char replaces[Natts_pg_class]; char replaces[Natts_pg_class];
Relation idescs[Num_pg_class_indices]; Relation idescs[Num_pg_class_indices];
int free_old_acl = 0; bool isNull;
bool free_old_acl = false;
/* /*
* Find the pg_class tuple matching 'relname' and extract the ACL. If * Find the pg_class tuple matching 'relname' and extract the ACL. If
* there's no ACL, create a default using the pg_class.relowner field. * there's no ACL, create a default using the pg_class.relowner field.
*
* We can't use the syscache here, since we need to do a heap_update on
* the tuple we find.
*/ */
relation = heap_openr(RelationRelationName, RowExclusiveLock); relation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(RELNAME, tuple = SearchSysCacheTuple(RELNAME,
...@@ -117,25 +118,37 @@ ChangeAcl(char *relname, ...@@ -117,25 +118,37 @@ ChangeAcl(char *relname,
relname); relname);
} }
if (!heap_attisnull(tuple, Anum_pg_class_relacl)) old_acl = (Acl *) heap_getattr(tuple,
old_acl = (Acl *) heap_getattr(tuple, Anum_pg_class_relacl,
Anum_pg_class_relacl, RelationGetDescr(relation),
RelationGetDescr(relation), &isNull);
(bool *) NULL); if (isNull)
if (!old_acl || ACL_NUM(old_acl) < 1)
{ {
#ifdef ACLDEBUG_TRACE #ifdef ACLDEBUG_TRACE
elog(DEBUG, "ChangeAcl: using default ACL"); elog(DEBUG, "ChangeAcl: using default ACL");
#endif #endif
/* old_acl = acldefault(((Form_pg_class) GETSTRUCT(tuple))->relowner); */
old_acl = acldefault(relname); old_acl = acldefault(relname);
free_old_acl = 1; free_old_acl = true;
}
/* Need to detoast the old ACL for modification */
old_acl = DatumGetAclP(PointerGetDatum(old_acl));
if (ACL_NUM(old_acl) < 1)
{
#ifdef ACLDEBUG_TRACE
elog(DEBUG, "ChangeAcl: old ACL has zero length");
#endif
old_acl = acldefault(relname);
free_old_acl = true;
} }
#ifdef ACLDEBUG_TRACE #ifdef ACLDEBUG_TRACE
dumpacl(old_acl); dumpacl(old_acl);
#endif #endif
new_acl = aclinsert3(old_acl, mod_aip, modechg); new_acl = aclinsert3(old_acl, mod_aip, modechg);
#ifdef ACLDEBUG_TRACE #ifdef ACLDEBUG_TRACE
dumpacl(new_acl); dumpacl(new_acl);
#endif #endif
...@@ -148,7 +161,7 @@ ChangeAcl(char *relname, ...@@ -148,7 +161,7 @@ ChangeAcl(char *relname,
* anyway */ * anyway */
} }
replaces[Anum_pg_class_relacl - 1] = 'r'; replaces[Anum_pg_class_relacl - 1] = 'r';
values[Anum_pg_class_relacl - 1] = (Datum) new_acl; values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
tuple = heap_modifytuple(tuple, relation, values, nulls, replaces); tuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
heap_update(relation, &tuple->t_self, tuple, NULL); heap_update(relation, &tuple->t_self, tuple, NULL);
...@@ -193,20 +206,20 @@ get_groname(AclId grosysid) ...@@ -193,20 +206,20 @@ get_groname(AclId grosysid)
if (HeapTupleIsValid(tuple)) if (HeapTupleIsValid(tuple))
name = NameStr(((Form_pg_group) GETSTRUCT(tuple))->groname); name = NameStr(((Form_pg_group) GETSTRUCT(tuple))->groname);
else else
elog(NOTICE, "get_groname: group %d not found", grosysid); elog(NOTICE, "get_groname: group %u not found", grosysid);
return name; return name;
} }
static int32 static bool
in_group(AclId uid, AclId gid) in_group(AclId uid, AclId gid)
{ {
Relation relation; Relation relation;
HeapTuple tuple; HeapTuple tuple;
Acl *tmp; Acl *tmp;
unsigned i, int i,
num; num;
AclId *aidp; AclId *aidp;
int32 found = 0; bool found = false;
relation = heap_openr(GroupRelationName, RowExclusiveLock); relation = heap_openr(GroupRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(GROSYSID, tuple = SearchSysCacheTuple(GROSYSID,
...@@ -219,13 +232,15 @@ in_group(AclId uid, AclId gid) ...@@ -219,13 +232,15 @@ in_group(AclId uid, AclId gid)
Anum_pg_group_grolist, Anum_pg_group_grolist,
RelationGetDescr(relation), RelationGetDescr(relation),
(bool *) NULL); (bool *) NULL);
/* be sure the IdList is not toasted */
tmp = DatumGetIdListP(PointerGetDatum(tmp));
/* XXX make me a function */ /* XXX make me a function */
num = IDLIST_NUM(tmp); num = IDLIST_NUM(tmp);
aidp = IDLIST_DAT(tmp); aidp = IDLIST_DAT(tmp);
for (i = 0; i < num; ++i) for (i = 0; i < num; ++i)
if (aidp[i] == uid) if (aidp[i] == uid)
{ {
found = 1; found = true;
break; break;
} }
} }
...@@ -344,8 +359,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) ...@@ -344,8 +359,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
{ {
HeapTuple tuple; HeapTuple tuple;
AclId id; AclId id;
Acl *acl = (Acl *) NULL, Acl *acl = (Acl *) NULL;
*tmp;
int32 result; int32 result;
Relation relation; Relation relation;
...@@ -396,12 +410,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) ...@@ -396,12 +410,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
} }
if (!heap_attisnull(tuple, Anum_pg_class_relacl)) if (!heap_attisnull(tuple, Anum_pg_class_relacl))
{ {
tmp = (Acl *) heap_getattr(tuple, /* get a detoasted copy of the ACL */
Anum_pg_class_relacl, acl = DatumGetAclPCopy(heap_getattr(tuple,
RelationGetDescr(relation), Anum_pg_class_relacl,
(bool *) NULL); RelationGetDescr(relation),
acl = makeacl(ACL_NUM(tmp)); (bool *) NULL));
memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
} }
else else
{ {
...@@ -410,13 +423,10 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) ...@@ -410,13 +423,10 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
* if the acl is null, by default the owner can do whatever he * if the acl is null, by default the owner can do whatever he
* wants to with it * wants to with it
*/ */
int4 ownerId; AclId ownerId;
ownerId = (int4) heap_getattr(tuple, ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
Anum_pg_class_relowner, acl = aclownerdefault(relname, ownerId);
RelationGetDescr(relation),
(bool *) NULL);
acl = aclownerdefault(relname, (AclId) ownerId);
} }
heap_close(relation, RowExclusiveLock); heap_close(relation, RowExclusiveLock);
#else #else
...@@ -427,12 +437,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) ...@@ -427,12 +437,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
if (HeapTupleIsValid(tuple) && if (HeapTupleIsValid(tuple) &&
!heap_attisnull(tuple, Anum_pg_class_relacl)) !heap_attisnull(tuple, Anum_pg_class_relacl))
{ {
tmp = (Acl *) heap_getattr(tuple, /* get a detoasted copy of the ACL */
Anum_pg_class_relacl, acl = DatumGetAclPCopy(heap_getattr(tuple,
RelationGetDescr(relation), Anum_pg_class_relacl,
(bool *) NULL); RelationGetDescr(relation),
acl = makeacl(ACL_NUM(tmp)); (bool *) NULL));
memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
} }
heap_close(relation, RowExclusiveLock); heap_close(relation, RowExclusiveLock);
#endif #endif
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.47 2000/06/14 18:17:42 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.48 2000/07/31 22:39:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static char *getid(char *s, char *n); static char *getid(char *s, char *n);
static int32 aclitemeq(AclItem *a1, AclItem *a2); static bool aclitemeq(AclItem *a1, AclItem *a2);
static int32 aclitemgt(AclItem *a1, AclItem *a2); static bool aclitemgt(AclItem *a1, AclItem *a2);
static char *aclparse(char *s, AclItem *aip, unsigned *modechg); static char *aclparse(char *s, AclItem *aip, unsigned *modechg);
#define ACL_IDTYPE_GID_KEYWORD "group" #define ACL_IDTYPE_GID_KEYWORD "group"
...@@ -229,18 +229,14 @@ makeacl(int n) ...@@ -229,18 +229,14 @@ makeacl(int n)
* RETURNS: * RETURNS:
* the new AclItem * the new AclItem
*/ */
AclItem * Datum
aclitemin(char *s) aclitemin(PG_FUNCTION_ARGS)
{ {
unsigned modechg; char *s = PG_GETARG_CSTRING(0);
AclItem *aip; AclItem *aip;
unsigned modechg;
if (!s)
elog(ERROR, "aclitemin: null string");
aip = (AclItem *) palloc(sizeof(AclItem)); aip = (AclItem *) palloc(sizeof(AclItem));
if (!aip)
elog(ERROR, "aclitemin: palloc failed");
s = aclparse(s, aip, &modechg); s = aclparse(s, aip, &modechg);
if (modechg != ACL_MODECHG_EQL) if (modechg != ACL_MODECHG_EQL)
elog(ERROR, "aclitemin: cannot accept anything but = ACLs"); elog(ERROR, "aclitemin: cannot accept anything but = ACLs");
...@@ -248,7 +244,7 @@ aclitemin(char *s) ...@@ -248,7 +244,7 @@ aclitemin(char *s)
++s; ++s;
if (*s) if (*s)
elog(ERROR, "aclitemin: extra garbage at end of specification"); elog(ERROR, "aclitemin: extra garbage at end of specification");
return aip; PG_RETURN_ACLITEM_P(aip);
} }
/* /*
...@@ -259,24 +255,17 @@ aclitemin(char *s) ...@@ -259,24 +255,17 @@ aclitemin(char *s)
* RETURNS: * RETURNS:
* the new string * the new string
*/ */
char * Datum
aclitemout(AclItem *aip) aclitemout(PG_FUNCTION_ARGS)
{ {
AclItem *aip = PG_GETARG_ACLITEM_P(0);
char *p; char *p;
char *out; char *out;
HeapTuple htup; HeapTuple htup;
unsigned i; unsigned i;
static AclItem default_aclitem = {ACL_ID_WORLD,
ACL_IDTYPE_WORLD,
ACL_WORLD_DEFAULT};
char *tmpname; char *tmpname;
if (!aip)
aip = &default_aclitem;
p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN); p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN);
if (!out)
elog(ERROR, "aclitemout: palloc failed");
*p = '\0'; *p = '\0';
switch (aip->ai_idtype) switch (aip->ai_idtype)
...@@ -319,36 +308,28 @@ aclitemout(AclItem *aip) ...@@ -319,36 +308,28 @@ aclitemout(AclItem *aip)
*p++ = ACL_MODE_STR[i]; *p++ = ACL_MODE_STR[i];
*p = '\0'; *p = '\0';
return out; PG_RETURN_CSTRING(out);
} }
/* /*
* aclitemeq * aclitemeq
* aclitemgt * aclitemgt
* AclItem equality and greater-than comparison routines. * AclItem equality and greater-than comparison routines.
* Two AclItems are equal iff they are both NULL or they have the * Two AclItems are equal iff they have the
* same identifier (and identifier type). * same identifier (and identifier type).
* *
* RETURNS: * RETURNS:
* a boolean value indicating = or > * a boolean value indicating = or >
*/ */
static int32 static bool
aclitemeq(AclItem *a1, AclItem *a2) aclitemeq(AclItem *a1, AclItem *a2)
{ {
if (!a1 && !a2)
return 1;
if (!a1 || !a2)
return 0;
return a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id; return a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id;
} }
static int32 static bool
aclitemgt(AclItem *a1, AclItem *a2) aclitemgt(AclItem *a1, AclItem *a2)
{ {
if (a1 && !a2)
return 1;
if (!a1 || !a2)
return 0;
return ((a1->ai_idtype > a2->ai_idtype) || return ((a1->ai_idtype > a2->ai_idtype) ||
(a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id)); (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id));
} }
...@@ -384,25 +365,28 @@ acldefault(char *relname) ...@@ -384,25 +365,28 @@ acldefault(char *relname)
return acl; return acl;
} }
/*
* Add or replace an item in an ACL array.
*
* NB: caller is responsible for having detoasted the input ACL, if needed.
*/
Acl * Acl *
aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg)
{ {
Acl *new_acl; Acl *new_acl;
AclItem *old_aip, AclItem *old_aip,
*new_aip; *new_aip;
unsigned src, int src,
dst, dst,
num; num;
/* These checks for null input are probably dead code, but... */
if (!old_acl || ACL_NUM(old_acl) < 1) if (!old_acl || ACL_NUM(old_acl) < 1)
{ old_acl = makeacl(0);
new_acl = makeacl(0);
return new_acl;
}
if (!mod_aip) if (!mod_aip)
{ {
new_acl = makeacl(ACL_NUM(old_acl)); new_acl = makeacl(ACL_NUM(old_acl));
memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
return new_acl; return new_acl;
} }
...@@ -422,7 +406,7 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) ...@@ -422,7 +406,7 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg)
{ {
/* modify in-place */ /* modify in-place */
new_acl = makeacl(ACL_NUM(old_acl)); new_acl = makeacl(ACL_NUM(old_acl));
memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
new_aip = ACL_DAT(new_acl); new_aip = ACL_DAT(new_acl);
src = dst; src = dst;
} }
...@@ -470,60 +454,58 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) ...@@ -470,60 +454,58 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg)
/* /*
* if the newly added entry has no permissions, delete it from the * if the newly added entry has no permissions, delete it from the
* list. For example, this helps in removing entries for users who no * list. For example, this helps in removing entries for users who no
* longer exists... * longer exist...
*/ */
for (dst = 1; dst < num; dst++) if (new_aip[dst].ai_mode == 0)
{ {
if (new_aip[dst].ai_mode == 0) int i;
{
int i;
for (i = dst + 1; i < num; i++) for (i = dst + 1; i < num; i++)
{ {
new_aip[i - 1].ai_id = new_aip[i].ai_id; new_aip[i - 1].ai_id = new_aip[i].ai_id;
new_aip[i - 1].ai_idtype = new_aip[i].ai_idtype; new_aip[i - 1].ai_idtype = new_aip[i].ai_idtype;
new_aip[i - 1].ai_mode = new_aip[i].ai_mode; new_aip[i - 1].ai_mode = new_aip[i].ai_mode;
}
ARR_DIMS(new_acl)[0] = num - 1;
/* Adjust also the array size because it is used for memmove */
ARR_SIZE(new_acl) -= sizeof(AclItem);
break;
} }
ARR_DIMS(new_acl)[0] = num - 1;
/* Adjust also the array size because it is used for memmove */
ARR_SIZE(new_acl) -= sizeof(AclItem);
} }
return new_acl; return new_acl;
} }
/* /*
* aclinsert * aclinsert (exported function)
*
*/ */
Acl * Datum
aclinsert(Acl *old_acl, AclItem *mod_aip) aclinsert(PG_FUNCTION_ARGS)
{ {
return aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL); Acl *old_acl = PG_GETARG_ACL_P(0);
AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL));
} }
Acl * Datum
aclremove(Acl *old_acl, AclItem *mod_aip) aclremove(PG_FUNCTION_ARGS)
{ {
Acl *old_acl = PG_GETARG_ACL_P(0);
AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
Acl *new_acl; Acl *new_acl;
AclItem *old_aip, AclItem *old_aip,
*new_aip; *new_aip;
unsigned dst, int dst,
old_num, old_num,
new_num; new_num;
/* These checks for null input should be dead code, but... */
if (!old_acl || ACL_NUM(old_acl) < 1) if (!old_acl || ACL_NUM(old_acl) < 1)
{ old_acl = makeacl(0);
new_acl = makeacl(0);
return new_acl;
}
if (!mod_aip) if (!mod_aip)
{ {
new_acl = makeacl(ACL_NUM(old_acl)); new_acl = makeacl(ACL_NUM(old_acl));
memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
return new_acl; PG_RETURN_ACL_P(new_acl);
} }
old_num = ACL_NUM(old_acl); old_num = ACL_NUM(old_acl);
...@@ -534,12 +516,12 @@ aclremove(Acl *old_acl, AclItem *mod_aip) ...@@ -534,12 +516,12 @@ aclremove(Acl *old_acl, AclItem *mod_aip)
if (dst >= old_num) if (dst >= old_num)
{ /* not found or empty */ { /* not found or empty */
new_acl = makeacl(ACL_NUM(old_acl)); new_acl = makeacl(ACL_NUM(old_acl));
memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
} }
else else
{ {
new_num = old_num - 1; new_num = old_num - 1;
new_acl = makeacl(ACL_NUM(old_acl) - 1); new_acl = makeacl(new_num);
new_aip = ACL_DAT(new_acl); new_aip = ACL_DAT(new_acl);
if (dst == 0) if (dst == 0)
{ /* start */ { /* start */
...@@ -561,23 +543,24 @@ aclremove(Acl *old_acl, AclItem *mod_aip) ...@@ -561,23 +543,24 @@ aclremove(Acl *old_acl, AclItem *mod_aip)
(new_num - dst) * sizeof(AclItem)); (new_num - dst) * sizeof(AclItem));
} }
} }
return new_acl; PG_RETURN_ACL_P(new_acl);
} }
int32 Datum
aclcontains(Acl *acl, AclItem *aip) aclcontains(PG_FUNCTION_ARGS)
{ {
unsigned i, Acl *acl = PG_GETARG_ACL_P(0);
num; AclItem *aip = PG_GETARG_ACLITEM_P(1);
AclItem *aidat; AclItem *aidat;
int i,
num;
if (!acl || !aip || ((num = ACL_NUM(acl)) < 1)) num = ACL_NUM(acl);
return 0;
aidat = ACL_DAT(acl); aidat = ACL_DAT(acl);
for (i = 0; i < num; ++i) for (i = 0; i < num; ++i)
if (aclitemeq(aip, aidat + i)) if (aclitemeq(aip, aidat + i))
return 1; PG_RETURN_BOOL(true);
return 0; PG_RETURN_BOOL(false);
} }
/* parser support routines */ /* parser support routines */
...@@ -638,7 +621,7 @@ aclmakepriv(char *old_privlist, char new_priv) ...@@ -638,7 +621,7 @@ aclmakepriv(char *old_privlist, char new_priv)
* "G" - group * "G" - group
* "U" - user * "U" - user
* *
* concatentates the two strings together with a space in between * concatenates the two strings together with a space in between
* *
* this routine is used in the parser * this routine is used in the parser
* *
...@@ -649,7 +632,7 @@ aclmakeuser(char *user_type, char *user) ...@@ -649,7 +632,7 @@ aclmakeuser(char *user_type, char *user)
{ {
char *user_list; char *user_list;
user_list = palloc(strlen(user) + 3); user_list = palloc(strlen(user_type) + strlen(user) + 2);
sprintf(user_list, "%s %s", user_type, user); sprintf(user_list, "%s %s", user_type, user);
return user_list; return user_list;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_attribute.h,v 1.61 2000/07/03 23:10:05 wieck Exp $ * $Id: pg_attribute.h,v 1.62 2000/07/31 22:39:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -124,15 +124,16 @@ CATALOG(pg_attribute) BOOTSTRAP ...@@ -124,15 +124,16 @@ CATALOG(pg_attribute) BOOTSTRAP
char attstorage; char attstorage;
/* /*----------
* attstorage tells for VARLENA attributes, what the heap access * attstorage tells for VARLENA attributes, what the heap access
* methods can do to it if a given tuple doesn't fit into a page. * methods can do to it if a given tuple doesn't fit into a page.
* Possible values are 'p': Value must be stored plain allways 'e': * Possible values are
* Value can be stored in "secondary" relation (if relation has * 'p': Value must be stored plain always
* rellongrelid attached) 'c': Value can be stored compressed inline * 'e': Value can be stored in "secondary" relation (if relation
* 'x': Value can be stored compressed inline or in "secondary". * has rellongrelid attached)
* * 'm': Value can be stored compressed inline
* Note: compressed storage * 'x': Value can be stored compressed inline or in "secondary"
*----------
*/ */
bool attisset; bool attisset;
...@@ -439,7 +440,7 @@ DATA(insert OID = 0 ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i f f)); ...@@ -439,7 +440,7 @@ DATA(insert OID = 0 ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
{ 1259, {"relhaspkey"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhaspkey"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1259, {"relhasrules"}, 16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhasrules"}, 16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1259, {"relhassubclass"},16, 0, 1, 20, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhassubclass"},16, 0, 1, 20, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1259, {"relacl"}, 1034, 0, -1, 21, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } { 1259, {"relacl"}, 1034, 0, -1, 21, 0, -1, -1, '\0', 'm', '\0', 'i', '\0', '\0' }
DATA(insert OID = 0 ( 1259 relname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 relname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1259 reltype 26 0 4 2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 reltype 26 0 4 2 0 -1 -1 t p f i f f));
...@@ -461,7 +462,7 @@ DATA(insert OID = 0 ( 1259 relrefs 21 0 2 17 0 -1 -1 t p f s f f)); ...@@ -461,7 +462,7 @@ DATA(insert OID = 0 ( 1259 relrefs 21 0 2 17 0 -1 -1 t p f s f f));
DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 18 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 18 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 19 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 19 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 20 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 20 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 21 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 21 0 -1 -1 f m f i f f));
DATA(insert OID = 0 ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.153 2000/07/30 22:14:01 tgl Exp $ * $Id: pg_proc.h,v 1.154 2000/07/31 22:39:05 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -1256,16 +1256,16 @@ DATA(insert OID = 1029 ( nullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100 ...@@ -1256,16 +1256,16 @@ DATA(insert OID = 1029 ( nullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100
DESCR("(internal)"); DESCR("(internal)");
DATA(insert OID = 1030 ( nonnullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100 nonnullvalue - )); DATA(insert OID = 1030 ( nonnullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100 nonnullvalue - ));
DESCR("(internal)"); DESCR("(internal)");
DATA(insert OID = 1031 ( aclitemin PGUID 11 f t f t 1 f 1033 "0" 100 0 0 100 aclitemin - )); DATA(insert OID = 1031 ( aclitemin PGUID 12 f t f t 1 f 1033 "0" 100 0 0 100 aclitemin - ));
DESCR("(internal)"); DESCR("(internal)");
DATA(insert OID = 1032 ( aclitemout PGUID 11 f t f t 1 f 23 "0" 100 0 0 100 aclitemout - )); DATA(insert OID = 1032 ( aclitemout PGUID 12 f t f t 1 f 23 "1033" 100 0 0 100 aclitemout - ));
DESCR("(internal)"); DESCR("(internal)");
DATA(insert OID = 1035 ( aclinsert PGUID 11 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclinsert - )); DATA(insert OID = 1035 ( aclinsert PGUID 12 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclinsert - ));
DESCR("addition"); DESCR("add/update ACL item");
DATA(insert OID = 1036 ( aclremove PGUID 11 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclremove - )); DATA(insert OID = 1036 ( aclremove PGUID 12 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclremove - ));
DESCR("subtract"); DESCR("remove ACL item");
DATA(insert OID = 1037 ( aclcontains PGUID 11 f t f t 2 f 16 "1034 1033" 100 0 0 100 aclcontains - )); DATA(insert OID = 1037 ( aclcontains PGUID 12 f t f t 2 f 16 "1034 1033" 100 0 0 100 aclcontains - ));
DESCR("matches regex., case-sensitive"); DESCR("does ACL contain item?");
DATA(insert OID = 1038 ( seteval PGUID 12 f t f t 1 f 23 "26" 100 0 0 100 seteval - )); DATA(insert OID = 1038 ( seteval PGUID 12 f t f t 1 f 23 "26" 100 0 0 100 seteval - ));
DESCR(""); DESCR("");
DATA(insert OID = 1044 ( bpcharin PGUID 12 f t t t 3 f 1042 "0 26 23" 100 0 0 100 bpcharin - )); DATA(insert OID = 1044 ( bpcharin PGUID 12 f t t t 3 f 1042 "0 26 23" 100 0 0 100 bpcharin - ));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1995, Regents of the University of California * Portions Copyright (c) 1995, Regents of the University of California
* *
* $Id: postgres.h,v 1.43 2000/07/03 23:09:56 wieck Exp $ * $Id: postgres.h,v 1.44 2000/07/31 22:39:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
typedef int4 aclitem;
#define InvalidOid ((Oid) 0) #define InvalidOid ((Oid) 0)
#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid)) #define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
...@@ -57,6 +55,8 @@ typedef Oid RegProcedure; ...@@ -57,6 +55,8 @@ typedef Oid RegProcedure;
#define RegProcedureIsValid(p) OidIsValid(p) #define RegProcedureIsValid(p) OidIsValid(p)
typedef int4 aclitem; /* PHONY definition for catalog use only */
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Section 2: variable length and array types * Section 2: variable length and array types
* ---------------------------------------------------------------- * ----------------------------------------------------------------
......
...@@ -7,17 +7,16 @@ ...@@ -7,17 +7,16 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: acl.h,v 1.25 2000/04/12 17:16:54 momjian Exp $ * $Id: acl.h,v 1.26 2000/07/31 22:39:02 tgl Exp $
* *
* NOTES * NOTES
* For backward-compatability purposes we have to allow there * For backward-compatibility purposes we have to allow there
* to be a null ACL in a pg_class tuple. This will be defined as * to be a null ACL in a pg_class tuple. This will be defined as
* meaning "no protection" (i.e., old catalogs get old semantics). * meaning "no protection" (i.e., old catalogs get old semantics).
* *
* The AclItems in an ACL array are currently kept in sorted order. * The AclItems in an ACL array are currently kept in sorted order.
* Things will break hard if you change that without changing the * Things will break hard if you change that without changing the
* code wherever this is included. * code wherever this is included.
*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef ACL_H #ifndef ACL_H
...@@ -78,7 +77,7 @@ typedef struct AclItem ...@@ -78,7 +77,7 @@ typedef struct AclItem
AclMode ai_mode; AclMode ai_mode;
/* /*
* This is actually type 'aclitem', and we want a fixed size for for * This is actually type 'aclitem', and we want a fixed size for
* all platforms, so we pad this with dummies. * all platforms, so we pad this with dummies.
*/ */
char dummy1, char dummy1,
...@@ -88,22 +87,30 @@ typedef struct AclItem ...@@ -88,22 +87,30 @@ typedef struct AclItem
/* Note: if the size of AclItem changes, /* Note: if the size of AclItem changes,
change the aclitem typlen in pg_type.h */ change the aclitem typlen in pg_type.h */
/* /*
* The value of the first dimension-array element. Since these arrays * Definitions for convenient access to Acl (array of AclItem) and IdList
* always have a lower-bound of 0, this is the same as the number of * (array of AclId). These are standard Postgres arrays, but are restricted
* elements in the array. * to have one dimension. We also ignore the lower bound when reading,
* and set it to zero when writing.
*
* CAUTION: as of Postgres 7.1, these arrays are toastable (just like all
* other array types). Therefore, be careful to detoast them with the
* macros provided, unless you know for certain that a particular array
* can't have been toasted. Presently, we do not provide toast tables for
* pg_class or pg_group, so the entries in those tables won't have been
* stored externally --- but they could have been compressed!
*/ */
#define ARR_DIM0(a) (((unsigned *) (((char *) a) + sizeof(ArrayType)))[0])
/* /*
* Acl a one-dimensional POSTGRES array of AclItem * Acl a one-dimensional POSTGRES array of AclItem
*/ */
typedef ArrayType Acl; typedef ArrayType Acl;
#define ACL_NUM(ACL) ARR_DIM0(ACL) #define ACL_NUM(ACL) (ARR_DIMS(ACL)[0])
#define ACL_DAT(ACL) ((AclItem *) ARR_DATA_PTR(ACL)) #define ACL_DAT(ACL) ((AclItem *) ARR_DATA_PTR(ACL))
#define ACL_N_SIZE(N) \ #define ACL_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem)))
((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem))))
#define ACL_SIZE(ACL) ARR_SIZE(ACL) #define ACL_SIZE(ACL) ARR_SIZE(ACL)
/* /*
...@@ -111,12 +118,32 @@ typedef ArrayType Acl; ...@@ -111,12 +118,32 @@ typedef ArrayType Acl;
*/ */
typedef ArrayType IdList; typedef ArrayType IdList;
#define IDLIST_NUM(IDL) ARR_DIM0(IDL) #define IDLIST_NUM(IDL) (ARR_DIMS(IDL)[0])
#define IDLIST_DAT(IDL) ((AclId *) ARR_DATA_PTR(IDL)) #define IDLIST_DAT(IDL) ((AclId *) ARR_DATA_PTR(IDL))
#define IDLIST_N_SIZE(N) \ #define IDLIST_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId)))
((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId))))
#define IDLIST_SIZE(IDL) ARR_SIZE(IDL) #define IDLIST_SIZE(IDL) ARR_SIZE(IDL)
/*
* fmgr macros for these types
*/
#define DatumGetAclItemP(X) ((AclItem *) DatumGetPointer(X))
#define PG_GETARG_ACLITEM_P(n) DatumGetAclItemP(PG_GETARG_DATUM(n))
#define PG_RETURN_ACLITEM_P(x) PG_RETURN_POINTER(x)
#define DatumGetAclP(X) ((Acl *) PG_DETOAST_DATUM(X))
#define DatumGetAclPCopy(X) ((Acl *) PG_DETOAST_DATUM_COPY(X))
#define PG_GETARG_ACL_P(n) DatumGetAclP(PG_GETARG_DATUM(n))
#define PG_GETARG_ACL_P_COPY(n) DatumGetAclPCopy(PG_GETARG_DATUM(n))
#define PG_RETURN_ACL_P(x) PG_RETURN_POINTER(x)
#define DatumGetIdListP(X) ((IdList *) PG_DETOAST_DATUM(X))
#define DatumGetIdListPCopy(X) ((IdList *) PG_DETOAST_DATUM_COPY(X))
#define PG_GETARG_IDLIST_P(n) DatumGetIdListP(PG_GETARG_DATUM(n))
#define PG_GETARG_IDLIST_P_COPY(n) DatumGetIdListPCopy(PG_GETARG_DATUM(n))
#define PG_RETURN_IDLIST_P(x) PG_RETURN_POINTER(x)
/* mode indicators for I/O */
#define ACL_MODECHG_STR "+-=" /* list of valid characters */ #define ACL_MODECHG_STR "+-=" /* list of valid characters */
#define ACL_MODECHG_ADD_CHR '+' #define ACL_MODECHG_ADD_CHR '+'
#define ACL_MODECHG_DEL_CHR '-' #define ACL_MODECHG_DEL_CHR '-'
...@@ -157,11 +184,11 @@ extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee, ...@@ -157,11 +184,11 @@ extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee,
* exported routines (from acl.c) * exported routines (from acl.c)
*/ */
extern Acl *makeacl(int n); extern Acl *makeacl(int n);
extern AclItem *aclitemin(char *s); extern Datum aclitemin(PG_FUNCTION_ARGS);
extern char *aclitemout(AclItem *aip); extern Datum aclitemout(PG_FUNCTION_ARGS);
extern Acl *aclinsert(Acl *old_acl, AclItem *mod_aip); extern Datum aclinsert(PG_FUNCTION_ARGS);
extern Acl *aclremove(Acl *old_acl, AclItem *mod_aip); extern Datum aclremove(PG_FUNCTION_ARGS);
extern int32 aclcontains(Acl *acl, AclItem *aip); extern Datum aclcontains(PG_FUNCTION_ARGS);
/* /*
* prototypes for functions in aclchk.c * prototypes for functions in aclchk.c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment