88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.87 2003/06/02 19:00:29 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.88 2003/06/11 09:23:55 petere Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3232
3333static const char * getid (const char * s ,char * n );
3434static void putid (char * p ,const char * s );
35- static Acl * makeacl (int n );
35+ static Acl * allocacl (int n );
3636static const char * aclparse (const char * s ,AclItem * aip );
3737static bool aclitemeq (const AclItem * a1 ,const AclItem * a2 );
3838static Acl * recursive_revoke (Acl * acl ,AclId grantee ,
3939AclMode revoke_privs ,DropBehavior behavior );
4040
41+ static AclMode convert_priv_string (text * priv_type_text );
42+
4143static Oid convert_table_name (text * tablename );
4244static AclMode convert_table_priv_string (text * priv_type_text );
4345static Oid convert_database_name (text * databasename );
@@ -265,20 +267,20 @@ aclparse(const char *s, AclItem *aip)
265267}
266268
267269/*
268- *makeacl
270+ *allocacl
269271 *Allocates storage for a new Acl with 'n' entries.
270272 *
271273 * RETURNS:
272274 *the new Acl
273275 */
274276static Acl *
275- makeacl (int n )
277+ allocacl (int n )
276278{
277279Acl * new_acl ;
278280Size size ;
279281
280282if (n < 0 )
281- elog (ERROR ,"makeacl : invalid size: %d" ,n );
283+ elog (ERROR ,"allocacl : invalid size: %d" ,n );
282284size = ACL_N_SIZE (n );
283285new_acl = (Acl * )palloc0 (size );
284286new_acl -> size = size ;
@@ -471,7 +473,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
471473break ;
472474}
473475
474- acl = makeacl ((world_default != ACL_NO_RIGHTS ?1 :0 )
476+ acl = allocacl ((world_default != ACL_NO_RIGHTS ?1 :0 )
475477+ (ownerid ?1 :0 ));
476478aip = ACL_DAT (acl );
477479
@@ -513,10 +515,10 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
513515
514516/* These checks for null input are probably dead code, but... */
515517if (!old_acl || ACL_NUM (old_acl )< 1 )
516- old_acl = makeacl (1 );
518+ old_acl = allocacl (1 );
517519if (!mod_aip )
518520{
519- new_acl = makeacl (ACL_NUM (old_acl ));
521+ new_acl = allocacl (ACL_NUM (old_acl ));
520522memcpy ((char * )new_acl , (char * )old_acl ,ACL_SIZE (old_acl ));
521523return new_acl ;
522524}
@@ -536,7 +538,7 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
536538if (aclitemeq (mod_aip ,old_aip + dst ))
537539{
538540/* found a match, so modify existing item */
539- new_acl = makeacl (num );
541+ new_acl = allocacl (num );
540542new_aip = ACL_DAT (new_acl );
541543memcpy (new_acl ,old_acl ,ACL_SIZE (old_acl ));
542544break ;
@@ -546,7 +548,7 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
546548if (dst == num )
547549{
548550/* need to append a new item */
549- new_acl = makeacl (num + 1 );
551+ new_acl = allocacl (num + 1 );
550552new_aip = ACL_DAT (new_acl );
551553memcpy (new_aip ,old_aip ,num * sizeof (AclItem ));
552554
@@ -671,10 +673,10 @@ aclremove(PG_FUNCTION_ARGS)
671673
672674/* These checks for null input should be dead code, but... */
673675if (!old_acl || ACL_NUM (old_acl )< 1 )
674- old_acl = makeacl (1 );
676+ old_acl = allocacl (1 );
675677if (!mod_aip )
676678{
677- new_acl = makeacl (ACL_NUM (old_acl ));
679+ new_acl = allocacl (ACL_NUM (old_acl ));
678680memcpy ((char * )new_acl , (char * )old_acl ,ACL_SIZE (old_acl ));
679681PG_RETURN_ACL_P (new_acl );
680682}
@@ -689,13 +691,13 @@ aclremove(PG_FUNCTION_ARGS)
689691if (dst >=old_num )
690692{
691693/* Not found, so return copy of source ACL */
692- new_acl = makeacl (old_num );
694+ new_acl = allocacl (old_num );
693695memcpy ((char * )new_acl , (char * )old_acl ,ACL_SIZE (old_acl ));
694696}
695697else
696698{
697699new_num = old_num - 1 ;
698- new_acl = makeacl (new_num );
700+ new_acl = allocacl (new_num );
699701new_aip = ACL_DAT (new_acl );
700702if (dst == 0 )
701703{/* start */
@@ -734,13 +736,97 @@ aclcontains(PG_FUNCTION_ARGS)
734736aidat = ACL_DAT (acl );
735737for (i = 0 ;i < num ;++ i )
736738{
737- if (aip -> ai_grantee == aidat [i ].ai_grantee &&
738- aip -> ai_privs == aidat [i ].ai_privs )
739+ if (aip -> ai_grantee == aidat [i ].ai_grantee
740+ && ACLITEM_GET_IDTYPE (* aip )== ACLITEM_GET_IDTYPE (aidat [i ])
741+ && aip -> ai_grantor == aidat [i ].ai_grantor
742+ && (ACLITEM_GET_PRIVS (* aip )& ACLITEM_GET_PRIVS (aidat [i ]))== ACLITEM_GET_PRIVS (* aip )
743+ && (ACLITEM_GET_GOPTIONS (* aip )& ACLITEM_GET_GOPTIONS (aidat [i ]))== ACLITEM_GET_GOPTIONS (* aip ))
739744PG_RETURN_BOOL (true);
740745}
741746PG_RETURN_BOOL (false);
742747}
743748
749+ Datum
750+ makeaclitem (PG_FUNCTION_ARGS )
751+ {
752+ int32 u_grantee = PG_GETARG_INT32 (0 );
753+ int32 g_grantee = PG_GETARG_INT32 (1 );
754+ int32 grantor = PG_GETARG_INT32 (2 );
755+ text * privtext = PG_GETARG_TEXT_P (3 );
756+ bool goption = PG_GETARG_BOOL (4 );
757+ AclItem * aclitem ;
758+ AclMode priv ;
759+
760+ priv = convert_priv_string (privtext );
761+
762+ aclitem = (AclItem * )palloc (sizeof (* aclitem ));
763+ if (u_grantee == 0 && g_grantee == 0 )
764+ {
765+ aclitem -> ai_grantee = 0 ;
766+ ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_WORLD );
767+ }
768+ else if (u_grantee != 0 && g_grantee != 0 )
769+ {
770+ elog (ERROR ,"cannot specify both user and group" );
771+ }
772+ else if (u_grantee != 0 )
773+ {
774+ aclitem -> ai_grantee = u_grantee ;
775+ ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_UID );
776+ }
777+ else if (g_grantee != 0 )
778+ {
779+ aclitem -> ai_grantee = g_grantee ;
780+ ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_GID );
781+ }
782+
783+ aclitem -> ai_grantor = grantor ;
784+ ACLITEM_SET_PRIVS (* aclitem ,priv );
785+ if (goption )
786+ ACLITEM_SET_GOPTIONS (* aclitem ,priv );
787+ else
788+ ACLITEM_SET_GOPTIONS (* aclitem ,ACL_NO_RIGHTS );
789+
790+ PG_RETURN_ACLITEM_P (aclitem );
791+ }
792+
793+ static AclMode
794+ convert_priv_string (text * priv_type_text )
795+ {
796+ char * priv_type ;
797+
798+ priv_type = DatumGetCString (DirectFunctionCall1 (textout ,
799+ PointerGetDatum (priv_type_text )));
800+
801+ if (strcasecmp (priv_type ,"SELECT" )== 0 )
802+ return ACL_SELECT ;
803+ if (strcasecmp (priv_type ,"INSERT" )== 0 )
804+ return ACL_INSERT ;
805+ if (strcasecmp (priv_type ,"UPDATE" )== 0 )
806+ return ACL_UPDATE ;
807+ if (strcasecmp (priv_type ,"DELETE" )== 0 )
808+ return ACL_DELETE ;
809+ if (strcasecmp (priv_type ,"RULE" )== 0 )
810+ return ACL_RULE ;
811+ if (strcasecmp (priv_type ,"REFERENCES" )== 0 )
812+ return ACL_REFERENCES ;
813+ if (strcasecmp (priv_type ,"TRIGGER" )== 0 )
814+ return ACL_TRIGGER ;
815+ if (strcasecmp (priv_type ,"EXECUTE" )== 0 )
816+ return ACL_EXECUTE ;
817+ if (strcasecmp (priv_type ,"USAGE" )== 0 )
818+ return ACL_USAGE ;
819+ if (strcasecmp (priv_type ,"CREATE" )== 0 )
820+ return ACL_CREATE ;
821+ if (strcasecmp (priv_type ,"TEMP" )== 0 )
822+ return ACL_CREATE_TEMP ;
823+ if (strcasecmp (priv_type ,"TEMPORARY" )== 0 )
824+ return ACL_CREATE_TEMP ;
825+
826+ elog (ERROR ,"invalid privilege type %s" ,priv_type );
827+ return ACL_NO_RIGHTS ;/* keep compiler quiet */
828+ }
829+
744830
745831/*
746832 * has_table_privilege variants