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;