1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 salv_directory:
 15      proc (arg_info_p, message, arg_old_dir_p, arg_old_dir_len, arg_code);
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 dcl  arg_branch_p ptr;                                      
 61 dcl  arg_code fixed bin (35);                               
 62 dcl  arg_dp ptr;                                            
 63 dcl  arg_info_p ptr;                                        
 64 dcl  arg_old_dir_len fixed bin;                             
 65 dcl  arg_old_dir_p ptr;                                     
 66 dcl  message char (*) var;                                  
 67 
 68 
 69 
 70 dcl  astep (4) ptr;                                         
 71 dcl  branch_p ptr;                                          
 72 dcl  caller fixed bin;                                      
 73 dcl  child_dirmod bit (1) aligned;                          
 74 dcl  code fixed bin (35);
 75 dcl  1 copy_args aligned like salv_args;                    
 76 dcl  dir_uid bit (36) aligned;                              
 77 dcl  1 event_flags aligned like audit_event_flags;          
 78 dcl  info_p ptr;                                            
 79 dcl  new_dir_pages fixed bin;                               
 80 dcl  parent_dirmod bit (1) aligned;                         
 81 dcl  root bit (1) aligned;                                  
 82 dcl  1 root_entry aligned like entry;                       
 83 dcl  set_security_oosw bit (1) aligned;                     
 84 dcl  should_dump bit (1) aligned;                           
 85 dcl  unlock_dir bit (1) aligned;                            
 86 dcl  unlock_parent bit (1) aligned;                         
 87 
 88 
 89 
 90 dcl  1 dir_branch aligned like entry based (branch_p);
 91 dcl  1 info aligned like salv_args based (info_p);
 92 
 93 
 94 
 95 dcl  ME char (14) int static options (constant) init ("salv_directory");
 96 dcl  MAX_MESSAGE_SIZE fixed bin (18) int static options (constant) init (16 * 1024);
 97 dcl  NEW_LINE char (1) int static options (constant) init ("
 98 ");
 99 dcl  ONLINE fixed bin int static options (constant) init (3);
100 dcl  RING_0 fixed bin int static options (constant) init (1);
101 dcl  RING_4 fixed bin int static options (constant) init (2);
102 dcl  packed_null ptr unal int static options (constant) init (null ());
103 
104 
105 
106 dcl  access_operations_$fs_obj_set_soos bit (36) aligned external;
107 dcl  error_table_$ external static;
108 dcl  error_table_$no_terminal_quota fixed bin (35) external;
109 dcl  error_table_$mylock fixed bin (35) external static;
110 dcl  pds$processid bit (36) aligned external static;
111 dcl  pvt$root_lvid bit (36) aligned external;
112 dcl  pvt$root_pvid bit (36) aligned external;
113 dcl  pvt$root_vtocx fixed bin (17) external;
114 dcl  sys_info$default_dir_max_length fixed bin (19) external;
115 
116 
117 
118 dcl  access_audit_$log_obj_class entry options (variable);
119 dcl  arg_count_ entry returns (fixed bin);
120 dcl  arg_list_ptr_ entry returns (pointer);
121 dcl  dir_dump entry (ptr, fixed bin);
122 dcl  formline_ entry (fixed bin, fixed bin, ptr, fixed bin, fixed bin (35));
123 dcl  grab_aste$prewithdraw entry (ptr, fixed bin (18), fixed bin (35)) returns (ptr);
124 dcl  grab_aste$release_prewithdraw entry (ptr);
125 dcl  level$get entry () returns (fixed bin);
126 dcl  lock$dir_unlock entry (pointer);
127 dcl  lock$dir_unlock_given_uid entry (bit (36) aligned);
128 dcl  salv_dir_checker_ entry (ptr, ptr, entry, bit (1) aligned, fixed bin);
129 dcl  salv_check_vtoce_ entry (ptr, char (*), bit (1) aligned, entry);
130 dcl  salv_err_msg$path entry options (variable);
131 dcl  sum$dirmod entry (pointer);
132 dcl  sum$getbranch_root_my entry (ptr, bit (1) aligned, ptr, fixed bin (35));
133 dcl  syserr entry options (variable);
134 dcl  truncate_vtoce entry (ptr, fixed bin, fixed bin (35));
135 dcl  vtoc_attributes$get_info entry (bit (36) aligned, bit (36) aligned, fixed bin, ptr, fixed bin (35));
136 dcl  vtoc_attributes$set_max_lth
137           entry (bit (36) aligned, bit (36) aligned, fixed bin, fixed bin (9), bit (1) aligned, fixed bin (35));
138 
139 
140 
141 dcl  cleanup condition;
142 
143 dcl  (addr, baseno, divide, hbound, length, min, null, ptr, rel, rtrim, string, substr, unspec) builtin;
144 %page;
145 
146 
147           call setup;
148           caller = RING_4;
149           arg_old_dir_len = 0;
150           copy_args = arg_info_p -> salv_args;
151           info_p = addr (copy_args);
152 
153           goto START;
154 
155 
156 ring0_salvage:
157      entry (arg_info_p, arg_code);
158 
159           call setup;
160           caller = RING_0;
161           info_p = arg_info_p;
162           goto START;
163 
164 
165 
166 
167 
168 online_salvage:
169      entry (arg_info_p, arg_branch_p, arg_dp, arg_code);
170 
171           call setup;
172           info_p = arg_info_p;
173           branch_p = arg_branch_p;
174           dp = arg_dp;
175           caller = ONLINE;
176 
177 
178 START:
179           arg_code = 0;
180 
181 
182 
183 
184 
185 
186 
187 
188 
189 
190           unlock_dir, unlock_parent = "0"b;
191 
192           on cleanup call clean_up;
193 
194           if caller = RING_4 then do;
195                call hold_segs (code);
196                if code ^= 0 then do;
197                     arg_code = code;
198                     call rel_segs;
199                     return;
200                     end;
201                end;
202 
203           call get_dir (code);
204           if code = 0 then do;
205 
206 
207                should_dump = info.dump;
208 
209                if dir_branch.master_dir
210                then info.master_dir_uid = dir_branch.uid;
211                else info.master_dir_uid = ptr (branch_p, 0) -> dir.master_dir_uid;
212 
213                if root
214                then info.tree_depth = 0;
215                else info.tree_depth = ptr (branch_p, 0) -> dir.tree_depth + 1;
216 
217                info.branch_ptr = branch_p;
218 
219 
220 
221                call vtoc_attributes$get_info ((dir_branch.uid), (dir_branch.pvid), (dir_branch.vtocx), addr (sc_info),
222                     code);
223                if code = 0 then do;
224                     info.current_length = divide (sc_info.csl + 1023, 1024, 17, 0);
225                     if sc_info.msl ^= sys_info$default_dir_max_length then do;
226                          call vtoc_attributes$set_max_lth ((dir_branch.uid), (dir_branch.pvid), (dir_branch.vtocx),
227                               divide (sys_info$default_dir_max_length, 1024, 9, 0), "0"b, code);
228                          if code = 0
229                          then call print (SALV_LOG, ME, "Changed max length in VTOCE from ^d to ^d.", sc_info.msl,
230                                    sys_info$default_dir_max_length);
231                          else call print_code (SALV_LOG, ME, code, "Changing max length in VTOCE.");
232                          end;
233 
234                     call salv_dir_checker_ (dp, info_p, print, set_security_oosw, new_dir_pages);
235 
236 
237                     if new_dir_pages > 0 then do;
238                          child_dirmod = "1"b;
239 
240                          if new_dir_pages < info.current_length then do;
241                               call truncate_vtoce (branch_p, new_dir_pages, code);
242                               if code ^= 0
243                               then call print_code (SALV_ANNOUNCE, ME, code, "truncate_vtoce to length ^d failed.",
244                                         new_dir_pages);
245                               code = 0;
246                               end;
247                          end;
248                     call check_upgraded_dir;
249                     if set_security_oosw then do;
250                          dir_branch.security_oosw = "1"b;
251                          parent_dirmod = "1"b;
252                          end;
253 
254                     if info.check_vtoce
255                     then call salv_check_vtoce_ (dp, (info.pathname), (info.delete_connection_failure), print_code);
256                                                             
257 
258                     do ep = ptr (dp, dir.entryfrp) repeat ptr (dp, entry.efrp) while (rel (ep));
259 
260                          if entry.bs
261                          then if entry.security_oosw then do;
262                                    call print (SALV_LOG, ME,
263                                         "Branch is security out-of-service: " || addr (entry.primary_name) -> names.name);
264                                    string(event_flags) = ""b;
265                                    event_flags.special_op = "1"b;
266                                    event_flags.grant = "1"b; 
267                                    if caller = RING_4
268                                    then event_flags.priv_op = "1"b;
269                                    call access_audit_$log_obj_class ("salv_directory", level$get(),
270                                         string(event_flags), access_operations_$fs_obj_set_soos,
271                                         entry.access_class, target (info.pathname,
272                                         (addr(entry.primary_name)->names.name)), 0, null(), 0,
273                                         "switch found already on");
274 
275                                    end;
276 
277                     end;
278                     end;
279                end;
280           call clean_up;
281 
282           if code ^= 0 then do;                             
283                call print_code (SALV_ANNOUNCE, ME, code, "Could not read VTOCE attributes.");
284                arg_code = code;
285                end;
286 
287           return;
288 %page;
289 
290 
291 check_upgraded_dir:
292      proc;
293 
294 dcl  1 quota_info aligned like quota_cell defined (sc_info.qcell (0));
295 
296           if root then return;
297           if ptr (branch_p, 0) -> dir.access_class = dir.access_class then return;
298           if quota_info.quota = 0 then do;
299                call print (SALV_ANNOUNCE, ME, "Upgraded dir set security out-of-service due to no quota.");
300                string(event_flags) = ""b;
301                event_flags.special_op = "1"b;
302                event_flags.grant = "1"b;
303                if caller = RING_4
304                then event_flags.priv_op = "1"b;
305                call access_audit_$log_obj_class ("salv_directory", level$get(),
306                     string(event_flags), access_operations_$fs_obj_set_soos, dir.access_class,
307                     info.pathname, error_table_$no_terminal_quota, null(), 0);
308                set_security_oosw = "1"b;
309                end;
310 
311      end check_upgraded_dir;
312 %page;
313 get_dir:
314      proc (code);
315 
316 dcl  code fixed bin (35) parameter;
317 
318           root = (info.pathname = ">");
319           code = 0;
320 
321 
322 
323 
324           if caller = ONLINE then do;
325                if root then call setup_root_branch;
326                return;
327                end;
328 
329 
330 
331           call dc_find$dir_salvage (info.pathname, dir_uid, dp, code);
332           if code ^= 0 then return;
333           unlock_dir = "1"b;
334 
335           dir.modify = pds$processid;
336 
337 
338 
339           if root
340           then call setup_root_branch;
341           else do;
342                call sum$getbranch_root_my (dp, "1"b, branch_p, code);
343                if code = 0
344                then unlock_parent = "1"b;
345                else if code ^= error_table_$mylock then return;
346                end;
347 
348           return;
349 
350      end get_dir;
351 %page;
352 hold_segs:
353      proc (code);
354 
355 dcl  code fixed bin (35) parameter;
356 
357           astep (*) = null;
358 
359 
360           astep (1) = grab_aste$prewithdraw (addr (message), MAX_MESSAGE_SIZE, code);
361           if code ^= 0 then return;
362 
363 
364           if info.dump then do;
365                astep (2) = grab_aste$prewithdraw (arg_old_dir_p, 255 * 1024, code);
366                if code ^= 0 then return;
367                end;
368 
369 
370 
371           astep (3) = grab_aste$prewithdraw (info.temp2_ptr, 64 * 1024, code);
372           if code ^= 0 then return;
373 
374 
375 
376           astep (4) = grab_aste$prewithdraw (info.temp1_ptr, 255 * 1024, code);
377           return;
378 
379      end hold_segs;
380 %page;
381 clean_up:
382      proc;
383 
384 
385 
386 
387           if dp ^= null then dir.modify = "0"b;
388 
389           if child_dirmod
390           then call sum$dirmod (dp);
391           else if parent_dirmod then call sum$dirmod (ptr (branch_p, 0));
392 
393           if unlock_dir then call lock$dir_unlock_given_uid (dir_uid);
394           if unlock_parent then call lock$dir_unlock (ptr (branch_p, 0));
395           if dp ^= null then call dc_find$finished (dp, "0"b);
396 
397           if caller = RING_4 then call rel_segs;
398 
399      end clean_up;
400 
401 
402 
403 rel_segs:
404      proc;
405 
406 dcl  i fixed bin;
407 
408           do i = 1 to hbound (astep, 1);
409                if astep (i) ^= null then call grab_aste$release_prewithdraw (astep (i));
410           end;
411 
412      end rel_segs;
413 %page;
414 print:
415      procedure options (variable);
416 
417 
418 dcl  arg_list_arg_count fixed bin;
419 dcl  arg_list_ptr pointer;
420 dcl  caller_name char (32);
421 dcl  copy_len fixed bin;
422 dcl  have_code bit (1) aligned;                             
423 dcl  line char (256);                                       
424 dcl  line_len fixed bin;                                    
425 dcl  msg_len fixed bin;                                     
426 dcl  msg_p ptr unal;                                        
427 dcl  pic pic "99";
428 dcl  severity fixed bin;                                    
429 dcl  start fixed bin;                                       
430 dcl  string char (253) defined (line) pos (3);              
431 
432 dcl  based_code fixed bin (35) based;
433 dcl  based_severity fixed bin based;
434 dcl  based_caller_name char (32) based;
435 dcl  copy (copy_len) bit (36) based;
436 dcl  1 et aligned based (msg_p),                            
437        2 len fixed bin (8) unal,                            
438        2 msg char (et.len) unal;                            
439 %page;
440           have_code = "0"b;
441           start = 3;
442           goto FORMAT;
443 
444 print_code:
445      entry options (variable);
446 
447           have_code = "1"b;                                 
448           start = 4;
449 
450 FORMAT:                                                     
451           arg_list_ptr = arg_list_ptr_ ();
452           arg_list_arg_count = arg_count_ ();
453 
454           if arg_list_arg_count < 3 then call syserr (CRASH, "salv_directory: Invalid call to error message printer.");
455 
456           severity = arg_list_ptr -> arg_list_with_envptr.arg_ptrs (1) -> based_severity;
457           caller_name = substr (arg_list_ptr -> arg_list_with_envptr.arg_ptrs (2) -> based_caller_name,
458                1, arg_list_ptr -> arg_list_with_envptr.desc_ptrs (2) -> arg_descriptor.size);
459           if have_code
460           then code = arg_list_ptr -> arg_list_with_envptr.arg_ptrs (3) -> based_code;
461           else code = 0;
462           if code = 0 then have_code = "0"b;                
463 
464           line_len = length (string);
465           call formline_ (start, start + 1, addr (string), line_len, (0));
466           line_len = length (rtrim (substr (string, 1, line_len)));
467           substr (line, 1, 2) = "";
468           line_len = line_len + 2;
469 
470 
471 
472           if have_code then do;
473                unspec (msg_p) = unspec (code);
474                if baseno (msg_p) = baseno (packed_null) then do;
475                     msg_p = ptr (addr (error_table_$), rel (msg_p));
476                     msg_len = min (length (line) - line_len, et.len + 1);
477                     if msg_len > 0 then do;
478                          substr (line, line_len + 1, msg_len) = " " || et.msg;
479                          line_len = line_len + msg_len;
480                          end;
481                     end;
482                end;
483 
484 
485 
486 
487           if caller = RING_4 then do;
488                pic = severity;
489                if length (message) + line_len < MAX_MESSAGE_SIZE then do;
490                     message = message || pic;
491                     message = message || substr (line, 1, line_len) || NEW_LINE;
492                     if (severity = SALV_DEBUG) & should_dump then do;
493                          copy_len, arg_old_dir_len = info.current_length * 1024;
494                          arg_old_dir_p -> copy = dp -> copy;
495                          should_dump = "0"b;
496                          end;
497                     end;
498                end;
499           else do;
500                call salv_err_msg$path (severity, info.pathname, rtrim (caller_name) || ": " || substr (line, 1, line_len));
501                if (severity = SALV_DEBUG) & should_dump then do;
502                     call dir_dump (dp, info.current_length);
503                     should_dump = "0"b;
504                     end;
505                end;
506 
507      end print;
508 %page;
509 setup_root_branch:
510      procedure;
511 
512           branch_p = addr (root_entry);
513           unspec (root_entry) = "0"b;
514           root_entry.uid, root_entry.owner = (36)"1"b;
515           root_entry.pvid = pvt$root_pvid;
516           root_entry.sons_lvid = pvt$root_lvid;
517           root_entry.vtocx = pvt$root_vtocx;
518           root_entry.dirsw = "1"b;
519           root_entry.master_dir = "1"b;
520           root_entry.name_frp = rel (addr (root_entry.primary_name));
521           addr (root_entry.primary_name) -> names.name = ">";
522           root_entry.per_process_sw = "0"b;
523           root_entry.bs = "1"b;
524           root_entry.access_class = "0"b;
525 
526      end setup_root_branch;
527 
528 setup:
529      procedure;
530 
531 
532 
533           dp, branch_p = null ();
534           unlock_dir, unlock_parent = "0"b;
535           parent_dirmod, child_dirmod = "0"b;
536      end setup;
537 %page;
538 target: proc (dir, ent) returns (char (*));
539 
540 dcl       dir       char (*) parameter;
541 dcl       ent       char (*) parameter;
542 
543           if dir = ">"
544           then return (">"||ent);
545           else return (rtrim(dir)||">"||ent);
546 
547      end target;
548 %page;
549 %include arg_descriptor;
550 %page;
551 %include arg_list;
552 %page;
553 %include dc_find_dcls;
554 %page;
555 %include dir_allocation_area;
556 %page;
557 %include dir_entry;
558 %page;
559 %include dir_header;
560 %page;
561 %include dir_name;
562 %page;
563 %include quota_cell;
564 %page;
565 %include salv_args;
566 %page;
567 %include salvager_severities;
568 %page;
569 %include sc_info;
570 %page;
571 %include syserr_constants;
572 %page;
573 %include access_audit_eventflags;
574 %page;
575 
576 
577 
578 
579 
580 
581 
582 
583 
584 
585 
586 
587 
588 
589 
590 
591 
592 
593 
594 
595 
596 
597 
598 
599 
600 
601 
602 
603 
604 
605 
606 
607 
608 
609 
610 
611 
612 
613 
614 
615 
616 
617 
618 
619 
620 
621 
622 
623 
624 
625 
626 
627 
628 
629 
630 
631 
632 
633 
634 
635 
636 
637 
638 
639 
640 
641 
642 
643 
644 
645 
646 
647 
648 
649 
650 
651 
652 
653 
654 
655 
656 
657 
658 
659 
660 
661 
662 
663 
664 
665 
666 
667 
668 
669 
670 
671 
672 
673 
674 
675 
676 
677 
678 
679 
680 
681 
682 
683 
684 
685 
686 
687 
688 
689      end salv_directory;