?? RIGHT := 110 ??
?? TITLE := 'NOS/VE Permanent Files : Information Retrieval' ??
MODULE pfm$r2_get_info;

{ PURPOSE:
{   This module contains the procedures to get information about catalogs,
{   files, and cycles, and about their permits and log entries.

?? NEWTITLE := '  Global Declarations Referenced by this module.', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc osd$cybil_structure_definitions
*copyc pud$selection_criteria
*copyc ame$ring_validation_errors
*copyc pfe$error_condition_codes
*copyc pfe$external_archive_conditions
*copyc pfe$internal_error_conditions
*copyc dmt$error_condition_codes
*copyc dmt$stored_fmd_size
*copyc pft$catalog_info_selections
*copyc pft$catalog_media_description
*copyc pft$cycle_reservation_criteria
*copyc pft$file_media_description
*copyc pft$internal_cycle_path
*copyc pft$p_amd
*copyc pft$p_archive
*copyc pft$p_info
*copyc pft$p_object_list
*copyc pft$p_table_info
*copyc pft$reserved_cycles
*copyc put$include_volumes_option
*copyc pfc$average_share_history
*copyc pfc$maximum_pf_length
?? POP ??
*copyc avp$security_option_active
*copyc dmp$attach_file
*copyc dmp$delete_file_descriptor
*copyc dmp$get_stored_fmd_header_info
*copyc dmp$get_stored_fmd_volume_list
*copyc fmf$ring_attributes_valid
*copyc fsp$expand_file_label
*copyc i#current_sequence_position
*copyc i#move
*copyc mmp$get_segment_length
*copyc mmp$lock_catalog_segment
*copyc mmp$unlock_segment
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$file_access_condition
*copyc osp$recoverable_system_error
*copyc osp$set_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osv$catalog_name_security
*copyc osv$task_shared_heap
*copyc pfp$access_object
*copyc pfp$build_amd_pointer
*copyc pfp$build_archive_list_pointer
*copyc pfp$build_cycle_list_pointer
*copyc pfp$build_file_label_pointer
*copyc pfp$build_fmd_pointer
*copyc pfp$build_log_list_pointer
*copyc pfp$build_permit_list_pointer
*copyc pfp$check_cycle_busy
*copyc pfp$compute_checksum
*copyc pfp$convert_device_class_to_rm
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$cycle_attached_for_write
*copyc pfp$detach_permanent_file
*copyc pfp$detach_reserved_cycles
*copyc pfp$extract_permit_entry
*copyc pfp$increment_usage_counts
*copyc pfp$get_authority
*copyc pfp$get_catalog
*copyc pfp$get_sorted_object_name_list
*copyc pfp$locate_cycle
*copyc pfp$locate_log_entry
*copyc pfp$log_ascii
*copyc pfp$log_path
*copyc pfp$process_unexpected_status
*copyc pfp$reconcile_fmd
*copyc pfp$reduce_permits
*copyc pfp$release_locked_apfid
*copyc pfp$report_system_error
*copyc pfp$return_catalog
*copyc pfp$set_status_abnormal
*copyc pfp$shared_queue
*copyc pfp$validate_ownership
*copyc pfv$binary_catalog_search
*copyc pfv$locked_apfid
*copyc pfv$reserved_cycle_info
*copyc pfv$unlock_catalog_threshold
*copyc pmp$continue_to_cause
*copyc pmp$date_time_compare
*copyc pmp$get_pseudo_mainframe_id
*copyc sfp$emit_audit_statistic
*copyc stp$get_pf_root
*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
    read_share_selections: [oss$job_paged_literal, READ] pft$share_selections := [pfc$read],
    read_usage_selections: [oss$job_paged_literal, READ] pft$usage_selections := [pfc$read],
    reserved_cycle_array_entry_sp: [oss$job_paged_literal, READ] array [1 .. 46] of boolean :=
          [REP 46 OF FALSE],
    stale_data_mod_date_time: [oss$job_paged_literal, READ] ost$date_time := [0, 1, 1, 0, 0, 0, 0];

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_catalog_segment
    (    path: pft$complete_path;
     VAR p_info: pft$p_table_info;
     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_get_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_cell_array: ^array [1 .. * ] of cell,
      p_internal_path: ^pft$internal_path,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    VAR
      condition: pmt$condition,
      psa: ^ost$stack_frame_save_area;


    syp$push_inhibit_job_recovery;

  /get_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 /get_catalog_segment/;
      IFEND;

      pfp$validate_ownership (authority, path, status);
      IF NOT status.normal THEN
        EXIT /get_catalog_segment/;
      IFEND;

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

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

      mmp$get_segment_length (catalog_locator.p_catalog_file, validation_ring_number,
            catalog_segment_length, status);
      IF status.normal THEN
        NEXT p_cell_array: [1 .. catalog_segment_length] IN p_info;
        IF p_cell_array = NIL THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
        ELSE
          i#move (catalog_locator.p_catalog_file, p_cell_array, catalog_segment_length);
        IFEND;
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    END /get_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_get_catalog_segment;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_family_info
    (    set_name: stt$set_name;
         catalog_info_selections: pft$catalog_info_selections;
     VAR p_info: {i/o} pft$p_info;
     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_get_family_info;
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      internal_path: array [1 .. pfc$set_path_index] of pft$internal_name,
      local_status: ost$status,
      p_record_body: ^pft$info,
      path: array [1 .. pfc$set_path_index] of pft$name,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /get_family_info/
    BEGIN
      catalog_active := FALSE;
      path [pfc$set_path_index] := set_name;
      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 /get_family_info/;
      IFEND;

      pfp$get_catalog (path, pfc$read_access, authority, internal_path, charge_id, permit_entry,
            catalog_locator, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /get_family_info/;
      IFEND;

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

      locate_info_record_body (p_info, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_family_info/;
      IFEND;


      get_multi_object_info (^path, authority, permit_entry, catalog_locator.object_list_descriptor,
            catalog_info_selections, $pft$file_info_selections [], {p_cycle_reservation_criteria} NIL,
            catalog_locator.p_catalog_file, catalog_locator, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_family_info/;
      IFEND;


      build_info_record (pfc$family_info_record, i#current_sequence_position (p_record_body), p_info,
            status);
      IF NOT status.normal THEN
        EXIT /get_family_info/;
      IFEND;
    END /get_family_info/;

    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_get_family_info;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_item_info
    (    path: pft$complete_path;
         system_privilege: boolean;
         group: pft$group;
         catalog_info_selections: pft$catalog_info_selections;
         file_info_selections: pft$file_info_selections;
     VAR p_info: {i/o} pft$p_info;
     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_get_item_info;
    PROCEND initiate_non_local_exit;

    VAR
      access_kind: pft$access_kind,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      local_status: ost$status,
      object_count: pft$object_count,
      p_internal_path: ^pft$internal_path,
      p_physical_object: ^pft$physical_object,
      p_qualified_object_list: ^pft$object_list,
      p_record_body: ^pft$info,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

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

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

      IF catalog_info_selections <> $pft$catalog_info_selections [] THEN
        valid_objects := $pft$object_selections [pfc$catalog_object];
      ELSE
        valid_objects := $pft$object_selections [];
      IFEND;

      IF file_info_selections <> $pft$file_info_selections [] THEN
        valid_objects := valid_objects + $pft$object_selections [pfc$file_object];

        IF pfc$cycle_media_descriptor IN file_info_selections THEN
          access_kind := pfc$write_access;
        ELSE
          access_kind := pfc$read_access;
        IFEND;
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, access_kind, authority, valid_objects, charge_id,
            catalog_locator, p_physical_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /get_item_info/;
      IFEND;

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

      IF (pfc$catalog_object IN valid_objects) AND osv$catalog_name_security AND
            (authority.ownership = $pft$ownership []) AND ((permit_entry.entry_type =
            pfc$free_permit_entry) OR (permit_entry.usage_permissions = $pft$permit_selections [])) AND
            (p_physical_object^.object_entry.object_type = pfc$catalog_object) THEN
        pfp$return_catalog (catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);

        pfp$get_catalog (path, pfc$read_access, authority, p_internal_path^, charge_id, permit_entry,
              catalog_locator, status);
        IF status.normal THEN
          IF catalog_locator.object_list_descriptor.p_object_list <> NIL THEN
            PUSH p_qualified_object_list: [1 .. UPPERBOUND (catalog_locator.object_list_descriptor.
                  p_object_list^)];
          IFEND;
          build_qualified_object_list (catalog_locator.object_list_descriptor,
                $pft$object_selections [pfc$catalog_object, pfc$file_object],
                catalog_locator.p_catalog_file, authority, permit_entry, object_count,
                p_qualified_object_list);

          IF object_count = 0 THEN
            variant_path.complete_path := TRUE;
            variant_path.p_complete_path := ^path;
            CASE UPPERBOUND (path) OF
            = pfc$family_path_index =
              pfp$set_status_abnormal (variant_path, pfe$unknown_family, status);
            = pfc$master_catalog_path_index =
              pfp$set_status_abnormal (variant_path, pfe$unknown_master_catalog, status);
            ELSE
              pfp$set_status_abnormal (variant_path, pfe$unknown_last_subcatalog, status);
            CASEND;
          IFEND;

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

        IF status.normal THEN
          pfp$access_object (path, access_kind, authority, valid_objects, charge_id,
                catalog_locator, p_physical_object, p_internal_path^, permit_entry, status);
        IFEND;
      IFEND;
      IF NOT status.normal THEN
        EXIT /get_item_info/;
      IFEND;

      locate_info_record_body (p_info, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_item_info/;
      IFEND;

      get_object_info (path, authority, p_physical_object^.object_entry, catalog_info_selections,
            file_info_selections, catalog_locator.p_catalog_file, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_item_info/;
      IFEND;

      build_info_record (pfc$item_info_record, i#current_sequence_position (p_record_body), p_info, status);
    END /get_item_info/;

    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_get_item_info;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_master_catalog_info
    (    path: pft$complete_path;
         catalog_info_selections: pft$catalog_info_selections;
     VAR p_info: {i/o} pft$p_info;
     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_get_master_catalog_info;
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      charge_id: pft$charge_id,
      local_status: ost$status,
      catalog_locator: pft$catalog_locator,
      p_internal_path: ^pft$internal_path,
      p_record_body: ^pft$info,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /get_master_catalog_info/
    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 /get_master_catalog_info/;
      IFEND;

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


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

      locate_info_record_body (p_info, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_master_catalog_info/;
      IFEND;

      get_multi_object_info (^path, authority, permit_entry, catalog_locator.object_list_descriptor,
            catalog_info_selections, $pft$file_info_selections [], {p_cycle_reservation_criteria} NIL,
            catalog_locator.p_catalog_file, catalog_locator, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_master_catalog_info/;
      IFEND;

      build_info_record (pfc$master_catalog_info_record, i#current_sequence_position (p_record_body),
            p_info, status);
      IF NOT status.normal THEN
        EXIT /get_master_catalog_info/;
      IFEND;
    END /get_master_catalog_info/;

    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_get_master_catalog_info;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_multi_item_info
    (    path: pft$complete_path;
         system_privilege: boolean;
         group: pft$group;
         catalog_info_selections: pft$catalog_info_selections;
         file_info_selections: pft$file_info_selections;
         p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
     VAR p_info: {i/o} pft$p_info;
     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_get_multi_item_info;
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      local_status: ost$status,
      p_internal_path: ^pft$internal_path,
      p_record_body: ^pft$info,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

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

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

      IF (p_cycle_reservation_criteria <> NIL) AND (pfv$reserved_cycle_info.p_catalog_path <> NIL) THEN
        {
        { This should never happen but just in case!
        {
        pfp$detach_reserved_cycles (status);
        IF NOT status.normal THEN
          EXIT /get_multi_item_info/;
        IFEND;
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      IF (pfc$cycle_media_descriptor IN file_info_selections) OR (p_cycle_reservation_criteria <> NIL) THEN
        pfp$get_catalog (path, pfc$write_access, authority, p_internal_path^, charge_id, permit_entry,
              catalog_locator, status);
      ELSE
        pfp$get_catalog (path, pfc$read_access, authority, p_internal_path^, charge_id, permit_entry,
              catalog_locator, status);
      IFEND;
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /get_multi_item_info/;
      IFEND;

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

      locate_info_record_body (p_info, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_multi_item_info/;
      IFEND;

      IF p_cycle_reservation_criteria <> NIL THEN
        create_reserved_cycle_info (path, status);
        IF NOT status.normal THEN
          EXIT /get_multi_item_info/;
        IFEND;
      IFEND;

      get_multi_object_info (^path, authority, permit_entry, catalog_locator.object_list_descriptor,
            catalog_info_selections, file_info_selections, p_cycle_reservation_criteria,
            catalog_locator.p_catalog_file, catalog_locator, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_multi_item_info/;
      IFEND;

      build_info_record (pfc$multi_item_info_record, i#current_sequence_position (p_record_body), p_info,
            status);
    END /get_multi_item_info/;

    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_get_multi_item_info;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_stored_fmd
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
     VAR catalog: boolean;
     VAR catalog_recreated: boolean;
     VAR global_file_name: ost$binary_unique_name;
     VAR stored_fmd: dmt$stored_fmd;
     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_get_stored_fmd;
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      fmd_locator: pft$fmd_locator,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_cycle_list: ^pft$cycle_list,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_internal_path: ^pft$internal_path,
      p_physical_cycle: ^pft$physical_cycle,
      p_physical_fmd: ^pft$physical_fmd,
      p_physical_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

  /get_stored_fmd/
    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 /get_stored_fmd/;
      IFEND;

      pfp$validate_ownership (authority, path, status);
      IF NOT status.normal THEN
        EXIT /get_stored_fmd/;
      IFEND;

      IF UPPERBOUND (path) = pfc$family_path_index THEN
        get_root_stored_fmd (path, catalog, catalog_recreated, global_file_name, stored_fmd, status);
        EXIT /get_stored_fmd/;
      IFEND;

      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, $pft$object_selections
            [pfc$catalog_object, pfc$file_object], parent_charge_id, catalog_locator, p_physical_object,
            p_internal_cycle_path^.path, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /get_stored_fmd/;
      IFEND;

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

      IF p_physical_object^.object_entry.object_type = pfc$file_object THEN
        catalog := FALSE;
        pfp$build_cycle_list_pointer (p_physical_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 NOT status.normal THEN
          EXIT /get_stored_fmd/;
        IFEND;
        fmd_locator := p_physical_cycle^.cycle_entry.fmd_locator;
      ELSEIF p_physical_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
        catalog := TRUE;
        catalog_recreated := p_physical_object^.object_entry.catalog_recreated_by_restore;
        fmd_locator := p_physical_object^.object_entry.catalog_object_locator.fmd_locator;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Internal_catalogs do not have an FMD.', status);
        EXIT /get_stored_fmd/;
      IFEND;

      pfp$build_fmd_pointer (fmd_locator, catalog_locator.p_catalog_file, p_physical_fmd);
      IF p_physical_fmd = NIL THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := ^path;
        pfp$set_status_abnormal (variant_path, pfe$undefined_data, status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              p_physical_cycle^.cycle_entry.cycle_number, radix, NOT include_radix, status);
      ELSEIF #SIZE (stored_fmd) <> #SIZE (p_physical_fmd^.fmd) THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, 'FMD size mismatch.',
              status);
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
      ELSE
        stored_fmd := p_physical_fmd^.fmd;
        IF p_physical_object^.object_entry.object_type = pfc$file_object THEN
          global_file_name := p_physical_cycle^.cycle_entry.internal_cycle_name;
        ELSE
          global_file_name := p_physical_object^.object_entry.catalog_object_locator.global_file_name;
        IFEND;
      IFEND;
    END /get_stored_fmd/;

    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_get_stored_fmd;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_stored_fmd_size
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
     VAR device_class: rmt$device_class;
     VAR global_file_name: ost$binary_unique_name;
     VAR fmd_size: dmt$stored_fmd_size;
     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_get_stored_fmd_size;
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      fmd_locator: pft$fmd_locator,
      local_status: ost$status,
      p_cycle_list: ^pft$cycle_list,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_internal_path: ^pft$internal_path,
      p_physical_cycle: ^pft$physical_cycle,
      p_physical_fmd: ^pft$physical_fmd,
      p_physical_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

  /get_stored_fmd_size/
    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 /get_stored_fmd_size/;
      IFEND;

      pfp$validate_ownership (authority, path, status);
      IF NOT status.normal THEN
        EXIT /get_stored_fmd_size/;
      IFEND;

      IF UPPERBOUND (path) = pfc$family_path_index THEN
        get_root_stored_fmd_size (path, device_class, global_file_name, fmd_size, status);
        EXIT /get_stored_fmd_size/;
      IFEND;

      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, $pft$object_selections
            [pfc$catalog_object, pfc$file_object], parent_charge_id, catalog_locator, p_physical_object,
            p_internal_cycle_path^.path, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /get_stored_fmd_size/;
      IFEND;

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

      IF p_physical_object^.object_entry.object_type = pfc$file_object THEN
        pfp$build_cycle_list_pointer (p_physical_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 NOT status.normal THEN
          EXIT /get_stored_fmd_size/;
        IFEND;
        fmd_locator := p_physical_cycle^.cycle_entry.fmd_locator;
      ELSEIF p_physical_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
        fmd_locator := p_physical_object^.object_entry.catalog_object_locator.fmd_locator;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Internal_catalogs do not have an FMD.', status);
        EXIT /get_stored_fmd_size/;
      IFEND;

      pfp$build_fmd_pointer (fmd_locator, catalog_locator.p_catalog_file, p_physical_fmd);
      IF p_physical_fmd = NIL THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := ^path;
        pfp$set_status_abnormal (variant_path, pfe$undefined_data, status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              p_physical_cycle^.cycle_entry.cycle_number, radix, NOT include_radix, status);
      ELSE
        IF p_physical_object^.object_entry.object_type = pfc$file_object THEN
          IF p_physical_cycle^.cycle_entry.device_information.device_class_defined THEN
            pfp$convert_device_class_to_rm (p_physical_cycle^.cycle_entry.device_information.device_class,
                  device_class);
          ELSE
            device_class := rmc$mass_storage_device;
          IFEND;
          global_file_name := p_physical_cycle^.cycle_entry.internal_cycle_name;
        ELSE
          device_class := rmc$mass_storage_device;
          global_file_name := p_physical_object^.object_entry.catalog_object_locator.global_file_name;
        IFEND;
        fmd_size := #SIZE (p_physical_fmd^.fmd);
      IFEND;
    END /get_stored_fmd_size/;

    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_get_stored_fmd_size;

?? TITLE := '  pfp$unlock_catalog_pages', EJECT ??
{
{  PURPOSE:
{    This interface is intended for use when a catalog is to remain open for
{    an extended period of time and many pages of the catalog are modified.
{    This interface will unlock and relock the catalog.  The effect of this
{    will be to allow all modified pages of the catalog to be written to disk.
{    When a catalog is very large and many of the pages are modified it is
{    possible to exhaust all memory resources with modified catalog pages
{    and cause the system to hang.  Reserve_cycles and detach_reserve_cycles
{    are two good examples of this condition.
{
  PROCEDURE [XDCL] pfp$unlock_catalog_pages
    (VAR catalog_locator: {i/o} pft$catalog_locator;
     VAR status: ost$status);

    IF catalog_locator.attached AND catalog_locator.open AND catalog_locator.locked THEN
      IF catalog_locator.flush_catalog_pages THEN
        mmp$unlock_segment (catalog_locator.p_catalog_file, mmc$lus_protected_write, osc$nowait, status);
      ELSE
        mmp$unlock_segment (catalog_locator.p_catalog_file, mmc$lus_none, osc$nowait, status);
      IFEND;
      catalog_locator.locked := FALSE;
      pfp$process_unexpected_status (status);
    ELSE
      RETURN;
    IFEND;

    IF status.normal THEN
      IF catalog_locator.access_kind = pfc$read_access THEN
        mmp$lock_catalog_segment (catalog_locator.p_catalog_file, mmc$lus_lock_for_read, osc$wait, status);
      ELSE
        mmp$lock_catalog_segment (catalog_locator.p_catalog_file, mmc$lus_lock_for_write, osc$wait, status);
      IFEND;

      catalog_locator.locked := status.normal;
      IF NOT status.normal THEN
        IF osp$file_access_condition (status) THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_volume_unavailable, '', status);
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      IFEND;
    IFEND;
  PROCEND pfp$unlock_catalog_pages;

?? TITLE := '  [INLINE] allocate_cycle_directory', EJECT ??

  PROCEDURE [INLINE] allocate_cycle_directory
    (    number_of_cycles: pft$cycle_count;
     VAR p_cycle_array_extended: {Input, Output} pft$p_info;
     VAR p_cycle_directory_array: pft$p_cycle_directory_array;
     VAR status: ost$status);

    VAR
      p_cycle_directory_body: pft$p_info;

    locate_info_record_body (p_cycle_array_extended, p_cycle_directory_body, status);
    IF status.normal THEN
      IF number_of_cycles > 0 THEN
        NEXT p_cycle_directory_array: [1 .. number_of_cycles] IN p_cycle_directory_body;
        IF p_cycle_directory_array = NIL THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, ' cycle directory ', status);
        IFEND;
      ELSE
        p_cycle_directory_array := NIL;
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$cycle_directory_record, i#current_sequence_position (p_cycle_directory_body),
              p_cycle_array_extended, status);
      IFEND;
    IFEND;
  PROCEND allocate_cycle_directory;

?? TITLE := '  allocate_directory_array', EJECT ??

  PROCEDURE allocate_directory_array (VAR p_info: pft$p_info;
        directory_size: integer;
    VAR p_directory_array: pft$p_directory_array;
    VAR status: ost$status);

    VAR
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      IF directory_size > 0 THEN
        NEXT p_directory_array: [1 .. directory_size] IN p_record_body;
        IF p_directory_array = NIL THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
        IFEND;
      ELSE
        p_directory_array := NIL;
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$directory_array_record, i#current_sequence_position (p_record_body), p_info,
              status);
      IFEND;
    IFEND;
  PROCEND allocate_directory_array;

?? TITLE := '  append_log_entry', EJECT ??

  PROCEDURE append_log_entry (log_entry: pft$log_entry;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      log_info: pft$log_array_entry,
      p_log_info: pft$p_log_array_entry;

    status.normal := TRUE;

    IF log_entry.entry_type = pfc$normal_log_entry THEN
      NEXT p_log_info IN p_info;
      IF p_log_info <> NIL THEN
        log_info.user_id := log_entry.user_id;
        log_info.access_date_time := log_entry.access_date_time;
        log_info.access_count := log_entry.access_count;
        log_info.last_cycle := log_entry.last_cycle;
        p_log_info^ := log_info;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    IFEND;
  PROCEND append_log_entry;

?? TITLE := '  append_permit_entry', EJECT ??

  PROCEDURE append_permit_entry (permit_entry: pft$permit_entry;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_permit_info: pft$p_permit_array_entry,
      permit_info: pft$permit_array_entry;

    status.normal := TRUE;

    IF permit_entry.entry_type = pfc$normal_permit_entry THEN
      NEXT p_permit_info IN p_info;
      IF p_permit_info <> NIL THEN
        permit_info.permit_type := pfc$direct_permit;
        permit_info.group := permit_entry.group;
        permit_info.usage_permissions := permit_entry.usage_permissions;
        permit_info.share_requirements := permit_entry.share_requirements;
        permit_info.application_info := permit_entry.application_info;
        p_permit_info^ := permit_info;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    IFEND;
  PROCEND append_permit_entry;

?? TITLE := '  audit_cycle_attachment', EJECT ??

  PROCEDURE audit_cycle_attachment
    (    p_complete_path: {input} ^pft$complete_path;
         cycle_number: fst$cycle_number;
         ownership: pft$ownership;
         audit_status: ost$status);

    VAR
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      cycle_selector: pft$cycle_selector,
      usage_selections: pft$usage_selections;

    audit_information.audited_operation := sfc$ao_fs_attach_file;
    audited_object.variant_path.complete_path := TRUE;
    audited_object.variant_path.p_complete_path := p_complete_path;
    audited_object.object_type := sfc$afsot_cycle;
    cycle_selector.cycle_option := pfc$specific_cycle;
    cycle_selector.cycle_number := cycle_number;
    audited_object.cycle_selector_p := ^cycle_selector;
    audited_object.device_class := rmc$mass_storage_device;
    audit_information.attach_file.object_id_p := ^audited_object;
    audit_information.attach_file.ownership := ownership;
    usage_selections := $pft$usage_selections [pfc$read];
    audit_information.attach_file.access_mode_p := ^usage_selections;
    sfp$emit_audit_statistic (audit_information, audit_status);
  PROCEND audit_cycle_attachment;

?? TITLE := '  build_info_record', EJECT ??

  PROCEDURE build_info_record (record_type: pft$info_record_type;
        body_size: pft$info_record_body_size;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      local_body_size: pft$info_record_body_size,
      p_info_record: pft$p_info_record;

    IF p_info <> NIL THEN
      IF body_size = 0 THEN
        local_body_size := 1;
      ELSE
        local_body_size := body_size;
      IFEND;

      NEXT p_info_record: [[REP local_body_size OF cell]] IN p_info;
      IF p_info_record <> NIL THEN
        p_info_record^.record_type := record_type;
        p_info_record^.body_size := local_body_size;
        status.normal := TRUE;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    ELSE
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
    IFEND;
  PROCEND build_info_record;

?? TITLE := '  build_qualified_object_list', EJECT ??

  PROCEDURE build_qualified_object_list
    (    object_list_descriptor: pft$object_list_descriptor;
         selected_objects: pft$object_selections;
         p_catalog_file: pft$p_catalog_file;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
     VAR object_count: pft$object_count;
     VAR p_qualified_object_list: pft$p_object_list);

    VAR
      max_object_name_index: pft$object_count,
      max_sorted_object_index: pft$object_count,
      object_index: pft$object_index,
      object_name_index: pft$object_index,
      object_qualified: boolean,
      p_object_list: ^pft$object_list,
      p_object_name_list: ^pft$object_name_list,
      sorted_object_index: pft$object_index;

    object_count := 0;
    p_object_list := object_list_descriptor.p_object_list;
    IF p_object_list = NIL THEN
      RETURN;
    IFEND;

    IF pfv$binary_catalog_search THEN
      max_sorted_object_index := object_list_descriptor.sorted_object_count;
      sorted_object_index := 1;
      object_name_index := 1;

      IF object_list_descriptor.sorted_object_count = 0 THEN
        PUSH p_object_name_list: [1 .. UPPERBOUND (p_object_list^)];
      ELSE
        PUSH p_object_name_list: [1 .. UPPERBOUND (p_object_list^) -
              object_list_descriptor.sorted_object_count];
      IFEND;

      pfp$get_sorted_object_name_list (object_list_descriptor, p_object_name_list, max_object_name_index);

      WHILE (sorted_object_index <= max_sorted_object_index) OR
            (object_name_index <= max_object_name_index) DO
        IF object_name_index > max_object_name_index THEN
          object_index := sorted_object_index;
          sorted_object_index := sorted_object_index + 1;
        ELSEIF sorted_object_index > max_sorted_object_index THEN
          object_index := p_object_name_list^ [object_name_index].object_index;
          object_name_index := object_name_index + 1;
        ELSEIF p_object_list^ [sorted_object_index].object_entry.external_object_name >
              p_object_name_list^ [object_name_index].object_name THEN
          object_index := p_object_name_list^ [object_name_index].object_index;
          object_name_index := object_name_index + 1;
        ELSE
          object_index := sorted_object_index;
          sorted_object_index := sorted_object_index + 1;
        IFEND;

        test_object_qualifications (p_object_list^ [object_index].object_entry, selected_objects,
              p_catalog_file, authority, permit_entry, object_qualified);
        IF object_qualified THEN
          object_count := object_count + 1;
          p_qualified_object_list^ [object_count] := p_object_list^ [object_index];
        IFEND;
      WHILEND;
    ELSE
      FOR object_index := 1 TO UPPERBOUND (p_object_list^) DO
        test_object_qualifications (p_object_list^ [object_index].object_entry, selected_objects,
              p_catalog_file, authority, permit_entry, object_qualified);
        IF object_qualified THEN
          object_count := object_count + 1;
          p_qualified_object_list^ [object_count] := p_object_list^ [object_index];
        IFEND;
      FOREND;
    IFEND;
  PROCEND build_qualified_object_list;

?? TITLE := '  check_file_attributes', EJECT ??

  PROCEDURE check_file_attributes
    (    usage_mode: pft$usage_selections;
         validation_ring: ost$valid_ring;
         p_cycle: {input} ^pft$physical_cycle;
         p_catalog_file: {input} ^pft$catalog_file;
     VAR cycle_included: boolean;
     VAR status: ost$status);

    TYPE
      file_organization_set = set of amt$file_organization;

    VAR
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      expanded_label: bat$static_label_attributes,
      p_physical_label: ^pft$physical_file_label;

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

    pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, p_catalog_file, p_physical_label);
    IF p_physical_label <> NIL THEN
      fsp$expand_file_label (^p_physical_label^.file_label, expanded_label,
            cycle_formerly_opened_info.cycle_previously_opened, status);
      IF NOT status.normal OR NOT cycle_formerly_opened_info.cycle_previously_opened THEN
        RETURN;
      IFEND;

      cycle_formerly_opened_info.ring_attributes := expanded_label.ring_attributes;
      cycle_formerly_opened_info.ring_attributes_source := expanded_label.ring_attributes_source;

      cycle_included := fmf$ring_attributes_valid (cycle_formerly_opened_info, usage_mode, validation_ring);
      IF NOT cycle_included THEN
        osp$set_status_abnormal (amc$access_method_id, ame$ring_validation_error, '', status);
        RETURN;
      IFEND;
      {
      { Determine if AAM file has selected a logging option of ENABLE_MEDIA_RECOVERY.
      {
      cycle_included := NOT (((expanded_label.file_organization_source <> amc$undefined_attribute) AND
            (expanded_label.file_organization IN $file_organization_set
            [amc$indexed_sequential, amc$direct_access, amc$system_key])) AND
            ((expanded_label.logging_options_source <> amc$undefined_attribute) AND
            (amc$enable_media_recovery IN expanded_label.logging_options)));
    IFEND;
  PROCEND check_file_attributes;

?? TITLE := '  check_if_access_included', EJECT ??

  PROCEDURE check_if_access_included
    (    selection_criteria: put$selection_criteria;
         cycle_array_entry: pft$cycle_array_entry_version_2;
     VAR cycle_included: boolean);

    VAR
      before_time_after_cycle_time: boolean,
      comparison_result: pmt$comparison_result,
      cycle_date_time: ost$date_time,
      cycle_time_after_after_time: boolean,
      ignore_status: ost$status;

    IF (NOT selection_criteria.after_date_time_selected) AND
          (NOT selection_criteria.before_date_time_selected) THEN
      cycle_included := TRUE;
    ELSE
      select_cycle_date_time (cycle_array_entry, selection_criteria.mode, cycle_date_time);
      IF selection_criteria.after_date_time_selected THEN
        pmp$date_time_compare (cycle_date_time, selection_criteria.after_date_time, comparison_result,
              ignore_status);
        cycle_time_after_after_time := (comparison_result = pmc$left_is_greater);
      IFEND;
      IF selection_criteria.before_date_time_selected THEN
        pmp$date_time_compare (selection_criteria.before_date_time, cycle_date_time, comparison_result,
              ignore_status);
        before_time_after_cycle_time := (comparison_result = pmc$left_is_greater);
      IFEND;
      IF selection_criteria.after_date_time_selected AND selection_criteria.before_date_time_selected THEN
        IF selection_criteria.after_time_after_before_time THEN
          cycle_included := cycle_time_after_after_time OR before_time_after_cycle_time;
        ELSE
          cycle_included := cycle_time_after_after_time AND before_time_after_cycle_time;
        IFEND;
      ELSEIF selection_criteria.after_date_time_selected THEN
        cycle_included := cycle_time_after_after_time;
      ELSE
        cycle_included := before_time_after_cycle_time;
      IFEND;
    IFEND;

    IF cycle_array_entry.sparse_allocation OR (cycle_array_entry.device_class <> rmc$mass_storage_device)
          THEN
      cycle_included := FALSE;
    IFEND;

  PROCEND check_if_access_included;

?? TITLE := '  [INLINE] check_if_high_cycle_included', EJECT ??

  PROCEDURE [INLINE] check_if_high_cycle_included
    (    cycle_number: pft$cycle_index;
         p_cycle_list: {input} ^pft$cycle_list;
         p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
     VAR cycle_included: boolean);

    VAR
      cycle_index: pft$cycle_count,
      higher_cycles: pft$cycle_count;


    cycle_included := TRUE;
    IF p_cycle_reservation_criteria <> NIL THEN
      IF p_cycle_reservation_criteria^.exclude_highest_cycles = 0 THEN
        cycle_included := TRUE;
      ELSEIF p_cycle_reservation_criteria^.exclude_highest_cycles = pfc$maximum_cycle_number THEN
        cycle_included := FALSE;
      ELSE
        higher_cycles := 0;
        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
          IF (p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$normal_cycle_entry) AND
                (p_cycle_list^ [cycle_index].cycle_entry.cycle_number > cycle_number) THEN
            higher_cycles := higher_cycles + 1;
          IFEND;
        FOREND;
        cycle_included := (higher_cycles >= p_cycle_reservation_criteria^.exclude_highest_cycles);
      IFEND;
    IFEND;
  PROCEND check_if_high_cycle_included;

?? TITLE := '  check_if_size_included ', EJECT ??

  PROCEDURE check_if_size_included
    (    large_cycles_lower_bound: amt$file_length;
         small_cycles_upper_bound: amt$file_length;
         cycle_size: amt$file_length;
         p_cycle: {input} ^pft$physical_cycle;
     VAR cycle_included: boolean);

    VAR
      local_status: ost$status,
      comparison_result: pmt$comparison_result;

    cycle_included := FALSE;
    IF p_cycle^.cycle_entry.data_modification_date_time.year <= 0 THEN
      RETURN;
    ELSE
      pmp$date_time_compare (p_cycle^.cycle_entry.data_modification_date_time,
            p_cycle^.cycle_entry.cycle_statistics.modification_date_time, comparison_result, local_status);
      IF comparison_result = pmc$right_is_greater THEN
        RETURN;
      IFEND;
    IFEND;

    cycle_included := (cycle_size >= large_cycles_lower_bound) AND (cycle_size <= small_cycles_upper_bound);

  PROCEND check_if_size_included;

?? TITLE := '  check_if_usage_included ', EJECT ??

  PROCEDURE check_if_usage_included
    (    usage_intentions: pft$permit_selections;
         share_intentions: pft$share_selections;
         mainframe_id: pmt$binary_mainframe_id;
         p_cycle: {input} ^pft$physical_cycle;
         p_catalog: {input} ^pft$catalog_file;
     VAR cycle_included: boolean);

   VAR
     dummy_path: [STATIC] array [1 .. 1] of pft$name := ['DUMMY'],
     local_status: ost$status;

     IF p_cycle^.cycle_entry.attach_status.attach_count = 0 THEN
       cycle_included := TRUE;
     ELSE
       pfp$check_cycle_busy (dummy_path, usage_intentions, share_intentions, mainframe_id, p_catalog,
             p_cycle^.cycle_entry, local_status);
       cycle_included := local_status.normal;
     IFEND;
  PROCEND check_if_usage_included;

?? TITLE := '  check_if_volume_included ', EJECT ??

  PROCEDURE check_if_volume_included
    (    include_volumes_option: put$include_volumes_option;
         p_stored_fmd: ^dmt$stored_fmd;
         p_included_volume_list: ^pft$volume_list;
     VAR volume_included: boolean;
     VAR status: ost$status);

    VAR
      file_volume: integer,
      fmd_header: pft$fmd_header,
      included_volume: integer,
      p_actual_volume_list: ^pft$volume_list;

    status.normal := TRUE;

    IF p_included_volume_list = NIL THEN
      volume_included := TRUE;
    ELSE
      volume_included := FALSE;
      dmp$get_stored_fmd_header_info (p_stored_fmd, fmd_header, status);
      IF NOT status.normal OR (fmd_header.number_of_subfiles <= 0) THEN
        RETURN;
      IFEND;

      PUSH p_actual_volume_list: [1 .. fmd_header.number_of_subfiles];
      dmp$get_stored_fmd_volume_list (p_stored_fmd, p_actual_volume_list, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF include_volumes_option = puc$initial_volume THEN

      /search_for_volume_one/
        FOR included_volume := 1 TO UPPERBOUND (p_included_volume_list^) DO
          IF p_actual_volume_list^ [1] = p_included_volume_list^ [included_volume] THEN
            volume_included := TRUE;
            EXIT /search_for_volume_one/;
          IFEND;
        FOREND /search_for_volume_one/;

      ELSE { multiple volumes

      /search_included_volumes/
        FOR included_volume := 1 TO UPPERBOUND (p_included_volume_list^) DO
          FOR file_volume := 1 TO UPPERBOUND (p_actual_volume_list^) DO
            IF p_actual_volume_list^ [file_volume] = p_included_volume_list^ [included_volume] THEN
              volume_included := TRUE;
              EXIT /search_included_volumes/;
            IFEND;
          FOREND;
        FOREND /search_included_volumes/;
      IFEND;
    IFEND;
  PROCEND check_if_volume_included;

?? TITLE := '  create_reserved_cycle_info', EJECT ??

  PROCEDURE create_reserved_cycle_info
    (    path: pft$complete_path;
     VAR status: ost$status);


    osp$set_signature_lock (pfv$reserved_cycle_info.signature_lock, osc$nowait, status);
    IF NOT status.normal THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$reserved_cycle_table_locked, '', status);
      RETURN;
    IFEND;

    ALLOCATE pfv$reserved_cycle_info.p_catalog_path: [1 .. UPPERBOUND (path)] IN osv$task_shared_heap^;
    IF pfv$reserved_cycle_info.p_catalog_path = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
             'Unable to allocate space in Task Shared heap.', status);
      RETURN;
    IFEND;

    pfv$reserved_cycle_info.p_catalog_path^ := path;

  PROCEND create_reserved_cycle_info;

?? TITLE := '  get_amd', EJECT ??

  PROCEDURE { [INLINE] } get_amd (
        p_physical_amd: pft$p_physical_amd;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_amd: pft$p_amd,
      p_record_body: pft$p_info,
      size: pft$amd_size;

    locate_info_record_body (p_info, p_record_body, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF p_physical_amd = NIL THEN
      RETURN;
    IFEND;

    size := #SIZE (p_physical_amd^.amd);
    NEXT p_amd: [[REP size OF cell]] IN p_record_body;
    IF p_amd = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      RETURN;
    IFEND;
    p_amd^ := p_physical_amd^.amd;

    build_info_record (pfc$archive_amd_record, i#current_sequence_position (p_record_body), p_info, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND get_amd;

?? TITLE := '  get_archive_entry', EJECT ??

  PROCEDURE { [INLINE] } get_archive_entry (
        p_archive: pft$p_archive;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_archive_array_entry: pft$p_archive_array_entry,
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    NEXT p_archive_array_entry IN p_record_body;
    IF p_archive_array_entry = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
    ELSE

       p_archive_array_entry^.version := p_archive^.archive_entry.version;

       p_archive_array_entry^.archive_date_time := p_archive^.archive_entry.archive_date_time;

       p_archive_array_entry^.archive_identification := p_archive^.archive_entry.archive_identification;

       p_archive_array_entry^.file_size := p_archive^.archive_entry.file_size;

       p_archive_array_entry^.last_release_date_time := p_archive^.archive_entry.last_release_date_time;

       p_archive_array_entry^.last_retrieval_status := p_archive^.archive_entry.last_retrieval_status;

       p_archive_array_entry^.modification_date_time := p_archive^.archive_entry.modification_date_time;

       p_archive_array_entry^.release_candidate := p_archive^.archive_entry.release_candidate;

       p_archive_array_entry^.reserved_archive_array_entry_sp :=

        p_archive^.archive_entry.reserved_archive_entry_space;
       build_info_record (pfc$archive_array_entry_record, i#current_sequence_position

          (p_record_body), p_info, status);
     IFEND;


  PROCEND get_archive_entry;

?? TITLE := '  get_archive_list', EJECT ??

  PROCEDURE { [INLINE] } get_archive_list (
        p_archive_list: pft$p_archive_list;
        p_catalog_file: pft$p_catalog_file;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      archive_index: pft$archive_index,
      p_archive: pft$p_archive,
      p_physical_amd: pft$p_physical_amd,
      p_record_body: pft$p_info;

    status.normal := TRUE;

    /get_all_list_entries/
    FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
      p_archive := ^p_archive_list^[archive_index];
      locate_info_record_body (p_info, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_all_list_entries/;
      IFEND;
      get_archive_entry (p_archive, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_all_list_entries/;
      IFEND;
      pfp$build_amd_pointer (p_archive^.archive_entry.amd_locator, p_catalog_file, p_physical_amd);
      get_amd (p_physical_amd, p_record_body, status);
      IF NOT status.normal THEN
        EXIT /get_all_list_entries/;
      IFEND;
      build_info_record (pfc$archive_entry_record, i#current_sequence_position (p_record_body), p_info,
          status);
      IF NOT status.normal THEN
        EXIT /get_all_list_entries/;
      IFEND;
    FOREND;

  PROCEND get_archive_list;

?? TITLE := '  [INLINE] get_catalog_description_info', EJECT ??

  PROCEDURE [INLINE] get_catalog_description_info (catalog_object: pft$object_entry;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_catalog_description: pft$p_catalog_description,
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      NEXT p_catalog_description IN p_record_body;
      IF p_catalog_description <> NIL THEN
        p_catalog_description^.name := catalog_object.external_object_name;
        p_catalog_description^.charge_id := catalog_object.charge_id;
        build_info_record (pfc$catalog_description_record, i#current_sequence_position (p_record_body),
              p_info, status);
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    IFEND;
  PROCEND get_catalog_description_info;

?? TITLE := '  get_catalog_info', EJECT ??

  PROCEDURE get_catalog_info (catalog_object: pft$object_entry;
        catalog_info_selections: pft$catalog_info_selections;
        p_catalog_file: pft$p_catalog_file;
        authority: pft$authority;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_permit_list: pft$p_permit_list,
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      IF pfc$catalog_description IN catalog_info_selections THEN
        get_catalog_description_info (catalog_object, p_record_body, status);
      IFEND;

      IF status.normal AND (pfc$catalog_permits IN catalog_info_selections) THEN
        pfp$build_permit_list_pointer (catalog_object.permit_list_locator, p_catalog_file, p_permit_list);
        get_permit_info (p_permit_list, authority, p_record_body, status);
      IFEND;

      IF status.normal AND (pfc$catalog_media_descriptor IN catalog_info_selections) THEN
        get_catalog_media_info (catalog_object.internal_object_name, catalog_object.catalog_object_locator,
              p_catalog_file, p_record_body, status);
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$catalog_group_record, i#current_sequence_position (p_record_body), p_info,
              status);
      IFEND;
    IFEND;
  PROCEND get_catalog_info;

?? TITLE := '  [INLINE] get_catalog_media_info', EJECT ??

  PROCEDURE [INLINE] get_catalog_media_info
    (    internal_name: pft$internal_name;
         catalog_object_locator: pft$catalog_object_locator;
         p_catalog_file: pft$p_catalog_file;
     VAR p_catalog_group: {Input, Output} pft$p_info;
     VAR status: ost$status);

    VAR
      p_catalog_media_description: pft$p_catalog_media_description,
      p_catalog_media_record_body: pft$p_info,
      p_fmd_info: ^SEQ ( * ),
      p_physical_fmd: pft$p_physical_fmd;

    locate_info_record_body (p_catalog_group, p_catalog_media_record_body, status);
    IF status.normal THEN
      NEXT p_catalog_media_description IN p_catalog_media_record_body;
      IF p_catalog_media_description = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'Catalog media ', status);
      ELSE
        p_catalog_media_description^.internal_name := internal_name;
        p_catalog_media_description^.catalog_type := catalog_object_locator.catalog_type;

        IF catalog_object_locator.catalog_type = pfc$external_catalog THEN
          pfp$build_fmd_pointer (catalog_object_locator.fmd_locator, p_catalog_file, p_physical_fmd);
          IF p_physical_fmd <> NIL THEN
            p_catalog_media_description^.global_file_name := catalog_object_locator.global_file_name;
            p_catalog_media_description^.file_media_type.media_version := pfc$file_media_disk_version_1;
            p_catalog_media_description^.file_media_type.device_class := rmc$mass_storage_device;
            p_catalog_media_description^.checksum := p_physical_fmd^.checksum;
            NEXT p_fmd_info: [[REP #SIZE (p_physical_fmd^.fmd) OF cell]] IN p_catalog_media_record_body;
            IF p_fmd_info = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'Catalog fmd ', status);
              RETURN;
            ELSE
              p_fmd_info^ := p_physical_fmd^.fmd;
            IFEND;
          IFEND
        IFEND;

        build_info_record (pfc$catalog_media_record, i#current_sequence_position
              (p_catalog_media_record_body), p_catalog_group, status);
      IFEND;
    IFEND;
  PROCEND get_catalog_media_info;

?? TITLE := '  get_cycle_archive_info', EJECT ??

  PROCEDURE get_cycle_archive_info (
        p_archive_list: pft$p_archive_list;
        p_catalog_file: pft$p_catalog_file;
    VAR p_info: {i/o} pft$p_info;
    VAR status: ost$status);

    VAR
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    get_archive_list (p_archive_list, p_catalog_file, p_record_body, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    build_info_record (pfc$archive_info_record, i#current_sequence_position (p_record_body), p_info, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND get_cycle_archive_info;

?? TITLE := '  [INLINE] get_cycle_array', EJECT ??

  PROCEDURE [INLINE] get_cycle_array (p_cycle_list: pft$p_cycle_list;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      comparison_result: pmt$comparison_result,
      cycle_entry: pft$cycle_entry,
      cycle_index: pft$cycle_index,
      cycle_info: pft$cycle_array_entry,
      p_cycle_info: pft$p_cycle_array_entry,
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      IF p_cycle_list <> NIL THEN

      /get_cycle_info_loop/
        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
          cycle_entry := p_cycle_list^ [cycle_index].cycle_entry;
          IF cycle_entry.entry_type = pfc$normal_cycle_entry THEN
            NEXT p_cycle_info IN p_record_body;
            IF p_cycle_info <> NIL THEN
              cycle_info.cycle_number := cycle_entry.cycle_number;
              cycle_info.cycle_statistics := cycle_entry.cycle_statistics;
              cycle_info.expiration_date_time := cycle_entry.expiration_date_time;
              IF (cycle_entry.data_modification_date_time.year > 0) AND
                    (cycle_entry.data_residence <> pfc$unreleasable_data) THEN
                pmp$date_time_compare (cycle_entry.cycle_statistics.modification_date_time,
                    cycle_entry.data_modification_date_time, comparison_result, status);
                IF comparison_result = pmc$left_is_greater THEN
                  cycle_info.cycle_statistics.modification_date_time :=
                        cycle_entry.data_modification_date_time;
                IFEND;
              IFEND;
              p_cycle_info^ := cycle_info;
            ELSE
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
              EXIT /get_cycle_info_loop/;
            IFEND;
          IFEND;
        FOREND /get_cycle_info_loop/;
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$cycle_array_record, i#current_sequence_position (p_record_body), p_info,
              status);
      IFEND;
    IFEND;
  PROCEND get_cycle_array;

?? TITLE := '  get_cycle_array_extended', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to obtain the information required when
{   restoring a catalog.
{
{ DESIGN:
{   The information has the following format:
{     pfc$cycle_array_extended_record
{       pfc$cycle_array_directory
{       pfc$cycle_info_record (one for each cycle)
{         pfc$cycle_media_record
{         pfc$cycle_label_record
{         pfc$archive_info_record

  PROCEDURE get_cycle_array_extended
    (    p_complete_path: {input} ^pft$complete_path;
         ownership: pft$ownership;
         file_info_selections: pft$file_info_selections;
         p_cycle_list: {i/o^} ^pft$cycle_list;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR p_file_info: {i/o} ^pft$info;
     VAR status: ost$status);

    VAR
      cycle_index: pft$cycle_count,
      directory_index: pft$cycle_count,
      normal_cycle_count: pft$cycle_count,
      p_cycle_array_extended_body: ^pft$info,
      p_cycle_directory: ^pft$cycle_directory_array;

    locate_info_record_body (p_file_info, p_cycle_array_extended_body, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    normal_cycle_count := 0;
    IF p_cycle_list <> NIL THEN
      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
        IF p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$normal_cycle_entry THEN
          normal_cycle_count := normal_cycle_count + 1;
        IFEND;
      FOREND;
    IFEND;

    IF normal_cycle_count > 0 THEN
      allocate_cycle_directory (normal_cycle_count, p_cycle_array_extended_body, p_cycle_directory, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    directory_index := 0;
    IF (p_cycle_list <> NIL) AND (normal_cycle_count > 0) THEN
      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
        IF p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$normal_cycle_entry THEN
          directory_index := directory_index + 1;
          p_cycle_directory^ [directory_index].internal_name :=
                p_cycle_list^ [cycle_index].cycle_entry.internal_cycle_name;
          p_cycle_directory^ [directory_index].cycle_number :=
                p_cycle_list^ [cycle_index].cycle_entry.cycle_number;
          p_cycle_directory^ [directory_index].info_offset :=
                i#current_sequence_position (p_cycle_array_extended_body);

          get_cycle_info (p_complete_path, ownership, file_info_selections, p_catalog_file,
                ^p_cycle_list^ [cycle_index], p_cycle_array_extended_body, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        IFEND;
      FOREND;
    IFEND;

    build_info_record (pfc$cycle_array_extended_record,
          i#current_sequence_position (p_cycle_array_extended_body), p_file_info, status);
  PROCEND get_cycle_array_extended;

?? TITLE := '  get_cycle_array_version_2', EJECT ??

  PROCEDURE get_cycle_array_version_2
    (    p_complete_path: {input} ^pft$complete_path;
         ownership: pft$ownership;
         file_info_selections: pft$file_info_selections;
         p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
         p_file_object: {input^} ^pft$object_entry;
         p_cycle_list: {i^/o^} ^pft$cycle_list;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR p_info: {i/o} ^pft$info;
     VAR status: ost$status);

    VAR
      cycle_included: boolean,
      cycle_index: pft$cycle_index,
      cycle_info: pft$cycle_array_entry_version_2,
      p_cycle_entry: ^pft$cycle_entry,
      p_cycle_info: ^pft$cycle_array_entry_version_2,
      p_physical_fmd: ^pft$physical_fmd,
      p_record_body: ^pft$info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      IF p_cycle_list <> NIL THEN

      /get_cycle_info_loop/
        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
          IF p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$normal_cycle_entry THEN
            p_cycle_entry := ^p_cycle_list^ [cycle_index].cycle_entry;

            NEXT p_cycle_info IN p_record_body;
            IF p_cycle_info <> NIL THEN
              cycle_info.cycle_damage_symptoms := p_cycle_entry^.cycle_damage_symptoms;
              cycle_info.cycle_number := p_cycle_entry^.cycle_number;
              cycle_info.cycle_statistics := p_cycle_entry^.cycle_statistics;
              cycle_info.data_modification_date_time := p_cycle_entry^.data_modification_date_time;
              cycle_info.data_residence := p_cycle_entry^.data_residence;

              IF p_cycle_entry^.device_information.device_class_defined THEN
                pfp$convert_device_class_to_rm (p_cycle_entry^.device_information.device_class,
                      cycle_info.device_class);
              ELSE
                cycle_info.device_class := rmc$mass_storage_device;
              IFEND;

              pfp$build_fmd_pointer (p_cycle_entry^.fmd_locator, p_catalog_file, p_physical_fmd);
              IF (cycle_info.device_class = rmc$mass_storage_device) AND (p_physical_fmd <> NIL) THEN
                reconcile_fmd (p_complete_path, ownership, p_catalog_file, ^p_cycle_list^ [cycle_index],
                      p_physical_fmd, status);
              IFEND;

              IF (cycle_info.device_class = rmc$mass_storage_device) AND
                    (p_cycle_entry^.data_modification_date_time.year > 0) THEN
                IF pfp$cycle_attached_for_write (^p_cycle_list^ [cycle_index]) THEN
                  cycle_info.data_modification_date_time := stale_data_mod_date_time;
                  cycle_info.bytes_allocated := 0;
                  cycle_info.eoi := 0;
                ELSE
                  cycle_info.bytes_allocated := p_cycle_entry^.device_information.bytes_allocated;
                  cycle_info.eoi := p_cycle_entry^.device_information.eoi;
                IFEND;
              ELSE
                cycle_info.bytes_allocated := 0;
                cycle_info.eoi := 0;
              IFEND;

              cycle_info.expiration_date_time := p_cycle_entry^.expiration_date_time;
              cycle_info.original_unique_name := p_cycle_entry^.global_file_name;
              cycle_info.shared_queue_info := p_cycle_entry^.shared_queue_info;
              cycle_info.retrieve_option := p_cycle_entry^.retrieve_option;
              cycle_info.site_backup_option := p_cycle_entry^.site_backup_option;
              cycle_info.site_archive_option := p_cycle_entry^.site_archive_option;
              cycle_info.site_release_option := p_cycle_entry^.site_release_option;
              cycle_info.sparse_allocation := FALSE;
              cycle_info.reserved_cycle_array_entry_sp := reserved_cycle_array_entry_sp;
              IF status.normal AND (p_physical_fmd <> NIL) THEN
                reserve_cycle (p_complete_path, ownership, p_file_object, cycle_index,
                      p_cycle_reservation_criteria, p_physical_fmd, p_catalog_file, p_cycle_list,
                      ^cycle_info);
              ELSE
                cycle_info.cycle_reservation.cycle_reserved := FALSE;
                pfp$process_unexpected_status (status);
                status.normal := TRUE;
              IFEND;

              p_cycle_info^ := cycle_info;
            ELSE
              osp$set_status_condition (pfe$info_full, status);
              EXIT /get_cycle_info_loop/;
            IFEND;
          IFEND;
        FOREND /get_cycle_info_loop/;
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$cycle_array_version_2_rec, i#current_sequence_position (p_record_body), p_info,
              status);
      IFEND;
    IFEND;
  PROCEND get_cycle_array_version_2;

?? TITLE := '  get_cycle_info', EJECT ??

  PROCEDURE get_cycle_info
    (    p_complete_path: {input} ^pft$complete_path;
         ownership: pft$ownership;
         file_info_selections: pft$file_info_selections;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_cycle: {i^/o^} ^pft$physical_cycle;
     VAR p_cycle_array_extended_body: {i/o} ^pft$info;
     VAR status: ost$status);

    VAR
      device_class: rmt$device_class,
      existing_sft_entry: dmt$existing_sft_entry,
      exit_on_unknown_file: boolean,
      file_damaged: boolean,
      file_modified: boolean,
      fmd_modified: boolean,
      local_status: ost$status,
      p_archive_list: ^pft$archive_list,
      p_cycle_info: ^pft$info,
      p_physical_fmd: ^pft$physical_fmd,
      p_physical_label: ^pft$physical_file_label,
      system_file_id: gft$system_file_identifier;

    locate_info_record_body (p_cycle_array_extended_body, p_cycle_info, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF pfc$cycle_media_descriptor IN file_info_selections THEN
      IF p_cycle^.cycle_entry.device_information.device_class_defined THEN
        pfp$convert_device_class_to_rm (p_cycle^.cycle_entry.device_information.device_class,
              device_class);
      ELSE
        device_class := rmc$mass_storage_device;
      IFEND;

      pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
      IF p_physical_fmd <> NIL THEN
        IF device_class = rmc$mass_storage_device THEN
          reconcile_fmd (p_complete_path, ownership, p_catalog_file, p_cycle, p_physical_fmd, status);
          IF NOT status.normal THEN
            {
            { Don't terminate the get_info because an fmd could not be
            { reconciled. If the get_info is being called on behalf of bacpf,
            { this error will be displayed when the file is backed up.
            {
            pfp$report_unexpected_status (status);
            status.normal := TRUE;
          IFEND;
        IFEND;

        get_cycle_media_info (device_class, p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd,
              p_cycle_info, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    IF pfc$cycle_label_descriptor IN file_info_selections THEN
      pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, p_catalog_file,
            p_physical_label);
      IF p_physical_label <> NIL THEN
        get_cycle_label_info (p_physical_label, p_cycle_info, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    IF pfc$archive_descriptors IN file_info_selections THEN
      pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator, p_catalog_file,
            p_archive_list);
      IF p_archive_list <> NIL THEN
        get_cycle_archive_info (p_archive_list, p_catalog_file, p_cycle_info, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    build_info_record (pfc$cycle_info_record, i#current_sequence_position (p_cycle_info),
          p_cycle_array_extended_body, status);
  PROCEND get_cycle_info;

?? TITLE := '  get_cycle_label_info', EJECT ??

  PROCEDURE get_cycle_label_info
    (    p_physical_label: pft$p_stored_file_label;
     VAR p_cycle_info: {Input, Output} pft$p_info;
     VAR status: ost$status);

    VAR
      p_file_label_info: pft$p_stored_file_label,
      p_file_label_record_body: pft$p_info;

    locate_info_record_body (p_cycle_info, p_file_label_record_body, status);
    IF status.normal THEN
      NEXT p_file_label_info: [[REP #SIZE (p_physical_label^.file_label) OF cell]] IN
            p_file_label_record_body;
      IF p_file_label_info = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, ' Cycles label', status);
      ELSE
        p_file_label_info^ := p_physical_label^;
        build_info_record (pfc$cycle_label_record, i#current_sequence_position (p_file_label_record_body),
              p_cycle_info, status);
      IFEND;
    IFEND;
  PROCEND get_cycle_label_info;

?? TITLE := '  get_cycle_media_info', EJECT ??

  PROCEDURE get_cycle_media_info
    (    device_class: rmt$device_class;
         internal_cycle_name: pft$internal_name;
         p_physical_fmd: pft$p_physical_fmd;
     VAR p_cycle_info: {Input, Output} pft$p_info;
     VAR status: ost$status);

    VAR
      p_file_media_description: pft$p_file_media_description,
      p_file_media_record_body: pft$p_info;

    locate_info_record_body (p_cycle_info, p_file_media_record_body, status);
    IF status.normal THEN
      NEXT p_file_media_description: [[REP #SIZE (p_physical_fmd^.fmd) OF cell]] IN p_file_media_record_body;
      IF p_file_media_description = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, ' Cycles fmd', status);
      ELSE
        p_file_media_description^.global_file_name := internal_cycle_name;
        p_file_media_description^.file_media_type.media_version := pfc$file_media_disk_version_1;
        p_file_media_description^.file_media_type.device_class := device_class;
        p_file_media_description^.checksum := p_physical_fmd^.checksum;
        p_file_media_description^.file_media_descriptor := p_physical_fmd^.fmd;
        build_info_record (pfc$cycle_media_record, i#current_sequence_position (p_file_media_record_body),
              p_cycle_info, status);
      IFEND;
    IFEND;
  PROCEND get_cycle_media_info;

?? TITLE := '  [INLINE] get_file_description_info', EJECT ??

  PROCEDURE [INLINE] get_file_description_info
   (    file_object: pft$object_entry;
        authority: pft$authority;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      file_description: pft$file_description,
      p_file_description: pft$p_file_description,
      p_record_body: pft$p_info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      NEXT p_file_description IN p_record_body;
      IF p_file_description <> NIL THEN
        file_description.name := file_object.external_object_name;
        IF authority.ownership = $pft$ownership [] THEN
          file_description.password := osc$null_name;
        ELSE
          file_description.password := file_object.password;
        IFEND;
        file_description.charge_id := file_object.charge_id;
        file_description.logging_selection := file_object.logging_selection;
        p_file_description^ := file_description;
        build_info_record (pfc$file_description_record, i#current_sequence_position (p_record_body), p_info,
              status);
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    IFEND;
  PROCEND get_file_description_info;

?? TITLE := '  get_file_info', EJECT ??

  PROCEDURE get_file_info
    (   p_complete_path: {input} ^pft$complete_path;
        authority: pft$authority;
        file_object: pft$object_entry;
        file_info_selections: pft$file_info_selections;
        p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
        p_catalog_file: {i^/o^} ^pft$catalog_file;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_cycle_list: ^pft$cycle_list,
      p_log_list: ^pft$log_list,
      p_permit_list: ^pft$permit_list,
      p_record_body: ^pft$info;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal THEN
      IF pfc$file_description IN file_info_selections THEN
        get_file_description_info (file_object, authority, p_record_body, status);
      IFEND;

      IF status.normal AND (pfc$file_permits IN file_info_selections) THEN
        pfp$build_permit_list_pointer (file_object.permit_list_locator, p_catalog_file, p_permit_list);
        get_permit_info (p_permit_list, authority, p_record_body, status);
      IFEND;

      IF status.normal THEN
        pfp$build_cycle_list_pointer (file_object.cycle_list_locator, p_catalog_file, p_cycle_list);

        IF pfc$file_cycles IN file_info_selections  THEN
          get_cycle_array (p_cycle_list, p_record_body, status);
        ELSEIF pfc$file_cycles_version_2 IN file_info_selections THEN
          get_cycle_array_version_2 (p_complete_path, authority.ownership, file_info_selections,
                p_cycle_reservation_criteria, ^file_object, p_cycle_list, p_catalog_file, p_record_body,
                status);
        IFEND;
      IFEND;

      IF status.normal AND (pfc$file_log IN file_info_selections) THEN
        pfp$build_log_list_pointer (file_object.log_list_locator, p_catalog_file, p_log_list);
        get_log_info (p_log_list, authority, p_record_body, status);
      IFEND;

      IF (pfc$cycle_media_descriptor IN file_info_selections) OR
            (pfc$cycle_label_descriptor IN file_info_selections) OR
            (pfc$archive_descriptors IN file_info_selections) THEN
        IF (NOT (pfc$file_cycles IN file_info_selections)) AND
              NOT (pfc$file_cycles_version_2 IN file_info_selections) THEN
          pfp$build_cycle_list_pointer (file_object.cycle_list_locator, p_catalog_file, p_cycle_list);
        IFEND;

        get_cycle_array_extended (p_complete_path, authority.ownership, file_info_selections, p_cycle_list,
              p_catalog_file, p_record_body, status);
      IFEND;

      IF status.normal THEN
        build_info_record (pfc$file_group_record, i#current_sequence_position (p_record_body), p_info,
              status);
      IFEND;
    IFEND;
  PROCEND get_file_info;

?? TITLE := '  [INLINE] get_log_info', EJECT ??

  PROCEDURE [INLINE] get_log_info
   (    p_log_list: pft$p_log_list;
        authority: pft$authority;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      log_index: pft$log_index,
      p_log_entry: pft$p_log,
      p_record_body: pft$p_info,
      user_id: ost$user_identification;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal AND (p_log_list <> NIL) THEN
      IF authority.ownership = $pft$ownership [] THEN
        user_id.family := authority.family;
        user_id.user := authority.user;
        pfp$locate_log_entry (p_log_list, user_id, p_log_entry);
        IF p_log_entry <> NIL THEN
          append_log_entry (p_log_entry^.log_entry, p_record_body, status);
        IFEND;
      ELSE

      /get_log_info_loop/
        FOR log_index := 1 TO UPPERBOUND (p_log_list^) DO
          append_log_entry (p_log_list^ [log_index].log_entry, p_record_body, status);
          IF NOT status.normal THEN
            EXIT /get_log_info_loop/;
          IFEND;
        FOREND /get_log_info_loop/;
      IFEND;
    IFEND;

    IF status.normal THEN
      build_info_record (pfc$log_array_record, i#current_sequence_position (p_record_body), p_info, status);
    IFEND;
  PROCEND get_log_info;

?? TITLE := '  get_multi_object_info', EJECT ??

  PROCEDURE get_multi_object_info
   (    p_complete_path: {input} ^pft$complete_path;
        authority: pft$authority;
        permit_entry: pft$permit_entry;
        object_list_descriptor: pft$object_list_descriptor;
        catalog_info_selections: pft$catalog_info_selections;
        file_info_selections: pft$file_info_selections;
        p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
        p_catalog_file: {i^/o^} ^pft$catalog_file;
    VAR catalog_locator: {i/o} pft$catalog_locator;
    VAR p_record_body: {i/o} ^pft$info;
    VAR status: ost$status);

    VAR
      directory_entry: pft$directory_array_entry,
      fs_path_size: fst$path_size,
      object_count: pft$object_count,
      object_entry: pft$object_entry,
      object_index: pft$object_index,
      p_directory_array: ^pft$directory_array,
      p_file_path: ^pft$complete_path,
      p_fs_path: ^fst$path,
      p_qualified_object_list: ^pft$object_list,
      selected_objects: pft$object_selections;

    IF catalog_info_selections <> $pft$catalog_info_selections [] THEN
      selected_objects := $pft$object_selections [pfc$catalog_object];
    ELSE
      selected_objects := $pft$object_selections [];
    IFEND;
    IF file_info_selections <> $pft$file_info_selections [] THEN
      selected_objects := selected_objects + $pft$object_selections [pfc$file_object];
    IFEND;

    IF object_list_descriptor.p_object_list <> NIL THEN
      PUSH p_qualified_object_list: [1 .. UPPERBOUND (object_list_descriptor.p_object_list^)];
    IFEND;

    build_qualified_object_list (object_list_descriptor, selected_objects, p_catalog_file, authority,
          permit_entry, object_count, p_qualified_object_list);
    allocate_directory_array (p_record_body, object_count, p_directory_array, status);

    IF status.normal THEN
      IF object_count > 0 THEN
        IF pfc$file_object IN selected_objects THEN
          PUSH p_file_path: [1 .. UPPERBOUND (p_complete_path^) + 1];
          p_file_path^ := p_complete_path^;
        IFEND;

      /get_info_loop/
        FOR object_index := 1 TO object_count DO
          object_entry := p_qualified_object_list^ [object_index].object_entry;
          directory_entry.name := object_entry.external_object_name;
          directory_entry.info_offset := i#current_sequence_position (p_record_body);

          IF object_entry.object_type = pfc$catalog_object THEN
            directory_entry.name_type := pfc$catalog_name;
            get_catalog_info (object_entry, catalog_info_selections, p_catalog_file, authority, p_record_body,
                  status);
          ELSE
            directory_entry.name_type := pfc$file_name;
            p_file_path^ [UPPERBOUND (p_file_path^)] := object_entry.external_object_name;
            get_file_info (p_file_path, authority, object_entry, file_info_selections,
                  p_cycle_reservation_criteria, p_catalog_file, p_record_body, status);
          IFEND;

          IF status.normal THEN
            p_directory_array^ [object_index] := directory_entry;
          ELSE
            EXIT /get_info_loop/;
          IFEND;

          IF (object_index MOD pfv$unlock_catalog_threshold) = 0  THEN
            pfp$unlock_catalog_pages(catalog_locator, status);
            IF NOT status.normal THEN
              EXIT /get_info_loop/;
            IFEND;
          IFEND;
        FOREND /get_info_loop/;

      ELSEIF osv$catalog_name_security AND (authority.ownership = $pft$ownership []) AND
            ((permit_entry.entry_type = pfc$free_permit_entry) OR
            (permit_entry.usage_permissions = $pft$permit_selections [])) THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (p_complete_path^, p_fs_path^, fs_path_size);
        CASE UPPERBOUND (p_complete_path^) OF
        = pfc$family_path_index =
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_family,
                p_fs_path^ (1, fs_path_size), status);
        = pfc$master_catalog_path_index =
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_master_catalog,
                p_fs_path^ (1, fs_path_size), status);
        ELSE
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_last_subcatalog,
                p_fs_path^ (1, fs_path_size), status);
        CASEND;
      IFEND;
    IFEND;
  PROCEND get_multi_object_info;

?? TITLE := '  get_object_info', EJECT ??

  PROCEDURE get_object_info
    (    path: pft$complete_path;
         authority: pft$authority;
         object_entry: pft$object_entry;
         catalog_info_selections: pft$catalog_info_selections;
         file_info_selections: pft$file_info_selections;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR p_record_body: {i/o} ^pft$info;
     VAR status: ost$status);

    VAR
      directory_entry: pft$directory_array_entry,
      p_directory_array: ^pft$directory_array;

    allocate_directory_array (p_record_body, {directory_size} 1, p_directory_array, status);
    IF status.normal THEN
      directory_entry.name := object_entry.external_object_name;
      directory_entry.info_offset := i#current_sequence_position (p_record_body);

      IF object_entry.object_type = pfc$catalog_object THEN
        directory_entry.name_type := pfc$catalog_name;
        get_catalog_info (object_entry, catalog_info_selections, p_catalog_file, authority, p_record_body,
              status);
      ELSE
        directory_entry.name_type := pfc$file_name;
        get_file_info (^path, authority, object_entry, file_info_selections,
              {p_cycle_reservation_criteria} NIL, p_catalog_file, p_record_body, status);
      IFEND;

      p_directory_array^ [1] := directory_entry;
    IFEND;
  PROCEND get_object_info;

?? TITLE := '  get_permit_info', EJECT ??

  PROCEDURE get_permit_info
   (    p_permit_list: pft$p_permit_list;
        authority: pft$authority;
    VAR p_info: pft$p_info;
    VAR status: ost$status);

    VAR
      p_record_body: pft$p_info,
      permit_entry: pft$permit_entry,
      permit_index: pft$permit_index;

    locate_info_record_body (p_info, p_record_body, status);
    IF status.normal AND (p_permit_list <> NIL) THEN
      IF authority.ownership = $pft$ownership [] THEN
        pfp$extract_permit_entry (p_permit_list, authority, permit_entry);
        append_permit_entry (permit_entry, p_record_body, status);
      ELSE

      /get_permit_info_loop/
        FOR permit_index := 1 TO UPPERBOUND (p_permit_list^) DO
          append_permit_entry (p_permit_list^ [permit_index].permit_entry, p_record_body, status);
          IF NOT status.normal THEN
            EXIT /get_permit_info_loop/;
          IFEND;
        FOREND /get_permit_info_loop/;
      IFEND;
    IFEND;

    IF status.normal THEN
      build_info_record (pfc$permit_array_record, i#current_sequence_position (p_record_body), p_info,
            status);
    IFEND;
  PROCEND get_permit_info;

?? OLDTITLE ??
?? NEWTITLE := ' get_root_stored_fmd', EJECT ??

  PROCEDURE get_root_stored_fmd
    (    path: pft$complete_path;
     VAR catalog: boolean;
     VAR catalog_recreated: boolean;
     VAR global_file_name: ost$binary_unique_name;
     VAR stored_fmd: dmt$stored_fmd;
     VAR status: ost$status);

    VAR
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_root: ^pft$root,
      p_stored_fmd: ^dmt$stored_fmd,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      root_size: pft$root_size;

    root_size := 255; {estimate}
    REPEAT
      PUSH p_root: [[REP root_size OF cell]];
      RESET p_root;
      stp$get_pf_root (path [pfc$set_path_index], root_size, p_root^, status);
    UNTIL status.normal OR (status.condition <> ste$incorrect_root_size);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    RESET p_root;
    NEXT p_internal_catalog_name IN p_root;
    NEXT p_stored_fmd_size IN p_root;
    NEXT p_stored_fmd: [[REP p_stored_fmd_size^ OF cell]] IN p_root;

    catalog := TRUE;
    catalog_recreated := FALSE;
    global_file_name := p_internal_catalog_name^;
    stored_fmd := p_stored_fmd^;

  PROCEND get_root_stored_fmd;

?? OLDTITLE ??
?? NEWTITLE := ' get_root_stored_fmd_size', EJECT ??

  PROCEDURE get_root_stored_fmd_size
    (    path: pft$complete_path;
     VAR device_class: rmt$device_class;
     VAR global_file_name: ost$binary_unique_name;
     VAR fmd_size: dmt$stored_fmd_size;
     VAR status: ost$status);

    VAR
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_root: ^pft$root,
      p_stored_fmd: ^dmt$stored_fmd,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      root_size: pft$root_size;


    root_size := 255; {estimate}
    REPEAT
      PUSH p_root: [[REP root_size OF cell]];
      RESET p_root;
      stp$get_pf_root (path [pfc$set_path_index], root_size, p_root^, status);
    UNTIL status.normal OR (status.condition <> ste$incorrect_root_size);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    RESET p_root;
    NEXT p_internal_catalog_name IN p_root;
    NEXT p_stored_fmd_size IN p_root;
    NEXT p_stored_fmd: [[REP p_stored_fmd_size^ OF cell]] IN p_root;

    device_class := rmc$mass_storage_device;
    global_file_name := p_internal_catalog_name^;
    fmd_size := p_stored_fmd_size^;

  PROCEND get_root_stored_fmd_size;

?? TITLE := '  locate_info_record_body', EJECT ??

  PROCEDURE locate_info_record_body (p_info: pft$p_info;
    VAR p_record_body: pft$p_info;
    VAR status: ost$status);

    VAR
      body_size: integer,
      header_size: integer,
      local_p_info: pft$p_info,
      p_info_record: pft$p_info_record;

    IF p_info <> NIL THEN
      PUSH p_info_record: [[REP 1 OF cell]];
      header_size := #SIZE (p_info_record^) - 1;
      body_size := #SIZE (p_info^) - i#current_sequence_position (p_info) - header_size;
      IF body_size > 0 THEN
        local_p_info := p_info;
        NEXT p_record_body: [[REP header_size OF cell]] IN local_p_info;
        NEXT p_record_body: [[REP body_size OF cell]] IN local_p_info;
        RESET p_record_body;
        status.normal := TRUE;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
      IFEND;
    ELSE
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, '', status);
    IFEND;
  PROCEND locate_info_record_body;

?? TITLE := '  reconcile_fmd', EJECT ??

  PROCEDURE reconcile_fmd
    (    p_complete_path: {input} ^pft$complete_path;
         ownership: pft$ownership;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_cycle: {i^/o^} ^pft$physical_cycle;
     VAR p_physical_fmd: {i^/o} ^pft$physical_fmd;
     VAR status: ost$status);

    VAR
      existing_sft_entry: dmt$existing_sft_entry,
      exit_on_unknown_file: boolean,
      file_damaged: boolean,
      file_info: dmt$file_information,
      file_modified: boolean,
      fmd_modified: boolean,
      local_status: ost$status,
      system_file_id: gft$system_file_identifier;

    status.normal := TRUE;
    exit_on_unknown_file := pfp$cycle_attached_for_write (p_cycle);

    IF exit_on_unknown_file THEN

      dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
            p_physical_fmd^.fmd, $pft$usage_selections [pfc$read], $pft$share_selections [],
            pfc$average_share_history, pfc$maximum_pf_length, {restricted attach} FALSE,
            exit_on_unknown_file, {server_file} FALSE,
            pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info, $pft$share_selections []),
            file_damaged, system_file_id, existing_sft_entry, status);
      IF status.normal THEN
        IF existing_sft_entry = dmc$normal_entry THEN
          pfp$detach_permanent_file (p_complete_path, system_file_id, $pft$usage_selections [],
                {catalog_access_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_file_info,
                fmd_modified, file_info, local_status);
          pfp$process_unexpected_status (local_status);

          IF fmd_modified THEN
            pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
          IFEND;
        ELSE
          pfp$reconcile_fmd (p_complete_path, p_cycle^.cycle_entry.internal_cycle_name, existing_sft_entry,
                {update_catalog} TRUE, p_catalog_file, p_cycle, p_physical_fmd, status);

          IF status.normal THEN
            dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                  p_physical_fmd^.fmd, $pft$usage_selections [pfc$read], $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 (p_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_complete_path, system_file_id, $pft$usage_selections [],
                    {catalog_access_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_trimmed_length,
                    fmd_modified, file_info, local_status);
              pfp$process_unexpected_status (local_status);

              IF fmd_modified THEN
                pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
              IFEND;

              p_cycle^.cycle_entry.device_information.eoi := file_info.eoi_byte_address;
              p_cycle^.cycle_entry.device_information.bytes_allocated := file_info.total_allocated_length;
              pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND reconcile_fmd;

?? TITLE := '  reserve_cycle', EJECT ??

  PROCEDURE reserve_cycle
    (    p_complete_path: {input} ^pft$complete_path;
         ownership: pft$ownership;
         p_file_object: {input^} ^pft$object_entry;
         cycle_index: pft$cycle_index;
         p_cycle_reservation_criteria: {input} ^pft$cycle_reservation_criteria;
         p_physical_fmd: {input^} ^pft$physical_fmd;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_cycle_list: {i^/o^} ^pft$cycle_list;
         p_cycle_info: {i^/o^} ^pft$cycle_array_entry_version_2);

    VAR
      cycle_included: boolean,
      existing_sft_entry: dmt$existing_sft_entry,
      file_damaged: boolean,
      file_info: dmt$file_information,
      flush_catalog_pages: boolean,
      fmd_modified: boolean,
      local_status: ost$status,
      mainframe_id: pmt$binary_mainframe_id,
      p_cycle: ^pft$physical_cycle,
      reserved_cycle_index: ost$non_negative_integers,
      system_file_id: gft$system_file_identifier;

    p_cycle_info^.cycle_reservation.cycle_reserved := FALSE;

    IF p_cycle_reservation_criteria = NIL THEN
      RETURN;
    IFEND;

    p_cycle := ^p_cycle_list^ [cycle_index];
    IF (p_cycle^.cycle_entry.entry_type <> pfc$normal_cycle_entry) OR
          (p_cycle^.cycle_entry.cycle_damage_symptoms <> $fst$cycle_damage_symptoms []) OR
          (p_cycle^.cycle_entry.data_residence = pfc$offline_data) OR
          (p_cycle^.cycle_entry.device_information.device_class_defined AND
          (p_cycle^.cycle_entry.device_information.device_class <> pfc$mass_storage_device)) THEN
      RETURN;
    IFEND;

    check_if_access_included (p_cycle_reservation_criteria^.date_selection_criteria, p_cycle_info^,
          cycle_included);
    IF NOT cycle_included THEN
      RETURN;
    IFEND;

    check_if_size_included (p_cycle_reservation_criteria^.minimum_cycle_size,
          p_cycle_reservation_criteria^.maximum_cycle_size, p_cycle^.cycle_entry.device_information.eoi,
          p_cycle, cycle_included);
    IF NOT cycle_included THEN
      RETURN;
    IFEND;

    check_if_high_cycle_included (p_cycle^.cycle_entry.cycle_number, p_cycle_list,
          p_cycle_reservation_criteria, cycle_included);
    IF NOT cycle_included THEN
      RETURN;
    IFEND;

    cycle_included := NOT (p_cycle^.cycle_entry.site_backup_option IN p_cycle_reservation_criteria^.
          exclude_site_backup_options);
    IF NOT cycle_included THEN
      RETURN;
    IFEND;

    pmp$get_pseudo_mainframe_id (mainframe_id);
    check_if_usage_included ($pft$permit_selections [pfc$read], $pft$share_selections [pfc$read, pfc$execute],
          mainframe_id, p_cycle, p_catalog_file, cycle_included);
    IF NOT cycle_included THEN
      RETURN;
    IFEND;

    check_if_volume_included (p_cycle_reservation_criteria^.include_volumes_option, ^p_physical_fmd^.fmd,
          p_cycle_reservation_criteria^.p_volume_list, cycle_included, local_status);
    IF (NOT local_status.normal) OR NOT cycle_included THEN
      RETURN;
    IFEND;

    check_file_attributes ($pft$usage_selections [pfc$read], p_cycle_reservation_criteria^.validation_ring,
          p_cycle, p_catalog_file, cycle_included, local_status);
    IF (NOT local_status.normal) OR NOT cycle_included THEN
      RETURN;
    IFEND;

    dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
          p_physical_fmd^.fmd, $pft$usage_selections [pfc$read],
          $pft$share_selections [pfc$read, pfc$execute], pfc$average_share_history, pfc$maximum_pf_length,
          {restricted attach} FALSE, {exit_on_unknown_file} FALSE, {server_file} FALSE,
          pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info,
          $pft$share_selections [pfc$read, pfc$execute]), file_damaged, system_file_id,
          existing_sft_entry, local_status);

    IF avp$security_option_active (avc$vso_security_audit) THEN
      audit_cycle_attachment (p_complete_path, p_cycle^.cycle_entry.cycle_number, ownership, local_status);
    IFEND;

    IF NOT local_status.normal THEN
      RETURN;
    IFEND;


    IF NOT file_damaged THEN
      update_reserved_cycle_list (p_file_object^.external_object_name, p_file_object^.internal_object_name,
            p_cycle^.cycle_entry.cycle_number, p_cycle^.cycle_entry.internal_cycle_name, system_file_id,
            reserved_cycle_index, local_status);

      IF local_status.normal THEN
        pfp$increment_usage_counts (p_complete_path^, $pft$usage_selections [pfc$read],
              $pft$share_selections [pfc$read, pfc$execute], mainframe_id, p_catalog_file,
              flush_catalog_pages, p_cycle^.cycle_entry, local_status);

        IF local_status.normal THEN
          p_cycle_info^.cycle_reservation.cycle_reserved := TRUE;
          p_cycle_info^.cycle_reservation.reserved_cycle_index := reserved_cycle_index;
        IFEND;

        pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
      IFEND;
    IFEND;

    IF (NOT local_status.normal) OR file_damaged THEN
      pfp$detach_permanent_file (p_complete_path, system_file_id, $pft$usage_selections [pfc$read],
            {catalog_access_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_file_info,
            fmd_modified, file_info, local_status);
    IFEND;
  PROCEND reserve_cycle;

?? TITLE := '  [INLINE] select_cycle_date_time', EJECT ??

  PROCEDURE [INLINE] select_cycle_date_time
   (    cycle_array_entry: pft$cycle_array_entry_version_2;
        selection_criteria_mode: put$selection_criteria_mode;
    VAR cycle_date_time: ost$date_time);

    CASE selection_criteria_mode OF
    = puc$created =
      cycle_date_time := cycle_array_entry.cycle_statistics.creation_date_time;
    = puc$accessed =
      cycle_date_time := cycle_array_entry.cycle_statistics.access_date_time;
    = puc$modified =
      cycle_date_time := cycle_array_entry.cycle_statistics.modification_date_time;
    = puc$expired =
      cycle_date_time := cycle_array_entry.expiration_date_time;
    CASEND;
  PROCEND select_cycle_date_time;

?? TITLE := '  [INLINE] test_object_qualifications', EJECT ??

  PROCEDURE [INLINE] test_object_qualifications
   (    object_entry: pft$object_entry;
        selected_objects: pft$object_selections;
        p_catalog_file: pft$p_catalog_file;
        authority: pft$authority;
        permit_entry: pft$permit_entry;
    VAR object_qualified: boolean);

    VAR
      new_permit_entry: pft$permit_entry,
      p_permit_list: pft$p_permit_list;

    object_qualified := (object_entry.object_type IN selected_objects);
    IF object_qualified AND (authority.ownership = $pft$ownership []) THEN
      IF osv$catalog_name_security THEN
        IF (object_entry.object_type = pfc$catalog_object) OR
              (object_entry.object_type = pfc$file_object) THEN
          pfp$build_permit_list_pointer (object_entry.permit_list_locator, p_catalog_file, p_permit_list);
          pfp$extract_permit_entry (p_permit_list, authority, new_permit_entry);
          pfp$reduce_permits (permit_entry, new_permit_entry, new_permit_entry);
          object_qualified := ((new_permit_entry.entry_type = pfc$normal_permit_entry) AND
                (new_permit_entry.usage_permissions <> $pft$permit_selections []));
        IFEND;
      ELSE
        IF object_entry.object_type = pfc$file_object THEN
          pfp$build_permit_list_pointer (object_entry.permit_list_locator, p_catalog_file, p_permit_list);
          pfp$extract_permit_entry (p_permit_list, authority, new_permit_entry);
          pfp$reduce_permits (permit_entry, new_permit_entry, new_permit_entry);
          object_qualified := ((new_permit_entry.entry_type = pfc$normal_permit_entry) AND
                (new_permit_entry.usage_permissions <> $pft$permit_selections []));
        IFEND;
      IFEND;
    IFEND;
  PROCEND test_object_qualifications;

?? TITLE := '  [INLINE] update_reserved_cycle_list', EJECT ??

  PROCEDURE [INLINE] update_reserved_cycle_list
    (    external_object_name: pft$name;
         internal_object_name: pft$internal_name;
         cycle_number: fst$cycle_number;
         internal_cycle_name: pft$internal_name;
         system_file_id: gft$system_file_identifier;
     VAR reserved_cycle_index: ost$non_negative_integers;
     VAR status: ost$status);

    CONST
      reserved_cycle_expansion_size = 50;

    VAR
      p_reserved_cycles: ^pft$reserved_cycles;

    IF pfv$reserved_cycle_info.p_reserved_cycles = NIL THEN
      ALLOCATE pfv$reserved_cycle_info.p_reserved_cycles: [1 .. reserved_cycle_expansion_size] IN
            osv$task_shared_heap^;
      IF pfv$reserved_cycle_info.p_reserved_cycles = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
               'Unable to allocate space in Task Shared heap.', status);
        RETURN;
      IFEND;
      pfv$reserved_cycle_info.number_of_cycles_reserved := 0;
    ELSEIF pfv$reserved_cycle_info.number_of_cycles_reserved >=
          UPPERBOUND (pfv$reserved_cycle_info.p_reserved_cycles^) THEN
      p_reserved_cycles := pfv$reserved_cycle_info.p_reserved_cycles;
      ALLOCATE pfv$reserved_cycle_info.p_reserved_cycles:
            [1 .. (UPPERBOUND (p_reserved_cycles^) + reserved_cycle_expansion_size)] IN
            osv$task_shared_heap^;
      IF pfv$reserved_cycle_info.p_reserved_cycles = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
               'Unable to allocate space in Task Shared heap.', status);
        RETURN;
      IFEND;
      i#move (p_reserved_cycles, pfv$reserved_cycle_info.p_reserved_cycles, #SIZE (p_reserved_cycles^));
      FREE p_reserved_cycles IN osv$task_shared_heap^;
    IFEND;

    pfv$reserved_cycle_info.number_of_cycles_reserved := pfv$reserved_cycle_info.number_of_cycles_reserved +
          1;
    pfv$reserved_cycle_info.p_reserved_cycles^ [pfv$reserved_cycle_info.number_of_cycles_reserved].
          external_object_name := external_object_name;
    pfv$reserved_cycle_info.p_reserved_cycles^ [pfv$reserved_cycle_info.number_of_cycles_reserved].
          internal_object_name := internal_object_name;
    pfv$reserved_cycle_info.p_reserved_cycles^ [pfv$reserved_cycle_info.number_of_cycles_reserved].
          cycle_number := cycle_number;
    pfv$reserved_cycle_info.p_reserved_cycles^ [pfv$reserved_cycle_info.number_of_cycles_reserved].
          internal_cycle_name := internal_cycle_name;
    pfv$reserved_cycle_info.p_reserved_cycles^ [pfv$reserved_cycle_info.number_of_cycles_reserved].
          system_file_id := system_file_id;
    reserved_cycle_index := pfv$reserved_cycle_info.number_of_cycles_reserved;
  PROCEND update_reserved_cycle_list;

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