88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.99 2003/09/25 06:58:03 petere Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.100 2003/10/29 22:20:54 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -542,26 +542,23 @@ acldefault(GrantObjectType objtype, AclId ownerid)
542542break ;
543543}
544544
545- acl = allocacl ((world_default != ACL_NO_RIGHTS ?1 :0 )
546- + (ownerid ?1 :0 ));
545+ acl = allocacl ((world_default != ACL_NO_RIGHTS ) ?2 :1 );
547546aip = ACL_DAT (acl );
548547
549548if (world_default != ACL_NO_RIGHTS )
550549{
551- aip [0 ].ai_grantee = ACL_ID_WORLD ;
552- aip [0 ].ai_grantor = ownerid ;
553- ACLITEM_SET_PRIVS_IDTYPE (aip [0 ],world_default ,ACL_NO_RIGHTS ,ACL_IDTYPE_WORLD );
550+ aip -> ai_grantee = ACL_ID_WORLD ;
551+ aip -> ai_grantor = ownerid ;
552+ ACLITEM_SET_PRIVS_IDTYPE (* aip ,world_default ,ACL_NO_RIGHTS ,
553+ ACL_IDTYPE_WORLD );
554+ aip ++ ;
554555}
555556
556- if (ownerid )
557- {
558- int index = (world_default != ACL_NO_RIGHTS ?1 :0 );
559-
560- aip [index ].ai_grantee = ownerid ;
561- aip [index ].ai_grantor = ownerid ;
562- /* owner gets default privileges with grant option */
563- ACLITEM_SET_PRIVS_IDTYPE (aip [index ],owner_default ,owner_default ,ACL_IDTYPE_UID );
564- }
557+ aip -> ai_grantee = ownerid ;
558+ aip -> ai_grantor = ownerid ;
559+ /* owner gets default privileges with grant option */
560+ ACLITEM_SET_PRIVS_IDTYPE (* aip ,owner_default ,owner_default ,
561+ ACL_IDTYPE_UID );
565562
566563return acl ;
567564}
@@ -574,17 +571,22 @@ acldefault(GrantObjectType objtype, AclId ownerid)
574571 * NB: caller is responsible for having detoasted the input ACL, if needed.
575572 */
576573Acl *
577- aclinsert3 (const Acl * old_acl ,const AclItem * mod_aip ,unsigned modechg ,DropBehavior behavior )
574+ aclinsert3 (const Acl * old_acl ,const AclItem * mod_aip ,
575+ unsigned modechg ,DropBehavior behavior )
578576{
579577Acl * new_acl = NULL ;
580578AclItem * old_aip ,
581579* new_aip = NULL ;
580+ AclMode old_privs ,
581+ old_goptions ,
582+ new_privs ,
583+ new_goptions ;
582584int dst ,
583585num ;
584586
585587/* These checks for null input are probably dead code, but... */
586- if (!old_acl || ACL_NUM (old_acl )< 1 )
587- old_acl = allocacl (1 );
588+ if (!old_acl || ACL_NUM (old_acl )< 0 )
589+ old_acl = allocacl (0 );
588590if (!mod_aip )
589591{
590592new_acl = allocacl (ACL_NUM (old_acl ));
@@ -629,16 +631,23 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
629631num ++ ;/* set num to the size of new_acl */
630632}
631633
632- /* apply the permissions mod */
634+ old_privs = ACLITEM_GET_PRIVS (new_aip [dst ]);
635+ old_goptions = ACLITEM_GET_GOPTIONS (new_aip [dst ]);
636+
637+ /* apply the specified permissions change */
633638switch (modechg )
634639{
635640case ACL_MODECHG_ADD :
636- ACLITEM_SET_PRIVS (new_aip [dst ],ACLITEM_GET_PRIVS (new_aip [dst ]) |ACLITEM_GET_PRIVS (* mod_aip ));
637- ACLITEM_SET_GOPTIONS (new_aip [dst ],ACLITEM_GET_GOPTIONS (new_aip [dst ]) |ACLITEM_GET_GOPTIONS (* mod_aip ));
641+ ACLITEM_SET_PRIVS (new_aip [dst ],
642+ old_privs |ACLITEM_GET_PRIVS (* mod_aip ));
643+ ACLITEM_SET_GOPTIONS (new_aip [dst ],
644+ old_goptions |ACLITEM_GET_GOPTIONS (* mod_aip ));
638645break ;
639646case ACL_MODECHG_DEL :
640- ACLITEM_SET_PRIVS (new_aip [dst ],ACLITEM_GET_PRIVS (new_aip [dst ])& ~ACLITEM_GET_PRIVS (* mod_aip ));
641- ACLITEM_SET_GOPTIONS (new_aip [dst ],ACLITEM_GET_GOPTIONS (new_aip [dst ])& ~ACLITEM_GET_GOPTIONS (* mod_aip ));
647+ ACLITEM_SET_PRIVS (new_aip [dst ],
648+ old_privs & ~ACLITEM_GET_PRIVS (* mod_aip ));
649+ ACLITEM_SET_GOPTIONS (new_aip [dst ],
650+ old_goptions & ~ACLITEM_GET_GOPTIONS (* mod_aip ));
642651break ;
643652case ACL_MODECHG_EQL :
644653ACLITEM_SET_PRIVS_IDTYPE (new_aip [dst ],
@@ -648,10 +657,13 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
648657break ;
649658}
650659
660+ new_privs = ACLITEM_GET_PRIVS (new_aip [dst ]);
661+ new_goptions = ACLITEM_GET_GOPTIONS (new_aip [dst ]);
662+
651663/*
652664 * If the adjusted entry has no permissions, delete it from the list.
653665 */
654- if (ACLITEM_GET_PRIVS ( new_aip [ dst ]) == ACL_NO_RIGHTS )
666+ if (new_privs == ACL_NO_RIGHTS && new_goptions == ACL_NO_RIGHTS )
655667{
656668memmove (new_aip + dst ,
657669new_aip + dst + 1 ,
@@ -661,12 +673,14 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
661673}
662674
663675/*
664- * Remove abandoned privileges (cascading revoke)
676+ * Remove abandoned privileges (cascading revoke). Currently we
677+ * can only handle this when the grantee is a user.
665678 */
666- if (modechg != ACL_MODECHG_ADD
667- && ACLITEM_GET_IDTYPE (* mod_aip )== ACL_IDTYPE_UID
668- && ACLITEM_GET_GOPTIONS (* mod_aip ))
669- new_acl = recursive_revoke (new_acl ,mod_aip -> ai_grantee ,ACLITEM_GET_GOPTIONS (* mod_aip ),behavior );
679+ if ((old_goptions & ~new_goptions )!= 0
680+ && ACLITEM_GET_IDTYPE (* mod_aip )== ACL_IDTYPE_UID )
681+ new_acl = recursive_revoke (new_acl ,mod_aip -> ai_grantee ,
682+ (old_goptions & ~new_goptions ),
683+ behavior );
670684
671685return new_acl ;
672686}
@@ -744,8 +758,8 @@ aclremove(PG_FUNCTION_ARGS)
744758new_num ;
745759
746760/* These checks for null input should be dead code, but... */
747- if (!old_acl || ACL_NUM (old_acl )< 1 )
748- old_acl = allocacl (1 );
761+ if (!old_acl || ACL_NUM (old_acl )< 0 )
762+ old_acl = allocacl (0 );
749763if (!mod_aip )
750764{
751765new_acl = allocacl (ACL_NUM (old_acl ));
@@ -773,27 +787,14 @@ aclremove(PG_FUNCTION_ARGS)
773787new_num = old_num - 1 ;
774788new_acl = allocacl (new_num );
775789new_aip = ACL_DAT (new_acl );
776- if (dst == 0 )
777- {/* start */
778- ereport (ERROR ,
779- (errcode (ERRCODE_DATA_EXCEPTION ),
780- errmsg ("aclitem for public may not be removed" )));
781- }
782- else if (dst == old_num - 1 )
783- {/* end */
784- memcpy ((char * )new_aip ,
785- (char * )old_aip ,
786- new_num * sizeof (AclItem ));
787- }
788- else
789- {/* middle */
790+ if (dst > 0 )
790791memcpy ((char * )new_aip ,
791792 (char * )old_aip ,
792793dst * sizeof (AclItem ));
794+ if (dst < new_num )
793795memcpy ((char * ) (new_aip + dst ),
794796 (char * ) (old_aip + dst + 1 ),
795797 (new_num - dst )* sizeof (AclItem ));
796- }
797798}
798799
799800PG_RETURN_ACL_P (new_acl );
@@ -839,7 +840,7 @@ makeaclitem(PG_FUNCTION_ARGS)
839840
840841if (u_grantee == 0 && g_grantee == 0 )
841842{
842- aclitem -> ai_grantee = 0 ;
843+ aclitem -> ai_grantee = ACL_ID_WORLD ;
843844
844845ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_WORLD );
845846}
@@ -851,18 +852,18 @@ makeaclitem(PG_FUNCTION_ARGS)
851852}
852853else if (u_grantee != 0 )
853854{
854- aclitem -> ai_grantee = u_grantee ;
855+ aclitem -> ai_grantee = u_grantee ;
855856
856857ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_UID );
857858}
858- else if (g_grantee != 0 )
859+ else /* (g_grantee != 0) */
859860{
860- aclitem -> ai_grantee = g_grantee ;
861+ aclitem -> ai_grantee = g_grantee ;
861862
862863ACLITEM_SET_IDTYPE (* aclitem ,ACL_IDTYPE_GID );
863864}
864865
865- aclitem -> ai_grantor = grantor ;
866+ aclitem -> ai_grantor = grantor ;
866867
867868ACLITEM_SET_PRIVS (* aclitem ,priv );
868869if (goption )