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 /* format: style2,indcomtxt */
 13 
 14 sum:
 15      procedure;
 16 
 17 /* Totally rewritten March 1975 by R. Bratt for new kst, to restructure to code, and to fix a horrid bug in dirmod */
 18 /* Mod 4/25/75 by BSG for NSS */
 19 /* Modified by Kobziar to drop get_ring entry */
 20 /* Last modified 760310 by LJS to use info-only entry in dir_control_error */
 21 /* Modified by Mike Grady 9/79 to stop using dir_control_error */
 22 /* Modified 12 August 1981, W. Olin Sibert, to move error code generation into validate_entryp */
 23 /* Modified 3/82 BIM for change_pclock in the dir header */
 24 /* Modified 84-03-14 BIM to make pc$updates actually do something for dirmod */
 25 /* Modified 84-10-15 Keith Loepere to move validate_entryp in here. */
 26 /* Modified 85-01-21 Keith Loepere for dtm setting covert event. */
 27 
 28 /* ---> sum$getbranch locks the directory and returns the branch pointer for
 29    a given segment.
 30 
 31    USAGE: call sum$getbranch (segptr, type_lock, aep, code);
 32 
 33    1) segptr ptr - - - pointer to a segment
 34    2) type_lock bit(36) aligned - - - string indicating whether lock is read or write lock (input)
 35    3) aep ptr - - - pointer to the branch of that segment (output)
 36    4) code fixed bin - - - error code (output)
 37 
 38    ---> sum$dirmod sets the file modified switch on a directory and reflects it up, and bumps the pclock in the dir.
 39 
 40    USAGE: call sum$dirmod (adp);
 41 
 42    1) adp ptr - - - pointer to the directory that has been modified
 43 */
 44 
 45 /* Parameters */
 46 
 47           dcl     a_code                 fixed bin (35);
 48           dcl     a_dp                   ptr;
 49           dcl     a_ep                   ptr;
 50           dcl     a_segptr               ptr;
 51           dcl     a_type_lock            bit (36) aligned;
 52 
 53 /* Variables */
 54 
 55           dcl     code                   fixed bin (35);
 56           dcl     dtm_changed            bit (1) aligned;
 57           dcl     lsw                    bit (1) aligned;
 58           dcl     my_lock_entry          bit (1) aligned init ("0"b);
 59           dcl     old_dtm                bit (36) aligned;
 60           dcl     segptr                 ptr;
 61           dcl     target_dp              ptr;
 62           dcl     type_lock              bit (36) aligned;
 63 
 64 /* External */
 65 
 66           dcl     error_table_$mylock    fixed bin (35) ext;
 67           dcl     error_table_$root      fixed bin (35) ext;
 68           dcl     error_table_$seg_deleted
 69                                          fixed bin (35) external static;
 70           dcl     pds$throttle_segment_state_changes
 71                                          bit (1) aligned external static;
 72           dcl     1 pds$transparent      external aligned,
 73                   ( 2 m                  bit (1),
 74                     2 u                  bit (1)
 75                     )                    unaligned;
 76 
 77 /* Entries */
 78 
 79           dcl     activate               ext entry (ptr, fixed bin (35)) returns (ptr);
 80           dcl     get_kstep              ext entry (fixed bin (17), ptr, fixed bin (35));
 81           dcl     limit_covert_channel   entry (fixed bin);
 82           dcl     lock$dir_unlock        external entry (ptr);
 83           dcl     lock$dir_wait          external entry (ptr, bit (36) aligned, fixed bin (35));
 84           dcl     lock$lock_ast          entry;
 85           dcl     lock$unlock_ast        entry;
 86           dcl     pc$updates             external entry (ptr);
 87           dcl     syserr                 external entry options (variable);
 88 
 89 /* Misc */
 90 
 91           dcl     (addr, baseno, fixed, null, pointer, ptr)
 92                                          builtin;
 93 
 94           dcl     (bad_dir_, fixedoverflow)
 95                                          condition;
 96 %page;
 97 getbranch_root_my:
 98      entry (a_segptr, a_type_lock, a_ep, a_code);
 99 
100 /* same as getbranch but returns the mylock error code. */
101 
102           my_lock_entry = "1"b;
103 
104 getbranch:
105      entry (a_segptr, a_type_lock, a_ep, a_code);
106 
107 /* entry to lock the directory and return the branch pointer for a given segment */
108 
109           segptr = a_segptr;
110           type_lock = a_type_lock;
111           a_code = 0;
112           a_ep = null ();
113           call get_kstep (fixed (baseno (segptr), 17), kstep, code);
114           if code ^= 0
115           then call abort (code);
116 
117           if kstep -> kste.uid = (36)"1"b                   /* is this the root */
118           then call abort (error_table_$root);              /* set the root code */
119 
120           dp = ptr (kste.entryp, 0);
121           lsw = "1"b;                                       /* set lock switch */
122           call lock$dir_wait (dp, type_lock, code);         /* lock the directory */
123           if code ^= 0
124           then if code ^= error_table_$mylock               /* not mylock */
125                then call abort (code);                      /* then done */
126                else if my_lock_entry                        /* old getbranch entry */
127                then do;
128                          lsw = "0"b;
129                          a_code = code;                     /* be sure caller knows not to unlock */
130                     end;
131                else call syserr (CRASH, "sum: mylock error on ^p", dp);
132 
133           ep = validate_entryp (kstep, code);
134           if ep = null ()
135           then do;
136                     call unlock ();
137                     call abort (code);
138                end;
139           a_ep = ep;
140           return;
141 %page;
142 dirmod:
143      entry (a_dp);
144 
145 /* entry to set the file modified switch on a directory and reflect it up */
146 
147           if pds$transparent.m = "1"b
148           then return;                                      /* Do nothing if in transparent modification mode. */
149           target_dp = a_dp;
150           on fixedoverflow
151                begin;
152                     target_dp -> dir.change_pclock = 0;
153                     go to clocked;
154                end;
155 
156 (fixedoverflow):
157           target_dp -> dir.change_pclock = target_dp -> dir.change_pclock + 1;
158 
159 clocked:
160           call get_kstep (fixed (baseno (target_dp), 17), kstep, code);
161           if code ^= 0
162           then return;                                      /* if segno invalid, skip it */
163           if kstep -> kste.uid = (36)"1"b
164           then do;                                          /* this is the root */
165                     call lock$lock_ast;                     /* so we can change gtms safely */
166                     astep = addr (sst_seg$) -> sst.root_astep;
167                                                             /* if so get the astep from the sst */
168                end;
169           else do;
170                     ep = validate_entryp (kstep, (0));      /* We don't care what is wrong, and code is already zero */
171                     if ep = null
172                     then return;                            /* if it was deleted, skip it */
173                     astep = activate (ep, code);            /* Get pointer to ASTE of dir */
174                                                             /* Dir oughtta have been locked, can't delete */
175                     if astep = null
176                     then call syserr (CRASH, "sum: dirmod failed to activate ^p", ep);
177                end;
178           aste.gtms = "0"b;                                 /* tell page control that we really mean it */
179           old_dtm = aste.dtm;
180           call pc$updates (astep);                          /* set the fms switch on */
181           dtm_changed = (old_dtm ^= aste.dtm);
182           aste.gtms = "1"b;                                 /* shut the door */
183           call lock$unlock_ast;
184           if pds$throttle_segment_state_changes
185           then if dtm_changed
186                then call limit_covert_channel (1);          /* setting dtm propogates up thru aim boundaries */
187           return;
188 %page;
189 unlock:
190      proc ();
191           if lsw
192           then call lock$dir_unlock (dp);
193      end unlock;
194 
195 abort:
196      proc (code);
197           dcl     code                   fixed bin (35);
198           a_code = code;
199           go to non_local_return;
200      end abort;
201 
202 non_local_return:
203           return;
204 %page;
205 validate_entryp:
206      procedure (a_kstep, a_code) returns (pointer);
207 
208 /* *      VALIDATE_ENTRYP
209    *
210    *      This procedure is used to ensure a kste entry pointer is valid; that is,
211    *      that the directory salvager has not moved it, and that repeated entry
212    *      deletions and creations have not rendered it invalid.
213    *
214    *      If the kste entry pointer points to an entry which passes a few simple
215    *      checks, it is assumed to be valid, and is returned. Otherwise, the
216    *      entire directory is searched for an entry with the proper matching UID,
217    *      and a pointer to that entry is returned. If this, too, fails, a null
218    *      pointer is returned, and an error code appropriate to the purpose,
219    *      depending on access.
220    *
221    *      The initial check avoids touching anything other than the entry structure
222    *      itself, to minimize page faults on the directory.
223    *
224    *      The caller of this procedure is assumed to have the directory already
225    *      locked. This procedure is capable of signalling bad_dir_.
226    *
227    *      Written April 1975 for new KST/RNT system by R. Bratt
228    *      Modified 8/76 by S.E. Barr for new hash table format
229    *      Modified 07/77 by THVV for bad_dir_ check
230    *      Modified 12 August 1981, W. Olin Sibert, to move the code for generation
231    *        of the error code here, from sum, and to change the calling sequence from
232    *        (entryp, uid) to (kstep, code).
233    *      Modified 23 March 1984, K. Loepere to check entry.bs
234 */
235 
236 /* Parameters */
237 
238           dcl     a_code                 fixed bin (35) parameter;
239           dcl     a_kstep                pointer parameter;
240 
241 /* Variables */
242 
243           dcl     dp                     pointer;
244           dcl     entries_in_dir         fixed bin;
245           dcl     entries_seen           fixed bin;
246           dcl     ep                     pointer;
247           dcl     kstep                  pointer;
248           dcl     np                     pointer;
249           dcl     rep                    bit (18) aligned;
250           dcl     uid                    bit (36) aligned;
251 %page;
252           kstep = a_kstep;
253           uid = kstep -> kste.uid;
254           ep = kstep -> kste.entryp;                        /* What we think it is now... */
255           dp = pointer (ep, 0);
256           np = addr (ep -> entry.primary_name);
257 
258 /* Consistency check:  UID matches in entry and in primary name; and type is valid. */
259 /* Also ensure entry.bs is on for branches */
260 
261           if uid = ep -> entry.uid
262           then if (ep -> entry.type = SEG_TYPE) | (ep -> entry.type = DIR_TYPE)
263                then if ep -> entry.bs = "1"b  /* Must have entry.bs on. */
264                     then if np -> names.owner = uid
265                          then do;
266                                    a_code = 0;              /* Looks OK */
267                                    return (ep);
268                               end;
269 
270 /* If it fails the check, then it has moved. We must go hunting for it. */
271 /* We should probably meter these events in active_hardcore_data.... */
272 
273           entries_in_dir = dp -> dir.seg_count + dp -> dir.dir_count + dp -> dir.lcount;
274           entries_seen = 0;
275 
276           do rep = dp -> dir.entryfrp repeat (ep -> entry.efrp) while (rep ^= "0"b);
277                ep = pointer (dp, rep);                      /* get a pointer to the next entry */
278                entries_seen = entries_seen + 1;
279 
280                if entries_seen > entries_in_dir
281                then signal condition (bad_dir_);
282 
283                if ep -> entry.bs
284                then if (ep -> entry.owner ^= dp -> dir.uid)
285                          | (ep -> entry.type ^= SEG_TYPE & ep -> entry.type ^= DIR_TYPE)
286                     then signal condition (bad_dir_);
287 
288                if ep -> entry.uid = uid
289                then do;                                     /* match is found */
290                          kstep -> kste.entryp = ep;         /* Update KSTE, so this will work next time */
291                          a_code = 0;                        /* Success */
292                          return (ep);
293                     end;
294           end;                                              /* Of loop through directory */
295 
296 /* Branch is no longer there.  Since this (sum) is just an internal interface,
297    we simply return error_table_$seg_deleted.  The gate entries (within
298    dc_find) will return a better (censored) error code. */
299 
300           a_code = error_table_$seg_deleted;
301           return (null ());                                 /* Indicate failure */
302      end validate_entryp;
303 %page;
304 %include aste;
305 %page;
306 %include dir_entry;
307 %page;
308 %include dir_header;
309 %page;
310 %include dir_name;
311 %page;
312 %include fs_types;
313 %page;
314 %include kst;
315 %page;
316 %include sst;
317 %page;
318 %include syserr_constants;
319 %page;
320 /* BEGIN MESSAGE DOCUMENTATION
321 
322    Message:
323    sum: mylock error on XXX|0
324 
325    S:     $crash
326 
327    T:     $run
328 
329    M:     A directory which should not be locked
330    is found locked.
331    $err
332 
333    A:     $recover
334 
335    Message:
336    sum: dirmod failed to activate XXX|0
337 
338    S:     $crash
339 
340    T:     $run
341 
342    M:     Directory control could not activate a directory.
343    $err
344    It is possible that the AST is damaged.
345 
346    A:     $recover
347 
348    END MESSAGE DOCUMENTATION */
349 
350      end sum;