aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r--src/backend/utils/adt/acl.c979
1 files changed, 523 insertions, 456 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 33580a95125..d4b8f1ca0b6 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* acl.c--
- * Basic access control list data structures manipulation routines.
+ * Basic access control list data structures manipulation routines.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.13 1997/08/19 21:34:10 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.14 1997/09/07 04:49:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,561 +21,629 @@
#include "utils/syscache.h"
#include "miscadmin.h"
-static char *getid(char *s, char *n);
-static int32 aclitemeq(AclItem *a1, AclItem *a2);
-static int32 aclitemgt(AclItem *a1, AclItem *a2);
-static char *aclparse(char *s, AclItem *aip, unsigned *modechg);
+static char *getid(char *s, char *n);
+static int32 aclitemeq(AclItem * a1, AclItem * a2);
+static int32 aclitemgt(AclItem * a1, AclItem * a2);
+static char *aclparse(char *s, AclItem * aip, unsigned *modechg);
-#define ACL_IDTYPE_GID_KEYWORD "group"
-#define ACL_IDTYPE_UID_KEYWORD "user"
+#define ACL_IDTYPE_GID_KEYWORD "group"
+#define ACL_IDTYPE_UID_KEYWORD "user"
/*
* getid
- * Consumes the first alphanumeric string (identifier) found in string
- * 's', ignoring any leading white space.
+ * Consumes the first alphanumeric string (identifier) found in string
+ * 's', ignoring any leading white space.
*
* RETURNS:
- * the string position in 's' that points to the next non-space character
- * in 's'. Also:
- * - loads the identifier into 'name'. (If no identifier is found, 'name'
- * contains an empty string).
+ * the string position in 's' that points to the next non-space character
+ * in 's'. Also:
+ * - loads the identifier into 'name'. (If no identifier is found, 'name'
+ * contains an empty string).
*/
-static char *
+static char *
getid(char *s, char *n)
{
- unsigned len;
- char *id;
-
- Assert(s && n);
-
- while (isspace(*s))
- ++s;
- for (id = s, len = 0; isalnum(*s) || *s == '_'; ++len, ++s)
- ;
- if (len > sizeof(NameData))
- elog(WARN, "getid: identifier cannot be >%d characters",
- sizeof(NameData));
- if (len > 0)
- memmove(n, id, len);
- n[len] = '\0';
- while (isspace(*s))
- ++s;
- return(s);
+ unsigned len;
+ char *id;
+
+ Assert(s && n);
+
+ while (isspace(*s))
+ ++s;
+ for (id = s, len = 0; isalnum(*s) || *s == '_'; ++len, ++s)
+ ;
+ if (len > sizeof(NameData))
+ elog(WARN, "getid: identifier cannot be >%d characters",
+ sizeof(NameData));
+ if (len > 0)
+ memmove(n, id, len);
+ n[len] = '\0';
+ while (isspace(*s))
+ ++s;
+ return (s);
}
/*
* aclparse
- * Consumes and parses an ACL specification of the form:
- * [group|user] [A-Za-z0-9]*[+-=][rwaR]*
- * from string 's', ignoring any leading white space or white space
- * between the optional id type keyword (group|user) and the actual
- * ACL specification.
+ * Consumes and parses an ACL specification of the form:
+ * [group|user] [A-Za-z0-9]*[+-=][rwaR]*
+ * from string 's', ignoring any leading white space or white space
+ * between the optional id type keyword (group|user) and the actual
+ * ACL specification.
*
- * This routine is called by the parser as well as aclitemin(), hence
- * the added generality.
+ * This routine is called by the parser as well as aclitemin(), hence
+ * the added generality.
*
* RETURNS:
- * the string position in 's' immediately following the ACL
- * specification. Also:
- * - loads the structure pointed to by 'aip' with the appropriate
- * UID/GID, id type identifier and mode type values.
- * - loads 'modechg' with the mode change flag.
+ * the string position in 's' immediately following the ACL
+ * specification. Also:
+ * - loads the structure pointed to by 'aip' with the appropriate
+ * UID/GID, id type identifier and mode type values.
+ * - loads 'modechg' with the mode change flag.
*/
-static char *
-aclparse(char *s, AclItem *aip, unsigned *modechg)
+static char *
+aclparse(char *s, AclItem * aip, unsigned *modechg)
{
- HeapTuple htp;
- char name[NAMEDATALEN];
-
- Assert(s && aip && modechg);
-
- aip->ai_idtype = ACL_IDTYPE_UID;
- s = getid(s, name);
- if (*s != ACL_MODECHG_ADD_CHR &&
- *s != ACL_MODECHG_DEL_CHR &&
- *s != ACL_MODECHG_EQL_CHR)
- { /* we just read a keyword, not a name */
- if (!strcmp(name, ACL_IDTYPE_GID_KEYWORD)) {
- aip->ai_idtype = ACL_IDTYPE_GID;
- } else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD)) {
- elog(WARN, "aclparse: bad keyword, must be [group|user]");
+ HeapTuple htp;
+ char name[NAMEDATALEN];
+
+ Assert(s && aip && modechg);
+
+ aip->ai_idtype = ACL_IDTYPE_UID;
+ s = getid(s, name);
+ if (*s != ACL_MODECHG_ADD_CHR &&
+ *s != ACL_MODECHG_DEL_CHR &&
+ *s != ACL_MODECHG_EQL_CHR)
+ { /* we just read a keyword, not a name */
+ if (!strcmp(name, ACL_IDTYPE_GID_KEYWORD))
+ {
+ aip->ai_idtype = ACL_IDTYPE_GID;
+ }
+ else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD))
+ {
+ elog(WARN, "aclparse: bad keyword, must be [group|user]");
+ }
+ s = getid(s, name); /* move s to the name beyond the keyword */
+ if (name[0] == '\0')
+ elog(WARN, "aclparse: a name must follow the [group|user] keyword");
}
- s = getid(s, name); /* move s to the name beyond the keyword */
if (name[0] == '\0')
- elog(WARN, "aclparse: a name must follow the [group|user] keyword");
- }
- if (name[0] == '\0')
- aip->ai_idtype = ACL_IDTYPE_WORLD;
-
- switch (*s) {
- case ACL_MODECHG_ADD_CHR: *modechg = ACL_MODECHG_ADD; break;
- case ACL_MODECHG_DEL_CHR: *modechg = ACL_MODECHG_DEL; break;
- case ACL_MODECHG_EQL_CHR: *modechg = ACL_MODECHG_EQL; break;
- default: elog(WARN, "aclparse: mode change flag must use \"%s\"",
- ACL_MODECHG_STR);
- }
-
- aip->ai_mode = ACL_NO;
- while (isalpha(*++s)) {
- switch (*s) {
- case ACL_MODE_AP_CHR: aip->ai_mode |= ACL_AP; break;
- case ACL_MODE_RD_CHR: aip->ai_mode |= ACL_RD; break;
- case ACL_MODE_WR_CHR: aip->ai_mode |= ACL_WR; break;
- case ACL_MODE_RU_CHR: aip->ai_mode |= ACL_RU; break;
- default: elog(WARN, "aclparse: mode flags must use \"%s\"",
- ACL_MODE_STR);
+ aip->ai_idtype = ACL_IDTYPE_WORLD;
+
+ switch (*s)
+ {
+ case ACL_MODECHG_ADD_CHR:
+ *modechg = ACL_MODECHG_ADD;
+ break;
+ case ACL_MODECHG_DEL_CHR:
+ *modechg = ACL_MODECHG_DEL;
+ break;
+ case ACL_MODECHG_EQL_CHR:
+ *modechg = ACL_MODECHG_EQL;
+ break;
+ default:
+ elog(WARN, "aclparse: mode change flag must use \"%s\"",
+ ACL_MODECHG_STR);
}
- }
-
- switch (aip->ai_idtype) {
- case ACL_IDTYPE_UID:
- htp = SearchSysCacheTuple(USENAME, PointerGetDatum(name),
- 0,0,0);
- if (!HeapTupleIsValid(htp))
- elog(WARN, "aclparse: non-existent user \"%s\"", name);
- aip->ai_id = ((Form_pg_user) GETSTRUCT(htp))->usesysid;
- break;
- case ACL_IDTYPE_GID:
- aip->ai_id = get_grosysid(name);
- break;
- case ACL_IDTYPE_WORLD:
- aip->ai_id = ACL_ID_WORLD;
- break;
- }
-
+
+ aip->ai_mode = ACL_NO;
+ while (isalpha(*++s))
+ {
+ switch (*s)
+ {
+ case ACL_MODE_AP_CHR:
+ aip->ai_mode |= ACL_AP;
+ break;
+ case ACL_MODE_RD_CHR:
+ aip->ai_mode |= ACL_RD;
+ break;
+ case ACL_MODE_WR_CHR:
+ aip->ai_mode |= ACL_WR;
+ break;
+ case ACL_MODE_RU_CHR:
+ aip->ai_mode |= ACL_RU;
+ break;
+ default:
+ elog(WARN, "aclparse: mode flags must use \"%s\"",
+ ACL_MODE_STR);
+ }
+ }
+
+ switch (aip->ai_idtype)
+ {
+ case ACL_IDTYPE_UID:
+ htp = SearchSysCacheTuple(USENAME, PointerGetDatum(name),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(htp))
+ elog(WARN, "aclparse: non-existent user \"%s\"", name);
+ aip->ai_id = ((Form_pg_user) GETSTRUCT(htp))->usesysid;
+ break;
+ case ACL_IDTYPE_GID:
+ aip->ai_id = get_grosysid(name);
+ break;
+ case ACL_IDTYPE_WORLD:
+ aip->ai_id = ACL_ID_WORLD;
+ break;
+ }
+
#ifdef ACLDEBUG_TRACE
- elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x",
- aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg);
+ elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x",
+ aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg);
#endif
- return(s);
+ return (s);
}
/*
* makeacl
- * Allocates storage for a new Acl with 'n' entries.
+ * Allocates storage for a new Acl with 'n' entries.
*
* RETURNS:
- * the new Acl
+ * the new Acl
*/
-Acl *
+Acl *
makeacl(int n)
{
- Acl *new_acl;
- Size size;
-
- if (n < 0)
- elog(WARN, "makeacl: invalid size: %d\n", n);
- size = ACL_N_SIZE(n);
- if (!(new_acl = (Acl *) palloc(size)))
- elog(WARN, "makeacl: palloc failed on %d\n", size);
- memset((char *) new_acl, 0, size);
- new_acl->size = size;
- new_acl->ndim = 1;
- new_acl->flags = 0;
- ARR_LBOUND(new_acl)[0] = 0;
- ARR_DIMS(new_acl)[0] = n;
- return(new_acl);
+ Acl *new_acl;
+ Size size;
+
+ if (n < 0)
+ elog(WARN, "makeacl: invalid size: %d\n", n);
+ size = ACL_N_SIZE(n);
+ if (!(new_acl = (Acl *) palloc(size)))
+ elog(WARN, "makeacl: palloc failed on %d\n", size);
+ memset((char *) new_acl, 0, size);
+ new_acl->size = size;
+ new_acl->ndim = 1;
+ new_acl->flags = 0;
+ ARR_LBOUND(new_acl)[0] = 0;
+ ARR_DIMS(new_acl)[0] = n;
+ return (new_acl);
}
/*
* aclitemin
- * Allocates storage for, and fills in, a new AclItem given a string
- * 's' that contains an ACL specification. See aclparse for details.
+ * Allocates storage for, and fills in, a new AclItem given a string
+ * 's' that contains an ACL specification. See aclparse for details.
*
* RETURNS:
- * the new AclItem
+ * the new AclItem
*/
-AclItem *
+AclItem *
aclitemin(char *s)
{
- unsigned modechg;
- AclItem *aip;
-
- if (!s)
- elog(WARN, "aclitemin: null string");
-
- aip = (AclItem *) palloc(sizeof(AclItem));
- if (!aip)
- elog(WARN, "aclitemin: palloc failed");
- s = aclparse(s, aip, &modechg);
- if (modechg != ACL_MODECHG_EQL)
- elog(WARN, "aclitemin: cannot accept anything but = ACLs");
- while (isspace(*s))
- ++s;
- if (*s)
- elog(WARN, "aclitemin: extra garbage at end of specification");
- return(aip);
+ unsigned modechg;
+ AclItem *aip;
+
+ if (!s)
+ elog(WARN, "aclitemin: null string");
+
+ aip = (AclItem *) palloc(sizeof(AclItem));
+ if (!aip)
+ elog(WARN, "aclitemin: palloc failed");
+ s = aclparse(s, aip, &modechg);
+ if (modechg != ACL_MODECHG_EQL)
+ elog(WARN, "aclitemin: cannot accept anything but = ACLs");
+ while (isspace(*s))
+ ++s;
+ if (*s)
+ elog(WARN, "aclitemin: extra garbage at end of specification");
+ return (aip);
}
/*
* aclitemout
- * Allocates storage for, and fills in, a new null-delimited string
- * containing a formatted ACL specification. See aclparse for details.
+ * Allocates storage for, and fills in, a new null-delimited string
+ * containing a formatted ACL specification. See aclparse for details.
*
* RETURNS:
- * the new string
+ * the new string
*/
-char *
-aclitemout(AclItem *aip)
+char *
+aclitemout(AclItem * aip)
{
- register char *p;
- char *out;
- HeapTuple htp;
- unsigned i;
- static AclItem default_aclitem = { ACL_ID_WORLD,
- ACL_IDTYPE_WORLD,
- ACL_WORLD_DEFAULT };
- extern char *int2out();
- char *tmpname;
-
- if (!aip)
- aip = &default_aclitem;
-
- p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN);
- if (!out)
- elog(WARN, "aclitemout: palloc failed");
- *p = '\0';
-
- switch (aip->ai_idtype) {
- case ACL_IDTYPE_UID:
- htp = SearchSysCacheTuple(USESYSID, ObjectIdGetDatum(aip->ai_id),
- 0,0,0);
- if (!HeapTupleIsValid(htp)) {
- char *tmp = int2out(aip->ai_id);
-
- elog(NOTICE, "aclitemout: usesysid %d not found",
- aip->ai_id);
- strcat(p, tmp);
- pfree(tmp);
- } else
- strncat(p, (char *) &((Form_pg_user)
- GETSTRUCT(htp))->usename,
- sizeof(NameData));
- break;
- case ACL_IDTYPE_GID:
- strcat(p, "group ");
- tmpname = get_groname(aip->ai_id);
- strncat(p, tmpname, NAMEDATALEN);
- break;
- case ACL_IDTYPE_WORLD:
- break;
- default:
- elog(WARN, "aclitemout: bad ai_idtype: %d", aip->ai_idtype);
- break;
- }
- while (*p)
- ++p;
- *p++ = '=';
- for (i = 0; i < N_ACL_MODES; ++i)
- if ((aip->ai_mode >> i) & 01)
- *p++ = ACL_MODE_STR[i];
- *p = '\0';
-
- return(out);
+ register char *p;
+ char *out;
+ HeapTuple htp;
+ unsigned i;
+ static AclItem default_aclitem = {ACL_ID_WORLD,
+ ACL_IDTYPE_WORLD,
+ ACL_WORLD_DEFAULT};
+ extern char *int2out();
+ char *tmpname;
+
+ if (!aip)
+ aip = &default_aclitem;
+
+ p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN);
+ if (!out)
+ elog(WARN, "aclitemout: palloc failed");
+ *p = '\0';
+
+ switch (aip->ai_idtype)
+ {
+ case ACL_IDTYPE_UID:
+ htp = SearchSysCacheTuple(USESYSID, ObjectIdGetDatum(aip->ai_id),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(htp))
+ {
+ char *tmp = int2out(aip->ai_id);
+
+ elog(NOTICE, "aclitemout: usesysid %d not found",
+ aip->ai_id);
+ strcat(p, tmp);
+ pfree(tmp);
+ }
+ else
+ strncat(p, (char *) &((Form_pg_user)
+ GETSTRUCT(htp))->usename,
+ sizeof(NameData));
+ break;
+ case ACL_IDTYPE_GID:
+ strcat(p, "group ");
+ tmpname = get_groname(aip->ai_id);
+ strncat(p, tmpname, NAMEDATALEN);
+ break;
+ case ACL_IDTYPE_WORLD:
+ break;
+ default:
+ elog(WARN, "aclitemout: bad ai_idtype: %d", aip->ai_idtype);
+ break;
+ }
+ while (*p)
+ ++p;
+ *p++ = '=';
+ for (i = 0; i < N_ACL_MODES; ++i)
+ if ((aip->ai_mode >> i) & 01)
+ *p++ = ACL_MODE_STR[i];
+ *p = '\0';
+
+ return (out);
}
/*
* aclitemeq
* aclitemgt
- * AclItem equality and greater-than comparison routines.
- * Two AclItems are equal iff they are both NULL or they have the
- * same identifier (and identifier type).
+ * AclItem equality and greater-than comparison routines.
+ * Two AclItems are equal iff they are both NULL or they have the
+ * same identifier (and identifier type).
*
* RETURNS:
- * a boolean value indicating = or >
+ * a boolean value indicating = or >
*/
-static int32
-aclitemeq(AclItem *a1, AclItem *a2)
+static int32
+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);
+ if (!a1 && !a2)
+ return (1);
+ if (!a1 || !a2)
+ return (0);
+ return (a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id);
}
-static int32
-aclitemgt(AclItem *a1, AclItem *a2)
+static int32
+aclitemgt(AclItem * a1, AclItem * a2)
{
- if (a1 && !a2)
- return(1);
- if (!a1 || !a2)
- return(0);
- return((a1->ai_idtype > a2->ai_idtype) ||
- (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id));
+ if (a1 && !a2)
+ return (1);
+ if (!a1 || !a2)
+ return (0);
+ return ((a1->ai_idtype > a2->ai_idtype) ||
+ (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id));
}
-Acl *
+Acl *
aclownerdefault(AclId ownerid)
{
- Acl *acl;
- AclItem *aip;
-
- acl = makeacl(2);
- aip = ACL_DAT(acl);
- aip[0].ai_idtype = ACL_IDTYPE_WORLD;
- aip[0].ai_id = ACL_ID_WORLD;
- aip[0].ai_mode = ACL_WORLD_DEFAULT;
- aip[1].ai_idtype = ACL_IDTYPE_UID;
- aip[1].ai_id = ownerid;
- aip[1].ai_mode = ACL_OWNER_DEFAULT;
- return(acl);
+ Acl *acl;
+ AclItem *aip;
+
+ acl = makeacl(2);
+ aip = ACL_DAT(acl);
+ aip[0].ai_idtype = ACL_IDTYPE_WORLD;
+ aip[0].ai_id = ACL_ID_WORLD;
+ aip[0].ai_mode = ACL_WORLD_DEFAULT;
+ aip[1].ai_idtype = ACL_IDTYPE_UID;
+ aip[1].ai_id = ownerid;
+ aip[1].ai_mode = ACL_OWNER_DEFAULT;
+ return (acl);
}
-Acl *
+Acl *
acldefault(void)
{
- Acl *acl;
- AclItem *aip;
-
- acl = makeacl(1);
- aip = ACL_DAT(acl);
- aip[0].ai_idtype = ACL_IDTYPE_WORLD;
- aip[0].ai_id = ACL_ID_WORLD;
- aip[0].ai_mode = ACL_WORLD_DEFAULT;
- return(acl);
+ Acl *acl;
+ AclItem *aip;
+
+ acl = makeacl(1);
+ aip = ACL_DAT(acl);
+ aip[0].ai_idtype = ACL_IDTYPE_WORLD;
+ aip[0].ai_id = ACL_ID_WORLD;
+ aip[0].ai_mode = ACL_WORLD_DEFAULT;
+ return (acl);
}
-Acl *
-aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg)
+Acl *
+aclinsert3(Acl * old_acl, AclItem * mod_aip, unsigned modechg)
{
- Acl *new_acl;
- AclItem *old_aip, *new_aip;
- unsigned src, dst, num;
-
- if (!old_acl || ACL_NUM(old_acl) < 1) {
- new_acl = makeacl(0);
- return(new_acl);
- }
- if (!mod_aip) {
- new_acl = makeacl(ACL_NUM(old_acl));
- memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
- return(new_acl);
- }
-
- num = ACL_NUM(old_acl);
- old_aip = ACL_DAT(old_acl);
-
- /*
- * Search the ACL for an existing entry for 'id'. If one exists,
- * just modify the entry in-place (well, in the same position, since
- * we actually return a copy); otherwise, insert the new entry in
- * sort-order.
- */
- /* find the first element not less than the element to be inserted */
- for (dst = 0; dst < num && aclitemgt(mod_aip, old_aip+dst); ++dst)
- ;
- if (dst < num && aclitemeq(mod_aip, old_aip+dst)) {
- /* modify in-place */
- new_acl = makeacl(ACL_NUM(old_acl));
- memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
- new_aip = ACL_DAT(new_acl);
- src = dst;
- } else {
- new_acl = makeacl(num + 1);
- new_aip = ACL_DAT(new_acl);
- if (dst == 0) { /* start */
- elog(WARN, "aclinsert3: insertion before world ACL??");
- } else if (dst >= num) { /* end */
- memmove((char *) new_aip,
- (char *) old_aip,
- num * sizeof(AclItem));
- } else { /* middle */
- memmove((char *) new_aip,
- (char *) old_aip,
- dst * sizeof(AclItem));
- memmove((char *) (new_aip+dst+1),
- (char *) (old_aip+dst),
- (num - dst) * sizeof(AclItem));
+ Acl *new_acl;
+ AclItem *old_aip,
+ *new_aip;
+ unsigned src,
+ dst,
+ num;
+
+ if (!old_acl || ACL_NUM(old_acl) < 1)
+ {
+ new_acl = makeacl(0);
+ return (new_acl);
}
- new_aip[dst].ai_id = mod_aip->ai_id;
- new_aip[dst].ai_idtype = mod_aip->ai_idtype;
- num++; /* set num to the size of new_acl */
- src = 0; /* world entry */
- }
- switch (modechg) {
- case ACL_MODECHG_ADD: new_aip[dst].ai_mode =
- old_aip[src].ai_mode | mod_aip->ai_mode;
- break;
- case ACL_MODECHG_DEL: new_aip[dst].ai_mode =
- old_aip[src].ai_mode & ~mod_aip->ai_mode;
- break;
- case ACL_MODECHG_EQL: new_aip[dst].ai_mode =
- mod_aip->ai_mode;
- break;
- }
- /* if the newly added entry has no permissions, delete it from
- the list. For example, this helps in removing entries for users who
- no longer exists...*/
- for (dst = 1; dst < num; dst++) {
- if (new_aip[dst].ai_mode == 0) {
- int i;
- for (i=dst+1; i<num; i++) {
- 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_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;
+ if (!mod_aip)
+ {
+ new_acl = makeacl(ACL_NUM(old_acl));
+ memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
+ return (new_acl);
}
- }
- return(new_acl);
+ num = ACL_NUM(old_acl);
+ old_aip = ACL_DAT(old_acl);
+
+ /*
+ * Search the ACL for an existing entry for 'id'. If one exists, just
+ * modify the entry in-place (well, in the same position, since we
+ * actually return a copy); otherwise, insert the new entry in
+ * sort-order.
+ */
+ /* find the first element not less than the element to be inserted */
+ for (dst = 0; dst < num && aclitemgt(mod_aip, old_aip + dst); ++dst)
+ ;
+ if (dst < num && aclitemeq(mod_aip, old_aip + dst))
+ {
+ /* modify in-place */
+ new_acl = makeacl(ACL_NUM(old_acl));
+ memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
+ new_aip = ACL_DAT(new_acl);
+ src = dst;
+ }
+ else
+ {
+ new_acl = makeacl(num + 1);
+ new_aip = ACL_DAT(new_acl);
+ if (dst == 0)
+ { /* start */
+ elog(WARN, "aclinsert3: insertion before world ACL??");
+ }
+ else if (dst >= num)
+ { /* end */
+ memmove((char *) new_aip,
+ (char *) old_aip,
+ num * sizeof(AclItem));
+ }
+ else
+ { /* middle */
+ memmove((char *) new_aip,
+ (char *) old_aip,
+ dst * sizeof(AclItem));
+ memmove((char *) (new_aip + dst + 1),
+ (char *) (old_aip + dst),
+ (num - dst) * sizeof(AclItem));
+ }
+ new_aip[dst].ai_id = mod_aip->ai_id;
+ new_aip[dst].ai_idtype = mod_aip->ai_idtype;
+ num++; /* set num to the size of new_acl */
+ src = 0; /* world entry */
+ }
+ switch (modechg)
+ {
+ case ACL_MODECHG_ADD:
+ new_aip[dst].ai_mode =
+ old_aip[src].ai_mode | mod_aip->ai_mode;
+ break;
+ case ACL_MODECHG_DEL:
+ new_aip[dst].ai_mode =
+ old_aip[src].ai_mode & ~mod_aip->ai_mode;
+ break;
+ case ACL_MODECHG_EQL:
+ new_aip[dst].ai_mode =
+ mod_aip->ai_mode;
+ break;
+ }
+
+ /*
+ * if the newly added entry has no permissions, delete it from the
+ * list. For example, this helps in removing entries for users who no
+ * longer exists...
+ */
+ for (dst = 1; dst < num; dst++)
+ {
+ if (new_aip[dst].ai_mode == 0)
+ {
+ int i;
+
+ for (i = dst + 1; i < num; i++)
+ {
+ 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_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;
+ }
+ }
+
+ return (new_acl);
}
/*
* aclinsert
*
*/
-Acl *
-aclinsert(Acl *old_acl, AclItem *mod_aip)
+Acl *
+aclinsert(Acl * old_acl, AclItem * mod_aip)
{
- return(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL));
+ return (aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL));
}
-Acl *
-aclremove(Acl *old_acl, AclItem *mod_aip)
+Acl *
+aclremove(Acl * old_acl, AclItem * mod_aip)
{
- Acl *new_acl;
- AclItem *old_aip, *new_aip;
- unsigned dst, old_num, new_num;
-
- if (!old_acl || ACL_NUM(old_acl) < 1) {
- new_acl = makeacl(0);
- return(new_acl);
- }
- if (!mod_aip) {
- new_acl = makeacl(ACL_NUM(old_acl));
- memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
- return(new_acl);
- }
-
- old_num = ACL_NUM(old_acl);
- old_aip = ACL_DAT(old_acl);
-
- for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip+dst); ++dst)
- ;
- if (dst >= old_num) { /* not found or empty */
- new_acl = makeacl(ACL_NUM(old_acl));
- memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
- } else {
- new_num = old_num - 1;
- new_acl = makeacl(ACL_NUM(old_acl) - 1);
- new_aip = ACL_DAT(new_acl);
- if (dst == 0) { /* start */
- elog(WARN, "aclremove: removal of the world ACL??");
- } else if (dst == old_num - 1) {/* end */
- memmove((char *) new_aip,
- (char *) old_aip,
- new_num * sizeof(AclItem));
- } else { /* middle */
- memmove((char *) new_aip,
- (char *) old_aip,
- dst * sizeof(AclItem));
- memmove((char *) (new_aip+dst),
- (char *) (old_aip+dst+1),
- (new_num - dst) * sizeof(AclItem));
+ Acl *new_acl;
+ AclItem *old_aip,
+ *new_aip;
+ unsigned dst,
+ old_num,
+ new_num;
+
+ if (!old_acl || ACL_NUM(old_acl) < 1)
+ {
+ new_acl = makeacl(0);
+ return (new_acl);
}
- }
- return(new_acl);
+ if (!mod_aip)
+ {
+ new_acl = makeacl(ACL_NUM(old_acl));
+ memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
+ return (new_acl);
+ }
+
+ old_num = ACL_NUM(old_acl);
+ old_aip = ACL_DAT(old_acl);
+
+ for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip + dst); ++dst)
+ ;
+ if (dst >= old_num)
+ { /* not found or empty */
+ new_acl = makeacl(ACL_NUM(old_acl));
+ memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
+ }
+ else
+ {
+ new_num = old_num - 1;
+ new_acl = makeacl(ACL_NUM(old_acl) - 1);
+ new_aip = ACL_DAT(new_acl);
+ if (dst == 0)
+ { /* start */
+ elog(WARN, "aclremove: removal of the world ACL??");
+ }
+ else if (dst == old_num - 1)
+ { /* end */
+ memmove((char *) new_aip,
+ (char *) old_aip,
+ new_num * sizeof(AclItem));
+ }
+ else
+ { /* middle */
+ memmove((char *) new_aip,
+ (char *) old_aip,
+ dst * sizeof(AclItem));
+ memmove((char *) (new_aip + dst),
+ (char *) (old_aip + dst + 1),
+ (new_num - dst) * sizeof(AclItem));
+ }
+ }
+ return (new_acl);
}
int32
-aclcontains(Acl *acl, AclItem *aip)
+aclcontains(Acl * acl, AclItem * aip)
{
- unsigned i, num;
- AclItem *aidat;
-
- if (!acl || !aip || ((num = ACL_NUM(acl)) < 1))
- return(0);
- aidat = ACL_DAT(acl);
- for (i = 0; i < num; ++i)
- if (aclitemeq(aip, aidat+i))
- return(1);
- return(0);
+ unsigned i,
+ num;
+ AclItem *aidat;
+
+ if (!acl || !aip || ((num = ACL_NUM(acl)) < 1))
+ return (0);
+ aidat = ACL_DAT(acl);
+ for (i = 0; i < num; ++i)
+ if (aclitemeq(aip, aidat + i))
+ return (1);
+ return (0);
}
/* parser support routines */
/*
* aclmakepriv
- * make a acl privilege string out of an existing privilege string
+ * make a acl privilege string out of an existing privilege string
* and a new privilege
*
* does not add duplicate privileges
- *
+ *
* the CALLER is reponsible for free'ing the string returned
*/
-char*
-aclmakepriv(char* old_privlist, char new_priv)
+char *
+aclmakepriv(char *old_privlist, char new_priv)
{
- char* priv;
- int i;
- int l;
+ char *priv;
+ int i;
+ int l;
- Assert(strlen(old_privlist)<5);
- priv = malloc(5); /* at most "rwaR" */;
+ Assert(strlen(old_privlist) < 5);
+ priv = malloc(5); /* at most "rwaR" */ ;
- if (old_privlist == NULL || old_privlist[0] == '\0') {
- priv[0] = new_priv;
- priv[1] = '\0';
- return priv;
- }
+ if (old_privlist == NULL || old_privlist[0] == '\0')
+ {
+ priv[0] = new_priv;
+ priv[1] = '\0';
+ return priv;
+ }
+
+ strcpy(priv, old_privlist);
+
+ l = strlen(old_privlist);
- strcpy(priv,old_privlist);
-
- l = strlen(old_privlist);
+ if (l == 4)
+ { /* can't add any more privileges */
+ return priv;
+ }
+
+ /* check to see if the new privilege is already in the old string */
+ for (i = 0; i < l; i++)
+ {
+ if (priv[i] == new_priv)
+ break;
+ }
+ if (i == l)
+ { /* we really have a new privilege */
+ priv[l] = new_priv;
+ priv[l + 1] = '\0';
+ }
- if (l == 4) { /* can't add any more privileges */
return priv;
- }
-
- /* check to see if the new privilege is already in the old string */
- for (i=0;i<l;i++) {
- if (priv[i] == new_priv)
- break;
- }
- if (i == l) { /* we really have a new privilege*/
- priv[l] = new_priv;
- priv[l+1] = '\0';
- }
-
- return priv;
}
/*
* aclmakeuser
- * user_type must be "A" - all users
- * "G" - group
- * "U" - user
+ * user_type must be "A" - all users
+ * "G" - group
+ * "U" - user
*
* concatentates the two strings together with a space in between
- *
+ *
* this routine is used in the parser
- *
+ *
* the CALLER is responsible for freeing the memory allocated
*/
-char*
-aclmakeuser(char* user_type, char* user)
+char *
+aclmakeuser(char *user_type, char *user)
{
- char* user_list;
-
- user_list = malloc(strlen(user) + 3);
- sprintf(user_list, "%s %s", user_type, user);
- return user_list;
+ char *user_list;
+
+ user_list = malloc(strlen(user) + 3);
+ sprintf(user_list, "%s %s", user_type, user);
+ return user_list;
}
/*
* makeAclStmt:
- * this is a helper routine called by the parser
+ * this is a helper routine called by the parser
* create a ChangeAclStmt
- * we take in the privilegs, relation_name_list, and grantee
+ * we take in the privilegs, relation_name_list, and grantee
* as well as a single character '+' or '-' to indicate grant or revoke
*
* returns a new ChangeACLStmt*
@@ -584,35 +652,34 @@ aclmakeuser(char* user_type, char* user)
* then calling aclparse;
*/
-ChangeACLStmt*
-makeAclStmt(char* privileges, List* rel_list, char* grantee,
- char grant_or_revoke)
+ChangeACLStmt *
+makeAclStmt(char *privileges, List * rel_list, char *grantee,
+ char grant_or_revoke)
{
- ChangeACLStmt *n = makeNode(ChangeACLStmt);
- char str[MAX_PARSE_BUFFER];
-
- n->aclitem = (AclItem*)palloc(sizeof(AclItem));
- /* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */
- if (grantee[0] == 'G') /* group permissions */
+ ChangeACLStmt *n = makeNode(ChangeACLStmt);
+ char str[MAX_PARSE_BUFFER];
+
+ n->aclitem = (AclItem *) palloc(sizeof(AclItem));
+ /* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */
+ if (grantee[0] == 'G') /* group permissions */
{
- sprintf(str,"%s %s%c%s",
- ACL_IDTYPE_GID_KEYWORD,
- grantee+2, grant_or_revoke,privileges);
- }
- else if (grantee[0] == 'U') /* user permission */
+ sprintf(str, "%s %s%c%s",
+ ACL_IDTYPE_GID_KEYWORD,
+ grantee + 2, grant_or_revoke, privileges);
+ }
+ else if (grantee[0] == 'U') /* user permission */
{
- sprintf(str,"%s %s%c%s",
- ACL_IDTYPE_UID_KEYWORD,
- grantee+2, grant_or_revoke,privileges);
+ sprintf(str, "%s %s%c%s",
+ ACL_IDTYPE_UID_KEYWORD,
+ grantee + 2, grant_or_revoke, privileges);
}
- else /* all permission */
+ else
+/* all permission */
{
- sprintf(str,"%c%s",
- grant_or_revoke,privileges);
+ sprintf(str, "%c%s",
+ grant_or_revoke, privileges);
}
- n->relNames = rel_list;
- aclparse(str, n->aclitem, (unsigned*)&n->modechg);
- return n;
+ n->relNames = rel_list;
+ aclparse(str, n->aclitem, (unsigned *) &n->modechg);
+ return n;
}
-
-