|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.49 2001/06/05 19:34:56 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.50 2001/06/09 23:21:54 petere Exp $ |
12 | 12 | *
|
13 | 13 | * NOTES
|
14 | 14 | * See acl.h.
|
@@ -63,95 +63,132 @@ dumpacl(Acl *acl)
|
63 | 63 |
|
64 | 64 | #endif /* ACLDEBUG */
|
65 | 65 |
|
| 66 | + |
66 | 67 | /*
|
67 |
| - * ChangeAcl |
| 68 | + * Called to execute the utility commands GRANT and REVOKE |
68 | 69 | */
|
69 | 70 | void
|
70 |
| -ChangeAcl(char *relname, |
71 |
| - AclItem *mod_aip, |
72 |
| - unsigned modechg) |
| 71 | +ExecuteGrantStmt(GrantStmt *stmt) |
73 | 72 | {
|
74 |
| - unsigned i; |
75 |
| - Acl *old_acl, |
76 |
| - *new_acl; |
77 |
| - Relation relation; |
78 |
| - HeapTuple tuple; |
79 |
| - HeapTuple newtuple; |
80 |
| - Datum aclDatum; |
81 |
| - Datum values[Natts_pg_class]; |
82 |
| - char nulls[Natts_pg_class]; |
83 |
| - char replaces[Natts_pg_class]; |
84 |
| - Relation idescs[Num_pg_class_indices]; |
85 |
| - bool isNull; |
| 73 | + List *i; |
| 74 | + List *j; |
86 | 75 |
|
87 |
| - /* |
88 |
| - * Find the pg_class tuple matching 'relname' and extract the ACL. If |
89 |
| - * there's no ACL, create a default using the pg_class.relowner field. |
90 |
| - */ |
91 |
| - relation = heap_openr(RelationRelationName, RowExclusiveLock); |
92 |
| - tuple = SearchSysCache(RELNAME, |
93 |
| - PointerGetDatum(relname), |
94 |
| - 0, 0, 0); |
95 |
| - if (!HeapTupleIsValid(tuple)) |
96 |
| - { |
97 |
| - heap_close(relation, RowExclusiveLock); |
98 |
| - elog(ERROR, "ChangeAcl: class \"%s\" not found", |
99 |
| - relname); |
100 |
| - } |
101 |
| - |
102 |
| - aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl, |
103 |
| - &isNull); |
104 |
| - if (isNull) |
105 |
| - { |
106 |
| - /* No ACL, so build default ACL for rel */ |
107 |
| - AclId ownerId; |
| 76 | + /* see comment in pg_type.h */ |
| 77 | + Assert(ACLITEMSIZE == sizeof(AclItem)); |
108 | 78 |
|
109 |
| - ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner; |
110 |
| - old_acl = acldefault(relname, ownerId); |
111 |
| - } |
112 |
| - else |
| 79 | + foreach(i, stmt->relnames) |
113 | 80 | {
|
114 |
| - /* get a detoasted copy of the rel's ACL */ |
115 |
| - old_acl = DatumGetAclPCopy(aclDatum); |
116 |
| - } |
| 81 | + char *relname = strVal(lfirst(i)); |
| 82 | + Relation relation; |
| 83 | + HeapTuple tuple; |
| 84 | + Form_pg_class pg_class_tuple; |
| 85 | + Datum aclDatum; |
| 86 | + bool isNull; |
| 87 | + Acl *old_acl; |
| 88 | + Acl *new_acl; |
| 89 | + unsigned i; |
| 90 | + HeapTuple newtuple; |
| 91 | + Datum values[Natts_pg_class]; |
| 92 | + char nulls[Natts_pg_class]; |
| 93 | + char replaces[Natts_pg_class]; |
| 94 | + |
| 95 | + |
| 96 | + if (!pg_ownercheck(GetUserId(), relname, RELNAME)) |
| 97 | + elog(ERROR, "permission denied"); |
| 98 | + |
| 99 | + /* open pg_class */ |
| 100 | + relation = heap_openr(RelationRelationName, RowExclusiveLock); |
| 101 | + tuple = SearchSysCache(RELNAME, |
| 102 | + PointerGetDatum(relname), |
| 103 | + 0, 0, 0); |
| 104 | + if (!HeapTupleIsValid(tuple)) |
| 105 | + { |
| 106 | + heap_close(relation, RowExclusiveLock); |
| 107 | + elog(ERROR, "relation \"%s\" not found", |
| 108 | + relname); |
| 109 | + } |
| 110 | + pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); |
| 111 | + |
| 112 | + if (pg_class_tuple->relkind == RELKIND_INDEX) |
| 113 | + elog(ERROR, "\"%s\" is an index", |
| 114 | + relname); |
| 115 | + |
| 116 | + /* |
| 117 | + * If there's no ACL, create a default using the |
| 118 | + * pg_class.relowner field. |
| 119 | + */ |
| 120 | + aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl, |
| 121 | + &isNull); |
| 122 | + if (isNull) |
| 123 | + old_acl = acldefault(relname, pg_class_tuple->relowner); |
| 124 | + else |
| 125 | + /* get a detoasted copy of the rel's ACL */ |
| 126 | + old_acl = DatumGetAclPCopy(aclDatum); |
117 | 127 |
|
118 | 128 | #ifdef ACLDEBUG
|
119 |
| - dumpacl(old_acl); |
| 129 | + dumpacl(old_acl); |
120 | 130 | #endif
|
| 131 | + new_acl = old_acl; |
121 | 132 |
|
122 |
| - new_acl = aclinsert3(old_acl, mod_aip, modechg); |
123 |
| - |
| 133 | + foreach(j, stmt->grantees) |
| 134 | + { |
| 135 | + PrivGrantee *grantee = (PrivGrantee *)lfirst(j); |
| 136 | + char *granteeString; |
| 137 | + char *aclString; |
| 138 | + AclItem aclitem; |
| 139 | + unsigned modechg; |
| 140 | + |
| 141 | + if (grantee->username) |
| 142 | + granteeString = aclmakeuser("U", grantee->username); |
| 143 | + else if (grantee->groupname) |
| 144 | + granteeString = aclmakeuser("G", grantee->groupname); |
| 145 | + else |
| 146 | + granteeString = aclmakeuser("A", ""); |
| 147 | + |
| 148 | + aclString = makeAclString(stmt->privileges, granteeString, |
| 149 | + stmt->is_grant ? '+' : '-'); |
| 150 | + |
| 151 | + /* Convert string ACL spec into internal form */ |
| 152 | + aclparse(aclString, &aclitem, &modechg); |
| 153 | + new_acl = aclinsert3(new_acl, &aclitem, modechg); |
124 | 154 | #ifdef ACLDEBUG
|
125 |
| - dumpacl(new_acl); |
| 155 | + dumpacl(new_acl); |
126 | 156 | #endif
|
| 157 | + } |
127 | 158 |
|
128 |
| - for (i = 0; i < Natts_pg_class; ++i) |
129 |
| - { |
130 |
| - replaces[i] = ' '; |
131 |
| - nulls[i] = ' '; /* ignored if replaces[i] == ' ' anyway */ |
132 |
| - values[i] = (Datum) NULL; /* ignored if replaces[i] == ' ' |
133 |
| - * anyway */ |
134 |
| - } |
135 |
| - replaces[Anum_pg_class_relacl - 1] = 'r'; |
136 |
| - values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); |
137 |
| - newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces); |
| 159 | + /* finished building new ACL value, now insert it */ |
| 160 | + for (i = 0; i < Natts_pg_class; ++i) |
| 161 | + { |
| 162 | + replaces[i] = ' '; |
| 163 | + nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */ |
| 164 | + values[i] = (Datum) NULL; /* ignored if replaces[i]==' ' anyway */ |
| 165 | + } |
| 166 | + replaces[Anum_pg_class_relacl - 1] = 'r'; |
| 167 | + values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); |
| 168 | + newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces); |
138 | 169 |
|
139 |
| - ReleaseSysCache(tuple); |
| 170 | + ReleaseSysCache(tuple); |
140 | 171 |
|
141 |
| - simple_heap_update(relation, &newtuple->t_self, newtuple); |
| 172 | + simple_heap_update(relation, &newtuple->t_self, newtuple); |
142 | 173 |
|
143 |
| - /* keep the catalog indices up to date */ |
144 |
| - CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, |
145 |
| - idescs); |
146 |
| - CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newtuple); |
147 |
| - CatalogCloseIndices(Num_pg_class_indices, idescs); |
| 174 | + { |
| 175 | + /* keep the catalog indexes up to date */ |
| 176 | + Relation idescs[Num_pg_class_indices]; |
| 177 | + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, |
| 178 | + idescs); |
| 179 | + CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newtuple); |
| 180 | + CatalogCloseIndices(Num_pg_class_indices, idescs); |
| 181 | + } |
148 | 182 |
|
149 |
| - heap_close(relation, RowExclusiveLock); |
| 183 | + pfree(old_acl); |
| 184 | + pfree(new_acl); |
150 | 185 |
|
151 |
| - pfree(old_acl); |
152 |
| - pfree(new_acl); |
| 186 | + heap_close(relation, RowExclusiveLock); |
| 187 | + } |
153 | 188 | }
|
154 | 189 |
|
| 190 | + |
| 191 | + |
155 | 192 | AclId
|
156 | 193 | get_grosysid(char *groname)
|
157 | 194 | {
|
|
0 commit comments