1 /****^  ***********************************************************
   2         *                                                         *
   3         * Copyright, (C) BULL HN Information Systems Inc., 1989   *
   4         *                                                         *
   5         * Copyright, (C) Honeywell Bull Inc., 1987                *
   6         *                                                         *
   7         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   8         *                                                         *
   9         * Copyright (c) 1972 by Massachusetts Institute of        *
  10         * Technology and Honeywell Information Systems, Inc.      *
  11         *                                                         *
  12         *********************************************************** */
  13 
  14 
  15 
  16 /****^  HISTORY COMMENTS:
  17   1) change(89-02-27,TLNguyen), approve(89-02-27,MCR8049),
  18      audit(89-02-28,Parisek), install(89-03-15,MR12.3-1025):
  19      a. removed create_branch_version_1.
  20      b. fixed size error.
  21      c. fixed stringsize error.
  22   2) change(89-03-31,TLNguyen), approve(89-03-31,PBF8049),
  23      audit(89-03-31,Farley), install(89-04-24,MR12.3-1031):
  24      Reinstated the check for create_branch_version_1 in order to retain
  25      binary compatibility.
  26                                                    END HISTORY COMMENTS */
  27 
  28 
  29 /* format: style4,indattr,ifthenstmt,ifthen,idind35,^indcomtxt */
  30 
  31 append: procedure;
  32 
  33 /* Modified 85-04-01 by Keith Loepere for new access_audit_check_ep_. */
  34 /* Modified 85-01-30 by Keith Loepere to get dtem right. */
  35 /* Modified 84-02-11 by Greg Texada to reference the arguments correctly in retv entry */
  36 /* Modified 84-12-14 by Keith Loepere to allow setting dir quota for dirs */
  37 /* Modified 84-11-27 by EJ Sharpe to change access_audit_ arg list */
  38 /* Modified 10/15/84 by Keith Loepere to explicitly activate dir being created.
  39    Also to prevent creation of upgraded MSFs.  Also for audit info.  Also for
  40    admin_gate_$create_branch_ */
  41 /* Modified 1984-10-01 BIM to fix retv max_auth for ^ac_sw case. */
  42 /* Modified 07/10/84 by Keith Loepere to use the new dc_find. */
  43 /* Modified 04/02/84 by K. Loepere to restrict link pathnames to valid 7-bit ASCII characters. */
  44 /* Modified 84-03-16 BIM to make retv work with AIM.
  45             this includes TEMPORARY change to set soos on multi-class
  46             objects retrieved. */
  47 /* Modified 05/07/82 by J. Bongiovanni to fix bug in cross-retrieval */
  48 /* Modified 02/15/82 by J. Bongiovanni to fix bug in duplicate uid check */
  49 /* Modified 11/01/79 by Mike Grady to set sons lvid for retv case (used by adopt seg) */
  50 /* Modified 02/19/79 by C. D. Tavares to set dir ex ring brackets and to correct several bad_ring_brackets err codes */
  51 /* modified 6/77 by D. Vinograd to check for duplicate uids in volume retriever case */
  52 /* modified 4/77 by M. Weaver to replace makeknown with makeknown_ */
  53 /* modified by D. Vinograd 9/76 to add entry retv. This entry used by the volume
  54    retriever to append an entry structure passed in by the caller. */
  55 /* modified by S.E. Barr 8/76 to use variable sized hash tables */
  56 /* modified by R. Bratt May 31, 1976 to call find_$finished */
  57 /* modified by L. Scheffler March 1976 to use info-only entry in dir_control_error */
  58 /* modified by Larry Johnson March 1976 for appending master dirs */
  59 /* modified by Bernard S. Greenberg, 4-24-75 for NSS */
  60 /* modified by Kobziar 4-11-75 to filter unused bits from access class */
  61 /* modified by Kobziar 10-20-74 to add new entry: create_branch */
  62 /* modified by Kobziar on 6-20-74 to copy  access_class from parent to branch */
  63 /* modified by Kobziar on 11-15-73 to take out "a" mode on segs */
  64 
  65 /*
  66    append$branch: Creates a non directory branch in the hierarchy and places
  67    the current user on the acl with the specified mode.
  68 
  69    USAGE: call append$branch(directory_name, entry_name, access_mode, error_code)
  70 
  71    1. directory_name char(*) - - - directory path name of new branch
  72    2. entry_name char(*) - - - created branch's name
  73    3. access_mode fixed bin(5) - - - mode desired on the created branch
  74    4. error_code fixed bin(35) - - - file system error code (Output)
  75 
  76    Default values are:
  77    1. Ringbrackets set from users validation level.
  78    2. User id set to creator User id with tag = "*".
  79    3. Copy switch set to off.
  80    4. Bit count set to 0.
  81 
  82    append$link: Creates a link in a specified directory with a given name
  83    to an other specified segment.
  84 
  85    USAGE: call append$link(directory_name, entry_name, link_to_name, error_code)
  86 
  87    1. directory_name char(*) - - - directory path name of new link
  88    2. entry_name char(*) - - - created link name
  89    3. link_to_name char(*) - - - path name of segment to be linked to
  90    4. error_code fixed bin(17) - - - file system error code (Output)
  91 
  92    append$branchx: Creates either a directory or non directory entry as specified with
  93    all the attributes described below as specified.
  94 
  95    USAGE: call append$branhcx(directory_name, entry_name, access_mode, ringbrackets,
  96    user_id, directory_switch, copy_switch, bit_count,
  97    error_code)
  98 
  99    1. directory_name char(*) - - - directory path name of new branch
 100    2. entry_name char(*) - - - created branch's entry name
 101    3. acces_mode fixed bin(5) - - - mode desired on the created branch
 102    4. ringbrackets arry(3) - - - fixed bin(6) - - - ring brackets desired on the created branch
 103    5. user_id char(*) - - - user_id desired on the acl
 104    6. directory_switch fixed bin(1) - - - directory branch switch
 105    7. copy_switch fixed bin(1) - - - segment copy switch
 106    8. bit_count fixed bin(24) - - - segment length in bits
 107    9. error_code fixed bin(17) - - - file system error code (Output)
 108 
 109    append$master_dir: create a master directory for a logical volume.
 110    Called from ring 1 after setting things up with the vol registration stuff.
 111 
 112    USAGE: call append$master_dir(directory_name, entry_name, access_mode, ringbrackets,
 113    user_id, sons_lvid, error_code);
 114 
 115    1-5. Same as branchx
 116    6. sons_lvid bit (36) - - - logical vol ID for sons
 117    7. error_code fixed bin - - - error code (output)
 118 
 119    append$create_branch_: Allows the setting of the access class field in a branch and  and the setting of
 120    quota in new directories.  admin_create_branch_ is the same but allows creation in lower class dirs.
 121 
 122    USAGE: call append$create_branch_(directory_name, entry_name, arg_ptr, code)
 123 
 124    1. - 2. as in branchx
 125    3. arg_ptr  ptr - - - pointer to a create_branch_info as given in
 126                                                   create_branch_info.incl.pl1
 127    4. error_code as above.
 128 */
 129 %page;
 130 
 131 /* Parameters */
 132 
 133 dcl  a_arg_ptr                          ptr parameter;
 134 dcl  a_bitcnt                           fixed bin (24) parameter;
 135 dcl  a_code                             fixed bin (35) parameter;
 136 dcl  a_copysw                           fixed bin (2) parameter;
 137 dcl  a_dirname                          char (*) parameter;
 138 dcl  a_dirsw                            fixed bin (1) parameter;
 139 dcl  a_ename                            char (*) parameter;
 140 dcl  a_linkname                         char (*) parameter;
 141 dcl  a_mode                             fixed bin (5) parameter;
 142 dcl  a_retv_append_argp                 ptr parameter;
 143 dcl  a_ringbrack                        (3) fixed bin (6) parameter;
 144 dcl  a_sons                             bit (36) parameter;
 145 dcl  a_uid_path                         (0:15) bit (36) aligned parameter;
 146 dcl  a_userid                           char (*) parameter;
 147 
 148 /* static variable */
 149 dcl  create_branch_version_1            fixed bin int static options (constant) init (1);
 150 
 151 /* Variables */
 152 
 153 dcl  ac_sw                              bit (1) aligned;
 154 dcl  acbr_version                       fixed bin;
 155 dcl  access_class                       bit (72) aligned;
 156 dcl  acl_count                          fixed bin;
 157 dcl  acl_start_ptr                      ptr;
 158 dcl  add_sw                             bit (1);
 159 dcl  admin_append                       bit (1) aligned;
 160 dcl  areap                              ptr;
 161 dcl  arg_ptr                            ptr;
 162 dcl  asize                              fixed bin;
 163 dcl  audit_eventflags                   bit (36) aligned;
 164 dcl  authp                              ptr;
 165 dcl  bcount                             fixed bin;
 166 dcl  bitcnt                             fixed bin (24);
 167 dcl  bmode                              bit (3) aligned;
 168 dcl  branch_sw                          bit (1);
 169 dcl  chase_sw                           bit (1) aligned;
 170 dcl  code                               fixed bin (35);
 171 dcl  copysw                             fixed bin (1);
 172 dcl  default_sw                         bit (1);
 173 dcl  dep                                ptr;
 174 dcl  dir_quota                          fixed bin (18);
 175 dcl  dirl                               bit (1) aligned;
 176 dcl  dirname                            char (168);
 177 dcl  dirp                               ptr;
 178 dcl  dirsw                              fixed bin (1);
 179 dcl  dtem                               bit (36) aligned;
 180 dcl  dumcode                            fixed bin (35);
 181 dcl  dummy                              char (32) aligned;
 182 dcl  ename                              char (32);
 183 dcl  ename_aligned                      char (32) aligned;
 184 dcl  i                                  fixed bin;
 185 dcl  iacl_start_ptr                     ptr;
 186 dcl  iaclp                              ptr;
 187 dcl  1 initial_acl                      aligned like input_acl;
 188 dcl  level                              fixed bin;
 189 dcl  linkname                           char (168) aligned;
 190 dcl  llngth                             fixed bin (18);
 191 dcl  1 local_entry                      like entry aligned;
 192 dcl  max_access_authorization           bit (72) aligned;
 193 dcl  1 mk_info                          aligned like makeknown_info;
 194 dcl  1 my_audit_user_info               aligned like audit_user_info;
 195 dcl  n_iacls                            fixed bin;
 196 dcl  newuid                             bit (36) aligned;
 197 dcl  nwords                             fixed bin;
 198 dcl  parent_access_class                bit (72) aligned;
 199 dcl  prevep                             ptr;
 200 dcl  prior_dir_acl_count                fixed bin;
 201 dcl  priv_mqsw                          bit (1) aligned;
 202 dcl  project                            char (32) aligned;
 203 dcl  quota                              fixed bin (18);
 204 dcl  read_lock                          bit (36) aligned;
 205 dcl  retv                               bit (1) aligned;
 206 dcl  retv_cross_segment                 bit (1) aligned;
 207 dcl  ringbrack                          (3) fixed bin (6);
 208 dcl  segno                              fixed bin;
 209 dcl  1 service_acl                      aligned,
 210        2 person                         char (32) init ("*"),
 211        2 project                        char (32) init ("SysDaemon"),
 212        2 tag                            char (1) init ("*"),
 213        2 mode                           bit (36) init ("101"b),
 214        2 exmode                         bit (36) init ("0"b);
 215 dcl  sons                               bit (36) aligned;
 216 dcl  sonsw                              bit (1) aligned;
 217 dcl  sp_sw                              bit (1) aligned;
 218 dcl  sysl                               bit (1) aligned;
 219 dcl  temp_b4                            bit (4) aligned;
 220 dcl  uid_path                           (0:15) bit (36) aligned;
 221 dcl  1 user_acl                         aligned,
 222        2 person                         char (32),
 223        2 project                        char (32),
 224        2 tag                            char (1),
 225        2 mode                           bit (36) init ("111"b),
 226        2 exmode                         bit (36) init ("0"b);
 227 dcl  userid                             char (32) aligned;
 228 dcl  vtocx_temp                         fixed bin;
 229 dcl  xsize                              fixed bin;
 230 
 231 /* Based */
 232 
 233 dcl  1 acbr                             like create_branch_info based (arg_ptr) aligned;
 234 dcl  1 input_acl                        based aligned,
 235        2 person                         char (32),
 236        2 project                        char (32),
 237        2 tag                            char (1),
 238        2 mode                           bit (36),
 239        2 exmode                         bit (36);
 240 
 241 /* External */
 242 
 243 dcl  active_all_rings_data$max_tree_depth external fixed bin;
 244 dcl  active_hardcore_data$alloc_sizes   (6) external fixed bin;
 245 dcl  active_hardcore_data$dir_arearp    ext fixed bin (35);
 246 dcl  active_hardcore_data$dir_hdrsize   external fixed bin;
 247 dcl  active_hardcore_data$elcsize       external fixed bin;
 248 dcl  active_hardcore_data$ensize        external fixed bin;
 249 dcl  active_hardcore_data$esize         external fixed bin;
 250 dcl  active_hardcore_data$nalloc_sizes  external fixed bin;
 251 dcl  error_table_$ai_restricted         external fixed bin (35);
 252 dcl  error_table_$argerr                external fixed bin (35);
 253 dcl  error_table_$invalid_mode          external fixed bin (35);
 254 dcl  error_table_$invalid_project_for_gate external fixed bin (35);
 255 dcl  error_table_$invalid_ring_brackets external fixed bin (35);
 256 dcl  error_table_$lower_ring            external fixed bin (35);
 257 dcl  error_table_$max_depth_exceeded    external fixed bin (35);
 258 dcl  error_table_$namedup               external fixed bin (35);
 259 dcl  error_table_$noalloc               external fixed bin (35);
 260 dcl  error_table_$noentry               external fixed bin (35);
 261 dcl  error_table_$unimplemented_version external fixed bin (35);
 262 dcl  1 pds$access_authorization         aligned like aim_template external;
 263 dcl  1 pds$access_name                  aligned external,
 264        2 person                         char (32),
 265        2 project                        char (32),
 266        2 tag                            char (1);
 267 dcl  pds$max_access_authorization       bit (72) aligned external;
 268 dcl  pds$processid                      bit (36) aligned external;
 269 dcl  sys_info$access_class_ceiling      external bit (72) aligned;
 270 dcl  sys_info$default_dir_max_length    fixed bin (19) external;
 271 
 272 /* Entries */
 273 
 274 dcl  acc_name_$elements                 entry (ptr, ptr, fixed bin (35));
 275 dcl  acc_name_$encode                   entry (ptr, ptr, fixed bin (35));
 276 dcl  access_audit_check_ep_$self        entry (bit (36) aligned, bit (36) aligned, ptr) returns (bit (1));
 277 dcl  access_audit_check_ep_$user        entry (bit (36) aligned, bit (36) aligned, ptr, bit (72) aligned, bit (36) aligned) returns (bit (1));
 278 dcl  access_audit_$log_entry_ptr        entry (char (*), fixed bin, bit (36) aligned, bit (36) aligned, ptr, fixed bin (35), ptr, fixed bin (18), char (*));
 279 dcl  access_audit_$log_entry_ptr_user   entry (char (*), fixed bin, bit (36) aligned, bit (36) aligned, ptr, fixed bin (35), ptr, fixed bin (18), ptr, char (*));
 280 dcl  acl_$add_entry                     entry (fixed bin, bit (36) aligned, ptr, ptr, bit (1), fixed bin (35));
 281 dcl  acl_$del_acl                       entry (fixed bin, bit (36) aligned, ptr);
 282 dcl  acl_$list_entry                    entry (fixed bin, bit (36) aligned, ptr, ptr, fixed bin, fixed bin (35));
 283 dcl  aim_check_$equal                   entry (bit (72) aligned, bit (72) aligned) returns (bit (1) aligned);
 284 dcl  aim_check_$greater                 entry (bit (72) aligned, bit (72) aligned) returns (bit (1) aligned);
 285 dcl  aim_check_$greater_or_equal        entry (bit (72) aligned, bit (72) aligned) returns (bit (1) aligned);
 286 dcl  allocate_dir_ht_                   entry (ptr, fixed bin, fixed bin (35));
 287 dcl  check_gate_acl_                    entry (ptr, bit (1) aligned, fixed bin, char (32) aligned, fixed bin (35));
 288 dcl  create_vtoce                       entry (ptr, bit (36), fixed bin (17), fixed bin (35));
 289 dcl  delete_vtoce                       entry (ptr, fixed bin (35));
 290 dcl  fs_alloc$alloc                     entry (ptr, fixed bin, ptr);
 291 dcl  fs_alloc$free                      entry (ptr, fixed bin, ptr);
 292 dcl  fs_alloc$init                      entry (ptr, fixed bin, ptr, fixed bin);
 293 dcl  getuid                             entry () returns (bit (36) aligned);
 294 dcl  hash$in                            entry (ptr, ptr, fixed bin (35));
 295 dcl  hash$out                           entry (ptr, ptr, ptr, fixed bin (35));
 296 dcl  hash$search                        entry (ptr, ptr, ptr, fixed bin (35));
 297 dcl  level$get                          entry returns (fixed bin);
 298 dcl  lock$dir_unlock                    entry (ptr);
 299 dcl  makeknown_                         entry (ptr, fixed bin, fixed bin, fixed bin (35));
 300 dcl  makeunknown_                       entry (fixed bin, bit (36) aligned, bit (1) aligned, fixed bin (35));
 301 dcl  mountedp                           entry (bit (36) aligned) returns (fixed bin (35));
 302 dcl  quota$append_mdir_set              entry (ptr, fixed bin (18), fixed bin (35));
 303 dcl  quota$check                        entry (ptr, fixed bin (18), fixed bin (35));
 304 dcl  quota$qmove_mylock                 entry (ptr, ptr, fixed bin (18), bit (1) aligned, fixed bin (35));
 305 dcl  sum$dirmod                         entry (ptr);
 306 dcl  syserr$error_code                  entry options (variable);
 307 dcl  truncate$trentry                   entry (ptr);
 308 dcl  uid_path_util$get                  entry (ptr, dim (0:15) bit (36) aligned, fixed bin (35));
 309 
 310 /* Misc */
 311 
 312 dcl  (addr, baseptr, bin, bit, clock, collate, divide, fixed, length, null, ptr, rel, rtrim, substr, unspec, verify) builtin;
 313 
 314 dcl  bad_dir_                           condition;
 315 %page;
 316 master_dir: entry (a_dirname, a_ename, a_arg_ptr, a_sons, a_uid_path, a_code);
 317 
 318           call setup;
 319 
 320           sons = a_sons;
 321           sonsw = "1"b;
 322 
 323           max_access_authorization = pds$max_access_authorization;
 324           go to cbcomm;
 325 
 326 retv: entry (a_dirname, a_ename, a_arg_ptr, a_retv_append_argp, a_code);
 327 
 328           call setup;
 329 
 330           retv = "1"b;
 331 
 332           retv_append_argp = a_retv_append_argp;
 333           if retv_append_args.version ^= RETV_APPEND_ARGS_VERSION_1 then do;
 334                a_code = error_table_$unimplemented_version;
 335                return;
 336           end;
 337 
 338           level = retv_append_args.level;
 339           max_access_authorization = retv_append_args.max_access_authorization;
 340 
 341           arg_ptr = addr (a_arg_ptr -> acbr);               /* prevent indirections and tallys */
 342           acbr_version = acbr.version;
 343           if acbr_version < create_branch_version_1 |
 344                acbr_version > create_branch_version_2 then go to arg_err;
 345 
 346           audit_user_info_ptr = addr (my_audit_user_info);
 347           unspec (audit_user_info) = "0"b;
 348 
 349           audit_user_info.version = audit_user_info_version_1;
 350           audit_user_info.user_id = acbr.userid;            /* we'll have to trust our caller for this,
 351                                                             the retriever is good about this */
 352           audit_user_info.process_id = "0"b;                /* unknown whether logged in */
 353           audit_user_info.authorization = retv_append_args.access_authorization; /* in non-retv case, access_mode gets from the pds */
 354           audit_user_info.authorization_range(2) = retv_append_args.max_access_authorization;
 355           audit_user_info.audit_flags = (36)"1"b;           /* audit anything until we get real audit_flags */
 356           audit_user_info.ring = retv_append_args.level;
 357 
 358           if retv_append_args.link then linkname = retv_append_args.ep -> link.pathname;
 359           else local_entry = retv_append_args.ep -> entry;
 360 
 361           if retv_append_args.link then goto join_link;
 362 
 363           retv_cross_segment = retv_append_args.cross_segment;
 364           goto cbcomm2;
 365 
 366 admin_create_branch_: entry (a_dirname, a_ename, a_arg_ptr, a_code);
 367 
 368           call setup;
 369 
 370           admin_append = "1"b;
 371 
 372           max_access_authorization = sys_info$access_class_ceiling;
 373           go to cbcomm;
 374 
 375 create_branch_: entry (a_dirname, a_ename, a_arg_ptr, a_code);
 376 
 377           call setup;
 378 
 379           max_access_authorization = pds$max_access_authorization;
 380 
 381 cbcomm:   arg_ptr = addr (a_arg_ptr -> acbr);               /* prevent indirections and tallys */
 382           acbr_version = acbr.version;
 383           if acbr_version < create_branch_version_1 |
 384                acbr_version > create_branch_version_2 then go to arg_err;
 385 
 386 cbcomm2:  ac_sw = ^acbr.parent_ac_sw;                       /* if no ac specified, have to get parent's entry point */
 387           if ac_sw then do;
 388                access_class = acbr.access_class;            /* If ac was specified, copy it */
 389                if ^aim_check_$greater_or_equal (max_access_authorization, access_class) then do;
 390                     code = error_table_$ai_restricted;
 391                     go to fin;
 392                end;
 393           end;
 394           copysw = fixed (acbr.switches.copy_sw, 1);
 395           bmode = acbr.mode;
 396           dirsw = fixed (acbr.switches.dir_sw, 1);
 397           ringbrack (1) = acbr.rings (1);
 398           ringbrack (2) = acbr.rings (2);
 399           if dirsw = 1 then ringbrack (3) = ringbrack (2);  /* ignore third bracket */
 400           else ringbrack (3) = acbr.rings (3);
 401           userid = acbr.userid;
 402           bitcnt = acbr.bitcnt;
 403           chase_sw = acbr.switches.chase_sw;
 404           priv_mqsw = acbr.switches.priv_upgrade_sw;
 405           quota = acbr.quota;
 406           if acbr_version > create_branch_version_1 then dir_quota = acbr.dir_quota;
 407           go to comm2;
 408 
 409 branchx: entry (a_dirname, a_ename, a_mode, a_ringbrack, a_userid, a_dirsw, a_copysw, a_bitcnt, a_code);
 410 
 411           call setup;
 412 
 413           if a_copysw = 0 then copysw = 0;
 414           else copysw = 1;
 415           if a_dirsw = 0 then dirsw = 0; else dirsw = 1;
 416           if dirsw = 0 then bmode = substr (bit (fixed (a_mode, 4), 4), 1, 3);
 417           else do;                                          /* map rewa to sma */
 418                temp_b4 = bit (fixed (a_mode, 4), 4);
 419                bmode = substr (temp_b4, 1, 1) || substr (temp_b4, 3, 2);
 420           end;
 421 
 422           userid = a_userid;                                /* copy process group id */
 423           ringbrack = a_ringbrack;                          /* pick up all three */
 424           if dirsw = 1 then ringbrack (3) = ringbrack (2);  /* except for dirs */
 425           bitcnt = a_bitcnt;                                /* and bitcount */
 426 comm2:
 427           branch_sw = "1"b;                                 /* indicate that we are appending a branch */
 428           default_sw = "0"b;                                /* turn off default attribute switch */
 429           do i = 1 to 3;                                    /* check input brackets */
 430                if ringbrack (i) >= 8 then go to inv_rb_err;
 431                if ringbrack (i) < 0 then go to inv_rb_err;
 432           end;
 433           if ^retv then
 434                level = level$get ();                        /* Get current validation level */
 435           if ^retv | (retv & ^local_entry.dirsw) then
 436                if ringbrack (1) < level then goto lower_ring_err;
 437                else if ringbrack (1) > ringbrack (2)
 438                          | ringbrack (2) > ringbrack (3) then
 439                     go to inv_rb_err;
 440 
 441           call acc_name_$elements (addr (userid), addr (user_acl), code); /* convert userid to 3 part access name */
 442           if code ^= 0 then go to arg_err;
 443           go to join;
 444 
 445 branch: entry (a_dirname, a_ename, a_mode, a_code);
 446 
 447           call setup;
 448 
 449           branch_sw,                                        /* indicate that we are appending a branch */
 450                default_sw = "1"b;                           /* indicate that we will select the default attributes */
 451 
 452           dirsw,                                            /* Set dirsw off -- can't be a directory */
 453                copysw,                                      /* And no copying */
 454                bitcnt = 0;                                  /* Bit count starts at zero */
 455 
 456           user_acl.person = pds$access_name.person;         /* set up final acl to be caller with a tag of "*" */
 457           user_acl.project = pds$access_name.project;
 458           user_acl.tag = "*";
 459           level,                                            /* save validation level */
 460                ringbrack (*) = level$get ();                /* set brackets to V, V, V */
 461 
 462           bmode = substr (bit (fixed (a_mode, 4), 4), 1, 3);/* strip off trap bit */
 463           go to join;
 464 
 465 link: entry (a_dirname, a_ename, a_linkname, a_code);
 466 
 467           call setup;
 468 
 469           linkname = a_linkname;                            /* copy and check linkname */
 470 join_link:
 471           branch_sw = "0"b;                                 /* indicate that we are appending a link */
 472           if substr (linkname, 1, 1) ^= ">" then go to arg_err;
 473 
 474 /* find length of linkname - allow embedded blanks */
 475           llngth = length (rtrim (linkname));
 476           if verify (substr (linkname, 1, llngth), collate ()) > 0 then go to arg_err; /* link must be all ascii */
 477 join:
 478           dirl = "0"b;
 479           code = 0;                                         /* clear error code */
 480           if retv then authp = addr (user_acl);
 481           else authp = addr (pds$access_name);              /* get pointer to 3 part access name */
 482 
 483           dirname = a_dirname;                              /* copy directory and entry name arguments */
 484           ename = a_ename;
 485 
 486           if branch_sw then do;                             /* if appending a branch */
 487 
 488 /* set up ACLS with proper mode */
 489 /* convert fixed bin(5) mode into new modes */
 490                if dirsw = 0 then user_acl.mode = bmode;
 491 
 492                else do;
 493                     user_acl.exmode = bmode;
 494                     if (user_acl.exmode & "11"b) = "01"b then /* don't allow M without S access */
 495                          go to invalid_mode;
 496                     service_acl.mode = "111"b;              /* set access field for directories */
 497                     service_acl.exmode = "111"b;            /* set extended mode for .SysDaemon access */
 498 
 499                end;
 500           end;
 501 
 502           if ^branch_sw then chase_sw = "0"b;               /* don't chase when adding links */
 503 
 504           if retv then do;
 505                call dc_find$dir_for_retrieve_append
 506                     (dirname, ename, bin (chase_sw, 1), audit_user_info_ptr, dep, dp, code);
 507                if code ^= 0 then go to fin;
 508                dirl = "1"b;
 509           end;
 510           else do;
 511                if admin_append then
 512                     call dc_find$dir_for_append_raw (dirname, ename, bin (chase_sw, 1), dep, dp, code);
 513                else call dc_find$dir_for_append (dirname, ename, bin (chase_sw, 1), dep, dp, code);
 514                if code ^= 0 then go to fin;
 515                dirl = "1"b;
 516           end;
 517 
 518           if dep = null then parent_access_class = "0"b;    /* assume root at  0 access class */
 519           else do;
 520                if branch_sw then parent_access_class = dep -> entry.access_class;
 521                call lock$dir_unlock (ptr (dep, 0));
 522                dep = null;
 523           end;
 524 
 525           code = 0;
 526           ename_aligned = ename;
 527 
 528           if branch_sw then do;                             /* make sure not lower than parent */
 529                if ac_sw then call check_aim_access;
 530                else access_class = parent_access_class;     /* make it same as parent */
 531           end;
 532 
 533           if retv then do;                                  /* check for duplicate uids */
 534                if ^retv_append_args.link then do;
 535                     i = 0;
 536                     bcount = dir.dir_count + dir.seg_count + dir.lcount;
 537                     do ep = ptr (dp, dir.entryfrp) repeat (ptr (dp, entry.efrp)) while (rel (ep) ^= "0"b);
 538                          i = i + 1;
 539                          if i > bcount then signal bad_dir_;
 540                          if entry.uid = local_entry.uid then goto name_dup;
 541                     end;
 542                end;
 543           end;
 544 
 545           if dirsw = 1 & dir.tree_depth >= active_all_rings_data$max_tree_depth then do;
 546                code = error_table_$max_depth_exceeded;
 547                go to unlock;
 548           end;
 549 
 550           call hash$search (dp, addr (ename_aligned), ep, code); /* See if the entry is already there */
 551           if code = 0 then go to name_dup;                  /* indicates that name already on another entry */
 552           if code ^= error_table_$noentry then signal bad_dir_; /* another code says that hash table is messed up */
 553 
 554           if ^branch_sw | (dirsw = 1) then code = 0;        /* Always ok to create links or dirs */
 555           else code = mountedp (dir.sons_lvid);             /* Can we create a VTOCE? */
 556           if code ^= 0 then go to unlock;
 557 
 558           areap = ptr (dp, dir.arearp);                     /* start to allocate */
 559           dir.modify = pds$processid;
 560 
 561           if retv then newuid = local_entry.uid;
 562           else newuid = getuid ();                          /* Get the unique ID */
 563           if branch_sw then do;                             /* if appending a branch */
 564                if dirsw = 1 then do;
 565                     iacl_start_ptr = addr (dir.iacl (level).dir_frp); /* get ptr to dir Initial ACL for V */
 566                     n_iacls = dir.iacl_count (level).dir;
 567                end;
 568                else do;
 569                     iacl_start_ptr = addr (dir.iacl (level).seg_frp); /* get ptr to seg IACl at validation level */
 570                     n_iacls = dir.iacl_count (level).seg;
 571                     if ringbrack (2) ^= ringbrack (3) then  /* check for valid project if creating gate seg */
 572                          if level > 1 then do;              /* in rings greater than administrative ring */
 573                               if retv then project = user_acl.project;
 574                               else project = pds$access_name.project;
 575                               if user_acl.project ^= project then
 576                                    if user_acl.project ^= "SysDaemon" then do;
 577                                         code = error_table_$invalid_project_for_gate;
 578                                         go to unlock;
 579                                    end;
 580                               call check_gate_acl_ (iacl_start_ptr, "1"b, 0, dummy, code); /* check Initial ACL for project */
 581                               if code ^= 0 then go to unlock;
 582                          end;
 583                end;
 584                xsize = active_hardcore_data$esize;          /* store size of an entry */
 585                call fs_alloc$alloc (areap, xsize, ep);      /* allocate the entry */
 586                if ep = null then go to alloc_err;
 587                if retv then do;
 588                     entry = local_entry;
 589                     entry.acl_frp, entry.acl_brp = "0"b;
 590                     entry.acle_count = 0;
 591                     dtem = entry.dtem;                      /* save for later */
 592                end;
 593                if dirsw = 1 then entry.type = DIR_TYPE;
 594                else entry.type = SEG_TYPE;
 595                entry.size = xsize;
 596                entry.owner = dir.uid;
 597 
 598                acl_count = 0;
 599                acl_start_ptr = addr (entry.acl_frp);        /* fill in items before call to acl_ */
 600                prior_dir_acl_count = dir.acle_total;        /* save total number of acl entries in directory */
 601                                                             /* put SysDaemon on ACL */
 602                if ^retv | retv_cross_segment then do;
 603                     call acl_$add_entry (0, newuid, acl_start_ptr, addr (service_acl), add_sw, code);
 604                     if code ^= 0 then go to cleanup_acl;
 605 
 606 /* This loop adds acls to the branch.  (code = error_table_$argerr is set when the end of the acl thread is passed) */
 607 
 608                     acl_count = 1;                          /* add on Initial ACL */
 609                     dir.acle_total = dir.acle_total + 1;
 610                     iaclp = addr (initial_acl);
 611                     do i = 1 by 1 while (code = 0);
 612                          call acl_$list_entry (n_iacls, dir.uid, iacl_start_ptr, iaclp, i, code);
 613                          if code = 0 then do;
 614                               call acl_$add_entry (acl_count, newuid, acl_start_ptr, iaclp, add_sw, code);
 615                               if code ^= 0 then goto cleanup_acl;
 616                               if add_sw then do;            /* If actually added */
 617                                    acl_count = acl_count + 1;
 618                                    dir.acle_total = dir.acle_total + 1;
 619                               end;
 620                          end;
 621                          else if code ^= error_table_$argerr then go to cleanup_acl;
 622                     end;
 623                                                             /* now put on ACL for user */
 624                     if ^retv_cross_segment then do;
 625                          call acl_$add_entry (acl_count, newuid, acl_start_ptr, addr (user_acl), add_sw, code);
 626                          if code ^= 0 then goto cleanup_acl;
 627                     end;
 628                     if add_sw then do;
 629                          acl_count = acl_count + 1;
 630                          dir.acle_total = dir.acle_total + 1;
 631                     end;
 632                     entry.acle_count = acl_count;           /* set acl count for entry */
 633                end;
 634 
 635           end;
 636 
 637           else do;                                          /* if appending a link, allocate the link */
 638                nwords = active_hardcore_data$elcsize + 3 + divide (llngth + 3, 4, 17, 0); /* first get number of words for link */
 639 
 640 /* find appropriate allocation size */
 641                do i = active_hardcore_data$nalloc_sizes - 1 to 1 by -1
 642                     while (nwords <= active_hardcore_data$alloc_sizes (i));
 643                end;
 644                xsize = active_hardcore_data$alloc_sizes (i + 1);
 645 
 646                call fs_alloc$alloc (areap, xsize, ep);
 647                if ep = null then go to alloc_err;
 648                link.type = LINK_TYPE;
 649                link.size = xsize;
 650                link.pathname_size = llngth;
 651                link.pathname = linkname;
 652                link.owner = dir.uid;                        /* Pathname size MUST be set for 'refer' to be correct */
 653 
 654           end;
 655 
 656           call acc_name_$encode (addr (entry.author), authp, code); /* set author */
 657           if code ^= 0 then go to cleanup_acl;
 658 
 659           np = addr (entry.primary_name);                   /* first name is in the branch */
 660           entry.name_frp,                                   /* fill in name info before hashing */
 661                entry.name_brp = rel (np);
 662           entry.nnames = 1;
 663           np -> names.entry_rp = rel (ep);
 664           np -> names.name = ename;
 665           np -> names.type = NAME_TYPE;
 666           np -> names.size = active_hardcore_data$ensize;
 667           np -> names.owner = newuid;
 668 
 669           call hash$in (dp, np, code);                      /* have already checked for name dup */
 670           if code ^= 0 then goto cleanup_acl;
 671 
 672 /* Fill in general entry info */
 673 
 674           entry.uid = newuid;                               /* Fill in the unique ID */
 675           entry.dtem = substr (bit (fixed (clock, 52), 52), 1, 36);
 676           if ^branch_sw then dir.lcount = dir.lcount + 1;   /* link */
 677           else do;
 678                entry.bs = "1"b;                             /* Entry is a branch */
 679                entry.per_process_sw = dir.per_process_sw;
 680                entry.bc = bitcnt;                           /* set bit count */
 681                entry.dirsw = bit (dirsw, 1);                /* Can't append segs to segs, you know! */
 682                entry.access_class = access_class & sys_info$access_class_ceiling;
 683                entry.multiple_class = sp_sw;                /* indicates class higher than parent */
 684 
 685 /**** Set the security oos for backup-retrieved multi-class segments.
 686        This is a temporary fix to circumvent the lack of information
 687        on authorization/max authorization in the volume dumper. */
 688 
 689                if retv then if entry.multiple_class then do;
 690                          if ^pds$access_authorization.soos then entry.security_oosw = "1"b;
 691                     end;
 692                entry.master_dir = sonsw;
 693 
 694                call acc_name_$encode (addr (entry.bc_author), authp, code); /* set bc author */
 695                if code ^= 0 then go to make_err;
 696 
 697                call uid_path_util$get (dp, uid_path, code); /* get uid pathname of parent */
 698                if code ^= 0 then go to make_err;
 699                uid_path (dir.tree_depth + 1) = entry.uid;   /* last component */
 700 
 701                if ^retv then do;
 702                     call create_vtoce (ep, entry.pvid, vtocx_temp, code);
 703                     if code ^= 0 then go to make_err;       /* problems. */
 704                     entry.vtocx = vtocx_temp;               /* Store in unal fld in branch */
 705                     if dirsw = 1 then call setup_directory;
 706                     else do;                                /* link */
 707                          entry.ring_brackets (1) = bit (fixed (ringbrack (1), 3), 3);
 708                          entry.ring_brackets (2) = bit (fixed (ringbrack (2), 3), 3);
 709                          entry.ring_brackets (3) = bit (fixed (ringbrack (3), 3), 3);
 710                          entry.copysw = bit (copysw, 1);    /* copy sw */
 711                          dir.seg_count = dir.seg_count + 1; /* and update segment count in directory */
 712                     end;
 713                end;
 714                else do;                                     /* retv case. */
 715                     if retv_cross_segment then do;
 716                          call create_vtoce (ep, entry.pvid, vtocx_temp, code);
 717                          if code ^= 0 then goto make_err;
 718                          entry.vtocx = vtocx_temp;
 719                     end;
 720                     if dirsw = 1 then do;
 721                          dir.dir_count = dir.dir_count + 1;
 722                          if ^entry.master_dir then
 723                               entry.sons_lvid = dir.sons_lvid; /* propagate the correct sons lvid */
 724                     end;
 725                     else dir.seg_count = dir.seg_count + 1;
 726                end;
 727           end;
 728 
 729           if dir.entryfrp = ""b then
 730                do;                                          /* first entry in directory */
 731                dir.entryfrp, dir.entrybrp = rel (ep);
 732                entry.efrp, entry.ebrp = ""b;
 733           end;
 734           else do;
 735                prevep = ptr (ep, dir.entrybrp);             /* get pointer to previous entry */
 736                entry.ebrp = rel (prevep);                   /* set back pointer of entry */
 737                prevep -> entry.efrp = rel (ep);             /* set forward pointer of prev. entry */
 738                entry.efrp = ""b;                            /* set forward pointer of entry */
 739                dir.entrybrp = rel (ep);                     /* reset dir rel back pointer */
 740           end;
 741 
 742 
 743           if retv then entry.dtem = dtem;
 744           dir.modify = "0"b;
 745           call sum$dirmod (dp);                             /* We've modified this directory */
 746 
 747           audit_eventflags = "0"b;
 748           addr (audit_eventflags) -> audit_event_flags.grant = "1"b;
 749           if retv then                                      /* audit the new object */
 750                if access_audit_check_ep_$user
 751                     (audit_eventflags, access_operations_$fs_obj_create, ep, audit_user_info.authorization, audit_user_info.audit_flags) then
 752                     call access_audit_$log_entry_ptr_user
 753                          ("append", level, audit_eventflags, access_operations_$fs_obj_create, ep, 0, null, 0, audit_user_info_ptr, "");
 754                else ;
 755           else if access_audit_check_ep_$self
 756                     (audit_eventflags, access_operations_$fs_obj_create, ep) then
 757                call access_audit_$log_entry_ptr
 758                     ("append", level, audit_eventflags, access_operations_$fs_obj_create, ep, 0, null, 0, "");
 759 
 760           call dc_find$finished (dp, dirl);
 761 
 762 fin:
 763           a_code = code;
 764 
 765           return;
 766 
 767 arg_err:
 768           code = error_table_$argerr; go to fin;
 769 lower_ring_err:
 770           code = error_table_$lower_ring; goto fin;
 771 inv_rb_err:
 772           code = error_table_$invalid_ring_brackets; go to fin;
 773 invalid_mode:
 774           code = error_table_$invalid_mode; go to fin;
 775 name_dup:
 776           code = error_table_$namedup; go to unlock;
 777 alloc_err:
 778           code = error_table_$noalloc; go to unlock;
 779 free_vtoce:
 780           call delete_vtoce (ep, dumcode);
 781           if dumcode ^= 0 then call syserr$error_code (4, dumcode, "append: err from delete_vtoce for ^a>^a:", dirname, ename);
 782 make_err:
 783           call hash$out (dp, addr (ename_aligned), np, dumcode);
 784           if dumcode ^= 0 then call syserr$error_code (4, dumcode, "append: error from hash$out for ^a>^a:", dirname, ename);
 785 cleanup_acl:
 786           if branch_sw then do;
 787                call acl_$del_acl (acl_count, newuid, acl_start_ptr);
 788                dir.acle_total = prior_dir_acl_count;        /* restore the acl count in the directory */
 789           end;
 790           call fs_alloc$free (areap, xsize, ep);
 791 unlock:
 792           if dep ^= null then call lock$dir_unlock (ptr (dep, 0));
 793           dir.modify = "0"b;
 794           call dc_find$finished (dp, dirl);
 795           go to fin;
 796 %page;
 797 check_aim_access: proc;
 798 
 799           if aim_check_$greater (access_class, parent_access_class) then do;
 800                if dirsw = 1 then do;                        /* see if privileged oos creation */
 801                     if quota <= 0 then if level > 1 then goto ai_err;
 802                          else if ^priv_mqsw then goto ai_err;
 803 
 804                     if bitcnt ^= 0 then if level > 1 then goto ai_err; /* no upgraded non-multiclass MSFs */
 805                     sp_sw = "1"b;                           /* this sets entry.multiple_class */
 806                end;
 807                else do;                                     /* will be a multiclass segment */
 808                     if ringbrack (3) > 1 then go to ai_err; /* can only create multi class seg from ring 1 */
 809                     if priv_mqsw then sp_sw = "1"b;
 810                     else go to ai_err;                      /* wasn't reall wanted, wrong access class passed */
 811                end;
 812           end;
 813           else if ^aim_check_$equal (access_class, parent_access_class) then do;
 814 ai_err:        code = error_table_$ai_restricted;           /* ok to return as have at least append mode */
 815                goto unlock;
 816           end;
 817 
 818      end check_aim_access;
 819 
 820 setup: proc;
 821 
 822           ac_sw = "0"b;
 823           admin_append = "0"b;
 824           chase_sw = "1"b;
 825           dir_quota = 0;
 826           priv_mqsw = "0"b;
 827           quota = 0;
 828           read_lock = "0"b;
 829           retv = "0"b;
 830           retv_cross_segment = "0"b;
 831           sonsw = "0"b;
 832           sp_sw = "0"b;
 833           sysl = "0"b;
 834           return;
 835      end setup;
 836 %page;
 837 
 838 /* This procedure fills in the directory header and moves quota down. */
 839 
 840 setup_directory: proc;
 841 
 842           if sonsw then entry.sons_lvid = sons;             /* Master dir? */
 843           else entry.sons_lvid = dir.sons_lvid;             /* if not, inherit */
 844                                                             /* set extended rb, normal rb are 0,0,0 */
 845           entry.ex_ring_brackets (1) = bit (bin (ringbrack (1), 3), 3);
 846           entry.ex_ring_brackets (2) = bit (bin (ringbrack (2), 3), 3);
 847 
 848           if ^sonsw then do;
 849                call quota$check (ep, quota, code);          /* check if quota can take quota more pages */
 850                if code ^= 0 then go to free_vtoce;
 851           end;
 852 
 853 /* make the new directory segment known */
 854 /* Turn the modify switch OFF in the parent while initializing the inferior directory. Note that there is a window
 855    until it is turned on again during which the modify   switch is OFF although the operation is not finished */
 856 
 857           dir.modify = "0"b;
 858 
 859           unspec (mk_info) = "0"b;
 860           mk_info.uid = entry.uid;
 861           mk_info.entryp = ep;
 862           mk_info.dirsw = "1"b;
 863           mk_info.allow_write = "1"b;
 864           mk_info.activate = "1"b;
 865           dirp = null;
 866           call makeknown_ (addr (mk_info), segno, (0), code);
 867           if code ^= 0 then go to free_vtoce;
 868           dirp = baseptr (segno);
 869 
 870           unspec (dirp -> dir) = "0"b;                      /* Zero the header */
 871           dirp -> dir.type = DIR_HEADER_TYPE;               /* Fill in constants */
 872           dirp -> dir.size = active_hardcore_data$dir_hdrsize;
 873           dirp -> dir.version_number = version_number_2;
 874           dirp -> dir.owner = dir.uid;
 875           dirp -> dir.uid = entry.uid;                      /* Fill in the unique id */
 876           dirp -> dir.arearp = bit (fixed (active_hardcore_data$dir_arearp, 18), 18);
 877           dirp -> dir.pvid = entry.pvid;
 878           dirp -> dir.per_process_sw = entry.per_process_sw;
 879           dirp -> dir.sons_lvid = entry.sons_lvid;
 880           dirp -> dir.master_dir = entry.master_dir;
 881           if entry.master_dir then dirp -> dir.master_dir_uid = entry.uid;
 882           else dirp -> dir.master_dir_uid = dir.master_dir_uid; /* Inherit */
 883           dirp -> dir.access_class = entry.access_class;
 884           dirp -> dir.vtocx = entry.vtocx;
 885           asize = sys_info$default_dir_max_length - fixed (dirp -> dir.arearp, 18);
 886           call fs_alloc$init (ptr (dirp, dirp -> dir.arearp), asize,
 887                addr (active_hardcore_data$alloc_sizes), active_hardcore_data$nalloc_sizes);
 888 
 889           call allocate_dir_ht_ (dirp, 0, (0));
 890           dirp -> dir.tree_depth = dir.tree_depth + 1;      /* set tree depth */
 891 
 892           if quota > 0 then                                 /* Set quota */
 893                if ^sonsw then do;                           /* non-master dir, move */
 894                     call quota$qmove_mylock (ep, dirp, quota, "0"b, code);
 895                     if code ^= 0 then do;                   /* drop this hot potato */
 896                                                             /* used to unlock new dir here */
 897 qerr:                    call truncate$trentry (ep);        /* and header page */
 898                          call makeunknown_ (segno, "0"b, ("0"b), dumcode);
 899                          if dumcode ^= 0 then call syserr$error_code (4, dumcode,
 900                                    "append: makeunknown_ err after quota err for ^a>^a:", dirname, ename);
 901                          go to free_vtoce;                  /* leave in kst if makeunknown_ fails */
 902                     end;
 903                end;
 904                else do;                                     /* master dir. */
 905                     call quota$append_mdir_set (ep, quota, code); /* set the quuota */
 906                     if code ^= 0 then go to qerr;
 907                end;
 908           else if priv_mqsw & ac_sw then do;                /* path for reloader to create upgraded dirs with no quota */
 909                if aim_check_$greater (access_class, parent_access_class) then
 910                     ep -> entry.security_oosw = "1"b;       /* by leaving entry oosw */
 911           end;
 912 
 913           if dir_quota > 0 then do;                         /* Set quota */
 914                call quota$qmove_mylock (ep, dirp, dir_quota, "1"b, code);
 915                if code ^= 0 then go to qerr;                /* drop this hot potato */
 916           end;
 917 
 918           call sum$dirmod (dirp);                           /* indicate that it has been modified */
 919           call makeunknown_ (segno, "0"b, ("0"b), code);
 920           if code ^= 0 then call syserr$error_code (4, code, "append: error from makeunknown_ for ^a>^a:", dirname, ename);
 921 
 922           dir.modify = pds$processid;                       /* Turn modify sw back on again to complete the creation
 923                                                                of the branch. This call will terminate the window
 924                                                                referred to above and created at the beginning of the
 925                                                                initialization of the inferior directory. */
 926 
 927           dir.dir_count = dir.dir_count + 1;                /* up directory count in parent */
 928           if sonsw then a_uid_path = uid_path;              /* return uid pathname to ring 1 */
 929 
 930           return;
 931 
 932      end setup_directory;
 933 %page; %include access_audit_eventflags;
 934 %page; %include access_audit_user_info;
 935 %page; %include aim_template;
 936 %page; %include create_branch_info;
 937 %page; %include dc_find_dcls;
 938 %page; %include dir_entry;
 939 %page; %include dir_header;
 940 %page; %include dir_ht;
 941 %page; %include dir_link;
 942 %page; %include dir_name;
 943 %page; %include fs_obj_access_codes;
 944 %page; %include fs_types;
 945 %page; %include makeknown_info;
 946 %page; %include null_addresses;
 947 %page; %include retv_append_args;
 948 %page;
 949 
 950 /* BEGIN MESSAGE DOCUMENTATION
 951 
 952 
 953    Message:
 954    append: error from delete_vtoce for PATH: ERROR_MESSAGE
 955 
 956    S:     $log
 957 
 958    T:     $run
 959 
 960    M:     While deleting a VTOC entry
 961    to clean up an unsuccessful attempt to create an branch,
 962    append got an error.
 963    $err
 964 
 965    A:     $note
 966 
 967 
 968    Message:
 969    append: error from hash$out for PATH: ERROR_CODE
 970 
 971    S:     $log
 972 
 973    T:     $run
 974 
 975    M:     While removing a name
 976    to clean up an unsuccessful attempt to create a branch,
 977    append got an error.
 978    $err
 979 
 980    A:     $note
 981 
 982 
 983    Message:
 984    append: makeunknown_ err after quota err for PATH: ERROR_CODE
 985 
 986    S:     $log
 987 
 988    T:     $run
 989 
 990    M:     During the creation of a new directory, append encountered an error moving quota.
 991    While cleaning up from this error a further error was encountered.
 992    The system continues to operate.
 993    $err
 994 
 995    A:     $note
 996 
 997 
 998    Message:
 999    append: error from makeunknown_ for PATH: ERROR_CODE
1000 
1001    S:     $log
1002 
1003    T:     $run
1004 
1005    M:     Append made the new directory PATH unknown after initializing its header.
1006    While doing so it encountered an error.
1007    $err
1008 
1009    A:     $note
1010 
1011    END MESSAGE DOCUMENTATION */
1012 
1013      end append;