?? RIGHT := 110 ??
?? TITLE := 'NOS/VE Permanent Files : Put Info' ??
MODULE pfm$r2_put_info;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains the procedures used to put backup information when
{   restoring from a backup file.  The information is of the format returned by
{   the permanent file 'get info' routines.

?? NEWTITLE := '  Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc pfc$average_share_history
*copyc pfc$maximum_pf_length
*copyc pud$selection_criteria
*copyc ame$put_validation_errors
*copyc pfe$error_condition_codes
*copyc pfe$external_archive_conditions
*copyc pfe$internal_error_conditions
*copyc ste$error_condition_codes
*copyc pft$array_index
*copyc pft$auditable_cycles
*copyc pft$auditable_permits
*copyc pft$backup_file_version
*copyc pft$chosen_cycles
*copyc pft$cycle_array_index
*copyc pft$family_location
*copyc pft$permit_level
*copyc pft$restore_catalog_status
*copyc stt$set_name
?? POP ??
*copyc avp$security_option_active
*copyc dmp$attach_file
*copyc dmp$build_sorted_dfl
*copyc dmp$get_reconciled_fmd
*copyc dmp$reconcile_fmd
*copyc dmv$reconcile_locator
*copyc i#move
*copyc osp$append_status_file
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$generate_unique_binary_name
*copyc osp$prevalidate_free
*copyc osp$recoverable_system_error
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc pfi$store_file_media_descriptor
*copyc pfp$access_last_object
*copyc pfp$access_next_catalog
*copyc pfp$access_object
*copyc pfp$allocate_archive_list
*copyc pfp$allocate_cycle_list
*copyc pfp$allocate_log_list
*copyc pfp$allocate_permit_list
*copyc pfp$attach_root_catalog
*copyc pfp$build_archive_entry
*copyc pfp$build_archive_list_locator
*copyc pfp$build_archive_list_pointer
*copyc pfp$build_cycle_list_locator
*copyc pfp$build_cycle_list_pointer
*copyc pfp$build_file_label_locator
*copyc pfp$build_fmd_locator
*copyc pfp$build_fmd_pointer
*copyc pfp$build_log_list_locator
*copyc pfp$build_log_list_pointer
*copyc pfp$build_mainfram_list_locator
*copyc pfp$build_object_list_locator
*copyc pfp$build_permit_list_locator
*copyc pfp$build_permit_list_pointer
*copyc pfp$check_archive_entries
*copyc pfp$check_group_by_permit_level
*copyc pfp$compute_checksum
*copyc pfp$convert_archive_ident
*copyc pfp$convert_device_class_to_pf
*copyc pfp$convert_device_class_to_rm
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$create_catalog
*copyc pfp$create_catalog_object
*copyc pfp$create_file_object
*copyc pfp$destroy_catalog
*copyc pfp$detach_permanent_file
*copyc pfp$determine_new_cycle_number
*copyc pfp$establish_free_cycle_entry
*copyc pfp$find_archive_info
*copyc pfp$find_catalog_description
*copyc pfp$find_catalog_media
*copyc pfp$find_cycle_array
*copyc pfp$find_cycle_array_extended
*copyc pfp$find_cycle_array_version_2
*copyc pfp$find_cycle_directory
*copyc pfp$find_cycle_label
*copyc pfp$find_cycle_media
*copyc pfp$find_direct_info_record
*copyc pfp$find_file_description
*copyc pfp$find_log_array
*copyc pfp$find_next_archive_entry
*copyc pfp$find_next_info_record
*copyc pfp$find_permit_array
*copyc pfp$get_authority
*copyc pfp$get_catalog
*copyc pfp$locate_cycle
*copyc pfp$locate_group_info_record
*copyc pfp$locate_object
*copyc pfp$locate_specific_cycle
*copyc pfp$log_ascii
*copyc pfp$log_path
*copyc pfp$process_unexpected_status
*copyc pfp$record_dm_file_parameters
*copyc pfp$release_locked_apfid
*copyc pfp$report_invalid_free
*copyc pfp$report_system_error
*copyc pfp$return_catalog
*copyc pfp$set_status_abnormal
*copyc pfp$shared_queue
*copyc pfp$validate_default_password
*copyc pfp$validate_family_ownership
*copyc pfp$validate_file_permission
*copyc pfp$validate_ownership
*copyc pfv$family_administrator
*copyc pfv$locked_apfid
*copyc pfv$null_catalog_entry_space
*copyc pfv$null_cycle_entry_space
*copyc pfv$null_date_time
*copyc pfv$null_file_entry_space
*copyc pfv$null_object_entry_space
*copyc pfv$system_administrator
*copyc pfv$task_family
*copyc pfv$task_user
*copyc pfv$unattached_status
*copyc pmp$continue_to_cause
*copyc pmp$date_time_compare
*copyc sfp$emit_audit_statistic
*copyc sfp$get_job_limit
*copyc sfv$dynamic_file_space_limits
*copyc stp$get_root_recreated
*copyc stv$system_set_name
*copyc syp$pop_inhibit_job_recovery
*copyc syp$push_inhibit_job_recovery
?? TITLE := '  Global Declarations Declared by this module', EJECT ??

  CONST
    include_radix = TRUE,
    radix = 10;

  VAR
    pfv$null_unique_name: [XDCL, oss$job_paged_literal, READ] ost$binary_unique_name :=
          [0, 0, 1980, 1, 1, 0, 0, 0, 0, 0];

  VAR
    cycle_array_entry_version_2: [oss$job_paged_literal, READ] pft$cycle_array_entry_version_2 :=
          [0, $fst$cycle_damage_symptoms [], * , * , * , pfc$unreleasable_data, rmc$mass_storage_device,
          0, * , * , FALSE, [FALSE], [FALSE], pfc$always_retrieve, pfc$null_site_backup_option,
          pfc$null_site_archive_option, pfc$null_site_release_option, [REP 46 of FALSE]];

?? TITLE := '  [XDCL, #GATE] pfp$r2_build_archive_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_build_archive_entry
    (    archive_identification: pft$archive_identification;
         p_archive_array_entry: pft$p_archive_array_entry;
         p_amd: pft$p_amd;
         p_catalog_file: pft$p_catalog_file;
         p_archive: pft$p_archive;
     VAR status: ost$status);

    VAR
      p_physical_amd: pft$p_physical_amd;

    ALLOCATE p_physical_amd: [[REP #SIZE (p_amd^) OF cell]] IN p_catalog_file^.catalog_heap;
    IF p_physical_amd = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, '', status);
      RETURN; {----->
    IFEND;

    p_physical_amd^.amd := p_amd^;

    pfp$build_archive_entry (archive_identification, p_archive_array_entry, p_physical_amd, p_catalog_file,
          p_archive, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

  PROCEND pfp$r2_build_archive_entry;

?? TITLE := '  [XDCL, #GATE] pfp$r2_build_sorted_dfl', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_build_sorted_dfl
    (VAR status: ost$status);

    dmp$build_sorted_dfl (stv$system_set_name, dmv$reconcile_locator, status);

  PROCEND pfp$r2_build_sorted_dfl;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_archive_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_archive_entry
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         archive_identification: pft$archive_identification;
         p_archive_array_entry: pft$p_archive_array_entry;
         p_amd: pft$p_amd;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_archive_entry; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      archive_index: pft$archive_index,
      archive_list_locator: pft$archive_list_locator,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_cycle_list: ^pft$cycle_list,
      p_internal_path: ^pft$internal_path,
      p_new_archive_list: ^pft$archive_list,
      p_old_archive_list: ^pft$archive_list,
      p_physical_cycle: ^pft$physical_cycle,
      p_physical_file_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      valid_archive_entry_exists: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      pfp$validate_ownership (authority, path, status);
    IFEND;

    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_physical_file_object, p_internal_path^, permit_entry,
            status);
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      pfp$build_cycle_list_pointer (p_physical_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_physical_cycle, status);

      IF status.normal THEN
        archive_list_locator := p_physical_cycle^.cycle_entry.archive_list_locator;
        pfp$build_archive_list_pointer (archive_list_locator, catalog_locator.p_catalog_file,
              p_old_archive_list);
        pfp$allocate_archive_list (archive_list_locator.archive_count + 1,
              ^catalog_locator.p_catalog_file^.catalog_heap, p_new_archive_list, status);
      IFEND;

      IF status.normal THEN
        pfp$r2_build_archive_entry (archive_identification, p_archive_array_entry, p_amd,
              catalog_locator.p_catalog_file, ^p_new_archive_list^ [1], status);

        IF status.normal THEN
          IF archive_list_locator.archive_count <> 0 THEN
            FOR archive_index := 1 TO archive_list_locator.archive_count DO
              p_new_archive_list^ [archive_index + 1] := p_old_archive_list^ [archive_index];
            FOREND;
            osp$prevalidate_free ((#OFFSET (p_old_archive_list) -
                  #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                  ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_old_archive_list IN catalog_locator.p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, ^p_physical_cycle^.cycle_entry.cycle_number, 'ARCHIVE_LIST',
                    'file', prevalidate_free_result, #OFFSET (p_old_archive_list));
              p_old_archive_list := NIL;
            IFEND;
          IFEND;

          pfp$build_archive_list_locator (p_new_archive_list, catalog_locator.p_catalog_file,
                archive_list_locator);
          p_physical_cycle^.cycle_entry.archive_list_locator := archive_list_locator;
          pfp$check_archive_entries (catalog_locator.p_catalog_file, p_physical_cycle,
                valid_archive_entry_exists, status);

          IF status.normal AND valid_archive_entry_exists AND
                (p_physical_cycle^.cycle_entry.fmd_locator.fmd_size <> 0) THEN
            p_physical_cycle^.cycle_entry.data_residence := pfc$releasable_data;
          IFEND;

          pfp$compute_checksum (#LOC (p_physical_cycle^.cycle_entry), #SIZE (pft$cycle_entry),
                p_physical_cycle^.checksum);
        ELSE
          osp$prevalidate_free ((#OFFSET (p_new_archive_list) -
                #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_new_archive_list IN catalog_locator.p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_physical_cycle^.cycle_entry.cycle_number, 'ARCHIVE_LIST',
                  'file', prevalidate_free_result, #OFFSET (p_new_archive_list));
            p_new_archive_list := NIL;
          IFEND;
        IFEND;
      IFEND;

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_archive_entry;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_archive_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_archive_info
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         p_cycle_info_record: pft$p_info_record;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_archive_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_cycle_list: ^pft$cycle_list,
      p_internal_path: ^pft$internal_path,
      p_physical_file_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      pfp$validate_ownership (authority, path, status);
    IFEND;

    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_physical_file_object, p_internal_path^, permit_entry,
            status);
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      pfp$build_cycle_list_pointer (p_physical_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      put_cycle_archive_info (catalog_locator.p_catalog_file, p_cycle_list, cycle_selector, path,
            p_cycle_info_record, status);

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_archive_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_catalog_media_info', EJECT ??
{ DESIGN:
{   This procedure restores the catalog information under the following rules:
{
{   CONDITIONS:
{     catalog registered               T   T   F   F
{     registered catalog on-line       T   F
{     parent re-created                        T   T
{     backup catalog on-line                   T   F
{   ACTIONS:
{     re-create catalog media              X       X
{     no change                        X
{     store backup fmd                         X
{     put catalog info (permits etc)           X   X

  PROCEDURE [XDCL, #GATE] pfp$r2_put_catalog_media_info
    (    path: pft$complete_path;
         p_catalog_group: {input} pft$p_info_record;
     VAR restore_catalog_status: pft$restore_catalog_status;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_catalog_media_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      family_location = pfc$local_mainframe,
      permit_level = pfc$pl_public;

    VAR
      all_permits_restored: boolean,
      audit_restorations: boolean,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      device_class: dmt$class,
      fmd_size: dmt$stored_fmd_size,
      local_status: ost$status,
      p_auditable_permits: ^pft$auditable_permits,
      p_backup_catalog_fmd: ^SEQ ( * ),
      p_backup_catalog_media_desc: ^pft$catalog_media_description,
      p_catalog_object: ^pft$physical_object,
      p_physical_fmd: ^pft$physical_fmd,
      parent_catalog_recreated: boolean,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      resides_on_system_device: boolean;

    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    IF dmv$reconcile_locator = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, 'NIL reconcile locator',
            status);
      RETURN; {----->
    IFEND;

    syp$push_inhibit_job_recovery;

    access_parent_and_object (path, $pft$object_selections [pfc$catalog_object, pfc$free_object], authority,
          parent_catalog_recreated, catalog_locator, p_catalog_object, status);
    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      IF p_catalog_object^.object_entry.object_type = pfc$catalog_object THEN
        {
        { Catalog exists in parent.
        {
        IF p_catalog_object^.object_entry.catalog_object_locator.catalog_type = pfc$internal_catalog THEN
          restore_catalog_status := pfc$catalog_already_exists;
        ELSE
          pfp$build_fmd_pointer (p_catalog_object^.object_entry.catalog_object_locator.fmd_locator,
                catalog_locator.p_catalog_file, p_physical_fmd);
          dmp$reconcile_fmd (dmv$reconcile_locator, p_catalog_object^.object_entry.catalog_object_locator.
                global_file_name, p_physical_fmd^.fmd, {purge_file} FALSE, device_class, fmd_size,
                resides_on_system_device, status);
          IF status.normal THEN
            restore_catalog_status := pfc$catalog_already_exists;
          ELSE
            {
            { The catalog does not reconcile; re-create the catalog.
            {
            osp$prevalidate_free ((#OFFSET (p_physical_fmd) -
                  #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                  ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR', 'catalog',
                    prevalidate_free_result, #OFFSET (p_physical_fmd));
              p_physical_fmd := NIL;
            IFEND;
            recreate_catalog_media (path, authority, catalog_locator.p_catalog_file, p_catalog_object,
                  status);
            restore_catalog_status := pfc$catalog_recreated;
          IFEND;
        IFEND;
      ELSE {free object}
        {
        { Catalog not found in parent and the parent was re-created.
        { Reconstruct the parent catalog's contents from the backup file.
        {
        pfp$find_catalog_media (p_catalog_group, p_backup_catalog_media_desc, p_backup_catalog_fmd, status);
        IF status.normal THEN
          IF p_backup_catalog_media_desc^.catalog_type = pfc$internal_catalog THEN
            audit_restorations := avp$security_option_active (avc$vso_security_audit);
            p_auditable_permits := NIL;
            put_catalog_info (p_catalog_group, family_location, path, authority, permit_level,
                  pfc$internal_catalog, {catalog_recreated} TRUE, catalog_locator.p_catalog_file,
                  p_catalog_object, audit_restorations, all_permits_restored, p_auditable_permits, status);
            restore_catalog_status := pfc$catalog_recreated;
          ELSE
            dmp$reconcile_fmd (dmv$reconcile_locator, p_backup_catalog_media_desc^.global_file_name,
                  p_backup_catalog_fmd^, {purge_file} FALSE, device_class, fmd_size, resides_on_system_device,
                  status);
            IF status.normal THEN
              {
              { Re-create the catalog entry and store the backed up fmd.
              {
              recreate_catalog_entry (p_catalog_group, path, authority.ownership, p_backup_catalog_media_desc,
                    p_backup_catalog_fmd, catalog_locator.p_catalog_file, p_catalog_object, status);
              restore_catalog_status := pfc$catalog_recovered;
            ELSE
              {
              { The catalog fmd from the backup file does not reconcile.
              { Re-create the catalog entry and the catalog itself.
              {
              { Note: This will restore deleted catalogs as the catalogs may
              { have moved since the backup.  This is unavoidable.
              {
              audit_restorations := avp$security_option_active (avc$vso_security_audit);
              p_auditable_permits := NIL;
              put_catalog_info (p_catalog_group, family_location, path, authority, permit_level,
                    pfc$external_catalog, {catalog_recreated} TRUE, catalog_locator.p_catalog_file,
                    p_catalog_object, audit_restorations, all_permits_restored, p_auditable_permits, status);
              restore_catalog_status := pfc$catalog_recreated;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_catalog_media_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_catalog_segment', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_catalog_segment
    (    path: pft$path;
         p_catalog_segment: ^SEQ ( * );
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_catalog_segment; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE,
      validation_ring_number = 2;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_segment_length: ost$segment_length,
      charge_id: pft$charge_id,
      local_status: ost$status,
      p_catalog_seq: ^SEQ ( * ),
      p_cell_array: ^array [1 .. * ] of cell,
      p_internal_path: ^pft$internal_path,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /put_catalog_segment/
    BEGIN
      catalog_active := FALSE;
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);

      pfp$get_authority (path, NOT system_privilege, authority, status);
      IF NOT status.normal THEN
        EXIT /put_catalog_segment/; {----->
      IFEND;

      pfp$validate_ownership (authority, path, status);
      IF NOT status.normal THEN
        EXIT /put_catalog_segment/; {----->
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$get_catalog (path, pfc$write_access, authority, p_internal_path^, charge_id, permit_entry,
            catalog_locator, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /put_catalog_segment/; {----->
      IFEND;

      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

      catalog_segment_length := #SIZE (p_catalog_segment^);
      p_catalog_seq := #SEQ (catalog_locator.p_catalog_file^);
      NEXT p_cell_array: [1 .. catalog_segment_length] IN p_catalog_seq;
      IF p_cell_array = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      ELSE
        i#move (p_catalog_segment, p_cell_array, catalog_segment_length);
      IFEND;
    END /put_catalog_segment/;

    IF catalog_active THEN
      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_catalog_segment;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_cycle_info', EJECT ??
  PROCEDURE [XDCL, #GATE] pfp$r2_put_cycle_info
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         cycle_array_entry: pft$cycle_array_entry_version_2;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_cycle_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      comparison_result: pmt$comparison_result,
      cycle_entry: pft$cycle_entry,
      cycle_list_locator: pft$cycle_list_locator,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      new_file_created: boolean,
      new_physical_file_object: pft$physical_object,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_physical_file_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      password: pft$password,
      permit_entry: pft$permit_entry,
      pf_device_class: pft$device_class,
      pfs_limit: sft$limit,
      process_non_local_exit: boolean,
      task_charge_id: pft$charge_id,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      IF (cycle_array_entry.device_class = rmc$magnetic_tape_device) AND
            (authority.ownership = $pft$ownership []) THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := ^path;
        pfp$set_status_abnormal (variant_path, pfe$usage_not_permitted, status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              '[READ] or [EXECUTE] or [SHORTEN] or [MODIFY] or [APPEND]', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, '[CYCLE] or [CONTROL]', status);
      IFEND;
    IFEND;

    IF status.normal THEN
      IF sfv$dynamic_file_space_limits AND (pfc$master_catalog_owner IN authority.ownership) THEN
        sfp$get_job_limit (avc$pfs_limit_name, pfs_limit, status);
        IF status.normal THEN
          IF pfs_limit.accumulator >= pfs_limit.job_abort_limit THEN
            osp$set_status_condition (ame$file_space_limit_exceeded, status);
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$append_status_file (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
            osp$append_status_parameter (osc$status_parameter_delimiter, 'Permanent', status);
          IFEND;
        ELSE
          status.normal := TRUE;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections
            [pfc$free_object, pfc$file_object], parent_charge_id, catalog_locator, p_physical_file_object,
            p_internal_path^, permit_entry, status);
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

      {
      { Cycle permit is only verified for non owners.
      {

      IF authority.ownership = $pft$ownership [] THEN
        pfp$validate_file_permission (path, authority, permit_entry, $pft$permit_selections [pfc$cycle],
              -$pft$share_selections [], status);
      IFEND;

      IF status.normal THEN
        IF p_physical_file_object^.object_entry.object_type = pfc$file_object THEN
          new_file_created := FALSE;
          pfp$validate_default_password (path, authority, password_selector, p_physical_file_object, status);
        ELSE {pfc$free_object}
          {
          { Do not use the real file object, in case an error occurs in
          { create_cycle_entry.
          {
          task_charge_id.account := authority.account;
          task_charge_id.project := authority.project;
          IF password_selector.password_specified = pfc$default_password_option THEN
            password := osc$null_name;
          ELSE
            password := password_selector.password;
          IFEND;
          pfp$create_file_object (path [UPPERBOUND (path)], authority, task_charge_id, password, pfc$no_log,
                new_physical_file_object.object_entry);
          p_internal_path^ [UPPERBOUND (path)] := new_physical_file_object.object_entry.internal_object_name;
          {
          { The file object checksum will be computed in add_cycle_entry.
          {
          new_file_created := TRUE;
        IFEND;
      IFEND;

      IF status.normal THEN
        IF new_file_created THEN
          cycle_list_locator := new_physical_file_object.object_entry.cycle_list_locator;
        ELSE
          cycle_list_locator := p_physical_file_object^.object_entry.cycle_list_locator;
        IFEND;
        pfp$convert_device_class_to_pf (cycle_array_entry.device_class, pf_device_class);
        create_cycle_entry (path, cycle_list_locator, catalog_locator.p_catalog_file, cycle_selector,
              pf_device_class, cycle_array_entry.cycle_statistics,
              cycle_array_entry.data_modification_date_time, cycle_array_entry.expiration_date_time,
              cycle_array_entry.cycle_damage_symptoms, cycle_array_entry.shared_queue_info,
              cycle_array_entry.retrieve_option, cycle_array_entry.site_backup_option,
              cycle_array_entry.site_archive_option, cycle_array_entry.site_release_option, cycle_entry,
              status);
      IFEND;

      IF status.normal THEN
        IF new_file_created THEN
          p_physical_file_object^ := new_physical_file_object;
        IFEND;
        add_cycle_entry (^path, cycle_entry, p_physical_file_object, catalog_locator.p_catalog_file, status);
      ELSEIF status.condition = pfe$duplicate_cycle THEN
        pfp$build_cycle_list_pointer (p_physical_file_object^.object_entry.cycle_list_locator,
              catalog_locator.p_catalog_file, p_cycle_list);
        pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, local_status);
        IF local_status.normal THEN
          pmp$date_time_compare (p_cycle^.cycle_entry.cycle_statistics.modification_date_time,
                cycle_array_entry.cycle_statistics.modification_date_time, comparison_result, local_status);
          IF local_status.normal AND (comparison_result = pmc$equal) THEN
            p_cycle^.cycle_entry.retrieve_option := cycle_array_entry.retrieve_option;
            p_cycle^.cycle_entry.site_archive_option := cycle_array_entry.site_archive_option;
            p_cycle^.cycle_entry.site_backup_option := cycle_array_entry.site_backup_option;
            p_cycle^.cycle_entry.site_release_option := cycle_array_entry.site_release_option;
          IFEND;
          pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
          IF (p_cycle^.cycle_entry.data_residence = pfc$offline_data) AND
                (NOT ((pfc$system_owner IN authority.ownership) OR (pfc$family_owner IN authority.ownership)))
                THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_offline_cycle,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                  radix, NOT include_radix, status);
          IFEND;
        IFEND;
      IFEND;

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_cycle_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_family_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_family_info
    (    set_name: stt$set_name;
         family_name: pft$name;
         p_info_record: {input} pft$p_info_record;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_family_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      permit_level = pfc$pl_public;

    VAR
      all_permits_restored: boolean,
      audit_restorations: boolean,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      internal_path: array [1 .. pfc$family_path_index] of pft$internal_name,
      local_status: ost$status,
      p_auditable_permits: ^pft$auditable_permits,
      p_physical_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      path: array [1 .. pfc$family_path_index] of pft$name,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

    path [pfc$set_path_index] := set_name;
    path [pfc$family_path_index] := family_name;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      pfp$validate_family_ownership (family_name, authority, status);
    IFEND;

    IF status.normal THEN
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$free_object],
            parent_charge_id, catalog_locator, p_physical_object, internal_path, permit_entry, status);
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      audit_restorations := avp$security_option_active (avc$vso_security_audit);
      p_auditable_permits := NIL;
      put_catalog_info (p_info_record, pfc$local_mainframe, path, authority, permit_level,
            pfc$internal_catalog, {catalog_recreated} FALSE, catalog_locator.p_catalog_file,
            p_physical_object, audit_restorations, all_permits_restored, p_auditable_permits, status);

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_family_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_file_media_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_file_media_info
    (    path: pft$complete_path;
         p_file_group: {input} pft$p_info_record;
         backup_file_version: pft$backup_file_version;
     VAR file_entry_recreated: boolean;
     VAR cycles_restored_with_fmd: pft$cycle_count;
     VAR cycles_restored_without_fmd: pft$cycle_count;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_file_media_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      permit_level = pfc$pl_public,
      restore_archive_information = TRUE;

    VAR
      all_permits_restored: boolean,
      audit_restorations: boolean,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      catalog_recreated: boolean,
      local_status: ost$status,
      p_auditable_cycles: ^pft$auditable_cycles,
      p_auditable_permits: ^pft$auditable_permits,
      p_file_object: ^pft$physical_object,
      process_non_local_exit: boolean,
      selection_criteria: put$selection_criteria;

    file_entry_recreated := FALSE;
    cycles_restored_with_fmd := 0;
    cycles_restored_without_fmd := 0;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    IF dmv$reconcile_locator = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, 'NIL reconcile locator',
            status);
      RETURN; {----->
    IFEND;

    syp$push_inhibit_job_recovery;

    access_parent_and_object (path, $pft$object_selections [pfc$file_object], authority, catalog_recreated,
          catalog_locator, p_file_object, status);
    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      IF catalog_recreated THEN
        IF p_file_object^.object_entry.object_type = pfc$file_object THEN
          {
          { The file occurs redundantly on the backup file so re-create
          { nonredundant cycles.
          {
          put_new_cycles_media (backup_file_version, p_file_group, path, authority.ownership,
                catalog_locator.p_catalog_file, p_file_object, cycles_restored_without_fmd,
                cycles_restored_with_fmd, status);
        ELSE {free object}
          {
          { Reconstruct the parent catalog's contents from the backup file.
          {
          file_entry_recreated := TRUE;
          selection_criteria.after_date_time_selected := FALSE;
          selection_criteria.before_date_time_selected := FALSE;
          audit_restorations := avp$security_option_active (avc$vso_security_audit);
          p_auditable_permits := NIL;
          p_auditable_cycles := NIL;
          put_file_info (backup_file_version, p_file_group, pfc$local_mainframe, path, authority.ownership,
                permit_level, selection_criteria, $fst$cycle_damage_symptoms
                [fsc$respf_modification_mismatch, fsc$parent_catalog_restored], restore_archive_information,
                {restore_media} TRUE, {replace_rem_media_fmd} TRUE, catalog_locator.p_catalog_file,
                p_file_object, audit_restorations, all_permits_restored, p_auditable_permits,
                cycles_restored_without_fmd, cycles_restored_with_fmd, p_auditable_cycles, status);
        IFEND;
      IFEND;

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_file_media_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_item_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_item_info
    (    backup_file_version: pft$backup_file_version;
         p_info_record: {input} ^pft$info_record;
         family_location: pft$family_location;
         path: pft$complete_path;
         permit_level: pft$permit_level;
         selection_criteria: put$selection_criteria;
         restore_archive_information: boolean;
     VAR audit_restorations: {i/o} boolean;
     VAR all_permits_restored: {i/o} boolean;
     VAR p_auditable_permits: {server only} ^pft$auditable_permits;
     VAR p_auditable_cycles: {server only} ^pft$auditable_cycles;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_item_info; {----->
    PROCEND initiate_non_local_exit;

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      cycles_media_restored: pft$cycle_count,
      cycles_recreated: pft$cycle_count,
      fs_path_size: fst$path_size,
      local_permit_level: pft$permit_level,
      local_status: ost$status,
      p_fs_path: ^fst$path,
      p_group_record: ^pft$info_record,
      p_internal_path: ^pft$internal_path,
      p_physical_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      pfs_limit: sft$limit,
      process_non_local_exit: boolean,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      IF authority.ownership <= $pft$ownership [pfc$master_catalog_owner] THEN
        local_permit_level := permit_level;
      ELSE
        local_permit_level := pfc$pl_public;
      IFEND;

      pfp$locate_group_info_record (p_info_record, p_group_record, status);
    IFEND;

    IF status.normal AND sfv$dynamic_file_space_limits AND
          (pfc$master_catalog_owner IN authority.ownership) THEN
      sfp$get_job_limit (avc$pfs_limit_name, pfs_limit, status);
      IF status.normal THEN
        IF pfs_limit.accumulator >= pfs_limit.job_abort_limit THEN
          osp$set_status_condition (ame$file_space_limit_exceeded, status);
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$append_status_file (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'Permanent', status);
        IFEND;
      ELSE
        status.normal := TRUE;
      IFEND;
    IFEND;

    IF status.normal THEN
      IF (p_group_record^.record_type = pfc$catalog_group_record) AND
            (UPPERBOUND (path) - 1 > pfc$maximum_catalog_depth) THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := ^path;
        pfp$set_status_abnormal (variant_path, pfe$too_many_catalogs_in_path, status);
        osp$append_status_integer (osc$status_parameter_delimiter, pfc$maximum_catalog_depth, radix,
              NOT include_radix, status);
        osp$append_status_integer (osc$status_parameter_delimiter, UPPERBOUND (path) - 1, radix,
              NOT include_radix, status);
      ELSE
        PUSH p_internal_path: [1 .. UPPERBOUND (path)];
        pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$free_object],
              parent_charge_id, catalog_locator, p_physical_object, p_internal_path^, permit_entry, status);
      IFEND;
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      CASE p_group_record^.record_type OF
      = pfc$catalog_group_record =
        pfp$validate_ownership (authority, path, status);
        IF status.normal THEN
          put_catalog_info (p_group_record, family_location, path, authority, local_permit_level,
                pfc$external_catalog, {catalog_recreated} FALSE, catalog_locator.p_catalog_file,
                p_physical_object, audit_restorations, all_permits_restored, p_auditable_permits, status);
        ELSEIF audit_restorations THEN
          p_auditable_permits := NIL;
          IF family_location = pfc$local_mainframe THEN
            audit_information.audited_operation := sfc$ao_fs_create_object;
            audited_object.variant_path.complete_path := TRUE;
            audited_object.variant_path.p_complete_path := ^path;
            audited_object.object_type := sfc$afsot_catalog;
            audit_information.create_fs_object.object_id_p := ^audited_object;
            audit_information.create_fs_object.ownership := authority.ownership;
            sfp$emit_audit_statistic (audit_information, status);
          IFEND;
        IFEND;
        p_auditable_cycles := NIL;

      = pfc$file_group_record =
        pfp$validate_file_permission (path, authority, permit_entry, $pft$permit_selections [pfc$cycle],
              -$pft$share_selections [], status);
        IF status.normal THEN
          put_file_info (backup_file_version, p_group_record, family_location, path, authority.ownership,
                local_permit_level, selection_criteria, $fst$cycle_damage_symptoms [],
                restore_archive_information, {restore_media} FALSE, {replace_rem_media_fmd} FALSE,
                catalog_locator.p_catalog_file, p_physical_object, audit_restorations, all_permits_restored,
                p_auditable_permits, cycles_recreated, cycles_media_restored, p_auditable_cycles, status);
        ELSEIF audit_restorations THEN
          p_auditable_permits := NIL;
          variant_path.complete_path := TRUE;
          variant_path.p_complete_path := ^path;
          audit_cycle_restorations (backup_file_version, p_group_record, family_location, variant_path,
                authority.ownership, selection_criteria, restore_archive_information, status,
                p_auditable_cycles);
          audit_restorations := p_auditable_cycles <> NIL;
        IFEND;

      ELSE
        audit_restorations := FALSE;
        p_auditable_permits := NIL;
        p_auditable_cycles := NIL;
        osp$set_status_condition (pfe$bad_info_record_format, status);
      CASEND;

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    ELSE
      audit_restorations := FALSE;
      p_auditable_permits := NIL;
      p_auditable_cycles := NIL;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_item_info;

?? TITLE := '  [XDCL, #GATE] pfp$r2_put_master_catalog_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_put_master_catalog_info
    (    set_name: stt$set_name;
         family_name: pft$name;
         master_catalog_name: pft$name;
         p_info_record: {input} pft$p_info_record;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_put_master_catalog_info; {----->
    PROCEND initiate_non_local_exit;

    CONST
      permit_level = pfc$pl_public;

    VAR
      all_permits_restored: boolean,
      audit_restorations: boolean,
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      internal_path: array [1 .. pfc$master_catalog_path_index] of pft$internal_name,
      local_status: ost$status,
      p_auditable_permits: ^pft$auditable_permits,
      p_physical_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      path: array [1 .. pfc$master_catalog_path_index] of pft$name,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

    path [pfc$set_path_index] := set_name;
    path [pfc$family_path_index] := family_name;
    path [pfc$master_catalog_path_index] := master_catalog_name;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      pfp$validate_family_ownership (family_name, authority, status);
    IFEND;

    IF status.normal THEN
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$free_object],
            parent_charge_id, catalog_locator, p_physical_object, internal_path, permit_entry, status);
    IFEND;

    IF status.normal THEN
      osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);
      audit_restorations := avp$security_option_active (avc$vso_security_audit);
      p_auditable_permits := NIL;
      put_catalog_info (p_info_record, pfc$local_mainframe, path, authority, permit_level,
            pfc$external_catalog, {catalog_recreated} FALSE, catalog_locator.p_catalog_file,
            p_physical_object, audit_restorations, all_permits_restored, p_auditable_permits, status);

      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_put_master_catalog_info;

?? TITLE := '  access_parent_and_object', EJECT ??

  PROCEDURE access_parent_and_object
    (    path: pft$complete_path;
         object_selections: pft$object_selections;
     VAR authority: pft$authority;
     VAR parent_recreated: boolean;
     VAR parent_catalog_locator: pft$catalog_locator;
     VAR p_physical_object: ^pft$physical_object;
     VAR status: ost$status);

    PROCEDURE access_parent_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           p_sfsa: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        variant_path: pft$variant_path,
        status_id: ost$status_identifier,
        local_status: ost$status;

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;

      IF NOT process_non_local_exit THEN
        pfp$log_ascii ('***PF Condition Handler***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
              pmc$msg_origin_system, {critical_message} FALSE, local_status);
        pfp$log_path (variant_path, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
              {critical_message} FALSE, local_status);
      IFEND;

      CASE condition.selector OF
      = pmc$system_conditions, pmc$block_exit_processing, mmc$segment_access_condition =
        IF process_non_local_exit THEN
          RETURN; {----->
        IFEND;

        IF parent_catalog_locator.attached THEN
          parent_catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (parent_catalog_locator, local_status);
          IF NOT local_status.normal THEN
            pfp$report_system_error (local_status);
          IFEND;
        IFEND;

        IF grandparent_catalog_locator.attached THEN
          grandparent_catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (grandparent_catalog_locator, local_status);
          IF NOT local_status.normal THEN
            pfp$report_system_error (local_status);
          IFEND;
        IFEND;

        osp$set_status_from_condition (status_id, condition, p_sfsa, local_status, handler_status);
        osp$recoverable_system_error ('UNEXPECTED STATUS', ^local_status);

        status := local_status;
        initiate_non_local_exit;

      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          { syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND access_parent_handler;

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT access_parent_and_object; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      catalog: pft$array_index,
      grandparent_catalog_locator: pft$catalog_locator,
      internal_name: pft$internal_name,
      local_object_selections: pft$object_selections,
      local_status: ost$status,
      p_parent_catalog_internal_path: ^pft$internal_path,
      p_parent_catalog_path: ^pft$complete_path,
      p_physical_parent_catalog_obj: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

  /access_parent/
    BEGIN
      grandparent_catalog_locator.attached := FALSE;
      parent_catalog_locator.attached := FALSE;
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);

      osp$establish_condition_handler (^access_parent_handler, {block_exit} TRUE);

      IF UPPERBOUND (path) = pfc$family_path_index THEN
        stp$get_root_recreated (path [pfc$set_path_index], parent_recreated, status);
        IF status.normal THEN
          pfp$attach_root_catalog (path [pfc$set_path_index], pfc$write_access, parent_catalog_locator,
                status);
          permit_entry.entry_type := pfc$free_permit_entry;
        IFEND;
        EXIT /access_parent/; {----->
      IFEND;
      {
      { Access the parent object entry to determine if it was re-created.
      {
      PUSH p_parent_catalog_path: [1 .. (UPPERBOUND (path) - 1)];
      FOR catalog := 1 TO (UPPERBOUND (path) - 1) DO
        p_parent_catalog_path^ [catalog] := path [catalog];
      FOREND;
      PUSH p_parent_catalog_internal_path: [1 .. (UPPERBOUND (path) - 1)];
      pfp$access_object (p_parent_catalog_path^, pfc$read_access, authority,
            $pft$object_selections [pfc$catalog_object], parent_charge_id, grandparent_catalog_locator,
            p_physical_parent_catalog_obj, p_parent_catalog_internal_path^, permit_entry, status);

      IF status.normal THEN
        parent_recreated := p_physical_parent_catalog_obj^.object_entry.catalog_recreated_by_restore;
        {
        { Access the parent catalog to look for this file or catalog.
        {
        pfp$access_next_catalog (pfc$write_access, grandparent_catalog_locator, p_physical_parent_catalog_obj,
              {catalog_remote} FALSE, parent_catalog_locator, status);
        IF (NOT status.normal) OR (p_physical_parent_catalog_obj^.object_entry.catalog_object_locator.
              catalog_type = pfc$external_catalog) THEN
          pfp$return_catalog (grandparent_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      IFEND;
    END /access_parent/;

  /access_object/
    BEGIN
      IF NOT status.normal THEN
        EXIT /access_object/; {----->
      IFEND;

      IF parent_recreated THEN
        {
        { The parent catalog was re-created and the object does not exist, so
        { create the object.
        {
        local_object_selections := object_selections + $pft$object_selections [pfc$free_object];
      ELSE
        {
        { The parent catalog was not re-created, so do not re-create any
        { deleted files or catalogs.
        {
        local_object_selections := object_selections;
      IFEND;

      pfp$access_last_object (path, authority, local_object_selections, parent_catalog_locator, permit_entry,
            p_physical_object, internal_name, status);
      IF NOT status.normal THEN
        pfp$return_catalog (parent_catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    END /access_object/;

    osp$disestablish_cond_handler;
  PROCEND access_parent_and_object;

?? TITLE := '  add_cycle_entry', EJECT ??

  PROCEDURE add_cycle_entry
    (    p_path: ^pft$complete_path;
         cycle_entry: pft$cycle_entry;
         p_file_object: pft$p_object;
         p_catalog_file: pft$p_catalog_file;
     VAR status: ost$status);

    VAR
      cycle_list_locator: pft$cycle_list_locator,
      new_cycle_list: boolean,
      new_cycle_list_locator: pft$cycle_list_locator,
      p_cycle: pft$p_cycle,
      p_cycle_list: pft$p_cycle_list,
      p_new_cycle_list: pft$p_cycle_list;

    cycle_list_locator := p_file_object^.object_entry.cycle_list_locator;

    pfp$build_cycle_list_pointer (cycle_list_locator, p_catalog_file, p_cycle_list);
    pfp$establish_free_cycle_entry (^p_catalog_file^.catalog_heap, p_cycle_list, p_new_cycle_list,
          new_cycle_list, p_cycle, status);
    IF status.normal THEN
      p_cycle^.cycle_entry := cycle_entry;
      pfp$compute_checksum (#LOC (cycle_entry), #SIZE (cycle_entry), p_cycle^.checksum);

      IF new_cycle_list THEN
        pfp$build_cycle_list_locator (p_new_cycle_list, p_catalog_file, new_cycle_list_locator);
        p_file_object^.object_entry.cycle_list_locator := new_cycle_list_locator;
        pfp$compute_checksum (#LOC (p_file_object^.object_entry), #SIZE (p_file_object^.object_entry),
              p_file_object^.checksum);
        free_cycle_list (p_path, cycle_list_locator, p_catalog_file);
      IFEND;
    IFEND;
  PROCEND add_cycle_entry;

?? TITLE := '  audit_cycle_deletions', EJECT ??

  PROCEDURE audit_cycle_deletions
    (    path: pft$complete_path;
         ownership: pft$ownership;
         p_catalog_file: {input^} ^pft$catalog_file;
         cycle_list_locator: pft$cycle_list_locator);

    VAR
      audit_information: sft$audit_information,
      audit_status: ost$status,
      audited_object: sft$audited_fs_object_id,
      cycle_index: pft$cycle_index,
      cycle_selector: pft$cycle_selector,
      p_cycle_list: ^pft$cycle_list;

    pfp$build_cycle_list_pointer (cycle_list_locator, p_catalog_file, p_cycle_list);
    IF p_cycle_list <> NIL THEN
      audit_information.audited_operation := sfc$ao_fs_delete_object;
      audited_object.variant_path.complete_path := TRUE;
      audited_object.variant_path.p_complete_path := ^path;
      audited_object.object_type := sfc$afsot_cycle;
      cycle_selector.cycle_option := pfc$specific_cycle;
      audited_object.cycle_selector_p := ^cycle_selector;
      audit_information.delete_fs_object.object_id_p := ^audited_object;
      audit_information.delete_fs_object.ownership := ownership;
      audit_status.normal := TRUE;

      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
        IF p_cycle_list^ [cycle_index].cycle_entry.entry_type <> pfc$free_cycle_entry THEN
          cycle_selector.cycle_number := p_cycle_list^ [cycle_index].cycle_entry.cycle_number;
          IF p_cycle_list^ [cycle_index].cycle_entry.device_information.device_class_defined THEN
            pfp$convert_device_class_to_rm (p_cycle_list^ [cycle_index].cycle_entry.device_information.
                  device_class, audited_object.device_class);
          ELSE
            audited_object.device_class := rmc$mass_storage_device;
          IFEND;
          sfp$emit_audit_statistic (audit_information, audit_status);
        IFEND;
      FOREND;
    IFEND;
  PROCEND audit_cycle_deletions;

?? TITLE := '  audit_cycle_restorations', EJECT ??

  PROCEDURE audit_cycle_restorations
    (    backup_file_version: pft$backup_file_version;
         p_file_group_record: ^pft$info_record;
         family_location: pft$family_location;
         variant_path: pft$variant_path;
         ownership: pft$ownership;
         selection_criteria: put$selection_criteria;
         restore_archive_information: boolean;
         audit_status: ost$status;
     VAR p_auditable_cycles: ^pft$auditable_cycles);

    VAR
      all_cycles_chosen: boolean,
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      cycle_count: pft$cycle_count,
      cycle_index: pft$array_index,
      cycle_selector: pft$cycle_selector,
      local_status: ost$status,
      p_chosen_cycles: ^pft$chosen_cycles,
      p_cycle_array_version_1: ^pft$cycle_array,
      p_cycle_array_version_2: ^pft$cycle_array_version_2,
      p_file_description: ^pft$file_description;

    pfp$find_file_description (p_file_group_record, p_file_description, local_status);
    IF local_status.normal THEN
      IF backup_file_version = pfc$backup_file_version_2 THEN
        pfp$find_cycle_array_version_2 (p_file_group_record, p_cycle_array_version_2, local_status);
        IF local_status.normal AND (p_cycle_array_version_2 = NIL) THEN
          p_auditable_cycles := NIL;
          RETURN; {----->
        IFEND;
      ELSE { backup_file_version = pfc$backup_file_version_1 }
        pfp$find_cycle_array (p_file_group_record, p_cycle_array_version_1, local_status);
        IF local_status.normal AND (p_cycle_array_version_1 = NIL) THEN
          p_auditable_cycles := NIL;
          RETURN; {----->
        IFEND;
      IFEND;
    IFEND;

    IF local_status.normal THEN
      IF backup_file_version = pfc$backup_file_version_1 THEN
        PUSH p_cycle_array_version_2: [1 .. UPPERBOUND (p_cycle_array_version_1^)];
        map_cycle_array_to_version_2 (p_cycle_array_version_1, p_cycle_array_version_2);
      IFEND;

      all_cycles_chosen := restore_archive_information AND
            (NOT selection_criteria.after_date_time_selected) AND
            NOT selection_criteria.before_date_time_selected;
      IF all_cycles_chosen THEN
        cycle_count := UPPERBOUND (p_cycle_array_version_2^);
      ELSE
        PUSH p_chosen_cycles: [1 .. UPPERBOUND (p_cycle_array_version_2^)];
        choose_relevant_cycles (p_file_group_record, ownership, p_cycle_array_version_2, selection_criteria,
              restore_archive_information, p_chosen_cycles, cycle_count, local_status);
      IFEND;
    IFEND;

    IF local_status.normal THEN
      IF cycle_count = 0 THEN
        p_auditable_cycles := NIL;
      ELSE
        IF family_location = pfc$local_mainframe THEN
          audit_information.audited_operation := sfc$ao_fs_create_object;
          audited_object.variant_path := variant_path;
          audited_object.object_type := sfc$afsot_cycle;
          cycle_selector.cycle_option := pfc$specific_cycle;
          audited_object.cycle_selector_p := ^cycle_selector;
          audit_information.create_fs_object.object_id_p := ^audited_object;
          audit_information.create_fs_object.ownership := ownership;
        IFEND;

        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_array_version_2^) DO
          IF all_cycles_chosen OR p_chosen_cycles^ [cycle_index] THEN
            IF family_location = pfc$local_mainframe THEN
              cycle_selector.cycle_number := p_cycle_array_version_2^ [cycle_index].cycle_number;
              audited_object.device_class := p_cycle_array_version_2^ [cycle_index].device_class;
              sfp$emit_audit_statistic (audit_information, audit_status);
            ELSE
              p_auditable_cycles^ [cycle_index].audit := TRUE;
              p_auditable_cycles^ [cycle_index].cycle_number :=
                    p_cycle_array_version_2^ [cycle_index].cycle_number;
              p_auditable_cycles^ [cycle_index].device_class :=
                    p_cycle_array_version_2^ [cycle_index].device_class;
              p_auditable_cycles^ [cycle_index].normal_status := FALSE;
              p_auditable_cycles^ [cycle_index].condition := audit_status.condition;
            IFEND;
          ELSEIF family_location = pfc$server_mainframe THEN
            p_auditable_cycles^ [cycle_index].audit := FALSE;
          IFEND;
        FOREND;
      IFEND;
    ELSE
      p_auditable_cycles := NIL;
    IFEND;
  PROCEND audit_cycle_restorations;

?? TITLE := '  audit_permit_deletions', EJECT ??

  PROCEDURE audit_permit_deletions
    (    path: pft$complete_path;
         object_type: sft$audited_fs_object_type;
         ownership: pft$ownership;
         p_catalog_file: {input^} ^pft$catalog_file;
         permit_list_locator: pft$permit_list_locator);

    VAR
      audit_information: sft$audit_information,
      audit_status: ost$status,
      audited_object: sft$audited_fs_object_id,
      p_permit_list: ^pft$permit_list,
      permit_index: pft$permit_index;

    pfp$build_permit_list_pointer (permit_list_locator, p_catalog_file, p_permit_list);
    IF p_permit_list <> NIL THEN
      audit_information.audited_operation := sfc$ao_fs_delete_permit;
      audited_object.variant_path.complete_path := TRUE;
      audited_object.variant_path.p_complete_path := ^path;
      audited_object.object_type := object_type;
      audit_information.delete_fs_permit.object_id_p := ^audited_object;
      audit_information.delete_fs_permit.ownership := ownership;
      audit_status.normal := TRUE;

      FOR permit_index := 1 TO UPPERBOUND (p_permit_list^) DO
        IF p_permit_list^ [permit_index].permit_entry.entry_type = pfc$normal_permit_entry THEN
          audit_information.delete_fs_permit.group_p := ^p_permit_list^ [permit_index].permit_entry.group;
          sfp$emit_audit_statistic (audit_information, audit_status);
        IFEND;
      FOREND;
    IFEND;
  PROCEND audit_permit_deletions;

?? TITLE := '  choose_relevant_cycles', EJECT ??
*copy pfh$choose_relevant_cycles

  PROCEDURE choose_relevant_cycles
    (    p_file_info_record: {input} ^pft$info_record;
         ownership: pft$ownership;
         p_cycle_array: {input} ^pft$cycle_array_version_2;
         selection_criteria: put$selection_criteria;
         restore_archive_information: boolean;
         p_chosen_cycles: {output^} ^pft$chosen_cycles;
     VAR chosen_cycles_count: pft$cycle_count;
     VAR status: ost$status);

    VAR
      comparison_result: pmt$comparison_result,
      cycle_array_extended_missing: boolean,
      cycle_date_time: ost$date_time,
      cycle_included: boolean,
      cycle_index: pft$cycle_count,
      cycle_time_after_after_time: boolean,
      cycle_time_before_before_time: boolean,
      local_status: ost$status,
      p_archive_list: ^pft$info_record,
      p_cycle_array_extended_record: ^pft$info_record,
      p_cycle_directory_array: ^pft$cycle_directory_array,
      p_cycle_info_record: ^pft$info_record,
      p_cycle_media_description: ^pft$file_media_description;

    chosen_cycles_count := 0;

    cycle_array_extended_missing := FALSE;
    IF restore_archive_information THEN
      status.normal := TRUE;
    ELSE
      pfp$find_cycle_array_extended (p_file_info_record, p_cycle_array_extended_record, status);
      IF status.normal THEN
        pfp$find_cycle_directory (p_cycle_array_extended_record, p_cycle_directory_array, status);
      ELSEIF status.condition = pfe$unknown_cycle_array THEN
        cycle_array_extended_missing := TRUE;
        status.normal := TRUE;
      IFEND;
    IFEND;

    IF status.normal THEN
      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_array^) DO
        IF (NOT selection_criteria.after_date_time_selected) AND
              NOT selection_criteria.before_date_time_selected THEN
          cycle_included := TRUE;
        ELSE
          CASE selection_criteria.mode OF
          = puc$created =
            cycle_date_time := p_cycle_array^ [cycle_index].cycle_statistics.creation_date_time;
          = puc$accessed =
            cycle_date_time := p_cycle_array^ [cycle_index].cycle_statistics.access_date_time;
          = puc$modified =
            cycle_date_time := p_cycle_array^ [cycle_index].cycle_statistics.modification_date_time;
          = puc$expired =
            cycle_date_time := p_cycle_array^ [cycle_index].expiration_date_time;
          ELSE
            ;
          CASEND;

          IF selection_criteria.after_date_time_selected THEN
            pmp$date_time_compare (selection_criteria.after_date_time, cycle_date_time, comparison_result,
                  local_status);
            cycle_time_after_after_time := (NOT local_status.normal) OR
                  (comparison_result = pmc$right_is_greater);
          IFEND;

          IF selection_criteria.before_date_time_selected THEN
            pmp$date_time_compare (cycle_date_time, selection_criteria.before_date_time, comparison_result,
                  local_status);
            cycle_time_before_before_time := (NOT local_status.normal) OR
                  (comparison_result = pmc$right_is_greater);
          IFEND;

          IF selection_criteria.after_date_time_selected THEN
            IF selection_criteria.before_date_time_selected THEN
              IF selection_criteria.after_time_after_before_time THEN
                cycle_included := cycle_time_before_before_time OR cycle_time_after_after_time;
              ELSE
                cycle_included := cycle_time_after_after_time AND cycle_time_before_before_time;
              IFEND;
            ELSE { after_date_time_selected by itself }
              cycle_included := cycle_time_after_after_time;
            IFEND;
          ELSE { before_date_time_selected by itself }
            cycle_included := cycle_time_before_before_time;
          IFEND;
        IFEND;

        IF cycle_included THEN
          IF restore_archive_information OR cycle_array_extended_missing THEN
            chosen_cycles_count := chosen_cycles_count + 1;
          ELSE
            {
            { Ignore the cycle if it had been archived and released.
            {
            pfp$find_direct_info_record (^p_cycle_array_extended_record^.body,
                  p_cycle_directory_array^ [cycle_index].info_offset, p_cycle_info_record, status);
            IF NOT status.normal THEN
              RETURN; {----->
            IFEND;

            pfp$find_archive_info (p_cycle_info_record, p_archive_list, status);
            IF status.normal THEN
              pfp$find_cycle_media (p_cycle_info_record, p_cycle_media_description, status);
              IF status.normal THEN
                chosen_cycles_count := chosen_cycles_count + 1;
              ELSEIF status.condition = pfe$unknown_cycle_media THEN
                cycle_included := FALSE;
                status.normal := TRUE;
              ELSE
                RETURN; {----->
              IFEND;
            ELSEIF status.condition = pfe$unknown_archive_info THEN
              chosen_cycles_count := chosen_cycles_count + 1;
              status.normal := TRUE;
            ELSE
              RETURN; {----->
            IFEND;
          IFEND;
        IFEND;

        p_chosen_cycles^ [cycle_index] := cycle_included AND
              (((p_cycle_array^ [cycle_index].device_class = rmc$mass_storage_device) AND
              NOT p_cycle_array^ [cycle_index].sparse_allocation) OR
              ((ownership <> $pft$ownership []) AND (p_cycle_array^ [cycle_index].device_class =
              rmc$magnetic_tape_device)));
      FOREND;
    IFEND;
  PROCEND choose_relevant_cycles;

?? TITLE := '  create_cycle_entry', EJECT ??

  PROCEDURE create_cycle_entry
    (    path: pft$complete_path;
         cycle_list_locator: pft$cycle_list_locator;
         p_catalog_file: pft$p_catalog_file;
         cycle_selector: pft$cycle_selector;
         pf_device_class: pft$device_class;
         cycle_statistics: pft$cycle_statistics;
         data_modification_date_time: ost$date_time;
         expiration_date_time: ost$date_time;
         cycle_damage_symptoms: fst$cycle_damage_symptoms;
         shared_queue_info: pft$shared_queue_info;
         retrieve_option: pft$retrieve_option;
         site_backup_option: pft$site_backup_option;
         site_archive_option: pft$site_archive_option;
         site_release_option: pft$site_release_option;
     VAR cycle_entry: pft$cycle_entry;
     VAR status: ost$status);

    VAR
      cycle_number: fst$cycle_number,
      p_cycle_list: pft$p_cycle_list;

    pfp$build_cycle_list_pointer (cycle_list_locator, p_catalog_file, p_cycle_list);
    pfp$determine_new_cycle_number (path, p_cycle_list, cycle_selector, cycle_number, status);
    IF status.normal THEN
      initialize_cycle_entry (cycle_number, pf_device_class, cycle_statistics, data_modification_date_time,
            expiration_date_time, cycle_damage_symptoms, shared_queue_info, retrieve_option,
            site_backup_option, site_archive_option, site_release_option, cycle_entry);
    IFEND;
  PROCEND create_cycle_entry;

?? TITLE := '  free_cycle_list', EJECT ??

  PROCEDURE free_cycle_list
    (    p_path: ^pft$complete_path;
         cycle_list_locator: pft$cycle_list_locator;
         p_catalog_file: pft$p_catalog_file);

    VAR
      p_cycle_list: pft$p_cycle_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    pfp$build_cycle_list_pointer (cycle_list_locator, p_catalog_file, p_cycle_list);
    IF p_cycle_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_cycle_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_cycle_list IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'CYCLE_LIST', 'file',
              prevalidate_free_result, #OFFSET (p_cycle_list));
        p_cycle_list := NIL;
      IFEND;
    IFEND;
  PROCEND free_cycle_list;

?? TITLE := '  free_log_list', EJECT ??

  PROCEDURE free_log_list
    (    p_path: ^pft$complete_path;
         log_list_locator: pft$log_list_locator;
         p_catalog_file: pft$p_catalog_file);

    VAR
      p_log_list: pft$p_log_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    pfp$build_log_list_pointer (log_list_locator, p_catalog_file, p_log_list);
    IF p_log_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_log_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_log_list IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'LOG_LIST', 'file',
              prevalidate_free_result, #OFFSET (p_log_list));
        p_log_list := NIL;
      IFEND;
    IFEND;
  PROCEND free_log_list;

?? TITLE := '  free_permit_list', EJECT ??

  PROCEDURE free_permit_list
    (    p_path: ^pft$complete_path;
         p_physical_catalog_object: ^pft$physical_object;
         permit_list_locator: pft$permit_list_locator;
         p_catalog_file: pft$p_catalog_file);

    VAR
      p_permit_list: pft$p_permit_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    pfp$build_permit_list_pointer (permit_list_locator, p_catalog_file, p_permit_list);
    IF p_permit_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_permit_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_permit_list IN p_catalog_file^.catalog_heap;
      ELSE
        IF p_physical_catalog_object^.object_entry.object_type = pfc$file_object THEN
          pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'PERMIT_LIST', 'file',
                prevalidate_free_result, #OFFSET (p_permit_list));
        ELSE
          pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'PERMIT_LIST', 'catalog',
                prevalidate_free_result, #OFFSET (p_permit_list));
        IFEND;
        p_permit_list := NIL;
      IFEND;
    IFEND;
  PROCEND free_permit_list;

?? TITLE := '  initialize_cycle_entry', EJECT ??

  PROCEDURE initialize_cycle_entry
    (    cycle_number: fst$cycle_number;
         pf_device_class: pft$device_class;
         cycle_statistics: pft$cycle_statistics;
         data_modification_date_time: ost$date_time;
         expiration_date_time: ost$date_time;
         cycle_damage_symptoms: fst$cycle_damage_symptoms;
         shared_queue_info: pft$shared_queue_info;
         retrieve_option: pft$retrieve_option;
         site_backup_option: pft$site_backup_option;
         site_archive_option: pft$site_archive_option;
         site_release_option: pft$site_release_option;
     VAR cycle_entry: pft$cycle_entry);

    VAR
      status: ost$status;

    osp$generate_unique_binary_name (cycle_entry.internal_cycle_name, status);
    pfp$process_unexpected_status (status);
    cycle_entry.entry_type := pfc$normal_cycle_entry;
    cycle_entry.cycle_number := cycle_number;
    cycle_entry.cycle_statistics := cycle_statistics;
    cycle_entry.expiration_date_time := expiration_date_time;
    cycle_entry.attach_status := pfv$unattached_status;
    cycle_entry.cycle_damage_symptoms := cycle_damage_symptoms;
    cycle_entry.data_modification_date_time := data_modification_date_time;
    cycle_entry.device_information.device_class_defined := TRUE;
    cycle_entry.device_information.device_class := pf_device_class;
    cycle_entry.device_information.eoi := 0;
    cycle_entry.device_information.bytes_allocated := 0;
    pfp$build_fmd_locator (NIL, NIL, cycle_entry.fmd_locator);
    pfp$build_file_label_locator (NIL, NIL, cycle_entry.file_label_locator);
    pfp$build_archive_list_locator (NIL, NIL, cycle_entry.archive_list_locator);
    cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
    pfp$build_mainfram_list_locator (NIL, NIL, cycle_entry.mainframe_usage_list_locator);
    cycle_entry.global_file_name := cycle_entry.internal_cycle_name;
    cycle_entry.data_residence := pfc$unreleasable_data;
    cycle_entry.shared_queue_info := shared_queue_info;
    cycle_entry.retrieve_option := retrieve_option;
    cycle_entry.site_backup_option := site_backup_option;
    cycle_entry.site_archive_option := site_archive_option;
    cycle_entry.site_release_option := site_release_option;
    cycle_entry.reserved_cycle_entry_space := pfv$null_cycle_entry_space;
  PROCEND initialize_cycle_entry;

?? TITLE := '  initialize_file_object', EJECT ??

  PROCEDURE initialize_file_object
    (    file_name: pft$name;
     VAR file_object: pft$object_entry);

    VAR
      status: ost$status;

    file_object.external_object_name := file_name;
    osp$generate_unique_binary_name (file_object.internal_object_name, status);
    pfp$process_unexpected_status (status);
    pfp$build_permit_list_locator (NIL, NIL, file_object.permit_list_locator);
    file_object.object_type := pfc$file_object;
    file_object.password := osc$null_name;
    file_object.charge_id.account := osc$null_name;
    file_object.charge_id.project := osc$null_name;
    file_object.logging_selection := pfc$no_log;
    pfp$build_log_list_locator (NIL, NIL, file_object.log_list_locator);
    pfp$build_cycle_list_locator (NIL, NIL, file_object.cycle_list_locator);
    file_object.reserved_object_entry_space := pfv$null_object_entry_space;
    file_object.reserved_file_entry_space := pfv$null_file_entry_space;
  PROCEND initialize_file_object;

?? TITLE := '  map_cycle_array_to_version_2', EJECT ??

  PROCEDURE map_cycle_array_to_version_2
    (    p_cycle_array: {input^} ^pft$cycle_array;
         p_cycle_array_version_2: {output^} ^pft$cycle_array_version_2);

    VAR
      cycle_array_index: pft$cycle_array_index;

    FOR cycle_array_index := 1 TO UPPERBOUND (p_cycle_array^) DO
      p_cycle_array_version_2^ [cycle_array_index] := cycle_array_entry_version_2;
      p_cycle_array_version_2^ [cycle_array_index].cycle_number :=
            p_cycle_array^ [cycle_array_index].cycle_number;
      p_cycle_array_version_2^ [cycle_array_index].cycle_statistics :=
            p_cycle_array^ [cycle_array_index].cycle_statistics;
      p_cycle_array_version_2^ [cycle_array_index].data_modification_date_time :=
            p_cycle_array^ [cycle_array_index].cycle_statistics.modification_date_time;
      p_cycle_array_version_2^ [cycle_array_index].device_class := rmc$mass_storage_device;
      p_cycle_array_version_2^ [cycle_array_index].expiration_date_time :=
            p_cycle_array^ [cycle_array_index].expiration_date_time;
      p_cycle_array_version_2^ [cycle_array_index].original_unique_name := pfv$null_unique_name;
      p_cycle_array_version_2^ [cycle_array_index].shared_queue_info.defined := FALSE;
      p_cycle_array_version_2^ [cycle_array_index].retrieve_option := pfc$always_retrieve;
      p_cycle_array_version_2^ [cycle_array_index].site_backup_option := pfc$null_site_backup_option;
      p_cycle_array_version_2^ [cycle_array_index].site_archive_option := pfc$null_site_archive_option;
      p_cycle_array_version_2^ [cycle_array_index].site_release_option := pfc$null_site_release_option;
    FOREND;
  PROCEND map_cycle_array_to_version_2;

?? TITLE := '  put_archive_info', EJECT ??

  PROCEDURE put_archive_info
    (    p_path: ^pft$complete_path;
         p_cycle_number: ^fst$cycle_number;
         p_catalog_file: pft$p_catalog_file;
         data_modification_date_time: ost$date_time;
     VAR file_size: amt$file_length;
     VAR p_archive_info: pft$p_info;
     VAR archive_list_locator: pft$archive_list_locator;
     VAR status: ost$status);

    VAR
      archive_count: pft$archive_count,
      archive_identification: pft$archive_identification,
      archive_index: pft$archive_index,
      local_archive_identification: pft$archive_identification,
      p_amd: pft$p_amd,
      p_archive: pft$p_archive,
      p_archive_array_entry: pft$p_archive_array_entry,
      p_archive_record: pft$p_info_record,
      p_new_archive_list: pft$p_archive_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    status.normal := TRUE;
    archive_count := 0;
    archive_identification.application_identifier := osc$null_name;
    archive_identification.media_identifier.media_device_class := osc$null_name;
    archive_identification.media_identifier.media_volume_identifier := '';
    p_new_archive_list := NIL;
    RESET p_archive_info;

  /build_archive_list/
    BEGIN

      REPEAT
        pfp$find_next_archive_entry (archive_identification, p_archive_info, p_archive_record,
              p_archive_array_entry, p_amd, status);

        IF status.normal THEN
          pfp$convert_archive_ident (p_archive_array_entry^.archive_identification,
                local_archive_identification, status);
          IF NOT status.normal THEN
            EXIT /build_archive_list/; {----->
          IFEND;
          archive_count := archive_count + 1;
          IF (data_modification_date_time = pfv$null_date_time) OR
                (p_archive_array_entry^.modification_date_time = data_modification_date_time) THEN
            file_size := p_archive_array_entry^.file_size;
          IFEND;
        IFEND;
      UNTIL NOT status.normal;
      IF status.condition = pfe$unknown_info_record THEN
        status.normal := TRUE; { all archive array entries found }
      IFEND;

      archive_list_locator.archive_count := 0;

      IF archive_count = 0 THEN
        EXIT /build_archive_list/; {----->
      IFEND;

      pfp$allocate_archive_list (archive_count, ^p_catalog_file^.catalog_heap, p_new_archive_list, status);
      IF NOT status.normal THEN
        EXIT /build_archive_list/; {----->
      IFEND;

      RESET p_archive_info;

    /build_new_archive_list/
      FOR archive_index := 1 TO archive_count DO
        pfp$find_next_archive_entry (archive_identification, p_archive_info, p_archive_record,
              p_archive_array_entry, p_amd, status);
        IF NOT status.normal THEN
          EXIT /build_archive_list/; {----->
        IFEND;
        p_archive := ^p_new_archive_list^ [archive_index];
        pfp$convert_archive_ident (p_archive_array_entry^.archive_identification,
              local_archive_identification, status);
        IF NOT status.normal THEN
          EXIT /build_archive_list/; {----->
        IFEND;
        pfp$r2_build_archive_entry (local_archive_identification, p_archive_array_entry, p_amd,
              p_catalog_file, p_archive, status);
        IF NOT status.normal THEN
          EXIT /build_archive_list/; {----->
        IFEND;
      FOREND /build_new_archive_list/;

    END /build_archive_list/;

    IF NOT status.normal THEN
      IF p_new_archive_list <> NIL THEN
        osp$prevalidate_free ((#OFFSET (p_new_archive_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
              ^p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_archive_list IN p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (p_path, p_cycle_number, 'ARCHIVE_LIST', 'file',
                prevalidate_free_result, #OFFSET (p_new_archive_list));
          p_new_archive_list := NIL;
        IFEND;
      IFEND;
    IFEND;

    pfp$build_archive_list_locator (p_new_archive_list, p_catalog_file, archive_list_locator);

  PROCEND put_archive_info;

?? TITLE := '  put_catalog_info', EJECT ??

  PROCEDURE put_catalog_info
    (    p_catalog_group_record: {input} ^pft$info_record;
         family_location: pft$family_location;
         path: pft$complete_path;
         authority: pft$authority;
         permit_level: pft$permit_level;
         catalog_type: pft$catalog_types;
         catalog_recreated: boolean;
         p_parent_catalog_file: {i^/o^} ^pft$catalog_file;
         p_physical_catalog_object: {output^} ^pft$physical_object;
     VAR audit_restorations: {i/o} boolean;
     VAR all_permits_restored: boolean;
     VAR p_auditable_permits: ^pft$auditable_permits;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      p_catalog_description: ^pft$catalog_description,
      permit_list_locator: pft$permit_list_locator,
      permit_restorations_audited: boolean;

    pfp$find_catalog_description (p_catalog_group_record, p_catalog_description, status);

    IF status.normal THEN
      put_permit_array (p_catalog_group_record, family_location, path, sfc$afsot_catalog, authority.ownership,
            permit_level, audit_restorations, p_parent_catalog_file, permit_list_locator,
            all_permits_restored, permit_restorations_audited, p_auditable_permits, status);

      IF status.normal THEN
        pfp$create_catalog_object (path, authority, catalog_type, p_catalog_description^.charge_id,
              p_catalog_description^.charge_id, {p_mass_storage_request_info} NIL, p_parent_catalog_file,
              p_physical_catalog_object, status);

        IF audit_restorations AND (family_location = pfc$local_mainframe) THEN
          audit_information.audited_operation := sfc$ao_fs_create_object;
          audited_object.variant_path.complete_path := TRUE;
          audited_object.variant_path.p_complete_path := ^path;
          audited_object.object_type := sfc$afsot_catalog;
          audit_information.create_fs_object.object_id_p := ^audited_object;
          audit_information.create_fs_object.ownership := authority.ownership;
          sfp$emit_audit_statistic (audit_information, status);
        IFEND;

        IF status.normal THEN
          p_physical_catalog_object^.object_entry.catalog_recreated_by_restore := catalog_recreated;
          p_physical_catalog_object^.object_entry.permit_list_locator := permit_list_locator;
          pfp$compute_checksum (#LOC (p_physical_catalog_object^.object_entry), #SIZE (pft$object_entry),
                p_physical_catalog_object^.checksum);
        ELSE
          IF permit_restorations_audited THEN
            audit_permit_deletions (path, sfc$afsot_catalog, authority.ownership, p_parent_catalog_file,
                  permit_list_locator);
          IFEND;
          p_auditable_permits := NIL;
          free_permit_list (^path, p_physical_catalog_object, permit_list_locator, p_parent_catalog_file);
        IFEND;
      ELSE
        audit_restorations := FALSE;
      IFEND;
    ELSE
      audit_restorations := FALSE;
      p_auditable_permits := NIL;
    IFEND;
  PROCEND put_catalog_info;

?? TITLE := '  put_cycle_archive_info', EJECT ??

  PROCEDURE put_cycle_archive_info
    (    p_catalog_file: pft$p_catalog_file;
         p_cycle_list: pft$p_cycle_list;
         cycle_selector: pft$cycle_selector;
         path: pft$complete_path;
         p_cycle_info_record: pft$p_info_record;
     VAR status: ost$status);

    VAR
      archive_list_locator: pft$archive_list_locator,
      data_modification_date_time: ost$date_time,
      file_size: amt$file_length,
      p_archive_info: ^pft$info,
      p_archive_info_record: ^pft$info_record,
      p_archive_list: pft$p_archive_list,
      p_cycle: pft$p_cycle,
      p_cycle_label: ^fmt$file_label,
      p_cycle_label_checksum: ^pft$checksum,
      p_cycle_label_info: ^SEQ ( * ),
      p_fmd_description: ^pft$file_media_description,
      p_new_stored_file_label: ^pft$physical_file_label,
      valid_archive_entry_exists: boolean;

    pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);

    IF status.normal THEN
      pfp$find_archive_info (p_cycle_info_record, p_archive_info_record, status);
      IF NOT status.normal THEN

{ Someday, restructure all these checks for normal status.  This change is
{ going in after the very last chance for 1.5.2, so it will not restructure.

        status.normal := TRUE;
        RETURN; {----->
      IFEND;
    IFEND;

    IF status.normal THEN
      IF p_cycle^.cycle_entry.archive_list_locator.archive_count = 0 THEN
        IF p_cycle^.cycle_entry.file_label_locator.file_label_size = 0 THEN
          pfp$find_cycle_label (p_cycle_info_record, p_cycle_label_info, status);
          IF status.normal THEN
            RESET p_cycle_label_info;
            NEXT p_cycle_label_checksum IN p_cycle_label_info;
            NEXT p_cycle_label: [[REP (#SIZE (p_cycle_label_info^) - #SIZE (pft$checksum)) OF cell]] IN
                  p_cycle_label_info;

            ALLOCATE p_new_stored_file_label: [[REP (#SIZE (p_cycle_label^)) OF cell]] IN
                  p_catalog_file^.catalog_heap;
            IF p_new_stored_file_label = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle label',
                    status);
            ELSE
              p_new_stored_file_label^.file_label := p_cycle_label^;
              pfp$compute_checksum (#LOC (p_cycle_label^), #SIZE (p_cycle_label^),
                    p_new_stored_file_label^.checksum);
              pfp$build_file_label_locator (p_new_stored_file_label, p_catalog_file,
                    p_cycle^.cycle_entry.file_label_locator);
            IFEND;
          ELSEIF status.condition = pfe$unknown_cycle_label THEN
            status.normal := TRUE;
          IFEND;
        IFEND;
        IF p_cycle^.cycle_entry.data_modification_date_time.year > 0 THEN
          data_modification_date_time := p_cycle^.cycle_entry.data_modification_date_time;
        ELSE
          data_modification_date_time := p_cycle^.cycle_entry.cycle_statistics.modification_date_time;
        IFEND;
        p_archive_info := ^p_archive_info_record^.body;
        put_archive_info (^path, ^p_cycle^.cycle_entry.cycle_number, p_catalog_file,
              data_modification_date_time, file_size, p_archive_info, archive_list_locator, status);
        IF status.normal AND (archive_list_locator.archive_count <> 0) THEN
          p_cycle^.cycle_entry.archive_list_locator := archive_list_locator;
          pfp$check_archive_entries (p_catalog_file, p_cycle, valid_archive_entry_exists, status);
          IF status.normal AND valid_archive_entry_exists AND
                (p_cycle^.cycle_entry.fmd_locator.fmd_size = 0) THEN
            p_cycle^.cycle_entry.data_residence := pfc$offline_data;
            p_cycle^.cycle_entry.device_information.device_class_defined := TRUE;
            p_cycle^.cycle_entry.device_information.device_class := pfc$mass_storage_device;
            p_cycle^.cycle_entry.device_information.bytes_allocated := 0;
            p_cycle^.cycle_entry.device_information.eoi := file_size;
            p_cycle^.cycle_entry.data_modification_date_time := data_modification_date_time;
          IFEND;
          pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
        IFEND;
      IFEND;
    IFEND;

  PROCEND put_cycle_archive_info;

?? TITLE := '  put_cycle_array', EJECT ??

  PROCEDURE put_cycle_array
    (    p_file_group_record: {input} ^pft$info_record;
         p_cycle_array_version_2: ^pft$cycle_array_version_2;
         family_location: pft$family_location;
         path: pft$complete_path;
         ownership: pft$ownership;
         selection_criteria: put$selection_criteria;
         cycle_damage_symptoms: fst$cycle_damage_symptoms;
         restore_archive_information: boolean;
         audit_cycle_restorations: boolean;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR cycle_list_locator: pft$cycle_list_locator;
     VAR cycle_count: pft$cycle_count;
     VAR cycle_restorations_audited: boolean;
     VAR p_auditable_cycles: ^pft$auditable_cycles;
     VAR status: ost$status);

    VAR
      all_cycles_chosen: boolean,
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      chosen_cycles_index: pft$array_index,
      cycle_index: pft$array_index,
      cycle_selector: pft$cycle_selector,
      free_physical_cycle: pft$physical_cycle,
      p_chosen_cycles: ^pft$chosen_cycles,
      p_cycle_list: ^pft$cycle_list,
      pf_device_class: pft$device_class;

    all_cycles_chosen := restore_archive_information AND (NOT selection_criteria.after_date_time_selected) AND
          NOT selection_criteria.before_date_time_selected;
    IF all_cycles_chosen THEN
      cycle_count := UPPERBOUND (p_cycle_array_version_2^);
    ELSE
      PUSH p_chosen_cycles: [1 .. UPPERBOUND (p_cycle_array_version_2^)];
      choose_relevant_cycles (p_file_group_record, ownership, p_cycle_array_version_2, selection_criteria,
            restore_archive_information, p_chosen_cycles, cycle_count, status);
      IF NOT status.normal THEN
        cycle_count := 0;
      IFEND;
    IFEND;

    IF cycle_count > 0 THEN
      pfp$allocate_cycle_list (cycle_count, ^p_catalog_file^.catalog_heap, p_cycle_list, status);

      IF status.normal THEN
        IF audit_cycle_restorations AND (family_location = pfc$local_mainframe) THEN
          audit_information.audited_operation := sfc$ao_fs_create_object;
          audited_object.variant_path.complete_path := TRUE;
          audited_object.variant_path.p_complete_path := ^path;
          audited_object.object_type := sfc$afsot_cycle;
          cycle_selector.cycle_option := pfc$specific_cycle;
          audited_object.cycle_selector_p := ^cycle_selector;
          audit_information.create_fs_object.object_id_p := ^audited_object;
          audit_information.create_fs_object.ownership := ownership;
          cycle_restorations_audited := TRUE;
        ELSE
          cycle_restorations_audited := FALSE;
        IFEND;

        chosen_cycles_index := 1;
        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_array_version_2^) DO
          IF all_cycles_chosen OR p_chosen_cycles^ [cycle_index] THEN
            pfp$convert_device_class_to_pf (p_cycle_array_version_2^ [cycle_index].device_class,
                  pf_device_class);
            initialize_cycle_entry (p_cycle_array_version_2^ [cycle_index].cycle_number, pf_device_class,
                  p_cycle_array_version_2^ [cycle_index].cycle_statistics,
                  p_cycle_array_version_2^ [cycle_index].data_modification_date_time,
                  p_cycle_array_version_2^ [cycle_index].expiration_date_time,
                  (p_cycle_array_version_2^ [cycle_index].cycle_damage_symptoms + cycle_damage_symptoms),
                  p_cycle_array_version_2^ [cycle_index].shared_queue_info, pfc$always_retrieve,
                  pfc$null_site_backup_option, pfc$null_site_archive_option, pfc$null_site_release_option,
                  p_cycle_list^ [chosen_cycles_index].cycle_entry);
            pfp$compute_checksum (#LOC (p_cycle_list^ [chosen_cycles_index].cycle_entry),
                  #SIZE (pft$cycle_entry), p_cycle_list^ [chosen_cycles_index].checksum);
            chosen_cycles_index := chosen_cycles_index + 1;

            IF audit_cycle_restorations THEN
              IF family_location = pfc$local_mainframe THEN
                cycle_selector.cycle_number := p_cycle_array_version_2^ [cycle_index].cycle_number;
                audited_object.device_class := p_cycle_array_version_2^ [cycle_index].device_class;
                sfp$emit_audit_statistic (audit_information, status);
              ELSE
                p_auditable_cycles^ [cycle_index].audit := TRUE;
                p_auditable_cycles^ [cycle_index].cycle_number :=
                      p_cycle_array_version_2^ [cycle_index].cycle_number;
                p_auditable_cycles^ [cycle_index].device_class :=
                      p_cycle_array_version_2^ [cycle_index].device_class;
                p_auditable_cycles^ [cycle_index].normal_status := TRUE;
              IFEND;
            IFEND;
          ELSEIF audit_cycle_restorations AND (family_location = pfc$server_mainframe) THEN
            p_auditable_cycles^ [cycle_index].audit := FALSE;
          IFEND;
        FOREND;

        free_physical_cycle.cycle_entry.entry_type := pfc$free_cycle_entry;
        pfp$compute_checksum (#LOC (free_physical_cycle.cycle_entry), #SIZE (pft$cycle_entry),
              free_physical_cycle.checksum);

        FOR cycle_index := cycle_count + 1 TO UPPERBOUND (p_cycle_list^) DO
          p_cycle_list^ [cycle_index] := free_physical_cycle;
        FOREND;

        pfp$build_cycle_list_locator (p_cycle_list, p_catalog_file, cycle_list_locator);
      ELSE
        cycle_restorations_audited := FALSE;
        p_auditable_cycles := NIL;
      IFEND;
    ELSE
      cycle_restorations_audited := FALSE;
      p_auditable_cycles := NIL;
    IFEND;
  PROCEND put_cycle_array;

?? TITLE := '  put_cycle_info', EJECT ??

  PROCEDURE put_cycle_info
    (    p_file_group: {input} ^pft$info_record;
         p_cycle_array_version_2: {input^} ^pft$cycle_array_version_2;
         path: pft$complete_path;
         cycle_list_locator: pft$cycle_list_locator;
         restore_archive_information: boolean;
         restore_media: boolean;
         replace_rem_media_fmd: boolean;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR cycles_media_restored: pft$cycle_count;
     VAR status: ost$status);

    VAR
      cycle_index: pft$array_index,
      cycle_list_index: pft$array_index,
      cycle_selector: pft$cycle_selector,
      media_restored: boolean,
      p_cycle_array_extended_record: ^pft$info_record,
      p_cycle_directory_array: ^pft$cycle_directory_array,
      p_cycle_info_record: ^pft$info_record,
      p_cycle_list: ^pft$cycle_list,
      p_fmd: ^pft$file_media_description;

    cycles_media_restored := 0;

    pfp$find_cycle_array_extended (p_file_group, p_cycle_array_extended_record, status);

    IF status.normal THEN
      pfp$find_cycle_directory (p_cycle_array_extended_record, p_cycle_directory_array, status);

      IF status.normal AND (p_cycle_directory_array <> NIL) THEN
        pfp$build_cycle_list_pointer (cycle_list_locator, p_catalog_file, p_cycle_list);
        cycle_list_index := 1;

        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_directory_array^) DO
          IF p_cycle_directory_array^ [cycle_index].cycle_number =
                p_cycle_list^ [cycle_list_index].cycle_entry.cycle_number THEN
            pfp$find_direct_info_record (^p_cycle_array_extended_record^.body,
                  p_cycle_directory_array^ [cycle_index].info_offset, p_cycle_info_record, status);

            IF status.normal THEN
              {
              { This code takes advantage of the fact that the cycle list in
              { the catalog and both the cycle array and the cycle array
              { extended info on the backup file are in the same order.
              {
              put_cycle_media_info (^path, p_cycle_array_version_2^ [cycle_index],
                    p_cycle_directory_array^ [cycle_index], p_cycle_info_record, restore_media,
                    replace_rem_media_fmd, p_catalog_file, p_cycle_list^ [cycle_list_index], media_restored,
                    status);
              IF NOT status.normal THEN
                RETURN; {----->
              ELSEIF media_restored THEN
                cycles_media_restored := cycles_media_restored + 1;
              IFEND;

              IF restore_archive_information THEN
                cycle_selector.cycle_option := pfc$specific_cycle;
                cycle_selector.cycle_number := p_cycle_directory_array^ [cycle_index].cycle_number;
                put_cycle_archive_info (p_catalog_file, p_cycle_list, cycle_selector, path,
                      p_cycle_info_record, status);
                IF status.condition = pfe$unknown_archive_info THEN
                  status.normal := TRUE; { cycle not archived }
                IFEND;
              IFEND;
            IFEND;

            IF NOT status.normal THEN
              RETURN; {----->
            IFEND;

            IF cycle_list_index = UPPERBOUND (p_cycle_list^) THEN
              RETURN; {----->
            IFEND;

            cycle_list_index := cycle_list_index + 1;
          IFEND;
        FOREND;
      IFEND;
    IFEND;
  PROCEND put_cycle_info;

?? TITLE := '  put_cycle_media_info', EJECT ??

  PROCEDURE put_cycle_media_info
    (    p_path: ^pft$complete_path;
         cycle_array_entry_version_2: pft$cycle_array_entry_version_2;
         cycle_directory_array_entry: pft$cycle_directory_array_entry;
         p_cycle_info_record: {input} ^pft$info_record;
         restore_media: boolean;
         replace_rem_media_fmd: boolean;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR physical_cycle: {i/o} pft$physical_cycle;
     VAR media_restored: boolean;
     VAR status: ost$status);

    VAR
      cycle_available: boolean,
      comparison_result: pmt$comparison_result,
      existing_sft_entry: dmt$existing_sft_entry,
      file_damaged: boolean,
      file_information: dmt$file_information,
      fmd_modified: boolean,
      fmd_size: dmt$stored_fmd_size,
      ignore_class: dmt$class,
      local_status: ost$status,
      p_cycle_label: ^fmt$file_label,
      p_cycle_label_checksum: ^pft$checksum,
      p_cycle_label_info: ^SEQ ( * ),
      p_fmd: ^pft$file_media_description,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_new_stored_file_label: ^pft$physical_file_label,
      resides_on_system_device: boolean,
      system_file_id: gft$system_file_identifier;

    status.normal := TRUE;
    media_restored := FALSE;

    IF restore_media AND (cycle_array_entry_version_2.device_class = rmc$mass_storage_device) THEN
      pfp$find_cycle_media (p_cycle_info_record, p_fmd, status);
      IF status.normal THEN
        dmp$reconcile_fmd (dmv$reconcile_locator, p_fmd^.global_file_name, p_fmd^.file_media_descriptor,
              {purge_file} FALSE, ignore_class, fmd_size, resides_on_system_device, status);

        IF status.normal OR (status.condition = dme$some_volumes_not_online) OR
              (status.condition = dme$update_fmd) OR (status.condition = dme$volume_unavailable) OR
              (status.condition = ste$master_not_active) OR (status.condition = ste$vol_not_found) THEN
          cycle_available := status.normal OR (status.condition = dme$update_fmd);
          {
          { Dme$some_volumes_not_online, dme$volume_unavailable,
          { ste$master_not_active, and ste$vol_not_found will be detected by
          { attach.
          {
          IF status.normal OR (status.condition <> dme$update_fmd) THEN
            ALLOCATE p_new_physical_fmd: [[REP #SIZE (p_fmd^.file_media_descriptor) OF cell]] IN
                  p_catalog_file^.catalog_heap;
            IF p_new_physical_fmd = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle fmd', status);
            ELSE
              status.normal := TRUE;
              p_new_physical_fmd^.fmd := p_fmd^.file_media_descriptor;
            IFEND;
          ELSE
            ALLOCATE p_new_physical_fmd: [[REP fmd_size OF cell]] IN p_catalog_file^.catalog_heap;
            IF p_new_physical_fmd = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle fmd', status);
            ELSE
              dmp$get_reconciled_fmd (dmv$reconcile_locator, p_fmd^.global_file_name,
                    p_fmd^.file_media_descriptor, p_new_physical_fmd^.fmd, status);
            IFEND;
          IFEND;

          IF status.normal THEN
            pfp$compute_checksum (#LOC (p_new_physical_fmd^.fmd), #SIZE (p_new_physical_fmd^.fmd),
                  p_new_physical_fmd^.checksum);
            pfp$build_fmd_locator (p_new_physical_fmd, p_catalog_file,
                  physical_cycle.cycle_entry.fmd_locator);
            physical_cycle.cycle_entry.internal_cycle_name := cycle_directory_array_entry.internal_name;
            physical_cycle.cycle_entry.global_file_name := p_fmd^.global_file_name;

            IF cycle_available THEN
              dmp$attach_file (physical_cycle.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                    p_new_physical_fmd^.fmd, $pft$usage_selections [], -$pft$share_selections [],
                    pfc$average_share_history, pfc$maximum_pf_length, {restricted_attach} FALSE,
                    {exit_on_unknown_file} FALSE, {server_file} FALSE,
                    pfp$shared_queue (physical_cycle.cycle_entry.shared_queue_info, -$pft$share_selections
                    []), file_damaged, system_file_id, existing_sft_entry, status);

              IF status.normal THEN
                pfp$detach_permanent_file (p_path, system_file_id, $pft$usage_selections [],
                      {catalog_access_allowed} TRUE, ^physical_cycle, p_catalog_file,
                      dmc$df_ignore_trimmed_length, fmd_modified, file_information, status);
              IFEND;

              IF status.normal THEN
                physical_cycle.cycle_entry.device_information.eoi := file_information.eoi_byte_address;
                physical_cycle.cycle_entry.device_information.bytes_allocated :=
                      file_information.total_allocated_length;
              ELSE
                pfp$report_unexpected_status (status);
                status.normal := TRUE;
                physical_cycle.cycle_entry.attach_status.attach_count := 1;
                physical_cycle.cycle_entry.attach_status.usage_counts [pfc$modify] := 1;
                physical_cycle.cycle_entry.device_information.eoi := cycle_array_entry_version_2.eoi;
                physical_cycle.cycle_entry.device_information.bytes_allocated :=
                      cycle_array_entry_version_2.bytes_allocated;
              IFEND;
            IFEND;

            media_restored := TRUE;
          IFEND;

          IF status.normal THEN
            pfp$compute_checksum (#LOC (physical_cycle.cycle_entry), #SIZE (physical_cycle.cycle_entry),
                  physical_cycle.checksum);
          IFEND;
        ELSE { Does not reconcile
          {
          { The cycle described in the catalog no longer exists.  Leave the cycle
          { in an 'undefined data' state (NIL FMD) to allow restore_excluded_file_cycles
          { to restore it.
          {
          { This restores deleted cycles, but allows for the case of a file whose
          { only available cycle is on the backup file.
          {
          media_restored := FALSE;
          status.normal := TRUE;
        IFEND;
      ELSEIF status.condition = pfe$unknown_cycle_media THEN
        media_restored := FALSE;
        status.normal := TRUE;
      IFEND;
    ELSEIF cycle_array_entry_version_2.device_class = rmc$magnetic_tape_device THEN
      pfp$find_cycle_media (p_cycle_info_record, p_fmd, status);
      IF status.normal THEN
        pfi$store_file_media_descriptor (^p_fmd^.file_media_descriptor, p_catalog_file, ^physical_cycle,
              replace_rem_media_fmd, status);
        media_restored := status.normal;
      ELSEIF status.condition = pfe$unknown_cycle_media THEN
        media_restored := FALSE;
        status.normal := TRUE;
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$find_cycle_label (p_cycle_info_record, p_cycle_label_info, status);
      IF status.normal THEN
        RESET p_cycle_label_info;
        NEXT p_cycle_label_checksum IN p_cycle_label_info;
        NEXT p_cycle_label: [[REP (#SIZE (p_cycle_label_info^) - #SIZE (pft$checksum)) OF cell]] IN
              p_cycle_label_info;

        ALLOCATE p_new_stored_file_label: [[REP (#SIZE (p_cycle_label^)) OF cell]] IN
              p_catalog_file^.catalog_heap;
        IF p_new_stored_file_label = NIL THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle label', status);
        ELSE
          p_new_stored_file_label^.file_label := p_cycle_label^;
          pfp$compute_checksum (#LOC (p_cycle_label^), #SIZE (p_cycle_label^),
                p_new_stored_file_label^.checksum);
          pfp$build_file_label_locator (p_new_stored_file_label, p_catalog_file,
                physical_cycle.cycle_entry.file_label_locator);
        IFEND;
      ELSEIF status.condition = pfe$unknown_cycle_label THEN
        status.normal := TRUE;
      IFEND;
    IFEND;

    IF status.normal THEN
      pmp$date_time_compare (physical_cycle.cycle_entry.cycle_statistics.modification_date_time,
            cycle_array_entry_version_2.cycle_statistics.modification_date_time, comparison_result,
            local_status);
      IF local_status.normal AND (comparison_result = pmc$equal) THEN
        physical_cycle.cycle_entry.retrieve_option := cycle_array_entry_version_2.retrieve_option;
        physical_cycle.cycle_entry.site_backup_option := cycle_array_entry_version_2.site_backup_option;
        physical_cycle.cycle_entry.site_archive_option := cycle_array_entry_version_2.site_archive_option;
        physical_cycle.cycle_entry.site_release_option := cycle_array_entry_version_2.site_release_option;
      IFEND;
      pfp$compute_checksum (#LOC (physical_cycle.cycle_entry), #SIZE (physical_cycle.cycle_entry),
            physical_cycle.checksum);
    IFEND;

  PROCEND put_cycle_media_info;

?? TITLE := '  put_file_info', EJECT ??

  PROCEDURE put_file_info
    (    backup_file_version: pft$backup_file_version;
         p_file_group_record: {input} ^pft$info_record;
         family_location: pft$family_location;
         path: pft$complete_path;
         ownership: pft$ownership;
         permit_level: pft$permit_level;
         selection_criteria: put$selection_criteria;
         cycle_damage_symptoms: fst$cycle_damage_symptoms;
         restore_archive_information: boolean;
         restore_media: boolean;
         replace_rem_media_fmd: boolean;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_file_object: {output^} ^pft$physical_object;
     VAR audit_restorations: {i/o} boolean;
     VAR all_permits_restored: boolean;
     VAR p_auditable_permits: ^pft$auditable_permits;
     VAR cycle_count: pft$cycle_count;
     VAR cycles_media_restored: pft$cycle_count;
     VAR p_auditable_cycles: ^pft$auditable_cycles;
     VAR status: ost$status);

    VAR
      cycle_index: pft$cycle_index,
      cycle_list_locator: pft$cycle_list_locator,
      cycle_restorations_audited: boolean,
      file_entry: pft$object_entry,
      log_list_locator: pft$log_list_locator,
      p_cycle_array_version_1: ^pft$cycle_array,
      p_cycle_array_version_2: ^pft$cycle_array_version_2,
      p_file_description: ^pft$file_description,
      permit_list_locator: pft$permit_list_locator,
      permit_restorations_audited: boolean;

    initialize_file_object (path [UPPERBOUND (path)], file_entry);

    pfp$find_file_description (p_file_group_record, p_file_description, status);
    IF status.normal THEN
      file_entry.charge_id := p_file_description^.charge_id;
      file_entry.password := p_file_description^.password;
      file_entry.logging_selection := p_file_description^.logging_selection;

      put_permit_array (p_file_group_record, family_location, path, sfc$afsot_file, ownership, permit_level,
            audit_restorations, p_catalog_file, permit_list_locator, all_permits_restored,
            permit_restorations_audited, p_auditable_permits, status);
      IF status.normal THEN
        file_entry.permit_list_locator := permit_list_locator;

        put_log_array (p_file_group_record, p_catalog_file, log_list_locator, status);
        IF status.normal THEN
          file_entry.log_list_locator := log_list_locator;

          IF backup_file_version = pfc$backup_file_version_2 THEN
            pfp$find_cycle_array_version_2 (p_file_group_record, p_cycle_array_version_2, status);
            IF status.normal AND (p_cycle_array_version_2 = NIL) THEN
              osp$set_status_condition (pfe$unknown_cycle_array, status);
            IFEND;
          ELSE { backup_file_version = pfc$backup_file_version_1 }
            pfp$find_cycle_array (p_file_group_record, p_cycle_array_version_1, status);
            IF status.normal THEN
              IF p_cycle_array_version_1 = NIL THEN
                osp$set_status_condition (pfe$unknown_cycle_array, status);
              ELSE
                PUSH p_cycle_array_version_2: [1 .. UPPERBOUND (p_cycle_array_version_1^)];
                map_cycle_array_to_version_2 (p_cycle_array_version_1, p_cycle_array_version_2);
              IFEND;
            IFEND;
          IFEND;

          IF status.normal THEN
            put_cycle_array (p_file_group_record, p_cycle_array_version_2, family_location, path, ownership,
                  selection_criteria, cycle_damage_symptoms, restore_archive_information, audit_restorations,
                  p_catalog_file, cycle_list_locator, cycle_count, cycle_restorations_audited,
                  p_auditable_cycles, status);
          ELSE
            cycle_restorations_audited := FALSE;
          IFEND;
        ELSE
          cycle_restorations_audited := FALSE;
        IFEND;
      ELSE
        cycle_restorations_audited := FALSE;
      IFEND;
    ELSE
      permit_restorations_audited := FALSE;
      cycle_restorations_audited := FALSE;
    IFEND;

    IF status.normal AND (cycle_count <> 0) THEN
      file_entry.cycle_list_locator := cycle_list_locator;
      p_file_object^.object_entry := file_entry;
      pfp$compute_checksum (#LOC (file_entry), #SIZE (file_entry), p_file_object^.checksum);

      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_array_version_2^) DO
        p_cycle_array_version_2^ [cycle_index].retrieve_option := pfc$always_retrieve;
        p_cycle_array_version_2^ [cycle_index].site_backup_option := pfc$null_site_backup_option;
        p_cycle_array_version_2^ [cycle_index].site_archive_option := pfc$null_site_archive_option;
        p_cycle_array_version_2^ [cycle_index].site_release_option := pfc$null_site_release_option;
      FOREND;
      put_cycle_info (p_file_group_record, p_cycle_array_version_2, path, cycle_list_locator,
            restore_archive_information, restore_media, replace_rem_media_fmd, p_catalog_file,
            cycles_media_restored, status);
    ELSE
      audit_restorations := FALSE;

      IF cycle_restorations_audited THEN
        audit_cycle_deletions (path, ownership, p_catalog_file, cycle_list_locator);
      IFEND;
      p_auditable_cycles := NIL;

      IF permit_restorations_audited THEN
        audit_permit_deletions (path, sfc$afsot_file, ownership, p_catalog_file, permit_list_locator);
      IFEND;
      p_auditable_permits := NIL;

      free_cycle_list (^path, file_entry.cycle_list_locator, p_catalog_file);
      free_log_list (^path, file_entry.log_list_locator, p_catalog_file);
      free_permit_list (^path, p_file_object, file_entry.permit_list_locator, p_catalog_file);
    IFEND;
  PROCEND put_file_info;

?? TITLE := '  put_log_array', EJECT ??

  PROCEDURE put_log_array
    (    p_file_group_record: pft$p_info_record;
         p_catalog_file: pft$p_catalog_file;
     VAR log_list_locator: pft$log_list_locator;
     VAR status: ost$status);

    VAR
      free_physical_log: pft$physical_log,
      log_array_entry: pft$log_array_entry,
      log_count: integer,
      log_entry: pft$log_entry,
      log_index: pft$array_index,
      p_catalog_heap: pft$p_catalog_heap,
      p_log_array: pft$p_log_array,
      p_log_list: pft$p_log_list;

    pfp$find_log_array (p_file_group_record, p_log_array, status);
    IF status.normal THEN
      IF p_log_array = NIL THEN
        pfp$build_log_list_locator (NIL, NIL, log_list_locator);
      ELSE
        log_count := UPPERBOUND (p_log_array^);
        p_catalog_heap := ^p_catalog_file^.catalog_heap;
        pfp$allocate_log_list (log_count, p_catalog_heap, p_log_list, status);
        IF status.normal THEN
          FOR log_index := 1 TO log_count DO
            log_array_entry := p_log_array^ [log_index];
            log_entry.entry_type := pfc$normal_log_entry;
            log_entry.user_id := log_array_entry.user_id;
            log_entry.access_date_time := log_array_entry.access_date_time;
            log_entry.access_count := log_array_entry.access_count;
            log_entry.last_cycle := log_array_entry.last_cycle;
            p_log_list^ [log_index].log_entry := log_entry;
            pfp$compute_checksum (#LOC (log_entry), #SIZE (log_entry), p_log_list^ [log_index].checksum);
          FOREND;

          free_physical_log.log_entry.entry_type := pfc$free_log_entry;
          pfp$compute_checksum (#LOC (free_physical_log.log_entry), #SIZE (pft$log_entry),
                free_physical_log.checksum);

          FOR log_index := log_count + 1 TO UPPERBOUND (p_log_list^) DO
            p_log_list^ [log_index] := free_physical_log;
          FOREND;

          pfp$build_log_list_locator (p_log_list, p_catalog_file, log_list_locator);
        IFEND;
      IFEND;
    ELSE
      IF status.condition = pfe$nil_pointer THEN
        status.normal := TRUE;
        pfp$build_log_list_locator (NIL, NIL, log_list_locator);
      IFEND;
    IFEND;
  PROCEND put_log_array;

?? TITLE := '  put_new_cycles_media', EJECT ??

  PROCEDURE put_new_cycles_media
    (    backup_file_version: pft$backup_file_version;
         p_file_group: {input} ^pft$info_record;
         path: pft$complete_path;
         ownership: pft$ownership;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_file_object: {i^/o^} ^pft$physical_object;
     VAR cycles_created: pft$cycle_count;
     VAR cycles_media_restored: pft$cycle_count;
     VAR status: ost$status);

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      cycle_entry: pft$cycle_entry,
      cycle_index: pft$array_index,
      cycle_selector: pft$cycle_selector,
      media_restored: boolean,
      p_archive_info: ^pft$info,
      p_archive_info_record: ^pft$info_record,
      p_cycle: ^pft$physical_cycle,
      p_cycle_array_extended_record: ^pft$info_record,
      p_cycle_array_version_1: ^pft$cycle_array,
      p_cycle_array_version_2: ^pft$cycle_array_version_2,
      p_cycle_directory_array: ^pft$cycle_directory_array,
      p_cycle_info_extended_body: ^pft$info,
      p_cycle_info_record: ^pft$info_record,
      p_cycle_list: ^pft$cycle_list,
      pf_device_class: pft$device_class;

    cycles_created := 0;
    cycles_media_restored := 0;

    IF backup_file_version = pfc$backup_file_version_2 THEN
      pfp$find_cycle_array_version_2 (p_file_group, p_cycle_array_version_2, status);
      IF status.normal AND (p_cycle_array_version_2 = NIL) THEN
        osp$set_status_condition (pfe$unknown_cycle_array, status);
      IFEND;
    ELSE { backup_file_version = pfc$backup_file_version_1 }
      pfp$find_cycle_array (p_file_group, p_cycle_array_version_1, status);
      IF status.normal AND (p_cycle_array_version_1 = NIL) THEN
        osp$set_status_condition (pfe$unknown_cycle_array, status);
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$find_cycle_array_extended (p_file_group, p_cycle_array_extended_record, status);
    IFEND;

    IF status.normal THEN
      pfp$find_cycle_directory (p_cycle_array_extended_record, p_cycle_directory_array, status);

      IF status.normal AND (p_cycle_directory_array <> NIL) THEN
        IF backup_file_version = pfc$backup_file_version_1 THEN
          PUSH p_cycle_array_version_2: [1 .. UPPERBOUND (p_cycle_array_version_1^)];
          map_cycle_array_to_version_2 (p_cycle_array_version_1, p_cycle_array_version_2);
        IFEND;

        pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
              p_cycle_list);
        cycle_selector.cycle_option := pfc$specific_cycle;

        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_array_version_2^) DO
          pfp$locate_specific_cycle (p_cycle_list, p_cycle_array_version_2^ [cycle_index].cycle_number,
                p_cycle);

          IF p_cycle = NIL THEN
            cycle_selector.cycle_number := p_cycle_array_version_2^ [cycle_index].cycle_number;
            pfp$convert_device_class_to_pf (p_cycle_array_version_2^ [cycle_index].device_class,
                  pf_device_class);
            initialize_cycle_entry (cycle_selector.cycle_number, pf_device_class,
                  p_cycle_array_version_2^ [cycle_index].cycle_statistics,
                  p_cycle_array_version_2^ [cycle_index].data_modification_date_time,
                  p_cycle_array_version_2^ [cycle_index].expiration_date_time,
                  $fst$cycle_damage_symptoms [fsc$respf_modification_mismatch, fsc$parent_catalog_restored],
                  p_cycle_array_version_2^ [cycle_index].shared_queue_info, pfc$always_retrieve,
                  pfc$null_site_backup_option, pfc$null_site_archive_option, pfc$null_site_release_option,
                  cycle_entry);
            add_cycle_entry (^path, cycle_entry, p_file_object, p_catalog_file, status);

            IF NOT status.normal THEN
              IF avp$security_option_active (avc$vso_security_audit) THEN
                audit_information.audited_operation := sfc$ao_fs_create_object;
                audited_object.variant_path.complete_path := TRUE;
                audited_object.variant_path.p_complete_path := ^path;
                audited_object.object_type := sfc$afsot_cycle;
                audited_object.cycle_selector_p := ^cycle_selector;
                audited_object.device_class := p_cycle_array_version_2^ [cycle_index].device_class;
                audit_information.create_fs_object.object_id_p := ^audited_object;
                audit_information.create_fs_object.ownership := ownership;
                sfp$emit_audit_statistic (audit_information, status);
              IFEND;
              RETURN; {----->
            IFEND;

            cycles_created := cycles_created + 1;
            pfp$find_direct_info_record (^p_cycle_array_extended_record^.body,
                  p_cycle_directory_array^ [cycle_index].info_offset, p_cycle_info_record, status);
            IF status.normal THEN
              {
              { This code takes advantage of the fact that the cycle list in
              { the catalog and both the cycle array and the cycle array
              { extended info on the backup file are in the same order.
              {
              put_cycle_media_info (^path, p_cycle_array_version_2^ [cycle_index],
                    p_cycle_directory_array^ [cycle_index], p_cycle_info_record, {restore_media} TRUE,
                    TRUE {replace_rem_media_fmd}, p_catalog_file, p_cycle_list^ [cycle_index], media_restored,
                    status);
            IFEND;

            IF avp$security_option_active (avc$vso_security_audit) THEN
              audit_information.audited_operation := sfc$ao_fs_create_object;
              audited_object.variant_path.complete_path := TRUE;
              audited_object.variant_path.p_complete_path := ^path;
              audited_object.object_type := sfc$afsot_cycle;
              audited_object.cycle_selector_p := ^cycle_selector;
              audited_object.device_class := p_cycle_array_version_2^ [cycle_index].device_class;
              audit_information.create_fs_object.object_id_p := ^audited_object;
              audit_information.create_fs_object.ownership := ownership;
              sfp$emit_audit_statistic (audit_information, status);
            IFEND;

            IF status.normal THEN
              IF media_restored THEN
                cycles_media_restored := cycles_media_restored + 1;
              IFEND;

              put_cycle_archive_info (p_catalog_file, p_cycle_list, cycle_selector, path, p_cycle_info_record,
                    status);
            IFEND;

            IF NOT status.normal THEN
              RETURN; {----->
            IFEND;
          IFEND;
        FOREND;
      IFEND;
    IFEND;
  PROCEND put_new_cycles_media;

?? TITLE := '  put_permit_array', EJECT ??

  PROCEDURE put_permit_array
    (    p_file_group_record: {input} ^pft$info_record;
         family_location: pft$family_location;
         path: pft$complete_path;
         object_type: sft$audited_fs_object_type;
         ownership: pft$ownership;
         permit_level: pft$permit_level;
         audit_permit_restorations: boolean;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR permit_list_locator: pft$permit_list_locator;
     VAR all_permits_restored: boolean;
     VAR permit_restorations_audited: boolean;
     VAR p_auditable_permits: ^pft$auditable_permits;
     VAR status: ost$status);

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      free_physical_permit: pft$physical_permit,
      p_catalog_heap: ^pft$catalog_heap,
      p_permit_array: ^pft$permit_array,
      p_permit_list: ^pft$permit_list,
      permit_count: pft$permit_count,
      permit_entry: pft$permit_entry,
      permit_index: pft$array_index;

    all_permits_restored := TRUE;

    pfp$find_permit_array (p_file_group_record, p_permit_array, status);
    IF status.normal THEN
      IF p_permit_array = NIL THEN
        permit_restorations_audited := FALSE;
        p_auditable_permits := NIL;
        pfp$build_permit_list_locator ({p_permit_list} NIL, p_catalog_file, permit_list_locator);
      ELSE
        permit_count := UPPERBOUND (p_permit_array^);
        p_catalog_heap := ^p_catalog_file^.catalog_heap;
        pfp$allocate_permit_list (permit_count, p_catalog_heap, p_permit_list, status);

        IF status.normal THEN
          free_physical_permit.permit_entry.entry_type := pfc$free_permit_entry;
          pfp$compute_checksum (#LOC (free_physical_permit.permit_entry), #SIZE (pft$permit_entry),
                free_physical_permit.checksum);

          IF audit_permit_restorations AND (family_location = pfc$local_mainframe) THEN
            audit_information.audited_operation := sfc$ao_fs_create_permit;
            audited_object.variant_path.complete_path := TRUE;
            audited_object.variant_path.p_complete_path := ^path;
            audited_object.object_type := object_type;
            audit_information.create_fs_permit.object_id_p := ^audited_object;
            audit_information.create_fs_permit.ownership := ownership;
            permit_restorations_audited := TRUE;
          ELSE
            permit_restorations_audited := FALSE;
          IFEND;

          FOR permit_index := 1 TO permit_count DO
            IF pfv$system_administrator OR pfv$family_administrator THEN
              status.normal := TRUE;
            ELSE
              pfp$check_group_by_permit_level (permit_level, p_permit_array^ [permit_index].group, status);
            IFEND;

            IF status.normal THEN
              permit_entry.entry_type := pfc$normal_permit_entry;
              permit_entry.group := p_permit_array^ [permit_index].group;
              permit_entry.usage_permissions := p_permit_array^ [permit_index].usage_permissions;
              permit_entry.share_requirements := p_permit_array^ [permit_index].share_requirements;
              permit_entry.application_info := p_permit_array^ [permit_index].application_info;
              p_permit_list^ [permit_index].permit_entry := permit_entry;
              pfp$compute_checksum (#LOC (permit_entry), #SIZE (permit_entry),
                    p_permit_list^ [permit_index].checksum);
            ELSE
              p_permit_list^ [permit_index] := free_physical_permit;
              all_permits_restored := FALSE;
            IFEND;

            IF audit_permit_restorations THEN
              IF family_location = pfc$local_mainframe THEN
                audit_information.create_fs_permit.group_p := ^p_permit_array^ [permit_index].group;
                audit_information.create_fs_permit.permit_selections_p :=
                      ^p_permit_array^ [permit_index].usage_permissions;
                sfp$emit_audit_statistic (audit_information, status);
              ELSE
                p_auditable_permits^ [permit_count].group := p_permit_array^ [permit_index].group;
                p_auditable_permits^ [permit_count].permit_selections :=
                      p_permit_array^ [permit_index].usage_permissions;
                IF status.normal THEN
                  p_auditable_permits^ [permit_count].normal_status := TRUE;
                ELSE
                  p_auditable_permits^ [permit_count].normal_status := FALSE;
                  p_auditable_permits^ [permit_count].condition := status.condition;
                IFEND;
              IFEND;
            IFEND;
          FOREND;

          FOR permit_index := permit_count + 1 TO UPPERBOUND (p_permit_list^) DO
            p_permit_list^ [permit_index] := free_physical_permit;
          FOREND;

          pfp$build_permit_list_locator (p_permit_list, p_catalog_file, permit_list_locator);
          status.normal := TRUE;
        ELSE
          permit_restorations_audited := FALSE;
          p_auditable_permits := NIL;
        IFEND;
      IFEND;
    ELSE
      permit_restorations_audited := FALSE;
      p_auditable_permits := NIL;
      IF status.condition = pfe$nil_pointer THEN
        pfp$build_permit_list_locator ({p_permit_list} NIL, p_catalog_file, permit_list_locator);
        status.normal := TRUE;
      IFEND;
    IFEND;
  PROCEND put_permit_array;

?? TITLE := '  recreate_catalog_entry', EJECT ??
{ PURPOSE:
{   This procedure recreates the catalog entry and stores the file media
{   descriptor from the backup.  The files in the catalog need not be marked as
{   damaged, as this catalog is the current one on the disk.

  PROCEDURE recreate_catalog_entry
    (    p_catalog_group: {input} ^pft$info_record;
         path: pft$complete_path;
         ownership: pft$ownership;
         p_catalog_media_description: {input^} ^pft$catalog_media_description;
         p_backup_catalog_fmd: {input^} ^SEQ ( * );
         p_parent_catalog_file: {i^/o^} ^pft$catalog_file;
         p_catalog_object: {output^} ^pft$physical_object;
     VAR status: ost$status);

    VAR
      all_permits_restored: boolean,
      audit_permit_restorations: boolean,
      p_auditable_permits: ^pft$auditable_permits,
      p_catalog_description: pft$p_catalog_description,
      p_catalog_fmd: pft$p_physical_fmd,
      permit_list_locator: pft$permit_list_locator,
      permit_restorations_audited: boolean;

    pfp$find_catalog_description (p_catalog_group, p_catalog_description, status);

    IF status.normal THEN
      audit_permit_restorations := avp$security_option_active (avc$vso_security_audit);
      p_auditable_permits := NIL;
      put_permit_array (p_catalog_group, pfc$local_mainframe, path, sfc$afsot_catalog, ownership,
            pfc$pl_public, audit_permit_restorations, p_parent_catalog_file, permit_list_locator,
            all_permits_restored, permit_restorations_audited, p_auditable_permits, status);
    IFEND;

    IF status.normal THEN
      ALLOCATE p_catalog_fmd: [[REP #SIZE (p_backup_catalog_fmd^) OF cell]] IN
            p_parent_catalog_file^.catalog_heap;
      IF p_catalog_fmd = NIL THEN
        IF permit_restorations_audited THEN
          audit_permit_deletions (path, sfc$afsot_catalog, ownership, p_parent_catalog_file,
                permit_list_locator);
        IFEND;
        free_permit_list (^path, p_catalog_object, permit_list_locator, p_parent_catalog_file);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'catalog fmd', status);
      IFEND;
    IFEND;

    IF status.normal THEN
      p_catalog_object^.object_entry.external_object_name := path [UPPERBOUND (path)];
      p_catalog_object^.object_entry.internal_object_name := p_catalog_media_description^.internal_name;
      p_catalog_object^.object_entry.permit_list_locator := permit_list_locator;
      p_catalog_object^.object_entry.charge_id := p_catalog_description^.charge_id;
      p_catalog_object^.object_entry.reserved_object_entry_space := pfv$null_object_entry_space;
      p_catalog_object^.object_entry.object_type := pfc$catalog_object;
      p_catalog_object^.object_entry.catalog_object_locator.catalog_type := pfc$external_catalog;

      p_catalog_fmd^.fmd := p_backup_catalog_fmd^;
      pfp$compute_checksum (#LOC (p_catalog_fmd^.fmd), #SIZE (p_catalog_fmd^.fmd), p_catalog_fmd^.checksum);
      pfp$build_fmd_locator (p_catalog_fmd, p_parent_catalog_file,
            p_catalog_object^.object_entry.catalog_object_locator.fmd_locator);

      p_catalog_object^.object_entry.catalog_object_locator.global_file_name :=
            p_catalog_media_description^.global_file_name;
      p_catalog_object^.object_entry.catalog_recreated_by_restore := FALSE;
      p_catalog_object^.object_entry.reserved_catalog_entry_space := pfv$null_catalog_entry_space;

      pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (p_catalog_object^.object_entry),
            p_catalog_object^.checksum);
    IFEND;
  PROCEND recreate_catalog_entry;

?? TITLE := '  recreate_catalog_media', EJECT ??
{ PURPOSE:
{   This procedure recreates the catalog, but leaves the catalog entry
{   (permits and charge) as is.
{
{ DESIGN:
{   The catalog contents will be reconstructed from files and subcatalogs yet
{   to be found on the backup file.  The file media descriptor of this catalog
{   from the backup file is not used, because it is not valid.  If the catalog
{   has not moved via pf recovery, then the fmd on the backup file describes a
{   catalog on an inactive device.  If the catalog has moved via pf recovery,
{   then the fmd on the backup file describes a catalog deleted via pf
{   recovery.  An attempt could be made to reconcile the fmd from the backup
{   file and, if it reconciles, to destroy it.

  PROCEDURE recreate_catalog_media
    (    path: pft$complete_path;
         authority: pft$authority;
         p_parent_catalog_file: {i^/o^} ^pft$catalog_file;
         p_catalog_object: {i^/o^} ^pft$physical_object;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      local_status: ost$status,
      new_catalog_locator: pft$catalog_locator,
      p_new_physical_fmd: pft$p_physical_fmd;

    pfp$create_catalog (path, {mass storage request} NIL, authority, {lock_catalog} TRUE, new_catalog_locator,
          status);
    IF status.normal THEN
      pfp$record_dm_file_parameters (^path, {p_cycle_number} NIL, new_catalog_locator.system_file_id,
            rmc$mass_storage_device, {p_removable_media_req_info} NIL, {p_volume_list} NIL,
            ^p_parent_catalog_file^.catalog_heap, p_new_physical_fmd, status);
      IF status.normal THEN
        pfp$build_fmd_locator (p_new_physical_fmd, p_parent_catalog_file,
              p_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
        p_catalog_object^.object_entry.catalog_object_locator.global_file_name :=
              new_catalog_locator.global_file_name;
        p_catalog_object^.object_entry.internal_object_name := new_catalog_locator.internal_catalog_name;
        p_catalog_object^.object_entry.catalog_recreated_by_restore := TRUE;
        pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (p_catalog_object^.object_entry),
              p_catalog_object^.checksum);
      ELSE
        pfp$destroy_catalog (new_catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;

    IF avp$security_option_active (avc$vso_security_audit) THEN
      audit_information.audited_operation := sfc$ao_fs_create_object;
      audited_object.variant_path.complete_path := TRUE;
      audited_object.variant_path.p_complete_path := ^path;
      audited_object.object_type := sfc$afsot_catalog;
      audit_information.create_fs_object.object_id_p := ^audited_object;
      audit_information.create_fs_object.ownership := authority.ownership;
      sfp$emit_audit_statistic (audit_information, status);
    IFEND;

    IF status.normal THEN
      pfp$return_catalog (new_catalog_locator, status);
    IFEND;
  PROCEND recreate_catalog_media;

?? OLDTITLE, SKIP := 2 ??
MODEND pfm$r2_put_info;
