1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1984 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 /* format: style4,indattr,ifthenstmt,ifthen,idind35,^indcomtxt */
 10 
 11 fs_modes: proc (a_segptr, a_mode, a_ex_mode, a_rings, a_code);
 12 
 13 /*        Created 10/11/84 from fs_get by Keith Loepere.
 14           Modified 4/9/85 to keep mode/ex_mode straight by Keith Loepere.
 15 */
 16 
 17 
 18 /****^  HISTORY COMMENTS:
 19   1) change(86-08-08,GDixon), approve(86-08-08,MCR7388),
 20      audit(86-09-02,Farley), install(86-09-08,MR12.0-1150):
 21      Add warning to fs_modes$locked entrypoint on requirements for properly
 22      calling the entry.
 23                                                    END HISTORY COMMENTS */
 24 
 25 
 26 /* This program is used by internal interfaces to look-up access modes
 27 on objects.  It makes no access checks.  Also, it is optimized to examine
 28 kst and sdw fields for access. */
 29 
 30 /* Parameters */
 31 
 32 dcl  a_code                             fixed bin (35) parameter;
 33 dcl  a_ex_mode                          bit (36) aligned parameter; /* extended access  bits EX ACC */
 34 dcl  a_mode                             bit (36) aligned parameter;
 35 dcl  a_rings                            (3) fixed bin (3) parameter;
 36 dcl  a_segptr                           ptr parameter;
 37 
 38 /* Constants */
 39 
 40 dcl  read_lock                          bit (36) aligned static options (constant) init ("0"b);
 41 
 42 /* Variables */
 43 
 44 dcl  code                               fixed bin (35);
 45 dcl  dirsw                              bit (1) aligned;
 46 dcl  dp                                 ptr;
 47 dcl  ex_mode                            bit (36) aligned;
 48 dcl  have_ep                            bit (1) aligned;
 49 dcl  lock_sw                            bit (1) aligned;
 50 dcl  mode                               bit (36) aligned;
 51 dcl  rb                                 (3) fixed bin (3);
 52 dcl  ring                               fixed bin;
 53 dcl  segno                              fixed bin (17);
 54 dcl  segptr                             ptr;
 55 
 56 /* External */
 57 
 58 dcl  dseg$                              (0:1) fixed bin (71) external;
 59 dcl  error_table_$mylock                fixed bin (35) external;
 60 
 61 /* Entries */
 62 
 63 dcl  get_kstep                          entry (fixed bin, ptr, fixed bin (35));
 64 dcl  level$get                          entry returns (fixed bin);
 65 dcl  lock$dir_unlock                    entry (ptr);
 66 dcl  sum$getbranch_root_my              entry (ptr, bit (36) aligned, ptr, fixed bin (35));
 67 dcl  update_kste_access                 entry (ptr, ptr, bit (36) aligned);
 68 
 69 /* Misc */
 70 
 71 dcl  (addr, baseno, binary, fixed, null, ptr) builtin;
 72 %page;
 73           have_ep = "0"b;
 74           go to join;
 75 
 76 locked: entry (a_segptr, a_mode, a_ex_mode, a_rings, a_code);
 77 
 78           have_ep = "1"b;
 79 
 80 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 81 /*                                                                           */
 82 /* WARNING:  When calling fs_modes$locked, sum$getbranch or                  */
 83 /* sum$getbranch_root_my must have been called to obtain a pointer to the    */
 84 /* directory entry corresponding to a_segptr.  This call to sum will lock    */
 85 /* the directory and validate kste.entryp (the pointer to the dir entry      */
 86 /* which is stored within the segment's KST entry).  The directory must      */
 87 /* remain locked until after fs_modes$locked returns, since fs_modes$locked  */
 88 /* uses kste.entryp to obtain a pointer to the dir entry.  Otherwise, the    */
 89 /* dir entry could be moved within the directory by another processor,       */
 90 /* causing fs_modes to reference a garbage location within the directory.    */
 91 /*                                                                           */
 92 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 93 
 94 
 95 join:     segptr = a_segptr;                                /* copy arg */
 96 
 97           call get_kstep (fixed (baseno (segptr), 17), kstep, code); /* get kst entry ptr for this seg */
 98           if code ^= 0 then go to RETURN;
 99 
100           if have_ep then ep = kste.entryp;                 /* dir locked => entryp valid */
101           else ep = null;
102 
103           dirsw = kstep -> kste.dirsw;                      /* pick up directory flag from kst */
104 
105           if kstep -> kste.uid = (36)"1"b then do;          /* special case the root */
106                lock_sw = "0"b;
107                dp = null;                                   /* get access to root */
108                if kstep -> kste.dtbm = (36)"1"b then call update_kste_access (kstep, ep, mode);
109                mode = RW_ACCESS;                            /* raw mode */
110                ex_mode = kstep -> kste.extended_access;     /* pick up directory access */
111                rb (1), rb (2), rb (3) = 7;
112           end;
113 
114           else do;                                          /* if a non directory try to get access from sdw */
115                if dirsw = "0"b then do;                     /* before locking the parent */
116                     dp = null;
117                     lock_sw = "0"b;
118                     segno = fixed (baseno (segptr), 17);
119                     sdwp = addr (dseg$ (segno));
120                     if sdwp -> sdw.df = "1"b then call get_sdw_access; /* access in sdw is ok, since no setfaults done */
121                     else do;                                /* lock parent to validate the dtbm in kste */
122                          call lock_dir;
123                                                             /* must update access in kste and change sdw access */
124                          if kstep -> kste.dtbm ^= ep -> entry.dtem then
125                               call update_kste_access (kstep, ep, mode);
126                          else mode = kstep -> kste.access;  /* access in kste okay */
127                          rb (*) = binary (ep -> entry.ring_brackets (*), 3);
128                     end;
129                     ex_mode = kstep -> kste.extended_access;
130                end;
131                else do;
132                     call lock_dir;
133                     if kstep -> kste.dtbm ^= ep -> entry.dtem then call update_kste_access (kstep, ep, mode);
134                     mode = RW_ACCESS;
135                     ex_mode = kstep -> kste.extended_access;
136                     rb (*) = binary (kstep -> kste.ex_rb (*), 3); /* factor in extended ring brackets */
137                end;
138           end;
139 
140           call compute_effective_mode;
141           if dirsw then call compute_effective_dir_mode;
142 
143           if lock_sw then call lock$dir_unlock (dp);
144 
145           a_rings = rb;
146           a_mode = mode;
147           a_ex_mode = ex_mode;
148 
149 RETURN:   a_code = code;
150           return;
151 %page;
152 get_sdw_access: proc;
153           mode = kstep -> kste.access;
154           rb (1) = fixed (sdwp -> sdw.r1, 3);
155           rb (2) = fixed (sdwp -> sdw.r2, 3);
156           rb (3) = fixed (sdwp -> sdw.r3, 3);
157      end get_sdw_access;
158 
159 lock_dir: proc;
160 
161           lock_sw = "0"b;
162           if ^have_ep then do;
163                call sum$getbranch_root_my (segptr, (read_lock), ep, code); /* lock parent and get pointer to entry */
164                if code ^= 0 then
165                     if code ^= error_table_$mylock then go to RETURN;
166                     else code = 0;                          /* allow parent to be locked by us */
167                else lock_sw = "1"b;
168           end;
169           dp = ptr (ep, 0);                                 /* get pointer to parent directory */
170 
171      end lock_dir;
172 
173 compute_effective_mode: proc;
174 
175           ring = level$get ();
176           if ring = rb (1) then ;
177           else if ring < rb (1) then mode = mode & "101"b;
178           else if ring <= rb (2) then mode = mode & "110"b;
179           else if ring <= rb (3) then mode = mode & "010"b;
180           else mode = "0"b;
181 
182      end compute_effective_mode;
183 
184 compute_effective_dir_mode: proc;
185 
186           ring = level$get ();
187           if ring <= rb (1) then ;
188           else if ring <= rb (2) then ex_mode = ex_mode & "100"b;
189           else ex_mode = "0"b;
190 
191      end compute_effective_dir_mode;
192 %page; %include access_mode_values;
193 %page; %include dir_entry;
194 %page; %include fs_types;
195 %page; %include kst;
196 %page; %include sdw;
197      end fs_modes;