1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 acl_: proc;                                                 /* performs function on a specified acl entry */
 14 
 15 /* Converted to v2 by E. Stone 12/73 */
 16 /* Modified by e Stone Nov 1974 to fix a bug in deleting whole acl */
 17 /* perm acls removed and new fields set 6/76 THVV */
 18 /* Modified 07/77 by THVV for bad_dir_ check */
 19 
 20 /*
 21    entry:
 22 
 23    add_entry(acl_start_ptr, acl_entry_ptr, a_add_sw, uid, code)
 24 
 25    .  given the addr of the entry acl frp and the acl entry str , add to acl list or insert new mode.
 26 
 27    del_entry(acl_start_ptr, acl_entry_ptr, code)
 28 
 29    .  given the addr of the entry acl frp and the acl str (name components are used here) delete the
 30    .  acl entry if it exists.
 31 
 32    del_acl(acl_start_ptr, code)
 33 
 34    .  delete the entire acl specified by the addr of the entry acl frp.
 35 
 36    list_entry(acl_start_ptr, acl_entry_ptr, offset, code)
 37 
 38    .  given the addr of the entry acl frp, then if offset ^= 0 then list the
 39    .  offset'th acl entry in the str pointed to by acl_entry_ptr, else match the access name given
 40    .  in the acl_entry_ptr structure and return the mode and ex_mode if a match exists.
 41 
 42    Arguments:
 43 
 44    1. acl_start_ptr ptr       points to the acl forward rel ptr in the entry.
 45    2. acl_entry_ptr ptr       points to the following structure:
 46    |      dcl 1 acl1 based aligned,
 47    |          2 ac_name,
 48    |          3 person char(32),
 49    |          3 project char(32),
 50    |          3 tag char(1),
 51    |          2 mode bit(36),
 52    |          2 ex_mode bit(36);
 53    3. offset fixed bin        is used to specify which acl entry to list if the ac_name isn't used
 54    .                          as a matching criterion.
 55    4. a_add_sw bit(1) aligned used to indicate if added an acl entry (= "1"b) or just replaced mode (="0"b).
 56    5. uid bit (36)            uid of owning entry
 57    6. code fixed bin(35)      standard error code.
 58 
 59 */
 60 
 61 dcl  a_offset fixed bin;                                    /* parameter */
 62 dcl  entry_uid bit (36) aligned;                            /* parameter */
 63 dcl  entry_acl_count fixed bin;                             /* Parameter */
 64 dcl  code fixed bin (35);                                   /* parameter */
 65 dcl (acl_start_ptr, acl_entry_ptr) ptr;                     /* parameter */
 66 dcl  a_add_sw bit (1);                                      /* parameter */
 67 
 68 dcl 1 ptr_list based aligned,                               /* dummy overlay for frp and brp */
 69     2 frp bit (18) unaligned,
 70     2 brp bit (18) unaligned;
 71 
 72 dcl 1 acl1 based (acl_entry_ptr) aligned,
 73     2 ac_name,
 74       3 person char (32),
 75       3 project char (32),
 76       3 tag char (1),
 77     2 mode bit (36),
 78     2 ex_mode bit (36);
 79 
 80 dcl (i, offset, point) fixed bin;
 81 dcl  np ptr;
 82 dcl  area_ptr ptr;
 83 dcl (rp, next_aclrp) bit (18) aligned;
 84 
 85 dcl  acc_list_$match ext entry (fixed bin, bit (36) aligned, ptr, ptr, ptr, fixed bin, fixed bin (35));
 86 dcl  acc_name_$delete ext entry (ptr);
 87 dcl  acc_name_$encode ext entry (ptr, ptr, fixed bin (35));
 88 dcl (fs_alloc$alloc, fs_alloc$free) ext entry (ptr, fixed bin, ptr);
 89 
 90 dcl (error_table_$user_not_found, error_table_$empty_acl) ext fixed bin (35);
 91 dcl (error_table_$argerr, error_table_$noalloc) ext fixed bin (35) ext;
 92 dcl  active_hardcore_data$aclsize ext fixed bin;
 93 
 94 dcl (addr, addrel, null, rel, ptr, unspec) builtin;
 95 dcl  bad_dir_ condition;
 96 
 97 %include fs_types;
 98 %include dir_header;
 99 % include dir_acl;
100 /* ^L */
101 
102 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
103 
104 list_entry: entry (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr, a_offset, code);
105 
106           code = 0;
107           point = a_offset;
108 
109           if point = 0 then do;                             /* want to match entry */
110                call acc_list_$match (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr,
111                     aclep, a_offset, code);
112                if code ^= 0 then return;
113                                                             /* a normal match return */
114                acl_entry_ptr -> acl1.mode = aclep -> acl_entry.mode;
115                acl_entry_ptr -> acl1.ex_mode = aclep -> acl_entry.ex_mode;
116                return;
117 
118           end;
119                                                             /* now for given index case */
120           aclep = acl_start_ptr;
121 
122           do i = 1 to point;
123                if aclep -> acl_entry.frp = "0"b then do;
124                     a_offset = i;
125                     code = error_table_$argerr;
126                     return;
127                end;
128 
129                aclep = ptr (aclep, aclep -> acl_entry.frp); /* move to next entry */
130           end;
131 
132 
133           if aclep -> acl_entry.name.pers_rp = "0"b then acl_entry_ptr -> acl1.ac_name.person = "*";
134           else acl_entry_ptr -> acl1.ac_name.person = ptr (aclep, aclep -> acl_entry.name.pers_rp) -> access_name.name;
135           if aclep -> acl_entry.name.proj_rp = "0"b then acl_entry_ptr -> acl1.ac_name.project = "*";
136           else acl_entry_ptr -> acl1.ac_name.project = ptr (aclep, aclep -> acl_entry.name.proj_rp) -> access_name.name;
137           acl_entry_ptr -> acl1.ac_name.tag = aclep -> acl_entry.name.tag;
138           acl_entry_ptr -> acl1.mode = aclep -> acl_entry.mode;
139           acl_entry_ptr -> acl1.ex_mode = aclep -> acl_entry.ex_mode;
140 
141           return;
142 
143 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
144 /* ^L */
145 del_entry: entry (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr, code);
146 
147 /* First the correct acl entry is found, then if it
148    is allocated the space is freed, while special casing
149    last, only, and first acl entry. */
150 
151           code = 0;
152 
153           dp = ptr (acl_start_ptr, 0);
154           area_ptr = ptr (dp, dp -> dir.arearp);
155 
156           call acc_list_$match (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr, aclep, point, code);
157                                                             /* point has the offset value of where match occured */
158           if code ^= 0 then return;
159 
160           call acc_name_$delete (addr (aclep -> acl_entry.name));
161 
162           if aclep -> acl_entry.frp = "0"b then do;         /* End of list. */
163                if aclep -> acl_entry.brp = "0"b then do;    /* only reset acl frp if no prev slots */
164                     acl_start_ptr -> ptr_list.frp,
165                          acl_start_ptr -> ptr_list.brp = "0"b;
166                end;
167                else do;
168                     ptr (aclep, aclep -> acl_entry.brp) -> acl_entry.frp = "0"b;
169                     acl_start_ptr -> ptr_list.brp = aclep -> acl_entry.brp;
170                end;
171           end;
172           else do;
173                ptr (aclep, aclep -> acl_entry.frp) -> acl_entry.brp = aclep -> acl_entry.brp;
174                if aclep -> acl_entry.brp = "0"b then acl_start_ptr -> ptr_list.frp = aclep -> acl_entry.frp;
175                else ptr (aclep, aclep -> acl_entry.brp) -> acl_entry.frp = aclep -> acl_entry.frp;
176           end;
177 
178           call fs_alloc$free (area_ptr, active_hardcore_data$aclsize, aclep);
179 
180           return;
181 
182 /*  *  *  *  *  *  *  *  *  *  *  *  */
183 
184 del_acl:  entry (entry_acl_count, entry_uid, acl_start_ptr); /* delete whole acl */
185 
186           if acl_start_ptr -> ptr_list.brp = "0"b then return; /* empty acl */
187 
188           dp = ptr (acl_start_ptr, 0);
189           area_ptr = ptr (dp, dp -> dir.arearp);
190 
191           i = 0;
192           do rp = acl_start_ptr -> acl_entry.frp repeat next_aclrp while (rp);
193                aclep = ptr (dp, rp);
194                i = i + 1;
195                if i > entry_acl_count
196                | aclep -> acl_entry.owner ^= entry_uid
197                | aclep -> acl_entry.type ^= ACLE_TYPE then signal bad_dir_;
198                call acc_name_$delete (addr (aclep -> acl_entry.name));
199 
200                next_aclrp = aclep -> acl_entry.frp;         /* get offset of next acl before freeing */
201 
202                call fs_alloc$free (area_ptr, active_hardcore_data$aclsize, aclep);
203 
204           end;                                              /* i loop */
205 
206           acl_start_ptr -> ptr_list.frp,                    /* adjust start ptrs */
207                acl_start_ptr -> ptr_list.brp = "0"b;
208           return;
209 
210 /* ^L */
211 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
212 
213 add_entry: entry (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr, a_add_sw, code);
214                                                             /* add or replace an acl */
215 
216 /* First an empty acl is handled, then adding to the bottom
217    of the list, then inserting into the list. */
218 
219           code = 0;
220           dp = ptr (acl_start_ptr, 0);
221           area_ptr = ptr (dp, dp -> dir.arearp);
222           a_add_sw = "0"b;
223 
224           call acc_list_$match (entry_acl_count, entry_uid, acl_start_ptr, acl_entry_ptr, np, (0), code);
225           if code = 0 then do;                              /* a normal replacement of mode */
226                np -> acl_entry.mode = acl_entry_ptr -> acl1.mode;
227                np -> acl_entry.ex_mode = acl_entry_ptr -> acl1.ex_mode;
228                return;
229           end;
230           else if code = error_table_$empty_acl | code = error_table_$user_not_found then do;
231                call fs_alloc$alloc (area_ptr, active_hardcore_data$aclsize, aclep);
232                if aclep = null then go to alloc_err;
233                if code = error_table_$empty_acl then do;
234                     acl_start_ptr -> ptr_list.frp, acl_start_ptr -> ptr_list.brp = rel (aclep);
235                     aclep -> acl_entry.frp, aclep -> acl_entry.brp = "0"b;
236                end;
237                else if np = null then do;                   /* must add to end of list */
238                     np = ptr (dp, acl_start_ptr -> ptr_list.brp);
239                                                             /* move to last entry */
240                     acl_start_ptr -> ptr_list.brp = rel (aclep);
241                     np -> acl_entry.frp = rel (aclep);
242                     aclep -> acl_entry.frp = "0"b;
243                     aclep -> acl_entry.brp = rel (np);
244                end;
245                else do;                                     /* an insertion, add before entry ptd to */
246                     aclep -> acl_entry.frp = rel (np);
247                     aclep -> acl_entry.brp = np -> acl_entry.brp;
248                     if aclep -> acl_entry.brp = "0"b then acl_start_ptr -> ptr_list.frp = rel (aclep);
249                     else ptr (aclep, aclep -> acl_entry.brp) -> acl_entry.frp = rel (aclep);
250                     np -> acl_entry.brp = rel (aclep);
251                end;
252           end;
253           else return;                                      /* some other code */
254 
255           a_add_sw = "1"b;                                  /* set to indicate entry added */
256           aclep -> acl_entry.type = ACLE_TYPE;
257           aclep -> acl_entry.size = active_hardcore_data$aclsize;
258           aclep -> acl_entry.owner = entry_uid;
259           call acc_name_$encode (addr (aclep -> acl_entry.name), acl_entry_ptr, code);
260           if code ^= 0 then return;
261 
262           aclep -> acl_entry.mode = acl_entry_ptr -> acl1.mode;
263           aclep -> acl_entry.ex_mode = acl_entry_ptr -> acl1.ex_mode;
264           return;
265 
266 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
267 
268 alloc_err:
269           code = error_table_$noalloc;
270           return;
271 
272      end acl_;