?? TITLE := 'NOS/VE Permanent Files : Ring 2 Interfaces' ??
MODULE pfm$r2_request_processor;
?? RIGHT := 110 ??
?? NEWTITLE := '  Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc fmc$unique_label_id
*copyc fsc$local
*copyc pfc$average_share_history
*copyc pfc$catalog_allocation_size
*copyc pfc$maximum_pf_length
*copyc pfc$null_shared_queue
*copyc pfc$test_jr_constants
*copyc dfd$file_server_info
*copyc dmd$null_global_file_name
*copyc osd$integer_limits
*copyc ame$open_validation_errors
*copyc dfe$error_condition_codes
*copyc fse$open_validation_errors
*copyc fse$path_exception_conditions
*copyc fse$system_conditions
*copyc pfe$error_condition_codes
*copyc pfe$external_archive_conditions
*copyc pfe$internal_error_conditions
*copyc rme$request_mass_storage
*copyc dmt$error_condition_codes
*copyc dmt$stored_fmd_size
*copyc dmt$stored_tape_fmd_header
*copyc dmt$stored_tape_volume_list
*copyc fmt$static_label_header
*copyc fst$file_changes
*copyc fst$path_resolution
*copyc fst$volume_condition_list
*copyc gft$system_file_identifier
*copyc pft$array_index
*copyc pft$change_list
*copyc pft$data_residence
*copyc pft$date_time
*copyc pft$exception_selection_info
*copyc pft$mandated_modification_time
*copyc pft$p_internal_cycle_path
*copyc pft$p_internal_path
*copyc pft$p_permit
*copyc pft$permit_level
*copyc pft$purge_cycle_options
*copyc pft$r2_attach_in
*copyc pft$release_data_info
*copyc pft$save_label_audit_info
*copyc pft$unique_volume_list
*copyc put$restore_data_selections
*copyc rmt$device_class
?? POP ??
*copyc fmf$ring_attributes_valid
*copyc avp$security_option_active
*copyc clp$convert_file_ref_to_string
*copyc clp$get_variable_value
*copyc clp$validate_new_file_name
*copyc clp$verify_time_increment
*copyc dfp$check_self_serving_job
*copyc dfp$fetch_served_family_entry
*copyc dfp$get_job_server_state
*copyc dfp$locate_served_family
*copyc dmp$attach_file
*copyc dmp$change_file_damaged
*copyc dmp$change_sft_damage_detection
*copyc dmp$change_sft_file_damaged
*copyc dmp$delete_file_descriptor
*copyc dmp$destroy_file
*copyc dmp$destroy_permanent_file
*copyc dmp$detach_file
*copyc dmp$enable_damage_detection
*copyc dmp$get_stored_fmd_header_info
*copyc dmp$get_stored_fmd_volume_list
*copyc dmp$get_unique_fmd_volume_list
*copyc dmp$locate_existing_sft_entry
*copyc fmp$change_recorded_cycle_num
*copyc fmp$change_recorded_file_name
*copyc fmp$delete_path_description
*copyc fmp$extract_dynamic_setfa_attrs
*copyc fmp$get_path_table_cycle_info
*copyc fmp$locate_cd_via_path_handle
*copyc fmp$lock_path_table
*copyc fmp$process_pt_request
*copyc fmp$unlock_path_table
*copyc fmp$validate_system_label
*copyc fsp$convert_device_class_to_fs
*copyc fsp$expand_file_label
*copyc fsp$path_element
*copyc iop$tape_file_attached
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$clear_signature_lock
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$file_access_condition
*copyc osp$generate_log_message
*copyc osp$generate_unique_binary_name
*copyc osp$get_set_name
*copyc osp$get_volume_condition
*copyc osp$log_job_recovery_message
*copyc osp$log_job_recovery_status
*copyc osp$prevalidate_free
*copyc osp$recoverable_system_error
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$test_signature_lock
*copyc pfp$access_last_object
*copyc pfp$access_next_catalog
*copyc pfp$access_object
*copyc pfp$allocate_archive_list
*copyc pfp$allocate_cycle_list
*copyc pfp$allocate_log_list
*copyc pfp$allocate_permit_list
*copyc pfp$assign_locked_apfid
*copyc pfp$attach_catalog
*copyc pfp$attach_permanent_file
*copyc pfp$audit_save_label
*copyc pfp$build_amd_locator
*copyc pfp$build_amd_pointer
*copyc pfp$build_archive_list_locator
*copyc pfp$build_archive_list_pointer
*copyc pfp$build_cycle_list_locator
*copyc pfp$build_cycle_list_pointer
*copyc pfp$build_file_label_locator
*copyc pfp$build_file_label_pointer
*copyc pfp$build_fmd_locator
*copyc pfp$build_fmd_pointer
*copyc pfp$build_log_list_locator
*copyc pfp$build_log_list_pointer
*copyc pfp$build_mainfram_list_locator
*copyc pfp$build_mainfram_list_pointer
*copyc pfp$build_object_list_locator
*copyc pfp$build_permit_list_locator
*copyc pfp$build_permit_list_pointer
*copyc pfp$build_permit_selections_str
*copyc pfp$catalog_access_retry_wait
*copyc pfp$change_object_name
*copyc pfp$check_catalog_alarm
*copyc pfp$clear_cycle_attachments
*copyc pfp$compute_checksum
*copyc pfp$convert_cycle_path_to_strng
*copyc pfp$convert_density_to_dm
*copyc pfp$convert_device_class_to_pf
*copyc pfp$convert_device_class_to_rm
*copyc pfp$convert_fs_to_complete_path
*copyc pfp$convert_fs_to_pft$path
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$convert_pf_to_fs_structure
*copyc pfp$convert_pft$path_to_fs_str
*copyc pfp$convert_shared_queue_to_ord
*copyc pfp$create_catalog
*copyc pfp$create_permanent_file
*copyc pfp$cycle_attached_for_write
*copyc pfp$delete_catalog_object
*copyc pfp$delete_file_object
*copyc pfp$destroy_catalog
*copyc pfp$detach_all_catalogs
*copyc pfp$detach_all_files
*copyc pfp$detach_permanent_file
*copyc pfp$detach_unavail_queued_cat
*copyc pfp$determine_new_cycle_number
*copyc pfp$establish_free_cycle_entry
*copyc pfp$extract_permit_entry
*copyc pfp$form_administrator_permit
*copyc pfp$get_allowed_device_classes
*copyc pfp$get_authority
*copyc pfp$get_catalog
*copyc pfp$get_cycle_damage_options
*copyc pfp$get_ownership
*copyc pfp$get_rem_media_req_info
*copyc pfp$get_rem_media_volume_list
*copyc pfp$internal_access_object
*copyc pfp$internal_locate_object
*copyc pfp$locate_attached_file
*copyc pfp$locate_cycle
*copyc pfp$locate_log_entry
*copyc pfp$locate_object
*copyc pfp$lock_apfid
*copyc pfp$log_ascii
*copyc pfp$log_error
*copyc pfp$log_path
*copyc pfp$map_usage_selections
*copyc pfp$process_unexpected_status
*copyc pfp$r2_build_archive_entry
*copyc pfp$r2_df_client_attach
*copyc pfp$r2_df_client_attach_or_cref
*copyc pfp$r2_df_client_clear_cy_att
*copyc pfp$r2_df_client_return
*copyc pfp$r2_df_client_save_label
*copyc pfp$r2_df_client_validate_pw
*copyc pfp$reattach_server_file
*copyc pfp$reconcile_fmd
*copyc pfp$record_dm_file_parameters
*copyc pfp$reduce_permits
*copyc pfp$release_locked_apfid
*copyc pfp$remove_queued_catalogs
*copyc pfp$report_system_error
*copyc pfp$report_unexpected_status
*copyc pfp$return_catalog
*copyc pfp$set_status_abnormal
*copyc pfp$setup_attached_pf_recovery
*copyc pfp$share_for_write
*copyc pfp$shared_queue
*copyc pfp$system_privilege_authority
*copyc pfp$unlock_apfid
*copyc pfp$unlock_catalog_pages
*copyc pfp$update_object_list_locator
*copyc pfp$validate_default_password
*copyc pfp$validate_family_ownership
*copyc pfp$validate_file_permission
*copyc pfp$validate_ored_permission
*copyc pfp$validate_ownership
*copyc pfp$validate_password
*copyc pfp$validate_ring_access
*copyc pmp$compute_date_time
*copyc pmp$continue_to_cause
*copyc pmp$date_time_compare
*copyc pmp$format_compact_date
*copyc pmp$format_compact_time
*copyc pmp$get_compact_date_time
*copyc pmp$get_pseudo_mainframe_id
*copyc pmp$log_ascii
*copyc rmp$build_mass_storage_info
*copyc sfp$accumulate_file_space
*copyc sfp$auditing_operation
*copyc sfp$emit_audit_statistic
*copyc stp$get_pf_root
*copyc syp$hang_if_job_jrt_set
*copyc syp$invalidate_open_sfid
*copyc syp$pop_inhibit_job_recovery
*copyc syp$push_inhibit_job_recovery
*copyc syp$replace_sfid
*copyc dfv$file_server_info_enabled
*copyc dmv$active_volume_table
*copyc fmv$default_file_attributes
*copyc gfv$null_sfid
*copyc osv$recover_system_set_phase
*copyc osv$system_family_name
*copyc osv$task_shared_heap
*copyc pfv$flush_catalogs
*copyc pfv$locked_apfid
*copyc pfv$null_tape_fmd_header_space
*copyc pfv$null_unique_name
*copyc pfv$p_locked_catalog
*copyc pfv$p_p_job_heap
*copyc pfv$reserved_cycle_info
*copyc pfv$restrict_catalog_flushing
*copyc pfv$space_character
*copyc pfv$system_authority
*copyc pfv$task_family
*copyc pfv$task_user
*copyc stv$system_set_name
*copyc fmi$get_ring_attributes
*copyc i#move
*copyc pfi$convert_cycle_reference
*copyc pfi$get_create_file_option
*copyc pfi$get_password
*copyc pfi$store_file_media_descriptor

  VAR
    pfv$honor_scl_var_create_file: [XREF] boolean;

{Debug code

  PROCEDURE [XREF] syp$increment_rsv_cycle_counter
    (    counter_type: (syc$ircc_detach_nil, syc$ircc_detach_purged, syc$ircc_reattach_purged));

{End Debug code

?? TITLE := '  Global Declarations Declared by this module', EJECT ??

  CONST
    include_radix = TRUE,
    inhibit_path_table_lock = TRUE,
    maximum_group_type_string_size = 12,
    max_free_result_string = 26,
    radix = 10;

  VAR
    pfv$allow_catalog_write: [XDCL, #GATE, oss$task_private] boolean := FALSE,
    pfv$null_catalog_entry_space: [XDCL, oss$job_paged_literal, READ] array [1 .. 47] of
          boolean := [REP 47 of FALSE],
    pfv$null_cycle_entry_space: [XDCL, oss$job_paged_literal, READ] array [1 .. 34] of
          boolean := [REP 34 of FALSE],
    pfv$null_date_time: [XDCL, oss$job_paged_literal, READ] ost$date_time := [{year} 1, {month} 1, {day} 1,
          {hour} 0, {minute} 0, {second} 0, {millisecond} 0],
    pfv$null_file_entry_space: [XDCL, oss$job_paged_literal, READ] array [1 .. 48] of
          boolean := [REP 48 of FALSE],
    pfv$null_object_entry_space: [XDCL, oss$job_paged_literal, READ] array [1 .. 6] of
          integer := [REP 6 of 0],
    pfv$unattached_status: [XDCL, oss$job_paged_literal, READ] pft$attach_status :=
          [0, [REP 5 of 0], [REP 5 of 0]],
    pfv$unlock_catalog_threshold: [XDCL, #GATE] integer := 500,
    pfv$write_usage: [XDCL, #GATE, oss$job_paged_literal, READ] pft$usage_selections :=
          [pfc$shorten, pfc$append, pfc$modify];

  VAR
    null_archive_entry_space: [oss$job_paged_literal, READ] array [1 .. 48] of boolean := [REP 48 of FALSE],
    prevalidate_free_result_strings: [oss$job_paged_literal,
          READ] array [ost$prevalidate_free_result] of record
      size: 1 .. max_free_result_string,
      value: string (max_free_result_string),
    recend := [[26, 'HEAP_ALLOCATION_ID_INVALID'], [15, 'HEAP_FREE_VALID'], [20, 'HEAP_LINKAGE_INVALID'], [20,
          'HEAP_POINTER_INVALID'], [25, 'HEAP_VERIFICATION_FAILURE']],
    process_pt_work_list: [oss$job_paged_literal, READ] bat$process_pt_work_list :=
          [bac$inhibit_locking_pt, bac$record_path, bac$resolve_path];


?? TITLE := '  [XDCL] pfp$build_archive_entry', EJECT ??

  PROCEDURE [XDCL] pfp$build_archive_entry
    (    archive_identification: pft$archive_identification;
         p_archive_array_entry: pft$p_archive_array_entry;
         p_physical_amd: pft$p_physical_amd,
         p_catalog_file: pft$p_catalog_file;
         p_archive: pft$p_archive;
     VAR status: ost$status);

    status.normal := TRUE;

    p_archive^.archive_entry.version := pfc$archive_entry_version_1;
    p_archive^.archive_entry.archive_date_time := p_archive_array_entry^.archive_date_time;
    p_archive^.archive_entry.archive_identification := archive_identification;
    p_archive^.archive_entry.file_size := p_archive_array_entry^.file_size;
    p_archive^.archive_entry.last_release_date_time := p_archive_array_entry^.last_release_date_time;
    p_archive^.archive_entry.last_retrieval_status := p_archive_array_entry^.last_retrieval_status;
    p_archive^.archive_entry.modification_date_time := p_archive_array_entry^.modification_date_time;
    p_archive^.archive_entry.release_candidate := p_archive_array_entry^.release_candidate;
    p_archive^.archive_entry.reserved_archive_entry_space := null_archive_entry_space;

    pfp$build_amd_locator (p_physical_amd, p_catalog_file, p_archive^.archive_entry.amd_locator);

    pfp$compute_checksum (#LOC (p_physical_amd^.amd), #SIZE (p_physical_amd^.amd), p_physical_amd^.checksum);

    pfp$compute_checksum (#LOC (p_archive^.archive_entry), #SIZE (p_archive^.archive_entry),
          p_archive^.checksum);

  PROCEND pfp$build_archive_entry;

?? TITLE := '  [XDCL] pfp$check_archive_entries', EJECT ??

  PROCEDURE [XDCL] pfp$check_archive_entries
    (    p_catalog_file: {input^} pft$p_catalog_file;
         p_cycle: {input^} pft$p_cycle;
     VAR valid_archive_entry_exists: boolean;
     VAR status: ost$status);

    VAR
      archive_date_time: ost$date_time,
      archive_index: pft$archive_index,
      comparison_result: pmt$comparison_result,
      data_modification_date_time: ost$date_time,
      p_archive_list: pft$p_archive_list;

    pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator, p_catalog_file,
          p_archive_list);
    IF p_archive_list = NIL THEN
      status.normal := TRUE;
      valid_archive_entry_exists := FALSE;
    ELSE
      archive_date_time := p_archive_list^ [1].archive_entry.archive_date_time;

    /search_archive_list/
      FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
        pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.archive_date_time,
              archive_date_time, comparison_result, status);
        IF NOT status.normal THEN
          CYCLE /search_archive_list/; {----->
        IFEND;
        IF comparison_result = pmc$left_is_greater THEN
          archive_date_time := p_archive_list^ [archive_index].archive_entry.archive_date_time;
        IFEND;
      FOREND /search_archive_list/;

      IF p_cycle^.cycle_entry.data_modification_date_time.year > 0 THEN
        data_modification_date_time := p_cycle^.cycle_entry.data_modification_date_time;
      ELSE
        data_modification_date_time := p_cycle^.cycle_entry.cycle_statistics.modification_date_time;
      IFEND;
      pmp$date_time_compare (archive_date_time, data_modification_date_time, comparison_result, status);
      valid_archive_entry_exists := status.normal AND (comparison_result = pmc$left_is_greater);
    IFEND;

  PROCEND pfp$check_archive_entries;

?? TITLE := '  [XDCL] pfp$check_cycle_busy', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to determine if the current
{   file activity specified by the attach_status would allow the proposed
{   activity specified by the usage_intentions and share_intentions.
{   This procedure also determines if the requested usage conflicts with
{   usage by another mainframe.

  PROCEDURE [XDCL] pfp$check_cycle_busy
    (    path: pft$complete_path;
         usage_intentions: pft$permit_selections;
         share_intentions: pft$share_selections;
         mainframe_id: pmt$binary_mainframe_id;
         p_catalog_file: {input^} ^pft$catalog_file;
         cycle_entry: pft$cycle_entry;
     VAR status: ost$status);

    VAR
      fs_path_size: fst$path_size,
      p_fs_path: ^fst$path;

    status.normal := TRUE;

    IF cycle_entry.attach_status.attach_count > 0 THEN
      IF cycle_busy_due_to_usage (cycle_entry.attach_status, usage_intentions) THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, p_fs_path^ (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, 10, FALSE,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict, status);
        RETURN; {----->
      IFEND;

      IF cycle_busy_due_to_sharing (cycle_entry.attach_status, share_intentions) THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, p_fs_path^ (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, 10, FALSE,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_share_conflict, status);
        RETURN; {----->
      IFEND;

      check_mainframe_usage (path, mainframe_id, usage_intentions, p_catalog_file, cycle_entry, status);
    IFEND;
  PROCEND pfp$check_cycle_busy;

?? TITLE := '  [XDCL] pfp$check_device_availability', EJECT ??
{
{    This procedure determines if access to the attached file should proceed,
{ for example as a result of an open file.
{ For a file attached on the local mainframe this is currently unimplemented
{   and always returns that the device is available.
{ For a file attached on the server mainframe this routine determines if the
{    the server is available, and if the server is active determines if
{    the job is at the same lifetime as the server mainframe.
{     If the server is active the following table holds:
{     --------------------------------------------------
{ CASE
{     server lifetime    =   =   =
{     job    lifetime    =   =   <
{     file   lifetime    =   <       0
{ CONDITION
{              Active    X
{  Job needs recovery            X
{     File terminated        X       X

  PROCEDURE [XDCL] pfp$check_device_availability
    (    apfid: pft$attached_permanent_file_id;
     VAR status: ost$status);

    VAR
      job_lifetime: dft$server_lifetime,
      p_served_family_entry: ^dft$served_family_table_entry,
      server_found: boolean;

    IF apfid.family_location = pfc$local_mainframe THEN
      status.normal := TRUE;
    ELSE {pfc$server_mainframe}
      dfp$fetch_served_family_entry (apfid.served_family_table_index, p_served_family_entry, status);
      IF status.normal THEN
        IF apfid.server_lifetime = 0 THEN
          { File has been terminated.
          osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated,
                p_served_family_entry^.family_name, status);
          RETURN; {----->
        IFEND;

        CASE p_served_family_entry^.server_state OF
        = dfc$awaiting_recovery, dfc$inactive, dfc$deactivated =
          dfp$get_job_server_state (p_served_family_entry^.server_mainframe_id, server_found, job_lifetime);
          IF apfid.server_lifetime < job_lifetime THEN
            { Even though the state of the server is inactive, this is an old
            { file.
            osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated,
                  p_served_family_entry^.family_name, status);
          ELSE
            { Return the status of dfe$server_not_active to allow waiting
            { to be performed as a result of waiting for unavailable server.
            osp$set_status_abnormal (dfc$file_server_id, dfe$server_not_active,
                  p_served_family_entry^.family_name, status);
          IFEND;
        = dfc$recovering =
          { Wait for the server to become active to sort out the lifetime.
          osp$set_status_abnormal (dfc$file_server_id, dfe$server_not_active,
                p_served_family_entry^.family_name, status);
        = dfc$terminated, dfc$deleted =
          osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated,
                p_served_family_entry^.family_name, status);
        ELSE { Active
          IF p_served_family_entry^.server_lifetime = apfid.server_lifetime THEN
            { The file and the server are at the same lifetime - all is active.
            { The job must be at the same lifetime, because the file could
            { not be at the same lifetime without the job being at the same
            { lifetime.
          ELSE { The file is at a different lifetime than the server.
            dfp$get_job_server_state (p_served_family_entry^.server_mainframe_id, server_found, job_lifetime);
            IF job_lifetime = p_served_family_entry^.server_lifetime THEN
              { The job and the server are at the same lifetime, but the
              { file is at a different lifetime, the apfid must be old,
              { so the file did not recover.
              osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated,
                    p_served_family_entry^.family_name, status);
            ELSE
              { The job is at a previous lifetime than the server so the
              { job has not gone through job recovery yet.
              osp$set_status_abnormal (dfc$file_server_id, dfe$server_not_active,
                    p_served_family_entry^.family_name, status);
            IFEND;
          IFEND;
        CASEND;
      ELSE { The server must have terminated
        osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, '', status);
      IFEND;
    IFEND;
  PROCEND pfp$check_device_availability;

?? TITLE := '  [XDCL] pfp$check_group_by_permit_level', EJECT ??

  PROCEDURE [XDCL] pfp$check_group_by_permit_level
    (    permit_level: pft$permit_level;
         group: pft$group;
     VAR status: ost$status);

    TYPE
      group_type_set = set of pft$group_types;

    VAR
      group_type_string: string (maximum_group_type_string_size),
      group_type_string_size: 1 .. maximum_group_type_string_size;

    status.normal := TRUE;

    CASE permit_level OF
    = pfc$pl_public =
      ;

    = pfc$pl_family =
      IF group.group_type = pfc$public THEN
        convert_group_type_to_string (group.group_type, group_type_string, group_type_string_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group_type,
              group_type_string (1, group_type_string_size), status);
      IFEND;

    = pfc$pl_account =
      IF group.group_type IN $group_type_set [pfc$public, pfc$family] THEN
        convert_group_type_to_string (group.group_type, group_type_string, group_type_string_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group_type,
              group_type_string (1, group_type_string_size), status);
      IFEND;

    = pfc$pl_project =
      IF group.group_type IN $group_type_set [pfc$public, pfc$family, pfc$account] THEN
        convert_group_type_to_string (group.group_type, group_type_string, group_type_string_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group_type,
              group_type_string (1, group_type_string_size), status);
      IFEND;

    = pfc$pl_user =
      IF group.group_type IN $group_type_set [pfc$public, pfc$family, pfc$account, pfc$project] THEN
        convert_group_type_to_string (group.group_type, group_type_string, group_type_string_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group_type,
              group_type_string (1, group_type_string_size), status);
      IFEND;

    = pfc$pl_owner =
      IF group.group_type IN $group_type_set [pfc$public, pfc$family, pfc$account, pfc$project] THEN
        convert_group_type_to_string (group.group_type, group_type_string, group_type_string_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group_type,
              group_type_string (1, group_type_string_size), status);
      ELSE
        {
        { The family_name and user name must be that of the requestor, but any
        { account and project is valid.
        {
        IF ((group.group_type = pfc$user) AND (group.user_description.family <> pfv$task_family)) OR
              ((group.group_type = pfc$user_account) AND (group.user_account_description.family <>
              pfv$task_family)) OR ((group.group_type = pfc$member) AND
              (group.member_description.family <> pfv$task_family)) THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group, 'family name', status);
        ELSEIF ((group.group_type = pfc$user) AND (group.user_description.user <> pfv$task_user)) OR
              ((group.group_type = pfc$user_account) AND (group.user_account_description.user <>
              pfv$task_user)) OR ((group.group_type = pfc$member) AND
              (group.member_description.user <> pfv$task_user)) THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_group, 'user name', status);
        IFEND;
      IFEND;

    ELSE
      {
      { Should never occur; but if it does, treat as pfc$pl_public.
      {
    CASEND;
  PROCEND pfp$check_group_by_permit_level;

?? TITLE := '  [XDCL] pfp$create_catalog_object', EJECT ??

  PROCEDURE [XDCL] pfp$create_catalog_object
    (    path: pft$complete_path;
         authority: pft$authority;
         catalog_type: pft$catalog_types;
         parent_charge_id: pft$charge_id;
         charge_id: pft$charge_id;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         p_parent_catalog_file: {i^/o^} ^pft$catalog_file;
         p_catalog_object: {output^} ^pft$physical_object;
     VAR status: ost$status);

    VAR
      local_catalog_object_locator: pft$catalog_object_locator,
      local_status: ost$status,
      new_catalog_locator: pft$catalog_locator,
      new_internal_catalog_name: pft$internal_name,
      p_physical_fmd: ^pft$physical_fmd;

    local_catalog_object_locator.catalog_type := catalog_type;
    {
    { For external catalogs, the catalog is created when the object is created,
    { because the process to update the object would be difficult when
    { allocating the first object in the catalog. For internal catalogs, the
    { object list is created when the first object must be created in the
    { object list.
    {
    IF catalog_type = pfc$external_catalog THEN
      pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} TRUE,
            new_catalog_locator, status);
      IF status.normal THEN
        pfp$record_dm_file_parameters (^path, {p_cycle_number} NIL, new_catalog_locator.system_file_id,
              rmc$mass_storage_device, {p_removable_media_req_info} NIL, {p_volume_list} NIL,
              ^p_parent_catalog_file^.catalog_heap, p_physical_fmd, status);
        IF status.normal THEN
          pfp$build_fmd_locator (p_physical_fmd, p_parent_catalog_file,
                local_catalog_object_locator.fmd_locator);
          local_catalog_object_locator.global_file_name := new_catalog_locator.global_file_name;
          new_internal_catalog_name := new_catalog_locator.internal_catalog_name;
          pfp$return_catalog (new_catalog_locator, status);
        ELSE
          pfp$destroy_catalog (new_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

      ELSEIF (status.condition = rme$file_class_not_valid) OR (status.condition = rme$job_not_valid) OR
            (status.condition = rme$volume_overflow_required) OR
            (status.condition = rme$vsn_not_part_of_set) OR (status.condition = dme$unable_to_alloc_all_space)
            THEN
        {
        { Allow abnormal status to filter up to user ring.
        {
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    ELSE {internal catalog}
      osp$generate_unique_binary_name (new_internal_catalog_name, status);
      pfp$process_unexpected_status (status);
      pfp$build_object_list_locator ({sorted_object_count} 0, {free_sorted_object_count} 0,
            {p_object_list} NIL, p_parent_catalog_file, local_catalog_object_locator.object_list_locator);
    IFEND;

    IF status.normal THEN
      p_catalog_object^.object_entry.object_type := pfc$catalog_object;
      p_catalog_object^.object_entry.external_object_name := path [UPPERBOUND (path)];
      p_catalog_object^.object_entry.internal_object_name := new_internal_catalog_name;
      pfp$build_permit_list_locator ({p_permit_list} NIL, p_parent_catalog_file,
            p_catalog_object^.object_entry.permit_list_locator);
      IF (pfc$system_owner IN authority.ownership) AND (pfc$master_catalog_path_index < UPPERBOUND (path))
            THEN
        p_catalog_object^.object_entry.charge_id := parent_charge_id;
      ELSE
        p_catalog_object^.object_entry.charge_id := charge_id;
      IFEND;
      p_catalog_object^.object_entry.reserved_object_entry_space := pfv$null_object_entry_space;
      p_catalog_object^.object_entry.catalog_recreated_by_restore :=
            osv$recover_system_set_phase = osc$reinitialize_system_device;
      p_catalog_object^.object_entry.catalog_object_locator := local_catalog_object_locator;
      p_catalog_object^.object_entry.reserved_catalog_entry_space := pfv$null_catalog_entry_space;
      pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (pft$object_entry),
            p_catalog_object^.checksum);
    IFEND;
  PROCEND pfp$create_catalog_object;

?? TITLE := '  [XDCL] pfp$create_file_object', EJECT ??

  PROCEDURE [XDCL] pfp$create_file_object
    (    file_name: pft$name;
         authority: pft$authority;
         parent_charge_id: pft$charge_id;
         password: pft$password;
         log: pft$log;
     VAR object_entry: pft$object_entry);

    VAR
      status: ost$status;

    object_entry.external_object_name := file_name;
    osp$generate_unique_binary_name (object_entry.internal_object_name, status);
    pfp$process_unexpected_status (status);
    pfp$build_permit_list_locator ({p_permit_list} NIL, {p_catalog_file} NIL,
          object_entry.permit_list_locator);
    IF pfc$system_owner IN authority.ownership THEN
      object_entry.charge_id := parent_charge_id;
    ELSE
      object_entry.charge_id.account := authority.account;
      object_entry.charge_id.project := authority.project;
    IFEND;
    object_entry.object_type := pfc$file_object;
    object_entry.password := password;
    object_entry.logging_selection := log;
    pfp$build_log_list_locator ({p_log_list} NIL, {p_catalog_file} NIL, object_entry.log_list_locator);
    pfp$build_cycle_list_locator ({p_cycle_list} NIL, {p_catalog_file} NIL, object_entry.cycle_list_locator);
    object_entry.reserved_object_entry_space := pfv$null_object_entry_space;
    object_entry.reserved_file_entry_space := pfv$null_file_entry_space;
  PROCEND pfp$create_file_object;

?? TITLE := '  [XDCL, #GATE] pfp$dm_return_item', EJECT ??
*copy pfh$dm_return_item

  PROCEDURE [XDCL, #GATE] pfp$dm_return_item
    (    sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      file_info: dmt$file_information,
      file_modified: boolean,
      fmd_modified: boolean;

    dmp$detach_file (sfid, {access_allowed} TRUE, {flush_pages} TRUE, dmc$df_ignore_file_info, file_modified,
          fmd_modified, file_info, status);
    IF status.normal THEN
      dmp$delete_file_descriptor (sfid, status);
      status.normal := status.normal OR (status.condition = dme$file_descriptor_not_deleted);
    IFEND;
  PROCEND pfp$dm_return_item;
?? TITLE := '  pfp$r2_get_vol_condition_list', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_get_vol_condition_list
    (    unique_volume_list: pft$unique_volume_list;
     VAR volume_condition_list: fst$volume_condition_list);

    VAR
      conditions: fst$file_access_conditions,
      volume_index: ost$non_negative_integers;

    FOR volume_index := LOWERBOUND (unique_volume_list) TO UPPERBOUND (unique_volume_list) DO
      volume_condition_list [volume_index] := osp$get_volume_condition (unique_volume_list [volume_index]);
    FOREND;

  PROCEND pfp$r2_get_vol_condition_list;

?? TITLE := '  [XDCL] pfp$increment_usage_counts', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to increment the attach status and the
{   mainframe usage to reflect the additional activity indicated by the usage_selections
{   and share_selections parameters.

  PROCEDURE [XDCL] pfp$increment_usage_counts
    (    path: pft$complete_path;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         mainframe_id: pmt$binary_mainframe_id;
         p_catalog_file: {input, output} ^pft$catalog_file;
     VAR flush_catalog_pages: boolean;
     VAR cycle_entry {input, output} : pft$cycle_entry;
     VAR status: ost$status);

    update_mainframe_usage (path, mainframe_id, usage_selections, p_catalog_file, flush_catalog_pages,
          cycle_entry, status);
    IF status.normal THEN
      increment_attach_status (cycle_entry.attach_status, usage_selections, share_selections,
            cycle_entry.attach_status);
    IFEND;
  PROCEND pfp$increment_usage_counts;

?? TITLE := '  [XDCL] pfp$initialize_job_recovery', EJECT ??
{       PFP$INITIALIZE_JOB_RECOVERY
{
{   This procedure initializes the permanent file part of file recovery with
{ active job recovery. This involves deleting queued catalogs and marking all
{ attached files as being in recovery.

  PROCEDURE [XDCL] pfp$initialize_job_recovery
    (    file_recovery_state: pft$attached_pf_recovery_state;
     VAR status: ost$status);

    pfp$remove_queued_catalogs;
    pfp$setup_attached_pf_recovery (file_recovery_state, status);
  PROCEND pfp$initialize_job_recovery;

?? TITLE := '  [XDCL] pfp$internal_return_file', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to return an attached permanent file.
{   This routine always runs on the mainframe where the catalogs reside.
{   The caller is required to pass in the attached permanent file table index
{   and the mainframe_id of the mainframe that has the file attached.

  PROCEDURE [XDCL] pfp$internal_return_file
    (    attached_pf_table_index: pft$attached_pf_table_index;
         mainframe_id: pmt$binary_mainframe_id;
     VAR authority: pft$authority;
     VAR bytes_allocated_change: sft$counter;
     VAR status: ost$status);

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

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

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := p_attached_pf_entry^.p_external_path;

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

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

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

        syp$pop_inhibit_job_recovery;

        pfp$unlock_apfid (attached_pf_table_index, p_attached_pf_entry, local_status);
        IF pfv$locked_apfid <> 0 THEN
          pfp$release_locked_apfid (pfv$locked_apfid, local_status);
          pfv$locked_apfid := 0;
        IFEND;

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

        status := local_status;
        initiate_non_local_exit;


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

    PROCEND internal_return_file_handler;

    PROCEDURE initiate_non_local_exit;

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

    CONST
      extract_permits = TRUE,
      system_privilege = TRUE;

    VAR
      access_kind: pft$access_kind,
      bytes_released: amt$file_byte_address,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      date_time: ost$date_time,
      device_class: rmt$device_class,
      disk_image_deleted: boolean,
      file_info: dmt$file_information,
      fmd_modified: boolean,
      internal_cycle_name: pft$internal_name,
      local_status: ost$status,
      p_attached_pf_entry: pft$p_attached_pf_entry,
      p_cycle: pft$p_cycle,
      p_cycle_list: pft$p_cycle_list,
      p_file_object: pft$p_object,
      p_internal_path: pft$p_internal_path,
      p_path_string: ^ost$string,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      purge_cycle_options: pft$purge_cycle_options,
      set_name: stt$set_name,
      sfid: gft$system_file_identifier,
      share_selections: pft$share_selections,
      update_catalog: boolean,
      usage_selections: pft$usage_selections;

    syp$push_inhibit_job_recovery;
    bytes_allocated_change := 0;
    status.normal := TRUE;
    pfp$lock_apfid (attached_pf_table_index, p_attached_pf_entry, status);
    IF NOT status.normal THEN
      pfp$report_unexpected_status (status);
      RETURN; {----->
    ELSEIF p_attached_pf_entry = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
            'NIL p_attached_pf_entry AND valid apfid.', status);
      RETURN; {----->
    IFEND;

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

      set_name := p_attached_pf_entry^.p_external_path^ [pfc$set_path_index];
      p_internal_path := ^p_attached_pf_entry^.internal_cycle_path.path;
      internal_cycle_name := p_attached_pf_entry^.internal_cycle_path.cycle_name;
      update_catalog := p_attached_pf_entry^.update_catalog;
      IF update_catalog THEN
        access_kind := pfc$write_access;
      ELSE
        access_kind := pfc$read_access;
      IFEND;
      usage_selections := p_attached_pf_entry^.usage_selections;
      share_selections := p_attached_pf_entry^.share_selections;
      IF (p_attached_pf_entry^.sfid_status.recovery_state = pfc$attached_pf_normal) OR
            (p_attached_pf_entry^.sfid_status.recovery_state = pfc$attached_pf_awaiting_client) THEN
        sfid := p_attached_pf_entry^.sfid_status.sfid;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Return called with non-normal sfid.', status);
        EXIT /internal_return_file/; {----->
      IFEND;

      pfp$get_authority (p_attached_pf_entry^.p_external_path^, NOT system_privilege, authority, status);
      IF NOT status.normal THEN
        EXIT /internal_return_file/; {----->
      IFEND;

    /internal_access_object/
      WHILE TRUE DO
        pfp$internal_access_object (set_name, p_internal_path^, access_kind, authority, NOT extract_permits,
              (p_attached_pf_entry^.p_external_path^ [pfc$family_path_index] <> osv$system_family_name),
              p_file_object, catalog_locator, permit_entry, status);
        IF status.normal OR (status.condition <> pfe$catalog_access_retry) THEN
          EXIT /internal_access_object/; {----->
        ELSE
          syp$pop_inhibit_job_recovery;
          pfp$catalog_access_retry_wait ('PFP$INTERNAL_ACCESS_OBJECT');
          syp$push_inhibit_job_recovery;
        IFEND;
      WHILEND /internal_access_object/;

      catalog_active := status.normal;
      IF NOT status.normal THEN
        IF (NOT update_catalog) AND (status.condition = pfe$unknown_permanent_file) THEN
          {
          { This error will occur if a job terminates, and its swap file is
          { deleted, before job recovery completes and it attempts to detach
          { the swap file.
          {
          status.normal := TRUE;
        IFEND;
        EXIT /internal_return_file/; {----->
      IFEND;

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

      IF pfv$restrict_catalog_flushing THEN
        catalog_locator.flush_catalog_pages := FALSE;
      IFEND;

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      internal_locate_cycle (p_cycle_list, internal_cycle_name, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /internal_return_file/; {----->
      IFEND;

      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;

      IF device_class = rmc$mass_storage_device THEN
        pfp$detach_permanent_file (^p_attached_pf_entry^.p_external_path^, sfid, usage_selections,
              update_catalog, p_cycle, catalog_locator.p_catalog_file, dmc$df_return_file_info, fmd_modified,
              file_info, status);
      ELSEIF device_class = rmc$magnetic_tape_device THEN
        file_info.trimmed_length := 0;
        file_info.eoi_byte_address := 0;
        file_info.total_allocated_length := 0;
      IFEND;

      IF NOT update_catalog THEN
        EXIT /internal_return_file/; {----->
      IFEND;

      IF status.normal OR NOT osp$file_access_condition (status) THEN
        decrement_usage_counts (usage_selections, share_selections, mainframe_id,
              catalog_locator.p_catalog_file, p_cycle^.cycle_entry);
        bytes_allocated_change := -file_info.trimmed_length;
        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;

        IF p_attached_pf_entry^.update_cycle_statistics THEN
          pmp$get_compact_date_time (date_time, local_status);
          pfp$process_unexpected_status (local_status);
          update_cycle_statistics (p_cycle^.cycle_entry.cycle_statistics, date_time, usage_selections,
                share_selections, p_cycle^.cycle_entry.cycle_statistics,
                p_cycle^.cycle_entry.data_modification_date_time);
        IFEND;

        IF fmd_modified THEN
          catalog_locator.flush_catalog_pages := pfv$flush_catalogs;
        IFEND;

        CASE p_cycle^.cycle_entry.data_residence OF
        = pfc$release_data_requested =
          release_cycle_data (p_attached_pf_entry^.p_external_path^, p_cycle, catalog_locator.p_catalog_file,
                {p_release_data_info} NIL, local_status);
        = pfc$offline_data =
          p_cycle^.cycle_entry.entry_type := pfc$normal_cycle_entry;
        ELSE
          ;
        CASEND;

        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      ELSEIF status.condition = pfe$pf_system_error THEN
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (p_attached_pf_entry^.p_external_path^,
              p_attached_pf_entry^.cycle_number, p_path_string^);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_path_string^.
              value (1, p_path_string^.size), status);
      IFEND;

      IF (status.normal OR NOT osp$file_access_condition (status)) AND
            (p_cycle^.cycle_entry.entry_type = pfc$purged_cycle_entry) THEN
        purge_cycle_options.preserve_cycle_entry := FALSE;
        purge_cycle (p_attached_pf_entry^.p_external_path^, device_class, purge_cycle_options,
              {p_data_modification_date_time} NIL, p_cycle, catalog_locator.p_catalog_file, p_file_object,
              catalog_locator.object_list_descriptor, disk_image_deleted, bytes_released, local_status);
        IF status.normal THEN
          IF local_status.normal THEN
            bytes_allocated_change := -bytes_released;
          ELSE
            status := local_status;
          IFEND;
        IFEND;
        pfp$process_unexpected_status (local_status);
      IFEND;

      syp$hang_if_job_jrt_set (pfc$tjr_return);
    END /internal_return_file/;

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

    IF status.normal OR NOT osp$file_access_condition (status) THEN
      IF p_attached_pf_entry^.p_external_path <> NIL THEN
        FREE p_attached_pf_entry^.p_external_path IN pfv$p_p_job_heap^^;
      IFEND;
      FREE p_attached_pf_entry IN pfv$p_p_job_heap^^;
      pfp$release_locked_apfid (attached_pf_table_index, local_status);
      pfp$process_unexpected_status (local_status);
    ELSE
      pfp$unlock_apfid (attached_pf_table_index, p_attached_pf_entry, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$internal_return_file;

?? TITLE := '  [XDCL] pfp$internal_save_file_label', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to save a file label for an attached
{   permanent file cycle.  The file label specified by the caller replaces any
{   file label previously saved for the cycle.
{
{ DESIGN:
{   If the cycle does not yet have a file label stored in the catalog, then
{   whatever permission was necessary to get to this point is sufficient to
{   save the file label provided.  If the cycle already has a file label
{   stored in the catalog and the cycle has not been previously opened, then
{   either append permission is necessary to save the new file label.  If the
{   cycle already has a file label stored in the catalog and the cycle has been
{   previously opened, then control permission is necessary to save the new
{   file label.

  PROCEDURE [XDCL] pfp$internal_save_file_label
    (    apfid: pft$attached_permanent_file_id;
         system_authority: pft$system_authority;
         required_permission: pft$permit_options;
         p_file_label: {input} ^fmt$file_label;
     VAR p_save_file_label_audit_seq: {i/o} ^SEQ ( * );
     VAR status: ost$status);

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

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

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := p_attached_pf_entry^.p_external_path;

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

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

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

        syp$pop_inhibit_job_recovery;

        IF apfid_locked THEN
          pfp$unlock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, local_status);
        IFEND;

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

        status := local_status;
        initiate_non_local_exit;


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

    PROCEND save_file_label_handler;

    PROCEDURE initiate_non_local_exit;

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

    VAR
      apfid_locked: boolean,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      date_time: ost$date_time,
      file_previously_opened: boolean,
      internal_cycle_name: pft$internal_name,
      local_status: ost$status,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_complete_path: ^pft$complete_path,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_local_file_label: ^fmt$file_label,
      p_path_string: ^ost$string,
      p_save_label_audit_info: ^pft$save_label_audit_info,
      p_static_label_header: ^fmt$static_label_header,
      p_stored_file_label: ^pft$physical_file_label,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      static_label_attributes: bat$static_label_attributes,
      system_privilege: boolean;

    syp$push_inhibit_job_recovery;

  /internal_save_file_label/
    BEGIN
      apfid_locked := FALSE;
      catalog_active := FALSE;
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);
      status.normal := TRUE;

      IF p_file_label = NIL THEN
        osp$set_status_condition (pfe$nil_pointer, status);
        EXIT /internal_save_file_label/; {----->
      IFEND;

      pfp$lock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, status);
      apfid_locked := status.normal;
      IF (NOT status.normal) OR (p_attached_pf_entry = NIL) THEN
        p_save_file_label_audit_seq := NIL;
        EXIT /internal_save_file_label/; {----->
      IFEND;

      IF p_attached_pf_entry^.update_catalog THEN
        {
        { This procedure is only callable from ring 3 or below.  Therefore, the
        { caller's ring need not be used in determining system_privilege.
        {
        system_privilege := pfp$system_privilege_authority (system_authority, osc$tsrv_ring,
              p_attached_pf_entry^.p_external_path^ [pfc$master_catalog_path_index]);
        pfp$get_authority (p_attached_pf_entry^.p_external_path^, system_privilege, authority, status);
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Save file label issued but catalog update not allowed.', status);
        EXIT /internal_save_file_label/; {----->
      IFEND;

    /internal_access_object/
      WHILE TRUE DO
        pfp$internal_access_object (p_attached_pf_entry^.p_external_path^ [pfc$set_path_index],
              p_attached_pf_entry^.internal_cycle_path.path, pfc$write_access, authority,
              {extract_permits} TRUE, (p_attached_pf_entry^.p_external_path^ [pfc$family_path_index] <>
              osv$system_family_name), p_file_object, catalog_locator, permit_entry, status);
        IF status.normal OR (status.condition <> pfe$catalog_access_retry) THEN
          EXIT /internal_access_object/; {----->
        ELSE
          syp$pop_inhibit_job_recovery;
          pfp$catalog_access_retry_wait ('PFP$INTERNAL_ACCESS_OBJECT');
          syp$push_inhibit_job_recovery;
        IFEND;
      WHILEND /internal_access_object/;

      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /internal_save_file_label/; {----->
      IFEND;

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

      internal_cycle_name := p_attached_pf_entry^.internal_cycle_path.cycle_name;
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      internal_locate_cycle (p_cycle_list, internal_cycle_name, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /internal_save_file_label/; {----->
      IFEND;

      IF p_save_file_label_audit_seq <> NIL THEN
        RESET p_save_file_label_audit_seq;
        NEXT p_save_label_audit_info IN p_save_file_label_audit_seq;

        NEXT p_complete_path: [1 .. UPPERBOUND (p_attached_pf_entry^.p_external_path^)] IN
              p_save_file_label_audit_seq;
        IF p_complete_path = NIL THEN
          p_save_file_label_audit_seq := NIL;
        ELSE
          p_complete_path^ := p_attached_pf_entry^.p_external_path^;
          p_save_label_audit_info^.file_path_count := UPPERBOUND (p_attached_pf_entry^.p_external_path^);
          p_save_label_audit_info^.cycle_selector.cycle_option := pfc$specific_cycle;
          p_save_label_audit_info^.cycle_selector.cycle_number := p_cycle^.cycle_entry.cycle_number;

          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,
                  p_save_label_audit_info^.device_class);
          ELSE
            p_save_label_audit_info^.device_class := rmc$mass_storage_device;
          IFEND;

          p_save_label_audit_info^.ownership := authority.ownership;

          IF (p_file_label = NIL) OR (#SIZE (p_file_label^) < #SIZE (fmt$static_label_header)) THEN
            p_save_label_audit_info^.fap_audit_info.audit := FALSE;
            p_save_label_audit_info^.ring_audit_info.audit := FALSE;
          ELSE
            p_local_file_label := p_file_label;
            RESET p_local_file_label;
            NEXT p_static_label_header IN p_local_file_label;

            IF (p_static_label_header = NIL) OR (p_static_label_header^.unique_character <>
                  fmc$unique_label_id) THEN
              p_save_label_audit_info^.fap_audit_info.audit := FALSE;
              p_save_label_audit_info^.ring_audit_info.audit := FALSE;
            ELSE
              IF (fmc$file_access_procedure <= p_static_label_header^.highest_attribute_present) AND
                    p_static_label_header^.attribute_present [fmc$file_access_procedure] THEN
                fsp$expand_file_label (p_local_file_label, static_label_attributes, file_previously_opened,
                      local_status);
                IF local_status.normal THEN
                  p_save_label_audit_info^.fap_audit_info.audit := TRUE;
                  p_save_label_audit_info^.fap_audit_info.fap_name :=
                        static_label_attributes.file_access_procedure;
                ELSE
                  p_save_label_audit_info^.fap_audit_info.audit := FALSE;
                IFEND;
              ELSE
                p_save_label_audit_info^.fap_audit_info.audit := FALSE;
              IFEND;

              IF p_static_label_header^.file_previously_opened THEN
                p_save_label_audit_info^.ring_audit_info.audit := TRUE;
                p_save_label_audit_info^.ring_audit_info.ring_attributes :=
                      p_static_label_header^.ring_attributes;
              ELSE
                p_save_label_audit_info^.ring_audit_info.audit := FALSE;
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, catalog_locator.p_catalog_file,
            p_stored_file_label);
      IF p_stored_file_label = NIL THEN
        IF (p_save_file_label_audit_seq <> NIL) AND (NOT p_save_label_audit_info^.fap_audit_info.audit) AND
              NOT p_save_label_audit_info^.ring_audit_info.audit THEN
          p_save_file_label_audit_seq := NIL;
        IFEND;
      ELSE
        IF p_save_file_label_audit_seq <> NIL THEN
          IF #SIZE (fmt$static_label_header) <= #SIZE (p_stored_file_label^.file_label) THEN
            p_local_file_label := ^p_stored_file_label^.file_label;
            RESET p_local_file_label;
            NEXT p_static_label_header IN p_local_file_label;

            IF (p_static_label_header <> NIL) AND (p_static_label_header^.unique_character =
                  fmc$unique_label_id) THEN
              IF (fmc$file_access_procedure <= p_static_label_header^.highest_attribute_present) AND
                    p_static_label_header^.attribute_present [fmc$file_access_procedure] THEN
                fsp$expand_file_label (p_local_file_label, static_label_attributes, file_previously_opened,
                      local_status);
                IF local_status.normal THEN
                  IF p_save_label_audit_info^.fap_audit_info.audit THEN
                    p_save_label_audit_info^.fap_audit_info.audit :=
                          p_save_label_audit_info^.fap_audit_info.fap_name <>
                          static_label_attributes.file_access_procedure;
                  ELSE
                    p_save_label_audit_info^.fap_audit_info.audit := TRUE;
                    p_save_label_audit_info^.fap_audit_info.fap_name := osc$null_name;
                  IFEND;
                ELSEIF NOT p_save_label_audit_info^.fap_audit_info.audit THEN
                  p_save_label_audit_info^.fap_audit_info.audit := TRUE;
                  p_save_label_audit_info^.fap_audit_info.fap_name := osc$null_name;
                IFEND;
              IFEND;

              IF p_static_label_header^.file_previously_opened THEN
                p_save_label_audit_info^.ring_audit_info.audit :=
                      p_save_label_audit_info^.ring_audit_info.ring_attributes <>
                      p_static_label_header^.ring_attributes;
              IFEND;
            IFEND;
          IFEND;

          IF (NOT p_save_label_audit_info^.fap_audit_info.audit) AND
                NOT p_save_label_audit_info^.ring_audit_info.audit THEN
            p_save_file_label_audit_seq := NIL;
          IFEND;
        IFEND;

        IF required_permission = pfc$control THEN
          pfp$validate_file_permission (p_attached_pf_entry^.p_external_path^, authority, permit_entry,
                $pft$permit_selections [pfc$control], -$pft$share_selections [], status);
          IF NOT status.normal THEN
            EXIT /internal_save_file_label/; {----->
          IFEND;
        IFEND;
      IFEND;

      store_file_label (p_attached_pf_entry^.p_external_path^, p_file_label, catalog_locator.p_catalog_file,
            p_cycle, p_stored_file_label, status);
      IF NOT status.normal THEN
        EXIT /internal_save_file_label/; {----->
      IFEND;

      IF p_attached_pf_entry^.update_cycle_statistics THEN
        pmp$get_compact_date_time (date_time, local_status);
        pfp$process_unexpected_status (local_status);
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        p_cycle^.cycle_entry.data_modification_date_time := date_time;
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      IFEND;
    END /internal_save_file_label/;

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

    IF apfid_locked THEN
      pfp$unlock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$internal_save_file_label;

?? TITLE := '  [XDCL] pfp$pick_modes_for_open', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to pick the first set of access and share
{   modes specified which is compatible with how the cycle is already attached
{   within the job.

  PROCEDURE [XDCL] pfp$pick_modes_for_open
    (    evaluated_file_reference: fst$evaluated_file_reference;
         p_attachment_options: {input} ^fst$attachment_options;
         allowed_access: fst$file_access_options;
         required_sharing: fst$file_access_options;
         setfa_access_modes: fst$access_modes;
         device_class: rmt$device_class;
         cycle_formerly_opened_info: fmt$cycle_formerly_opened_info;
         called_by_attach: boolean;
         create_file: boolean;
         validation_ring: ost$valid_ring;
     VAR selected_access: fst$file_access_options;
     VAR selected_sharing: fst$file_access_options;
     VAR status: ost$status);

    VAR
      access_modes: fst$access_modes,
      access_selections: fst$file_access_options,
      fs_path_size: fst$path_size,
      ignore_status: ost$status,
      last_access_and_share_mode_ind: ost$non_negative_integers,
      local_status: ost$status,
      option_index: ost$non_negative_integers,
      p_fs_path: ^fst$path,
      permitted_access_modes_failure: boolean,
      share_modes: fst$share_modes,
      share_selections: fst$file_access_options,
      usage_selections: pft$usage_selections,
      valid_ring: boolean;

    IF p_attachment_options = NIL THEN
      last_access_and_share_mode_ind := 0;
    ELSE
      last_access_and_share_mode_ind := 0;

    /find_last_access_and_share_mode/
      FOR option_index := UPPERBOUND (p_attachment_options^) DOWNTO 1 DO
        IF p_attachment_options^ [option_index].selector = fsc$access_and_share_modes THEN
          last_access_and_share_mode_ind := option_index;
          EXIT /find_last_access_and_share_mode/; {----->
        IFEND;
      FOREND /find_last_access_and_share_mode/;
    IFEND;

    option_index := 0;
    REPEAT
      IF option_index < last_access_and_share_mode_ind THEN
        REPEAT
          option_index := option_index + 1;
        UNTIL p_attachment_options^ [option_index].selector = fsc$access_and_share_modes;
      IFEND;

      IF option_index > 0 THEN
        access_modes := p_attachment_options^ [option_index].access_modes;
        IF device_class = rmc$mass_storage_device THEN
          share_modes := p_attachment_options^ [option_index].share_modes;
        ELSEIF device_class = rmc$magnetic_tape_device THEN
          share_modes.selector := fsc$specific_share_modes;
          share_modes.value := $fst$file_access_options [];
        IFEND;
        status.normal := TRUE;
      ELSE
        {
        { Use setfa access modes and default share modes. (If access
        { modes were not specified via a setfa, they will default to
        { fsc$permitted_access_modes.)
        {
        access_modes := setfa_access_modes;
        IF device_class = rmc$mass_storage_device THEN
          share_modes.selector := fsc$determine_from_access_modes;
        ELSEIF device_class = rmc$magnetic_tape_device THEN
          share_modes.selector := fsc$specific_share_modes;
          share_modes.value := $fst$file_access_options [];
        IFEND;
        status.normal := TRUE;
      IFEND;

      IF status.normal THEN
        validate_access_and_share_modes (evaluated_file_reference, {last_access_and_share_modes}
              (option_index = last_access_and_share_mode_ind), access_modes, share_modes, allowed_access,
              required_sharing, {initial_open}
              ((NOT cycle_formerly_opened_info.cycle_previously_opened) AND NOT called_by_attach),
              create_file, device_class, access_selections, share_selections, permitted_access_modes_failure,
              status);
      IFEND;

      IF status.normal THEN
        IF cycle_formerly_opened_info.cycle_previously_opened THEN
          #UNCHECKED_CONVERSION (access_selections, usage_selections);
          ring_vote_selected_access (access_modes.selector, cycle_formerly_opened_info, validation_ring,
                usage_selections, valid_ring);
          IF (NOT valid_ring) AND (usage_selections <> $pft$usage_selections []) THEN
            permitted_access_modes_failure := (access_modes.selector = fsc$permitted_access_modes);
            IF (option_index = last_access_and_share_mode_ind) OR permitted_access_modes_failure THEN
              PUSH p_fs_path;
              clp$convert_file_ref_to_string (evaluated_file_reference, {include_open_position} FALSE,
                    p_fs_path^, fs_path_size, ignore_status);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_ring_access,
                    p_fs_path^ (1, fs_path_size), status);
            ELSE
              osp$set_status_condition (pfe$invalid_ring_access, status);
            IFEND;
          ELSE
            #UNCHECKED_CONVERSION (usage_selections, selected_access);
            selected_sharing := share_selections;
          IFEND;
        ELSE
          selected_access := access_selections;
          selected_sharing := share_selections;
        IFEND;
      IFEND;
    UNTIL status.normal OR (option_index = last_access_and_share_mode_ind) OR (option_index = 0) OR
          permitted_access_modes_failure OR ((status.condition <> pfe$cycle_busy) AND
          (status.condition <> ame$new_file_requires_append) AND
          (status.condition <> pfe$invalid_ring_access) AND (status.condition <>
          pfe$null_access_not_allowed));
  PROCEND pfp$pick_modes_for_open;

?? TITLE := '  [XDCL, #GATE] pfp$process_job_end', EJECT ??
*copy pfh$process_job_end

  PROCEDURE [XDCL, #GATE] pfp$process_job_end
    (    files_binary_mainframe_id: pmt$binary_mainframe_id;
     VAR return_files_option: pft$return_files_option);

    syp$push_inhibit_job_recovery;
    IF return_files_option.return_files THEN
      pfp$detach_all_files (files_binary_mainframe_id, return_files_option);
    IFEND;
    pfp$detach_all_catalogs;
    syp$pop_inhibit_job_recovery;
  PROCEND pfp$process_job_end;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_append_rem_media_vsn
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         volume_descriptor: rmt$volume_descriptor;
     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_append_rem_media_vsn; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_stored_fmd: ^pft$physical_fmd,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    status.normal := TRUE;

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;
    IF status.normal THEN
      pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file, p_stored_fmd);
      IF p_stored_fmd <> NIL THEN
        append_rem_media_vsn (path, volume_descriptor, catalog_locator.p_catalog_file, p_cycle, status);
      IFEND;
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_append_rem_media_vsn;

?? TITLE := '  [XDCL, #GATE] pfp$r2_attach', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to check whether the cycle is already
{   attached within the job, and to optionally call pfp$r2_df_attach or
{   pfp$r2_attach_file.
{
{ NOTE:
{   The path table must be locked throughout.

  PROCEDURE [XDCL, #GATE] pfp$r2_attach
    (    r2_attach_input: pft$r2_attach_in;
         update_catalog: boolean;
         update_cycle_statistics: boolean;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         system_privilege: boolean;
         validation_ring: ost$valid_ring;
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR cycle_number: fst$cycle_number;
     VAR cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR global_file_name: dmt$global_file_name;
     VAR status: ost$status);

    VAR
      allowed_usage_selections: pft$usage_selections,
      attachment_options: array [1 .. 1] of fst$attachment_option,
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      authority: pft$authority,
      authority_known: boolean,
      cycle_attached: boolean,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      cycle_selector: pft$cycle_selector,
      device_class: rmt$device_class,
      df_attach_input: pft$df_attach_in,
      evaluated_file_reference: fst$evaluated_file_reference,
      fs_path_size: fst$path_size,
      mainframe_id: pmt$binary_mainframe_id,
      p_cycle_description: ^fmt$cycle_description,
      p_file_server_buffers: ^pft$file_server_buffers,
      p_fs_path: ^fst$path,
      p_ignore_status: ^ost$status,
      p_local_status: ^ost$status,
      path_table_cycle_info: fmt$path_table_cycle_info,
      process_pt_results: bat$process_pt_results,
      required_share_selections: pft$share_selections,
      selected_access: fst$file_access_options,
      selected_sharing: fst$file_access_options,
      share_selector: pft$share_selector,
      tape_file_attached: boolean,
      usage_selector: pft$usage_selector;

    fmp$lock_path_table (status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF r2_attach_input.cycle_selector.cycle_option = pfc$specific_cycle THEN
      IF r2_attach_input.served_family THEN
        pfp$convert_pft$path_to_fs_str (r2_attach_input.p_path^, evaluated_file_reference);
      ELSE
        pfp$convert_pf_to_fs_structure (r2_attach_input.p_complete_path^, evaluated_file_reference);
      IFEND;
      evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
      evaluated_file_reference.cycle_reference.cycle_number := r2_attach_input.cycle_selector.cycle_number;
      fmp$get_path_table_cycle_info (inhibit_path_table_lock, evaluated_file_reference, path_table_cycle_info,
            status);

      cycle_attached := status.normal AND path_table_cycle_info.path_registered AND
            path_table_cycle_info.cycle_attachment_info.cycle_attached;

      IF cycle_attached THEN
        IF path_table_cycle_info.cycle_attachment_info.password_protected OR
              (r2_attach_input.password <> osc$null_name) THEN
          IF r2_attach_input.served_family THEN
            pfp$r2_df_client_validate_pw (r2_attach_input.served_family_locator, r2_attach_input.p_path^,
                  r2_attach_input.password, status);
          ELSE
            pfp$r2_validate_password (r2_attach_input.p_complete_path^, r2_attach_input.password, status);
          IFEND;
        IFEND;

        IF status.normal THEN
          IF path_table_cycle_info.cycle_device_info.device_assigned THEN
            device_class := path_table_cycle_info.cycle_device_info.device_class;
            cycle_formerly_opened_info := path_table_cycle_info.cycle_device_info.cycle_formerly_opened_info;
          ELSE
            device_class := rmc$mass_storage_device;
            cycle_formerly_opened_info.cycle_previously_opened := FALSE;
          IFEND;

          attachment_options [1].selector := fsc$access_and_share_modes;
          attachment_options [1].access_modes.selector := fsc$specific_access_modes;
          #UNCHECKED_CONVERSION (usage_selections, attachment_options [1].access_modes.value);
          attachment_options [1].share_modes.selector := fsc$specific_share_modes;
          #UNCHECKED_CONVERSION (share_selections, attachment_options [1].share_modes.value);

          pfp$pick_modes_for_open (evaluated_file_reference, ^attachment_options,
                path_table_cycle_info.cycle_attachment_info.allowed_access,
                path_table_cycle_info.cycle_attachment_info.required_sharing,
                path_table_cycle_info.setfa_access_modes, device_class, cycle_formerly_opened_info,
                {called_by_attach} TRUE, {create_file} FALSE, validation_ring, selected_access,
                selected_sharing, status);
        ELSE
          device_class := rmc$mass_storage_device;
        IFEND;

        IF status.normal THEN
          fmp$process_pt_request (process_pt_work_list, r2_attach_input.lfn, evaluated_file_reference,
                p_cycle_description, process_pt_results, status);

          IF status.normal THEN
            cycle_number := r2_attach_input.cycle_selector.cycle_number;
          IFEND;
        IFEND;
      ELSE
        device_class := rmc$mass_storage_device;
      IFEND;
    ELSE
      status.normal := TRUE;
      cycle_attached := FALSE;
    IFEND;

    IF status.normal AND NOT cycle_attached THEN
      pmp$get_pseudo_mainframe_id (mainframe_id);
      usage_selector.option := pfc$specific_usage_option;
      usage_selector.usage_selections := usage_selections;
      share_selector.option := pfc$specific_share_option;
      share_selector.share_selections := share_selections;

      IF r2_attach_input.served_family THEN
        df_attach_input.mainframe_id := mainframe_id;
        df_attach_input.cycle_selector := r2_attach_input.cycle_selector;
        df_attach_input.password := r2_attach_input.password;
        df_attach_input.usage_selector := usage_selector;
        df_attach_input.share_selector := share_selector;
        df_attach_input.allowed_device_classes := -$fst$device_classes [];
        df_attach_input.allowed_cycle_damage_symptoms := allowed_cycle_damage_symptoms;
        df_attach_input.system_privilege := system_privilege;
        df_attach_input.validation_ring := validation_ring;
        df_attach_input.update_catalog := update_catalog;
        df_attach_input.update_cycle_statistics := update_cycle_statistics;
        df_attach_input.path_length := UPPERBOUND (r2_attach_input.p_path^);
        pfp$r2_df_client_attach (r2_attach_input.served_family_locator, r2_attach_input.lfn,
              r2_attach_input.p_path^, df_attach_input, cycle_number, device_class, cycle_damage_symptoms,
              global_file_name, status);
        IF (NOT status.normal) AND (status.condition = pfe$tape_attached_on_client) THEN
          PUSH p_local_status;
          iop$tape_file_attached (global_file_name, tape_file_attached, p_local_status^);
          IF p_local_status^.normal THEN
            IF tape_file_attached THEN
              PUSH p_fs_path;
              pfp$convert_pf_path_to_fs_path (r2_attach_input.p_path^, p_fs_path^, fs_path_size);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
                    p_fs_path^ (1, fs_path_size), status);
              osp$append_status_integer (osc$status_parameter_delimiter, cycle_number, radix,
                    NOT include_radix, status);
              osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict,
                    status);
            ELSE
              pfp$r2_df_client_clear_cy_att (r2_attach_input.served_family_locator, r2_attach_input.p_path^,
                    r2_attach_input.cycle_selector, r2_attach_input.password, p_local_status^);
              IF NOT p_local_status^.normal THEN
                status := p_local_status^;
              IFEND;
            IFEND;
          ELSE
            status := p_local_status^;
          IFEND;
        IFEND;
        authority_known := FALSE;
      ELSE
        p_file_server_buffers := NIL;
        pfp$r2_attach_file (pfc$local_mainframe, mainframe_id, r2_attach_input.lfn,
              r2_attach_input.p_complete_path^, r2_attach_input.cycle_selector, r2_attach_input.password,
              update_catalog, update_cycle_statistics, usage_selector, share_selector, system_privilege,
              validation_ring, {allowed_device_classes} - $fst$device_classes [],
              allowed_cycle_damage_symptoms, device_class, cycle_number, allowed_usage_selections,
              required_share_selections, cycle_damage_symptoms, authority, global_file_name,
              p_file_server_buffers, status);
        authority_known := status.normal;
      IFEND;
    ELSE
      authority_known := FALSE;
    IFEND;

    fmp$unlock_path_table;

    IF avp$security_option_active (avc$vso_security_audit) THEN
      audit_information.audited_operation := sfc$ao_fs_attach_file;
      IF r2_attach_input.served_family THEN
        audited_object.variant_path.complete_path := FALSE;
        audited_object.variant_path.p_path := r2_attach_input.p_path;
      ELSE
        audited_object.variant_path.complete_path := TRUE;
        audited_object.variant_path.p_complete_path := r2_attach_input.p_complete_path;
      IFEND;
      audited_object.object_type := sfc$afsot_cycle;
      IF (r2_attach_input.cycle_selector.cycle_option = pfc$specific_cycle) OR NOT status.normal THEN
        audited_object.cycle_selector_p := ^r2_attach_input.cycle_selector;
      ELSE
        cycle_selector.cycle_option := pfc$specific_cycle;
        cycle_selector.cycle_number := cycle_number;
        audited_object.cycle_selector_p := ^cycle_selector;
      IFEND;
      audited_object.device_class := device_class;
      audit_information.attach_file.object_id_p := ^audited_object;
      IF authority_known THEN
        audit_information.attach_file.ownership := authority.ownership;
      ELSE
        PUSH p_ignore_status;
        pfp$get_ownership (audited_object.variant_path, system_privilege,
              audit_information.attach_file.ownership, p_ignore_status^);
      IFEND;
      audit_information.attach_file.access_mode_p := ^usage_selections;
      sfp$emit_audit_statistic (audit_information, status);
    IFEND;
  PROCEND pfp$r2_attach;

?? TITLE := '  [XDCL] pfp$r2_attach_file', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to access the cycle and to process the
{   "attachment" or to start processing the attachment, depending on whether or
{   not the cycle is already attached within the job.

  PROCEDURE [XDCL] pfp$r2_attach_file
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         lfn: amt$local_file_name;
         path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         update_catalog: boolean;
         update_cycle_statistics: boolean;
         requested_usage_selector: pft$usage_selector;
         requested_share_selector: pft$share_selector;
         system_privilege: boolean;
         validation_ring: ost$valid_ring;
         allowed_device_classes: fst$device_classes,
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR device_class: rmt$device_class;
     VAR cycle_number: fst$cycle_number;
     VAR allowed_usage_selections: pft$usage_selections;
     VAR required_share_selections: pft$share_selections;
     VAR cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR authority: pft$authority;
     VAR global_file_name: ost$binary_unique_name;
     VAR p_file_server_buffers: {server only: i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      fmp$process_pt_request (process_pt_work_list, lfn, evaluated_file_reference, p_cycle_description,
            process_pt_results, local_status);
      fmp$delete_path_description (evaluated_file_reference, {implicit_detach} FALSE,
            {return_permanent_file} TRUE, {detachment_options} NIL, local_status);
      EXIT pfp$r2_attach_file; {----->
    PROCEND initiate_non_local_exit;

    CONST
      implicit_attach = TRUE;

    VAR
      apft_index: pft$attached_pf_table_index,
      attachment_options: array [1 .. 1] of fst$attachment_option,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_attached: boolean,
      cycle_attachment_info: fmt$cycle_attachment_info,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      damage_symptoms_string: pft$selections_string,
      date_time: ost$date_time,
      dm_file_information: dmt$file_information,
      evaluated_file_reference: fst$evaluated_file_reference,
      existing_sft_entry: dmt$existing_sft_entry,
      file_damaged: boolean,
      fmd_modified: boolean,
      fs_device_class: fst$device_class,
      fs_path_size: fst$path_size,
      ignore_status: ost$status,
      local_status: ost$status,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_cycle: ^pft$physical_cycle,
      p_cycle_description: ^fmt$cycle_description,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_label: ^fmt$file_label,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_path_string: ^ost$string,
      p_physical_fmd: ^pft$physical_fmd,
      p_stored_file_label: ^pft$physical_file_label,
      parent_charge_id: pft$charge_id,
      path_handle: fmt$path_handle,
      path_registered: boolean,
      path_table_cycle_info: fmt$path_table_cycle_info,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      process_pt_results: bat$process_pt_results,
      selected_access: fst$file_access_options,
      selected_sharing: fst$file_access_options,
      sfid: gft$system_file_identifier,
      shared_queue: pft$shared_queue,
      share_selections: pft$share_selections,
      share_selector: pft$share_selector,
      usage_intentions: pft$permit_selections,
      usage_selections: pft$usage_selections,
      valid_archive_entry_exists: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pmp$get_compact_date_time (date_time, local_status);
    pfp$process_unexpected_status (local_status);

    pfp$get_authority (path, system_privilege, authority, status);
    IF status.normal THEN
      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      IF update_catalog THEN
        pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
              parent_charge_id, catalog_locator, p_file_object, p_internal_cycle_path^.path, permit_entry,
              status);
      ELSE
        pfp$access_object (path, pfc$read_access, authority, $pft$object_selections [pfc$file_object],
              parent_charge_id, catalog_locator, p_file_object, p_internal_cycle_path^.path, permit_entry,
              status);
      IFEND;
    IFEND;
    catalog_active := status.normal;

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      cycle_number := p_cycle^.cycle_entry.cycle_number;

      IF cycle_selector.cycle_option = pfc$specific_cycle THEN
        evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
        evaluated_file_reference.cycle_reference.cycle_number := cycle_selector.cycle_number;
        path_registered := FALSE;
      ELSEIF family_location = pfc$local_mainframe THEN
        pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
        evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
        evaluated_file_reference.cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
        fmp$get_path_table_cycle_info (inhibit_path_table_lock, evaluated_file_reference,
              path_table_cycle_info, status);
        IF status.normal THEN
          path_registered := path_table_cycle_info.path_registered;
        IFEND;
      ELSE {server mainframe and nonspecific cycle}
        path_registered := FALSE;
        pfp$locate_attached_file (p_cycle^.cycle_entry.internal_cycle_name, apft_index, p_attached_pf_entry,
              cycle_attached);
        IF cycle_attached THEN
          pfp$validate_password (path, authority, password, p_file_object, status);
          IF status.normal THEN
            osp$set_status_condition (pfe$cycle_attached_on_client, status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal AND update_catalog AND (p_cycle^.cycle_entry.attach_status.attach_count > 0) AND
          (p_cycle^.cycle_entry.data_residence = pfc$release_data_requested) THEN
      pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
            p_physical_fmd);

      IF p_physical_fmd <> NIL THEN
        shared_queue := pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info, -$pft$share_selections []);
        dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
              p_physical_fmd^.fmd, $pft$usage_selections [], -$pft$share_selections [],
              pfc$average_share_history, pfc$maximum_pf_length, {restricted_attach} FALSE,
              {exit_on_unknown_file} TRUE, (family_location = pfc$server_mainframe), shared_queue,
              file_damaged, sfid, existing_sft_entry, local_status);

        IF local_status.normal THEN
          IF existing_sft_entry = dmc$normal_entry THEN
            pfp$detach_permanent_file (^path, sfid, $pft$usage_selections [], {catalog_access_allowed} TRUE,
                  p_cycle, catalog_locator.p_catalog_file, dmc$df_ignore_file_info, fmd_modified,
                  dm_file_information, ignore_status);
          ELSEIF existing_sft_entry = dmc$entry_not_found THEN
            dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
                  ignore_status);
            osp$prevalidate_free ((#OFFSET (p_physical_fmd) -
                  #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                  ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR',
                    'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
            IFEND;
            pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
                  p_cycle^.cycle_entry.fmd_locator);
            pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator,
                  catalog_locator.p_catalog_file, p_mainframe_usage_list);
            IF p_mainframe_usage_list <> NIL THEN
              osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) -
                    #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                    ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
              IF prevalidate_free_result = osc$heap_free_valid THEN
                FREE p_mainframe_usage_list IN catalog_locator.p_catalog_file^.catalog_heap;
              ELSE
                pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST',
                      'file', prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
                p_mainframe_usage_list := NIL;
              IFEND;
            IFEND;
            pfp$build_mainfram_list_locator ({p_mainframe_list} NIL, {p_catalog_file} NIL,
                  p_cycle^.cycle_entry.mainframe_usage_list_locator);
            p_cycle^.cycle_entry.data_residence := pfc$offline_data;
            p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
            p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
            pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal AND (p_cycle^.cycle_entry.data_residence = pfc$offline_data) THEN
      pfp$check_archive_entries (catalog_locator.p_catalog_file, p_cycle, valid_archive_entry_exists, status);
      IF status.normal THEN
        PUSH p_fs_path;
        IF valid_archive_entry_exists THEN
          IF p_cycle^.cycle_entry.retrieve_option = pfc$explicit_retrieve_only THEN
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$explicit_retrieve_required,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                  radix, NOT include_radix, status);
          ELSE
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_data_resides_offline,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                  radix, NOT include_radix, status);
          IFEND;
        ELSE
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
                p_fs_path^ (1, fs_path_size), status);
          osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                radix, NOT include_radix, status);
        IFEND;
      IFEND;
    IFEND;

    IF status.normal 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;
      fsp$convert_device_class_to_fs (device_class, fs_device_class);

      IF device_class = rmc$mass_storage_device THEN
        share_selector := requested_share_selector;
      ELSEIF device_class = rmc$magnetic_tape_device THEN
        share_selector.option := pfc$specific_share_option;
        share_selector.share_selections := $pft$share_selections [];
      IFEND;

      IF path_registered AND path_table_cycle_info.cycle_attachment_info.cycle_attached THEN
        pfp$validate_password (path, authority, password, p_file_object, status);

        IF status.normal THEN
          pfp$locate_attached_file (p_cycle^.cycle_entry.internal_cycle_name, apft_index, p_attached_pf_entry,
                cycle_attached);
          IF cycle_attached THEN
            IF NOT (fs_device_class IN allowed_device_classes) THEN
              PUSH p_fs_path;
              pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$device_class_conflict,
                    p_fs_path^ (1, fs_path_size), status);
            ELSEIF allowed_cycle_damage_symptoms <> p_attached_pf_entry^.allowed_exception_conditions THEN
              PUSH p_fs_path;
              pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
              build_damage_symptoms_string (p_attached_pf_entry^.allowed_exception_conditions,
                    damage_symptoms_string);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$allowed_damage_mismatch,
                    p_fs_path^ (1, fs_path_size), status);
              osp$append_status_parameter (osc$status_parameter_delimiter, damage_symptoms_string.
                    value (1, damage_symptoms_string.size), status);
            IFEND;
          ELSE
            PUSH p_path_string;
            pfp$convert_cycle_path_to_strng (path, cycle_number, p_path_string^);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_purged_cycle,
                  p_path_string^.value (1, p_path_string^.size), status);
          IFEND;
        IFEND;

        IF status.normal THEN
          attachment_options [1].selector := fsc$access_and_share_modes;

          IF requested_usage_selector.option = pfc$default_usage_option THEN
            attachment_options [1].access_modes.selector := fsc$permitted_access_modes;
          ELSE
            attachment_options [1].access_modes.selector := fsc$specific_access_modes;
            #UNCHECKED_CONVERSION (requested_usage_selector.usage_selections,
                  attachment_options [1].access_modes.value);
          IFEND;

          IF share_selector.option = pfc$default_share_option THEN
            attachment_options [1].share_modes.selector := fsc$determine_from_access_modes;
          ELSE
            attachment_options [1].share_modes.selector := fsc$specific_share_modes;
            #UNCHECKED_CONVERSION (share_selector.share_selections, attachment_options [1].share_modes.value);
          IFEND;

          cycle_attachment_info := path_table_cycle_info.cycle_attachment_info;

          IF path_table_cycle_info.cycle_device_info.device_assigned THEN
            cycle_formerly_opened_info := path_table_cycle_info.cycle_device_info.cycle_formerly_opened_info;
          ELSE
            cycle_formerly_opened_info.cycle_previously_opened := FALSE;
          IFEND;

          pfp$pick_modes_for_open (evaluated_file_reference, ^attachment_options,
                cycle_attachment_info.allowed_access, cycle_attachment_info.required_sharing,
                path_table_cycle_info.setfa_access_modes, device_class, cycle_formerly_opened_info,
                {called_by_attach} TRUE, {create_file} FALSE, validation_ring, selected_access,
                selected_sharing, status);
        IFEND;

        IF status.normal THEN
          fmp$process_pt_request (process_pt_work_list, lfn, evaluated_file_reference, p_cycle_description,
                process_pt_results, status);
        IFEND;

        IF status.normal THEN
          cycle_number := evaluated_file_reference.cycle_reference.cycle_number;
          #UNCHECKED_CONVERSION (cycle_attachment_info.allowed_access, allowed_usage_selections);
          #UNCHECKED_CONVERSION (cycle_attachment_info.required_sharing, required_share_selections);
          cycle_damage_symptoms := $fst$cycle_damage_symptoms [];
        IFEND;
      ELSE
        {
        { Attach the file.
        {
        pfp$validate_password (path, authority, password, p_file_object, status);

        IF status.normal THEN
          pfp$form_administrator_permit (authority, permit_entry);
          determine_usage_permitted (requested_usage_selector, permit_entry, usage_selections,
                allowed_usage_selections);
          pfp$map_usage_selections (usage_selections, usage_intentions);
          determine_share_with_pf_option (share_selector, permit_entry, usage_selections, share_selections,
                required_share_selections);
          pfp$validate_file_permission (path, authority, permit_entry, usage_intentions, share_selections,
                status);
        IFEND;

        IF status.normal AND NOT (fs_device_class IN allowed_device_classes) THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$device_class_conflict,
                p_fs_path^ (1, fs_path_size), status);
        IFEND;

        IF status.normal THEN
          pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator,
                catalog_locator.p_catalog_file, p_stored_file_label);
          IF p_stored_file_label = NIL THEN
            p_label := NIL;
          ELSE
            p_label := ^p_stored_file_label^.file_label;
          IFEND;
          global_file_name := p_cycle^.cycle_entry.global_file_name;
          attach_cycle (family_location, mainframe_id, path, lfn, device_class, date_time, authority,
                update_catalog, update_cycle_statistics, usage_selections, share_selections,
                permit_entry.application_info, validation_ring, allowed_cycle_damage_symptoms,
                {enable_media_damage_detection} FALSE, NOT implicit_attach, p_label,
                catalog_locator.p_catalog_file, p_file_object, p_internal_cycle_path, p_cycle,
                catalog_locator.flush_catalog_pages, path_handle, cycle_damage_symptoms,
                p_file_server_buffers, status);
        IFEND;
      IFEND;
    ELSE
      device_class := rmc$mass_storage_device;
    IFEND;

    osp$disestablish_cond_handler;
    IF catalog_active THEN
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;
    pfv$locked_apfid := 0;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_attach_file;

?? TITLE := '  [XDCL] pfp$r2_attach_or_create', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to access the cycle and to process the
{   "attachment" or to start processing the creation or attachment, depending
{   on whether or not the cycle is already attached within the job.

  PROCEDURE [XDCL] pfp$r2_attach_or_create
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         validation_ring: ost$valid_ring;
         system_privilege: boolean;
         exception_selection_info: pft$exception_selection_info;
         p_attachment_options: {input} ^fst$attachment_options;
         p_file_label: {input} ^fmt$file_label;
         p_path_table_cycle_info: {input} ^fmt$path_table_cycle_info;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
     VAR evaluated_file_reference: {i/o} fst$evaluated_file_reference;
     VAR action_attempted: pft$action_attempted;
     VAR action_taken: pft$attach_or_create_action;
     VAR authority: pft$authority;
     VAR allowed_access: fst$file_access_options;
     VAR selected_access: fst$file_access_options;
     VAR required_sharing: fst$file_access_options;
     VAR selected_sharing: fst$file_access_options;
     VAR device_class: rmt$device_class;
     VAR global_file_name: ost$binary_unique_name;
     VAR new_global_file_name: ost$binary_unique_name;
     VAR new_remote_sfid: gft$system_file_identifier;
     VAR label_used: boolean;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {server only: i^/o^} ^pft$file_server_buffers;
     VAR status: ost$status);

?? NEWTITLE := '         attach_or_create_handler', EJECT ??

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

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

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

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

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

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

        syp$pop_inhibit_job_recovery;

        IF pfv$locked_apfid <> 0 THEN
          pfp$release_locked_apfid (pfv$locked_apfid, local_status);
          pfv$locked_apfid := 0;
        IFEND;

        fmp$delete_path_description (evaluated_file_reference, {implicit_detach} TRUE,
              {return_permanent_file} TRUE, {detachment_options} NIL, local_status);

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

        status := local_status;
        initiate_non_local_exit;

      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          pfp$log_ascii ('***Recover Files***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
                pmc$msg_origin_system, {critical_message} FALSE, local_status);
          { syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND attach_or_create_handler;

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

    PROCEDURE check_all_volumes_available
      (    p_stored_fmd: {input} ^dmt$stored_fmd;
       VAR all_volumes_available: boolean;
       VAR status: ost$status);

      VAR
        fmd_header: pft$fmd_header,
        p_unique_volume_list: ^pft$unique_volume_list,
        volume_index: integer;

      all_volumes_available := TRUE;

      dmp$get_stored_fmd_header_info (p_stored_fmd, fmd_header, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

      PUSH p_unique_volume_list: [1 .. fmd_header.number_of_subfiles];
      dmp$get_unique_fmd_volume_list (p_stored_fmd, p_unique_volume_list, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

    /search_volume_list/
      FOR volume_index := LOWERBOUND (p_unique_volume_list^) TO UPPERBOUND (p_unique_volume_list^) DO
        IF osp$get_volume_condition (p_unique_volume_list^ [volume_index]) IN
              $fst$file_access_conditions [fsc$media_missing, fsc$volume_unavailable] THEN
          all_volumes_available := FALSE;
          EXIT /search_volume_list/; {----->
        IFEND;
      FOREND /search_volume_list/;

    PROCEND check_all_volumes_available;

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

    PROCEDURE check_delete_data_allowed
      (    evaluated_file_reference: fst$evaluated_file_reference;
           exception_selection_info: pft$exception_selection_info;
           intended_access: fst$file_access_options;
           intended_sharing: fst$file_access_options;
           eoi: amt$file_byte_address;
           p_file_label: ^fmt$file_label;
           cycle_attachment_status: ost$status;
       VAR delete_data_allowed: boolean);

      VAR
        delete_data_specified: boolean,
        dynamic_label: bat$dynamic_label_attributes,
        file_organization: amt$file_organization,
        file_previously_opened: boolean,
        local_status: ost$status,
        never_opened: boolean,
        offline_data: boolean,
        open_position: amt$open_position,
        p_cycle_description: ^fmt$cycle_description,
        p_local_file_label: ^fmt$file_label,
        p_static_label_header: ^fmt$static_label_header,
        previously_opened: boolean,
        sequential_record_access: boolean,
        setfa_open_position: amt$open_position,
        setfa_open_position_source: amt$attribute_source,
        static_label_attributes: bat$static_label_attributes,
        undefined_data: boolean;

      setfa_open_position_source := amc$access_method_default;

      fmp$locate_cd_via_path_handle (evaluated_file_reference.path_handle_info.path_handle,
            {lock_path_table} FALSE, p_cycle_description, local_status);
      IF local_status.normal AND (p_cycle_description^.dynamic_setfa_entries <> NIL) THEN
        fmp$extract_dynamic_setfa_attrs (p_cycle_description^.dynamic_setfa_entries, dynamic_label);
        IF dynamic_label.open_position_source <> amc$access_method_default THEN
          setfa_open_position := dynamic_label.open_position;
          setfa_open_position_source := dynamic_label.open_position_source;
        IFEND;
      IFEND;
      IF (exception_selection_info.open_position_source = amc$access_method_default) AND
            (setfa_open_position_source <> amc$access_method_default) THEN
        open_position := setfa_open_position;
      ELSE
        open_position := exception_selection_info.open_position;
      IFEND;

      file_organization := amc$sequential;
      previously_opened := FALSE;

      IF p_file_label <> NIL THEN
        p_local_file_label := p_file_label;
        NEXT p_static_label_header IN p_local_file_label;
        IF (p_static_label_header <> NIL) AND (p_static_label_header^.unique_character = fmc$unique_label_id)
              THEN
          fsp$expand_file_label (p_file_label, static_label_attributes, file_previously_opened, local_status);
          IF local_status.normal THEN
            previously_opened := file_previously_opened;
            file_organization := static_label_attributes.file_organization;
          IFEND;
        IFEND;
      IFEND;

      { The data for the cycle resides offline.
      offline_data := ((NOT cycle_attachment_status.normal) AND
            (cycle_attachment_status.condition = pfe$cycle_data_resides_offline)) AND
            (intended_access * $fst$file_access_options [fsc$read, fsc$execute] = $fst$file_access_options
            []);

      { The cycle entry was restored but the cycle data was not.
      undefined_data := ((NOT cycle_attachment_status.normal) AND
            (cycle_attachment_status.condition = pfe$undefined_data)) AND
            (intended_access * $fst$file_access_options [fsc$read, fsc$execute] = $fst$file_access_options
            []);

      { The cycle has never been opened.
      never_opened := (cycle_attachment_status.normal OR ((NOT cycle_attachment_status.normal) AND
            (cycle_attachment_status.condition <> pfe$undefined_data))) AND (NOT previously_opened) AND
            (eoi = 0);

      { The delete_data attachment option was specified.
      delete_data_specified := exception_selection_info.delete_data;

      { The file organization is sequential and the file is being opened for record access.
      sequential_record_access := ((file_organization = amc$sequential) AND
            (exception_selection_info.access_level = amc$record) AND
            (intended_access * $fst$file_access_options [fsc$read, fsc$execute] = $fst$file_access_options
            []));

      delete_data_allowed := ((open_position = amc$open_at_boi) AND (fsc$shorten IN intended_access) AND
            (intended_sharing = $fst$file_access_options [])) AND
            (offline_data OR undefined_data OR never_opened OR delete_data_specified OR
            sequential_record_access);

    PROCEND check_delete_data_allowed;

?? EJECT ??
?? OLDTITLE ??

    PROCEDURE initiate_non_local_exit;

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

    CONST
      implicit_attach = TRUE;

    VAR
      allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms,
      allowed_device_classes: fst$device_classes,
      all_volumes_available: boolean,
      apft_index: pft$attached_pf_table_index,
      archive_status: ost$status,
      catalog_attached: boolean,
      catalog_locator: pft$catalog_locator,
      create_file: boolean,
      cycle_attached: boolean,
      cycle_attachment_info: fmt$cycle_attachment_info,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      cycle_number: fst$cycle_number,
      cycle_reference: fst$cycle_reference,
      cycle_selector: pft$cycle_selector,
      cycle_damage_symptoms: fst$cycle_damage_symptoms,
      damage_symptoms_string: pft$selections_string,
      date_time: ost$date_time,
      delete_data_allowed: boolean,
      device_assigned: boolean,
      dm_file_information: dmt$file_information,
      enable_media_damage_detection: boolean,
      existing_sft_entry: dmt$existing_sft_entry,
      fetch_new_cycle_info: boolean,
      file_damaged: boolean,
      file_index: 1 .. fsc$max_path_elements + 1,
      file_info: dmt$file_information,
      fmd_header_info: pft$fmd_header,
      fmd_modified: boolean,
      fmd_reconciliation_required: boolean,
      fs_device_class: fst$device_class,
      fs_path_size: fst$path_size,
      ignore_apft_index: pft$attached_pf_table_index,
      ignore_status: ost$status,
      intended_access: fst$file_access_options,
      intended_sharing: fst$file_access_options,
      internal_cycle_name: pft$internal_name,
      local_password: pft$password,
      local_status: ost$status,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_complete_path: ^pft$complete_path,
      p_cycle: ^pft$physical_cycle,
      p_cycle_description: ^fmt$cycle_description,
      p_cycle_list: ^pft$cycle_list,
      p_evaluated_file_reference: ^fst$evaluated_file_reference,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_label: ^fmt$file_label,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_path_element: ^fst$path_element_string,
      p_path_string: ^ost$string,
      p_physical_fmd: ^pft$physical_fmd,
      p_stored_file_label: ^pft$physical_file_label,
      parent_charge_id: pft$charge_id,
      password_specified: boolean,
      path_description_created: boolean,
      path_table_cycle_info: fmt$path_table_cycle_info,
      permit_entry: pft$permit_entry,
      physical_object: pft$physical_object,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      save_file_label: boolean,
      saved_attach_status: pft$attach_status,
      setfa_access_modes: fst$access_modes,
      sfid: gft$system_file_identifier,
      share_modes: fst$share_modes,
      share_option: pft$share_options,
      share_selections: pft$share_selections,
      shared_queue: pft$shared_queue,
      sharing_required: pft$share_selections,
      usage_allowed: pft$usage_selections,
      usage_option: pft$usage_options,
      usage_selections: pft$usage_selections,
      valid_file_name: boolean,
      valid_archive_entry_exists: boolean,
      valid_objects: pft$object_selections,
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

    action_attempted := pfc$no_action_attempted;
    bytes_allocated := 0;
    device_class := rmc$mass_storage_device;
    new_global_file_name := dmv$null_global_file_name;
    new_remote_sfid := gfv$null_sfid;
    label_used := FALSE;
    path_description_created := FALSE;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    selected_access := $fst$file_access_options [];
    status.normal := TRUE;
    archive_status.normal := TRUE;

    pmp$get_compact_date_time (date_time, local_status);
    pfp$process_unexpected_status (local_status);
    pfi$get_password (p_attachment_options, password_specified, local_password);
    pfp$get_allowed_device_classes (p_attachment_options, allowed_device_classes);
    pfp$get_cycle_damage_options (p_attachment_options, enable_media_damage_detection,
          allowed_cycle_damage_symptoms);

    file_index := evaluated_file_reference.number_of_path_elements + 1;
    PUSH p_complete_path: [1 .. file_index];
    pfp$convert_fs_to_complete_path (evaluated_file_reference, p_complete_path, status);

    IF status.normal THEN
      cycle_reference := evaluated_file_reference.cycle_reference;
      pfi$convert_cycle_reference (cycle_reference, cycle_selector, status);
    IFEND;

    IF status.normal THEN
      pfp$get_authority (p_complete_path^, system_privilege, authority, status);
    IFEND;

    IF status.normal THEN
      pfi$get_create_file_option (p_attachment_options, cycle_reference, create_file);
      IF create_file THEN
        valid_objects := $pft$object_selections [pfc$free_object, pfc$file_object];
      ELSE
        valid_objects := $pft$object_selections [pfc$file_object];
      IFEND;
      PUSH p_internal_cycle_path: [1 .. file_index];
      pfp$access_object (p_complete_path^, pfc$write_access, authority, valid_objects, parent_charge_id,
            catalog_locator, p_file_object, p_internal_cycle_path^.path, permit_entry, status);
      IF NOT status.normal THEN
        action_attempted := pfc$dm_attachment_attempted;
      IFEND;
    IFEND;
    catalog_attached := status.normal;
    osp$establish_condition_handler (^attach_or_create_handler, {block_exit} TRUE);

    IF status.normal AND (p_file_object^.object_entry.object_type = pfc$file_object) THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
    IFEND;

    IF status.normal AND (p_file_object^.object_entry.object_type = pfc$file_object) AND
          (cycle_reference.specification <> fsc$next_cycle) THEN
      pfp$locate_cycle (p_complete_path^, p_cycle_list, cycle_selector, p_cycle, status);

      IF status.normal THEN
        global_file_name := p_cycle^.cycle_entry.global_file_name;
        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);
        IFEND;
        fsp$convert_device_class_to_fs (device_class, fs_device_class);

        IF cycle_reference.specification <> fsc$cycle_number THEN
          cycle_reference.specification := fsc$cycle_number;
          cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
          evaluated_file_reference.cycle_reference := cycle_reference;

          IF family_location = pfc$local_mainframe THEN
            fmp$get_path_table_cycle_info (inhibit_path_table_lock, evaluated_file_reference,
                  path_table_cycle_info, status);
          ELSE {server mainframe and nonspecific cycle}
            IF p_path_table_cycle_info = NIL THEN
              path_table_cycle_info.path_registered := FALSE;
            ELSEIF p_cycle^.cycle_entry.cycle_number = p_path_table_cycle_info^.cycle_number THEN
              path_table_cycle_info := p_path_table_cycle_info^;
            ELSE
              check_path_table_cycle_number (p_cycle^.cycle_entry.cycle_number, cycle_selector,
                    p_path_table_cycle_info^.cycle_number, fetch_new_cycle_info);
              IF fetch_new_cycle_info THEN
                osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recheck_client_mainframe,
                      'attach_or_create', status);
              ELSE
                path_table_cycle_info.path_registered := FALSE;
              IFEND;
            IFEND;
          IFEND;
        ELSEIF p_path_table_cycle_info = NIL THEN
          path_table_cycle_info.path_registered := FALSE;
        ELSE
          path_table_cycle_info := p_path_table_cycle_info^;
        IFEND;
      IFEND;

      IF status.normal AND (p_cycle^.cycle_entry.attach_status.attach_count > 0) AND
            (p_cycle^.cycle_entry.data_residence = pfc$release_data_requested) THEN
        pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
              p_physical_fmd);

        IF p_physical_fmd <> NIL THEN
          shared_queue := pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info, -$pft$share_selections
                []);
          dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                p_physical_fmd^.fmd, $pft$usage_selections [], -$pft$share_selections [],
                pfc$average_share_history, pfc$maximum_pf_length, {restricted_attach} FALSE,
                {exit_on_unknown_file} TRUE, (family_location = pfc$server_mainframe), shared_queue,
                file_damaged, sfid, existing_sft_entry, local_status);

          IF local_status.normal THEN
            IF existing_sft_entry = dmc$normal_entry THEN
              pfp$detach_permanent_file (p_complete_path, sfid, $pft$usage_selections [],
                    {catalog_access_allowed} TRUE, p_cycle, catalog_locator.p_catalog_file,
                    dmc$df_ignore_file_info, fmd_modified, dm_file_information, ignore_status);
            ELSEIF existing_sft_entry = dmc$entry_not_found THEN
              dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
                    ignore_status);
              osp$prevalidate_free ((#OFFSET (p_physical_fmd) -
                    #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                    ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
              IF prevalidate_free_result = osc$heap_free_valid THEN
                FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
              ELSE
                pfp$report_invalid_free (p_complete_path, ^p_cycle^.cycle_entry.cycle_number,
                      'FILE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
              IFEND;
              pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
                    p_cycle^.cycle_entry.fmd_locator);
              pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator,
                    catalog_locator.p_catalog_file, p_mainframe_usage_list);
              IF p_mainframe_usage_list <> NIL THEN
                osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) -
                      #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                      ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
                IF prevalidate_free_result = osc$heap_free_valid THEN
                  FREE p_mainframe_usage_list IN catalog_locator.p_catalog_file^.catalog_heap;
                ELSE
                  pfp$report_invalid_free (p_complete_path, ^p_cycle^.cycle_entry.cycle_number,
                        'MAINFRAME_USAGE_LIST', 'file', prevalidate_free_result,
                        #OFFSET (p_mainframe_usage_list));
                IFEND;
              IFEND;
              pfp$build_mainfram_list_locator ({p_mainframe_list} NIL, {p_catalog_file} NIL,
                    p_cycle^.cycle_entry.mainframe_usage_list_locator);
              p_cycle^.cycle_entry.data_residence := pfc$offline_data;
              p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
              p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
              pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      IF status.normal AND (p_cycle^.cycle_entry.data_residence = pfc$offline_data) THEN
        pfp$check_archive_entries (catalog_locator.p_catalog_file, p_cycle, valid_archive_entry_exists,
              archive_status);
        IF archive_status.normal THEN
          PUSH p_fs_path;
          IF valid_archive_entry_exists THEN
            IF p_cycle^.cycle_entry.retrieve_option = pfc$explicit_retrieve_only THEN
              pfp$convert_pf_path_to_fs_path (p_complete_path^, p_fs_path^, fs_path_size);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$explicit_retrieve_required,
                    p_fs_path^ (1, fs_path_size), archive_status);
              osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                    radix, NOT include_radix, archive_status);
            ELSE
              pfp$convert_pf_path_to_fs_path (p_complete_path^, p_fs_path^, fs_path_size);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_data_resides_offline,
                    p_fs_path^ (1, fs_path_size), archive_status);
              osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                    radix, NOT include_radix, archive_status);
            IFEND;
          ELSE
            pfp$convert_pf_path_to_fs_path (p_complete_path^, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
                  p_fs_path^ (1, fs_path_size), archive_status);
            osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                  radix, NOT include_radix, archive_status);
          IFEND;
        IFEND;
      IFEND;

      IF status.normal THEN
        p_attached_pf_entry := NIL;
        IF path_table_cycle_info.path_registered AND path_table_cycle_info.cycle_attachment_info.
              cycle_attached THEN
          {
          { The cycle is already attached within the job.
          {
          action_attempted := pfc$fm_attachment_attempted;

          IF password_specified THEN
            pfp$validate_password (p_complete_path^, authority, local_password, p_file_object, status);
          IFEND;

          IF status.normal THEN
            pfp$locate_attached_file (p_cycle^.cycle_entry.internal_cycle_name, apft_index,
                  p_attached_pf_entry, cycle_attached);
            IF cycle_attached THEN
              IF NOT (fs_device_class IN allowed_device_classes) THEN
                variant_path.complete_path := TRUE;
                variant_path.p_complete_path := p_complete_path;
                pfp$set_status_abnormal (variant_path, fse$device_class_conflict, status);
              ELSEIF allowed_cycle_damage_symptoms <> p_attached_pf_entry^.allowed_exception_conditions THEN
                variant_path.complete_path := TRUE;
                variant_path.p_complete_path := p_complete_path;
                pfp$set_status_abnormal (variant_path, pfe$allowed_damage_mismatch, status);
                osp$append_status_parameter (osc$status_parameter_delimiter, damage_symptoms_string.
                      value (1, damage_symptoms_string.size), status);
              IFEND;
            ELSE
              PUSH p_path_string;
              pfp$convert_cycle_path_to_strng (p_complete_path^, p_cycle^.cycle_entry.cycle_number,
                    p_path_string^);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_purged_cycle,
                    p_path_string^.value (1, p_path_string^.size), status);
            IFEND;
          IFEND;

          IF status.normal THEN
            cycle_attachment_info := path_table_cycle_info.cycle_attachment_info;

            IF path_table_cycle_info.cycle_device_info.device_assigned THEN
              cycle_formerly_opened_info := path_table_cycle_info.cycle_device_info.
                    cycle_formerly_opened_info;
            ELSE
              cycle_formerly_opened_info.cycle_previously_opened := FALSE;
            IFEND;

            pfp$pick_modes_for_open (evaluated_file_reference, p_attachment_options,
                  cycle_attachment_info.allowed_access, cycle_attachment_info.required_sharing,
                  path_table_cycle_info.setfa_access_modes, device_class, cycle_formerly_opened_info,
                  {called_by_attach} FALSE, create_file, validation_ring, selected_access, selected_sharing,
                  status);
          IFEND;
          IF status.normal THEN
            evaluated_file_reference.cycle_reference := cycle_reference;
            evaluated_file_reference.path_resolution := fsc$cycle_path;
            action_taken := pfc$cycle_already_attached;
            allowed_access := cycle_attachment_info.allowed_access;
            required_sharing := cycle_attachment_info.required_sharing;

            IF (device_class = rmc$mass_storage_device) AND (cycle_attachment_info.open_count = 0) THEN
              pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator,
                    catalog_locator.p_catalog_file, p_stored_file_label);
              IF p_stored_file_label = NIL THEN
                p_label := NIL;
              ELSE
                p_label := ^p_stored_file_label^.file_label;
              IFEND;

              check_delete_data_allowed (evaluated_file_reference, exception_selection_info, selected_access,
                    selected_sharing, p_cycle^.cycle_entry.device_information.eoi, p_label, status,
                    delete_data_allowed);
              IF delete_data_allowed AND (p_cycle^.cycle_entry.attach_status.attach_count <= 1) THEN
                pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
                      p_physical_fmd);
                IF p_physical_fmd <> NIL THEN
                  check_all_volumes_available (^p_physical_fmd^.fmd, all_volumes_available, local_status);
                  IF NOT local_status.normal THEN
                    all_volumes_available := TRUE;
                  IFEND;
                ELSE
                  all_volumes_available := FALSE;
                IFEND;

                IF NOT all_volumes_available THEN
                  IF family_location = pfc$local_mainframe THEN
                    fmp$locate_cd_via_path_handle (evaluated_file_reference.path_handle_info.path_handle,
                          {lock_path_table} FALSE, p_cycle_description, local_status);
                  ELSE
                    p_cycle_description := NIL;
                    local_status.normal := TRUE;
                  IFEND;
                  IF local_status.normal THEN
                    #UNCHECKED_CONVERSION (selected_access, usage_selections);
                    #UNCHECKED_CONVERSION (selected_sharing, share_selections);
                    recreate_cycle_data (family_location, mainframe_id, p_complete_path^, authority,
                          usage_selections, share_selections, permit_entry.application_info, validation_ring,
                          {password_protected} (p_file_object^.object_entry.password <> osc$null_name),
                          enable_media_damage_detection, apft_index, p_label, p_cycle_description,
                          catalog_locator, p_cycle, p_internal_cycle_path, p_attached_pf_entry,
                          evaluated_file_reference, new_global_file_name, new_remote_sfid, bytes_allocated,
                          p_file_server_buffers, status);
                    IF status.normal THEN
                      action_taken := pfc$cycle_already_attached;
                    IFEND;
                  IFEND;
                IFEND;
              IFEND;
            IFEND;
          ELSEIF status.condition = pfe$cycle_busy THEN
            action_taken := pfc$cycle_already_attached;
          IFEND;
        ELSE
          {
          { The cycle exists but is not attached within the job.
          {
          action_attempted := pfc$dm_attachment_attempted;

          pfp$validate_password (p_complete_path^, authority, local_password, p_file_object, status);

          IF status.normal AND NOT (fs_device_class IN allowed_device_classes) THEN
            variant_path.complete_path := TRUE;
            variant_path.p_complete_path := p_complete_path;
            pfp$set_status_abnormal (variant_path, fse$device_class_conflict, status);
          IFEND;

          IF status.normal THEN
            fmd_reconciliation_required := FALSE;

            IF p_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
              IF device_class = rmc$mass_storage_device THEN
                dmp$locate_existing_sft_entry (p_cycle^.cycle_entry.internal_cycle_name,
                      gfc$fk_job_permanent_file, existing_sft_entry, file_info, status);
                IF status.normal THEN
                  IF existing_sft_entry = dmc$entry_not_found THEN
                    fmd_reconciliation_required := TRUE;
                    saved_attach_status := p_cycle^.cycle_entry.attach_status;
                    p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
                    p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
                    pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator,
                          catalog_locator.p_catalog_file, p_mainframe_usage_list);
                    IF p_mainframe_usage_list <> NIL THEN
                      osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) -
                            #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                            ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
                      IF prevalidate_free_result = osc$heap_free_valid THEN
                        FREE p_mainframe_usage_list IN catalog_locator.p_catalog_file^.catalog_heap;
                      ELSE
                        pfp$report_invalid_free (p_complete_path, ^p_cycle^.cycle_entry.cycle_number,
                              'MAINFRAME_USAGE_LIST', 'file', prevalidate_free_result,
                              #OFFSET (p_mainframe_usage_list));
                        p_mainframe_usage_list := NIL;
                      IFEND;
                    IFEND;
                    pfp$build_mainfram_list_locator ({p_mainframe_list} NIL, {p_catalog_file} NIL,
                          p_cycle^.cycle_entry.mainframe_usage_list_locator);
                    pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);
                  IFEND;
                ELSE
                  pfp$report_unexpected_status (status);
                IFEND;
              IFEND;
            IFEND;

            IF path_table_cycle_info.path_registered THEN
              setfa_access_modes := path_table_cycle_info.setfa_access_modes;
            ELSE
              setfa_access_modes.selector := fsc$permitted_access_modes;
            IFEND;

            pfp$form_administrator_permit (authority, permit_entry);
            pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator,
                  catalog_locator.p_catalog_file, p_stored_file_label);

            IF p_stored_file_label = NIL THEN
              pick_modes_for_attach (p_complete_path^, cycle_reference, mainframe_id, authority,
                    p_attachment_options, setfa_access_modes, device_class, permit_entry,
                    p_cycle^.cycle_entry, {p_old_file_label} NIL, p_file_label, validation_ring,
                    catalog_locator.p_catalog_file, usage_allowed, usage_selections, sharing_required,
                    share_selections, save_file_label, status);
            ELSE
              pick_modes_for_attach (p_complete_path^, cycle_reference, mainframe_id, authority,
                    p_attachment_options, setfa_access_modes, device_class, permit_entry,
                    p_cycle^.cycle_entry, ^p_stored_file_label^.file_label, p_file_label, validation_ring,
                    catalog_locator.p_catalog_file, usage_allowed, usage_selections, sharing_required,
                    share_selections, save_file_label, status);
            IFEND;
            #UNCHECKED_CONVERSION (usage_selections, selected_access);

            IF fmd_reconciliation_required THEN
              p_cycle^.cycle_entry.attach_status := saved_attach_status;
              pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);
            IFEND;
          IFEND;

          p_label := NIL;

          IF status.normal THEN
            status := archive_status;
            IF save_file_label AND (p_file_label <> NIL) THEN
              p_label := p_file_label;
            ELSEIF p_stored_file_label <> NIL THEN
              p_label := ^p_stored_file_label^.file_label;
            IFEND;
          ELSEIF (status.condition = pfe$cycle_busy) OR (status.condition = pfe$sharing_not_permitted) THEN
            IF NOT archive_status.normal THEN
              status := archive_status;
            IFEND;
          IFEND;

          IF status.normal THEN
            attach_cycle (family_location, mainframe_id, p_complete_path^, {lfn} osc$null_name, device_class,
                  date_time, authority, {update_catalog} TRUE, {update_cycle_statistics} TRUE,
                  usage_selections, share_selections, permit_entry.application_info, validation_ring,
                  allowed_cycle_damage_symptoms, enable_media_damage_detection, implicit_attach, p_label,
                  catalog_locator.p_catalog_file, p_file_object, p_internal_cycle_path, p_cycle,
                  catalog_locator.flush_catalog_pages, evaluated_file_reference.path_handle_info.path_handle,
                  cycle_damage_symptoms, p_file_server_buffers, status);
          IFEND;

          IF status.normal THEN
            IF family_location = pfc$local_mainframe THEN
              evaluated_file_reference.path_handle_info.path_handle_present := TRUE;
            IFEND;
            evaluated_file_reference.cycle_reference := cycle_reference;
            evaluated_file_reference.path_resolution := fsc$cycle_path;
            action_taken := pfc$cycle_newly_attached;
            #UNCHECKED_CONVERSION (usage_allowed, allowed_access);
            #UNCHECKED_CONVERSION (sharing_required, required_sharing);
            #UNCHECKED_CONVERSION (share_selections, selected_sharing);
            IF save_file_label AND (p_file_label <> NIL) THEN
              store_file_label (p_complete_path^, p_file_label, catalog_locator.p_catalog_file, p_cycle,
                    p_stored_file_label, status);
              label_used := status.normal;
            IFEND;
          ELSEIF status.condition = pfe$cycle_busy THEN
            action_taken := pfc$cycle_busy_elsewhere;
          ELSEIF (device_class = rmc$mass_storage_device) AND osp$file_access_condition (status) THEN
            #UNCHECKED_CONVERSION (usage_selections, intended_access);
            #UNCHECKED_CONVERSION (share_selections, intended_sharing);
            check_delete_data_allowed (evaluated_file_reference, exception_selection_info, intended_access,
                  intended_sharing, p_cycle^.cycle_entry.device_information.eoi, p_label, status,
                  delete_data_allowed);
            IF delete_data_allowed AND (fmd_reconciliation_required OR
                  (p_cycle^.cycle_entry.attach_status.attach_count = 0)) THEN
              recreate_cycle_data (family_location, mainframe_id, p_complete_path^, authority,
                    usage_selections, share_selections, permit_entry.application_info, validation_ring,
                    {password_protected} (p_file_object^.object_entry.password <> osc$null_name),
                    enable_media_damage_detection, ignore_apft_index, p_label, {p_cycle_description} NIL,
                    catalog_locator, p_cycle, p_internal_cycle_path, {p_attached_pf_entry} NIL,
                    evaluated_file_reference, new_global_file_name, new_remote_sfid, bytes_allocated,
                    p_file_server_buffers, status);
              IF status.normal THEN
                action_taken := pfc$cycle_newly_attached;
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF (status.normal AND ((cycle_reference.specification = fsc$next_cycle) OR
          (p_file_object^.object_entry.object_type <> pfc$file_object))) OR
          ((NOT status.normal) AND (status.condition = pfe$unknown_cycle)) THEN
      {
      { Create cycle and possibly file.
      {
      action_attempted := pfc$creation_attempted;
      fs_device_class := fsc$mass_storage_device;

      IF create_file THEN
        status.normal := TRUE;
      ELSEIF cycle_reference.specification = fsc$next_cycle THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := p_complete_path;
        pfp$set_status_abnormal (variant_path, pfe$unknown_cycle, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, '$NEXT', status);
      IFEND;

      IF status.normal AND NOT (fs_device_class IN allowed_device_classes) THEN
        variant_path.complete_path := TRUE;
        variant_path.p_complete_path := p_complete_path;
        pfp$set_status_abnormal (variant_path, fse$device_class_conflict, status);
      IFEND;

      IF status.normal THEN
        IF p_file_object^.object_entry.object_type = pfc$free_object THEN
          local_status.normal := TRUE;
          clp$validate_new_file_name (p_complete_path^ [file_index], p_complete_path^ [file_index],
                valid_file_name);
          IF valid_file_name THEN
            IF cycle_reference.specification = fsc$cycle_number THEN
              cycle_number := cycle_reference.cycle_number;
            ELSE
              cycle_number := 1;
            IFEND;
          ELSE
            file_index := file_index - 1;
            p_path_element := fsp$path_element (^evaluated_file_reference, file_index);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$bad_permanent_file_name,
                  p_path_element^, status);
          IFEND;
        ELSE
          pfp$validate_password (p_complete_path^, authority, local_password, p_file_object, status);
          pfp$determine_new_cycle_number (p_complete_path^, p_cycle_list, cycle_selector, cycle_number,
                local_status);
        IFEND;

        IF status.normal THEN
          pfp$validate_file_permission (p_complete_path^, authority, permit_entry,
                $pft$permit_selections [pfc$cycle], -$pft$share_selections [], status);
        IFEND;

        IF status.normal AND local_status.normal THEN
          IF cycle_reference.specification <> fsc$cycle_number THEN
            IF family_location = pfc$local_mainframe THEN
              evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
              evaluated_file_reference.cycle_reference.cycle_number := cycle_number;
              fmp$get_path_table_cycle_info (inhibit_path_table_lock, evaluated_file_reference,
                    path_table_cycle_info, status);
            ELSEIF p_path_table_cycle_info = NIL THEN
              path_table_cycle_info.path_registered := FALSE;
            ELSEIF cycle_number = p_path_table_cycle_info^.cycle_number THEN
              path_table_cycle_info := p_path_table_cycle_info^;
            ELSE
              check_path_table_cycle_number (cycle_number, cycle_selector,
                    p_path_table_cycle_info^.cycle_number, fetch_new_cycle_info);
              IF fetch_new_cycle_info THEN
                osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recheck_client_mainframe,
                      'attach_or_create', status);
              ELSE
                path_table_cycle_info.path_registered := FALSE;
              IFEND;
            IFEND;
          ELSEIF p_path_table_cycle_info = NIL THEN
            path_table_cycle_info.path_registered := FALSE;
          ELSE
            path_table_cycle_info := p_path_table_cycle_info^;
          IFEND;
        IFEND;

        IF status.normal AND local_status.normal THEN
          IF path_table_cycle_info.path_registered THEN
            setfa_access_modes := path_table_cycle_info.setfa_access_modes;
          ELSE
            setfa_access_modes.selector := fsc$permitted_access_modes;
          IFEND;
        IFEND;

        IF status.normal THEN
          pick_modes_for_create (p_complete_path^, p_attachment_options, setfa_access_modes,
                authority.ownership, permit_entry, usage_allowed, usage_selections, sharing_required,
                share_selections, status);
        IFEND;

        IF status.normal THEN
          pfp$validate_ring_access (p_complete_path^, p_file_label, -$pft$usage_selections [],
                validation_ring, status);
        IFEND;

        IF status.normal AND NOT local_status.normal THEN
          status := local_status;
        IFEND;

        IF status.normal THEN
          IF p_file_object^.object_entry.object_type = pfc$free_object THEN
            pfp$create_file_object (p_complete_path^ [file_index], authority, parent_charge_id,
                  local_password, pfc$no_log, p_file_object^.object_entry);
            pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
                  catalog_locator.p_catalog_file, p_cycle_list);
            p_internal_cycle_path^.path [file_index] := p_file_object^.object_entry.internal_object_name;
            evaluated_file_reference.path_resolution := fsc$new_file_path;
          ELSE
            evaluated_file_reference.path_resolution := fsc$new_cycle_path;
          IFEND;
        IFEND;

        IF status.normal THEN
          physical_object := p_file_object^;
          create_cycle (family_location, mainframe_id, p_complete_path^, cycle_number, {lfn} osc$null_name,
                date_time, authority, usage_selections, share_selections, permit_entry.application_info,
                validation_ring, enable_media_damage_detection, implicit_attach, catalog_cycle_attributes,
                p_file_label, device_class, {p_mass_storage_request_info} NIL, {p_removable_media_req_info}
                NIL, {p_volume_list} NIL, catalog_locator.p_catalog_file, p_file_object,
                p_internal_cycle_path, physical_object, p_cycle_list, p_cycle, sfid,
                evaluated_file_reference.path_handle_info.path_handle, bytes_allocated, p_file_server_buffers,
                status);
          path_description_created := status.normal;
          IF NOT status.normal THEN
            pfp$delete_file_object (p_complete_path, catalog_locator.p_catalog_file, p_file_object,
                  catalog_locator.object_list_descriptor, local_status);
          IFEND;
        IFEND;

        #UNCHECKED_CONVERSION (usage_selections, selected_access);
        IF status.normal THEN
          IF family_location = pfc$local_mainframe THEN
            evaluated_file_reference.path_handle_info.path_handle_present := TRUE;
          IFEND;
          evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
          evaluated_file_reference.cycle_reference.cycle_number := cycle_number;
          action_taken := pfc$cycle_created;
          #UNCHECKED_CONVERSION (usage_allowed, allowed_access);
          #UNCHECKED_CONVERSION (sharing_required, required_sharing);
          #UNCHECKED_CONVERSION (share_selections, selected_sharing);
          IF p_file_label <> NIL THEN
            p_stored_file_label := NIL;
            store_file_label (p_complete_path^, p_file_label, catalog_locator.p_catalog_file, p_cycle,
                  p_stored_file_label, status);
            label_used := status.normal;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF NOT status.normal AND path_description_created THEN
      dmp$destroy_file (sfid, sfc$no_limit, local_status);

      fmp$delete_path_description (evaluated_file_reference, {implicit_detach} FALSE,
            {return_permanent_file} FALSE, {detachment_options} NIL, local_status);

      pfp$locate_attached_file (p_cycle^.cycle_entry.internal_cycle_name, apft_index, p_attached_pf_entry,
            cycle_attached);
      IF cycle_attached THEN
        IF p_attached_pf_entry <> NIL THEN
          IF p_attached_pf_entry^.p_external_path <> NIL THEN
            FREE p_attached_pf_entry^.p_external_path IN pfv$p_p_job_heap^^;
          IFEND;
          FREE p_attached_pf_entry IN pfv$p_p_job_heap^^;
          pfp$release_locked_apfid (apft_index, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      IFEND;
    IFEND;

    osp$disestablish_cond_handler;
    IF catalog_attached THEN
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;
    pfv$locked_apfid := 0;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_attach_or_create;

?? TITLE := '  [XDCL, #GATE] pfp$r2_attach_or_create_file', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to check whether the cycle is already
{   attached within the job, and to optionally call pfp$r2_df_attach_or_cref or
{   pfp$r2_attach_or_create.
{
{ NOTE:
{   The path table must be locked throughout.

  PROCEDURE [XDCL, #GATE] pfp$r2_attach_or_create_file
    (    validation_ring: ost$valid_ring;
         system_privilege: boolean;
         exception_selection_info: pft$exception_selection_info;
         p_attachment_options: {input} ^fst$attachment_options;
         p_file_label: {input} fmt$p_file_label;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
     VAR evaluated_file_reference: {i/o} fst$evaluated_file_reference;
     VAR allowed_access: fst$file_access_options;
     VAR selected_access: fst$file_access_options;
     VAR required_sharing: fst$file_access_options;
     VAR selected_sharing: fst$file_access_options;
     VAR action_taken: pft$attach_or_create_action;
     VAR label_used: boolean;
     VAR device_class: rmt$device_class;
     VAR global_file_name: ost$binary_unique_name;
     VAR status: ost$status);

    CONST
      include_open_position = TRUE;

    VAR
      access_selected: fst$file_access_options,
      action_attempted: pft$action_attempted,
      audit_information: sft$audit_information,
      audited_object: sft$audited_fs_object_id,
      authority: pft$authority,
      bytes_allocated: amt$file_byte_address,
      create_file: boolean,
      cycle_attached: boolean,
      cycle_attachment_info: fmt$cycle_attachment_info,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      cycle_selector: pft$cycle_selector,
      first_path_element_name: fst$path_element_name,
      fs_path_size: fst$path_size,
      ignore_new_remote_sfid: gft$system_file_identifier,
      ignore_old_global_file_name: ost$binary_unique_name,
      ignore_status: ost$status,
      local_file: boolean,
      local_status: ost$status,
      mainframe_id: pmt$binary_mainframe_id,
      p_complete_path: ^pft$complete_path,
      p_file_server_buffers: ^pft$file_server_buffers,
      p_fs_path: ^fst$path,
      p_local_status: ^ost$status,
      p_path: ^pft$path,
      p_path_table_cycle_info: ^fmt$path_table_cycle_info,
      p_security_status: ^ost$status,
      password: pft$password,
      password_specified: boolean,
      password_status: ost$status,
      path_table_cycle_info: fmt$path_table_cycle_info,
      served_family: boolean,
      served_family_locator: pft$served_family_locator,
      sharing_required: fst$file_access_options,
      tape_file_attached: boolean,
      usage_selections: pft$usage_selections;

    first_path_element_name := fsp$path_element (^evaluated_file_reference, 1) ^;
    find_family_location (first_path_element_name, served_family, served_family_locator);
    local_file := first_path_element_name = fsc$local;
    fmp$lock_path_table (status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF (evaluated_file_reference.cycle_reference.specification = fsc$cycle_number) OR local_file THEN
      fmp$get_path_table_cycle_info (inhibit_path_table_lock, evaluated_file_reference, path_table_cycle_info,
            status);

      IF status.normal AND path_table_cycle_info.path_registered THEN
        p_path_table_cycle_info := ^path_table_cycle_info;
        cycle_attached := path_table_cycle_info.cycle_attachment_info.cycle_attached;

        IF cycle_attached THEN
          pfi$get_password (p_attachment_options, password_specified, password);

          IF password_specified AND (path_table_cycle_info.cycle_attachment_info.password_protected OR
                (password <> osc$null_name)) THEN
            IF served_family THEN
              PUSH p_path: [1 .. evaluated_file_reference.number_of_path_elements];
              pfp$convert_fs_to_pft$path (evaluated_file_reference, p_path^);
              IF NOT system_privilege THEN
                pfp$r2_df_client_validate_pw (served_family_locator, p_path^, password, status);
              IFEND;
            ELSE
              PUSH p_complete_path: [1 .. evaluated_file_reference.number_of_path_elements + 1];
              pfp$convert_fs_to_complete_path (evaluated_file_reference, p_complete_path, status);
              IF status.normal AND NOT system_privilege THEN
                pfp$r2_validate_password (p_complete_path^, password, status);
              IFEND;
            IFEND;
          IFEND;

          IF status.normal THEN
            cycle_attachment_info := path_table_cycle_info.cycle_attachment_info;

            IF path_table_cycle_info.cycle_device_info.device_assigned THEN
              device_class := path_table_cycle_info.cycle_device_info.device_class;
              cycle_formerly_opened_info := path_table_cycle_info.cycle_device_info.
                    cycle_formerly_opened_info;
            ELSE
              device_class := rmc$mass_storage_device;
              cycle_formerly_opened_info.cycle_previously_opened := FALSE;
            IFEND;

            pfi$get_create_file_option (p_attachment_options, evaluated_file_reference.cycle_reference,
                  create_file);
            pfp$pick_modes_for_open (evaluated_file_reference, p_attachment_options,
                  cycle_attachment_info.allowed_access, cycle_attachment_info.required_sharing,
                  path_table_cycle_info.setfa_access_modes, device_class, cycle_formerly_opened_info,
                  {called_by_attach} FALSE, create_file, validation_ring, selected_access, selected_sharing,
                  status);
          IFEND;

          IF status.normal THEN
            allowed_access := cycle_attachment_info.allowed_access;
            required_sharing := cycle_attachment_info.required_sharing;
            action_taken := pfc$cycle_already_attached;
            label_used := FALSE;
          ELSEIF status.condition = pfe$cycle_busy THEN
            action_taken := pfc$cycle_already_attached;
          IFEND;
        IFEND;
      ELSE
        p_path_table_cycle_info := NIL;
        cycle_attached := FALSE;
      IFEND;
    ELSE
      p_path_table_cycle_info := NIL;
      status.normal := TRUE;
      cycle_attached := FALSE;
    IFEND;

    IF status.normal AND (NOT local_file) AND (NOT cycle_attached) THEN
      IF served_family THEN
        pfp$r2_df_client_attach_or_cref (served_family_locator, validation_ring, system_privilege,
              exception_selection_info, p_attachment_options, p_file_label, p_path_table_cycle_info,
              catalog_cycle_attributes, evaluated_file_reference, action_attempted, action_taken, authority,
              allowed_access, selected_access, required_sharing, selected_sharing, device_class,
              global_file_name, label_used, bytes_allocated, status);
        IF status.normal THEN
          IF pfc$master_catalog_owner IN authority.ownership THEN
            sfp$accumulate_file_space (sfc$perm_file_space_limit, bytes_allocated);
          IFEND;
        ELSEIF status.condition = pfe$tape_attached_on_client THEN
          PUSH p_local_status;
          iop$tape_file_attached (global_file_name, tape_file_attached, p_local_status^);
          IF p_local_status^.normal THEN
            IF tape_file_attached THEN
              PUSH p_fs_path;
              clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
                    fs_path_size, ignore_status);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
                    p_fs_path^ (1, fs_path_size), status);
              osp$append_status_integer (osc$status_parameter_delimiter,
                    evaluated_file_reference.cycle_reference.cycle_number, radix, NOT include_radix, status);
              osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict,
                    status);
            ELSE
              cycle_selector.cycle_option := pfc$specific_cycle;
              cycle_selector.cycle_number := evaluated_file_reference.cycle_reference.cycle_number;
              PUSH p_path: [1 .. evaluated_file_reference.number_of_path_elements];
              pfp$convert_fs_to_pft$path (evaluated_file_reference, p_path^);
              pfp$convert_pf_path_to_fs_path (p_path^, p_fs_path^, fs_path_size);
              pfp$r2_df_client_clear_cy_att (served_family_locator, p_path^, cycle_selector, password,
                    p_local_status^);
              IF NOT p_local_status^.normal THEN
                status := p_local_status^;
              IFEND;
            IFEND;
          ELSE
            status := p_local_status^;
          IFEND;
        IFEND;
      ELSE
        pmp$get_pseudo_mainframe_id (mainframe_id);
        p_file_server_buffers := NIL;
        pfp$r2_attach_or_create (pfc$local_mainframe, mainframe_id, validation_ring, system_privilege,
              exception_selection_info, p_attachment_options, p_file_label, p_path_table_cycle_info,
              catalog_cycle_attributes, evaluated_file_reference, action_attempted, action_taken, authority,
              allowed_access, selected_access, required_sharing, selected_sharing, device_class,
              global_file_name, ignore_old_global_file_name, ignore_new_remote_sfid, label_used,
              bytes_allocated, p_file_server_buffers, status);
      IFEND;
      IF avp$security_option_active (avc$vso_security_audit) THEN
        IF action_attempted = pfc$dm_attachment_attempted THEN
          audit_information.audited_operation := sfc$ao_fs_attach_file;
          audited_object.variant_path.complete_path := FALSE;
          PUSH audited_object.variant_path.p_path: [1 .. evaluated_file_reference.number_of_path_elements];
          pfp$convert_fs_to_pft$path (evaluated_file_reference, audited_object.variant_path.p_path^);
          audited_object.object_type := sfc$afsot_cycle;
          PUSH p_security_status;
          pfi$convert_cycle_reference (evaluated_file_reference.cycle_reference, cycle_selector,
                p_security_status^);
          IF p_security_status^.normal THEN
            audited_object.cycle_selector_p := ^cycle_selector;
          ELSE
            audited_object.cycle_selector_p := NIL;
          IFEND;
          audited_object.device_class := device_class;
          audit_information.attach_file.object_id_p := ^audited_object;
          IF status.normal THEN
            audit_information.attach_file.ownership := authority.ownership;
            #UNCHECKED_CONVERSION (selected_access, usage_selections);
            audit_information.attach_file.access_mode_p := ^usage_selections;
          ELSE
            pfp$get_ownership (audited_object.variant_path, system_privilege,
                  audit_information.attach_file.ownership, p_security_status^);
            audit_information.attach_file.access_mode_p := NIL;
          IFEND;
          sfp$emit_audit_statistic (audit_information, status);
        ELSEIF action_attempted = pfc$creation_attempted THEN
          audit_information.audited_operation := sfc$ao_fs_create_object;
          audited_object.variant_path.complete_path := FALSE;
          PUSH audited_object.variant_path.p_path: [1 .. evaluated_file_reference.number_of_path_elements];
          pfp$convert_fs_to_pft$path (evaluated_file_reference, audited_object.variant_path.p_path^);
          audited_object.object_type := sfc$afsot_cycle;
          PUSH p_security_status;
          pfi$convert_cycle_reference (evaluated_file_reference.cycle_reference, cycle_selector,
                p_security_status^);
          IF p_security_status^.normal THEN
            audited_object.cycle_selector_p := ^cycle_selector;
          ELSE
            audited_object.cycle_selector_p := NIL;
          IFEND;
          audited_object.device_class := device_class;
          audit_information.create_fs_object.object_id_p := ^audited_object;
          IF status.normal THEN
            audit_information.create_fs_object.ownership := authority.ownership;
          ELSE
            pfp$get_ownership (audited_object.variant_path, system_privilege,
                  audit_information.create_fs_object.ownership, p_security_status^);
          IFEND;
          sfp$emit_audit_statistic (audit_information, status);
          audit_information.audited_operation := sfc$ao_fs_attach_file;
          IF status.normal THEN
            #UNCHECKED_CONVERSION (selected_access, usage_selections);
            audit_information.attach_file.access_mode_p := ^usage_selections;
          ELSE
            audit_information.attach_file.access_mode_p := NIL;
          IFEND;
          sfp$emit_audit_statistic (audit_information, status);
        ELSE {pfc$no_action_attempted or pfc$fm_attachment_attempted}
          ;
        IFEND;
      IFEND;
    IFEND;

    IF NOT status.normal THEN
      fmp$unlock_path_table;
    IFEND;

  PROCEND pfp$r2_attach_or_create_file;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_change
    (    family_location: pft$family_location;
         path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         system_privilege: boolean;
         change_list: pft$change_list;
     VAR cycle_number: fst$cycle_number;
     VAR device_class: rmt$device_class;
     VAR change_index: ost$non_negative_integers;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);

      IF path_table_lock_set THEN
        fmp$unlock_path_table;
        path_table_lock_set := FALSE;
        #SPOIL (path_table_lock_set);
      IFEND;

      EXIT pfp$r2_change; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      date_time: ost$date_time,
      file_permit_entry: pft$permit_entry,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      path_index: pft$file_path_index,
      path_table_lock_set: boolean,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    path_table_lock_set := FALSE;
    #SPOIL (path_table_lock_set);
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pmp$get_compact_date_time (date_time, local_status);
    pfp$process_unexpected_status (local_status);

    pfp$get_authority (path, system_privilege, authority, status);
    IF status.normal THEN
      IF family_location = pfc$local_mainframe THEN
        fmp$lock_path_table (status);
        IF NOT status.normal THEN
          syp$pop_inhibit_job_recovery;
          RETURN; {----->
        IFEND;
        path_table_lock_set := TRUE;
      IFEND;

      PUSH p_parent_path: [1 .. UPPERBOUND (path) - 1];
      FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
        p_parent_path^ [path_index] := path [path_index];
      FOREND;
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id,
            catalog_permit_entry, catalog_locator, status);
    IFEND;
    catalog_active := status.normal;

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

    IF status.normal THEN
      file_permit_entry := catalog_permit_entry;
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$file_object], catalog_locator,
            file_permit_entry, p_file_object, p_internal_path^ [UPPERBOUND (path)], status);
    IFEND;

    IF status.normal THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$validate_file_permission (path, authority, file_permit_entry, $pft$permit_selections [pfc$control],
            -$pft$share_selections [], status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      cycle_number := p_cycle^.cycle_entry.cycle_number;
      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;
      process_change_list (family_location, path, device_class, change_list, date_time,
            catalog_locator.p_catalog_file, authority, catalog_permit_entry, p_cycle, p_file_object,
            catalog_locator.object_list_descriptor, change_index, status);
    ELSE
      change_index := 0;
    IFEND;

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

    IF path_table_lock_set THEN
      fmp$unlock_path_table;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change;

?? TITLE := '  [XDCL, #GATE] pfp$r2_change_catalog_name', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to change the name of a catalog.
{
{ NOTE:
{   This routine should be used with care!  It is not normally advisable to
{   change the name of a catalog because:
{   1) The old external catalog name is currently used in job recovery to
{      re-attach the permanent file.
{   2) The current scheme of partial backups would not backup the unchanged
{      files in this catalog.  If we needed to restore from both the partials
{      and the full, the restore from the full would not find the cycles
{      because they were backed up under the old catalog name.

  PROCEDURE [XDCL, #GATE] pfp$r2_change_catalog_name
    (    path: pft$complete_path;
         new_catalog_name: pft$name;
     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_change_catalog_name; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_alarm_set: boolean,
      catalog_locator: pft$catalog_locator,
      changed_catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      global_file_name: ost$binary_unique_name,
      ignore_destroy_on_last_detach: boolean,
      index: pft$catalog_path_index,
      last_index: pft$catalog_path_index,
      local_status: ost$status,
      p_catalog_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      IF UPPERBOUND (path) <= pfc$master_catalog_path_index THEN
        pfp$validate_family_ownership (path [pfc$family_path_index], authority, status);
      ELSE
        pfp$validate_ownership (authority, path, status);
      IFEND;
    IFEND;

    IF status.normal THEN
      last_index := UPPERBOUND (path);
      PUSH p_parent_path: [1 .. last_index - 1];
      FOR index := 1 TO last_index - 1 DO
        p_parent_path^ [index] := path [index];
      FOREND;
      PUSH p_internal_path: [1 .. last_index];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id, permit_entry,
            catalog_locator, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$catalog_object], catalog_locator,
            permit_entry, p_catalog_object, p_internal_path^ [last_index], status);
    IFEND;

    IF status.normal THEN
      validate_object_name_change (path, new_catalog_name, catalog_locator.object_list_descriptor,
            catalog_locator.p_catalog_file, authority, permit_entry, status);
    IFEND;

    IF status.normal THEN
      p_catalog_object^.object_entry.external_object_name := new_catalog_name;
      pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (pft$object_entry),
            p_catalog_object^.checksum);
    IFEND;

    IF status.normal THEN
      IF p_catalog_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
        global_file_name := p_catalog_object^.object_entry.catalog_object_locator.global_file_name;
      ELSE
        global_file_name := catalog_locator.global_file_name;
      IFEND;
      pfp$check_catalog_alarm (global_file_name, catalog_alarm_set, ignore_destroy_on_last_detach);
      IF NOT catalog_alarm_set THEN
        {
        { Access the changed catalog so that an alarm may be set on it.
        {
        pfp$access_next_catalog (pfc$read_access, catalog_locator, p_catalog_object,
              (path [pfc$family_path_index] <> osv$system_family_name), changed_catalog_locator, status);
        IF status.normal THEN
          IF changed_catalog_locator.object_list_descriptor.catalog_type = pfc$internal_catalog THEN
            {
            { Set alarm on the parent.
            {
            catalog_locator.queuing_info.set_catalog_alarm := TRUE;
          ELSE { external catalog
            changed_catalog_locator.queuing_info.set_catalog_alarm := TRUE;
            pfp$return_catalog (changed_catalog_locator, status);
            pfp$process_unexpected_status (status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change_catalog_name;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_change_cycle_damage
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         new_damage_symptoms: fst$cycle_damage_symptoms;
     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_change_cycle_damage; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      device_class: rmt$device_class,
      dm_file_info: dmt$file_information,
      file_damaged: boolean,
      file_index: pft$file_path_index,
      fmd_modified: boolean,
      file_permit_entry: pft$permit_entry,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      path_index: pft$catalog_path_index,
      process_non_local_exit: boolean,
      sfid: gft$system_file_identifier;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      file_index := UPPERBOUND (path);
      PUSH p_parent_path: [1 .. file_index - 1];
      FOR path_index := 1 TO file_index - 1 DO
        p_parent_path^ [path_index] := path [path_index];
      FOREND;
      PUSH p_internal_path: [1 .. file_index];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id,
            catalog_permit_entry, catalog_locator, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      file_permit_entry := catalog_permit_entry;
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$file_object], catalog_locator,
            file_permit_entry, p_file_object, p_internal_path^ [file_index], status);
    IFEND;

    IF status.normal THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$validate_file_permission (path, authority, file_permit_entry, $pft$permit_selections [pfc$control],
            -$pft$share_selections [], status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      IF fsc$media_image_inconsistent IN new_damage_symptoms THEN
        IF p_cycle^.cycle_entry.attach_status.attach_count = 0 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;
          IF (device_class = rmc$mass_storage_device) AND (p_cycle^.cycle_entry.data_residence <>
                pfc$offline_data) THEN
            dm_attach_file (path, catalog_locator.p_catalog_file, $pft$usage_selections [pfc$read],
                  -$pft$share_selections [], p_cycle, sfid, file_damaged, status);
            IF status.normal THEN
              dmp$change_file_damaged (sfid, {file_damaged} TRUE, p_cycle^.cycle_entry.internal_cycle_name,
                    status);
              IF status.normal THEN
                pfp$detach_permanent_file (^path, sfid, $pft$usage_selections [pfc$read],
                      {catalog_update_allowed} TRUE, p_cycle, catalog_locator.p_catalog_file,
                      dmc$df_ignore_file_info, fmd_modified, dm_file_info, status);
              IFEND;
            ELSEIF status.condition = pfe$undefined_data THEN
              status.normal := TRUE;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      p_cycle^.cycle_entry.cycle_damage_symptoms := new_damage_symptoms -
            $fst$cycle_damage_symptoms [fsc$media_image_inconsistent];
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change_cycle_damage;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_change_cycle_date_time
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         new_access_date_time: pft$date_time;
         new_creation_date_time: pft$date_time;
         new_modification_date_time: pft$date_time;
     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_change_cycle_date_time; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      file_index: pft$file_path_index,
      file_permit_entry: pft$permit_entry,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      path_index: pft$catalog_path_index,
      process_non_local_exit: boolean,
      saved_access_date_time: ost$date_time,
      selections_string: pft$selections_string,
      update_checksum: boolean;

    syp$push_inhibit_job_recovery;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      file_index := UPPERBOUND (path);
      PUSH p_parent_path: [1 .. file_index - 1];
      FOR path_index := 1 TO file_index - 1 DO
        p_parent_path^ [path_index] := path [path_index];
      FOREND;
      PUSH p_internal_path: [1 .. file_index];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id,
            catalog_permit_entry, catalog_locator, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      file_permit_entry := catalog_permit_entry;
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$file_object], catalog_locator,
            file_permit_entry, p_file_object, p_internal_path^ [file_index], status);
    IFEND;

    IF status.normal AND ((new_modification_date_time.date_time_option = pfc$current_date_time) OR
          (new_modification_date_time.date_time_option = pfc$specified_date_time)) AND
          NOT (pfc$family_owner IN authority.ownership) AND NOT (pfc$system_owner IN authority.ownership) THEN
      IF (file_permit_entry.entry_type = pfc$free_permit_entry) OR
            (file_permit_entry.usage_permissions = $pft$permit_selections []) THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_permanent_file,
              p_fs_path^ (1, fs_path_size), status);
      ELSEIF file_permit_entry.usage_permissions - $pft$permit_selections [pfc$read,
            pfc$execute] = $pft$permit_selections [] THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$usage_not_permitted,
              p_fs_path^ (1, fs_path_size), status);
        pfp$build_permit_selections_str (file_permit_entry.usage_permissions, selections_string);
        osp$append_status_parameter (osc$status_parameter_delimiter, selections_string.
              value (1, selections_string.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              '[CONTROL, or CYCLE, or SHORTEN, or MODIFY, or APPEND]', status);
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    update_checksum := FALSE;
    IF status.normal THEN
      CASE new_access_date_time.date_time_option OF
      = pfc$no_date_time =
        ;

      = pfc$current_date_time =
        saved_access_date_time := p_cycle^.cycle_entry.cycle_statistics.access_date_time;
        p_cycle^.cycle_entry.cycle_statistics.access_date_time := new_access_date_time.current_date_time;
        update_checksum := TRUE;

      = pfc$specified_date_time =
        saved_access_date_time := p_cycle^.cycle_entry.cycle_statistics.access_date_time;
        p_cycle^.cycle_entry.cycle_statistics.access_date_time := new_access_date_time.specified_date_time;
        update_checksum := TRUE;

      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Invalid date_time_option:', status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              $INTEGER (new_access_date_time.date_time_option), radix, NOT include_radix, status);
      CASEND;
    IFEND;

    IF status.normal THEN
      CASE new_creation_date_time.date_time_option OF
      = pfc$no_date_time =
        ;

      = pfc$current_date_time =
        p_cycle^.cycle_entry.cycle_statistics.creation_date_time := new_creation_date_time.current_date_time;
        update_checksum := TRUE;

      = pfc$specified_date_time =
        p_cycle^.cycle_entry.cycle_statistics.creation_date_time :=
              new_creation_date_time.specified_date_time;
        update_checksum := TRUE;

      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Invalid date_time_option:', status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              $INTEGER (new_creation_date_time.date_time_option), radix, NOT include_radix, status);
      CASEND;
    IFEND;

    IF status.normal THEN
      CASE new_modification_date_time.date_time_option OF
      = pfc$no_date_time =
        ;

      = pfc$current_date_time =
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
              new_modification_date_time.current_date_time;
        p_cycle^.cycle_entry.data_modification_date_time := new_modification_date_time.current_date_time;
        update_checksum := TRUE;

      = pfc$specified_date_time =
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
              new_modification_date_time.specified_date_time;
        p_cycle^.cycle_entry.data_modification_date_time := new_modification_date_time.specified_date_time;
        update_checksum := TRUE;

      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Invalid date_time_option:', status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              $INTEGER (new_modification_date_time.date_time_option), radix, NOT include_radix, status);
      CASEND;
    IFEND;

    IF update_checksum THEN
      IF status.normal THEN
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      ELSE
        p_cycle^.cycle_entry.cycle_statistics.access_date_time := saved_access_date_time;
      IFEND;
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change_cycle_date_time;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_change_file
    (    family_location: pft$family_location;
         path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         system_privilege: boolean;
         file_changes: ^fst$file_changes;
     VAR cycle_number: fst$cycle_number;
     VAR device_class: rmt$device_class;
     VAR change_index: ost$non_negative_integers;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);

      IF path_table_lock_set THEN
        fmp$unlock_path_table;
        path_table_lock_set := FALSE;
        #SPOIL (path_table_lock_set);
      IFEND;

      EXIT pfp$r2_change_file; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      date_time: ost$date_time,
      file_permit_entry: pft$permit_entry,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      path_index: pft$file_path_index,
      path_table_lock_set: boolean,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    path_table_lock_set := FALSE;
    #SPOIL (path_table_lock_set);
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    pmp$get_compact_date_time (date_time, local_status);
    pfp$process_unexpected_status (local_status);

    pfp$get_authority (path, system_privilege, authority, status);
    IF status.normal THEN
      IF family_location = pfc$local_mainframe THEN
        fmp$lock_path_table (status);
        IF NOT status.normal THEN
          syp$pop_inhibit_job_recovery;
          RETURN; {----->
        IFEND;
        path_table_lock_set := TRUE;
      IFEND;

      PUSH p_parent_path: [1 .. UPPERBOUND (path) - 1];
      FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
        p_parent_path^ [path_index] := path [path_index];
      FOREND;
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id,
            catalog_permit_entry, catalog_locator, status);
    IFEND;
    catalog_active := status.normal;

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

    IF status.normal THEN
      file_permit_entry := catalog_permit_entry;
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$file_object], catalog_locator,
            file_permit_entry, p_file_object, p_internal_path^ [UPPERBOUND (path)], status);
    IFEND;

    IF status.normal THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$validate_file_permission (path, authority, file_permit_entry, $pft$permit_selections [pfc$control],
            -$pft$share_selections [], status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      cycle_number := p_cycle^.cycle_entry.cycle_number;
      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;
      process_file_changes (family_location, path, device_class, file_changes, date_time,
            catalog_locator.p_catalog_file, authority, catalog_permit_entry, p_cycle, p_file_object,
            catalog_locator.object_list_descriptor, change_index, status);
    ELSE
      change_index := 0;
    IFEND;

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

    IF path_table_lock_set THEN
      fmp$unlock_path_table;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change_file;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_change_res_to_releasable
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
     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_change_res_to_releasable; {----->
    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_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_parent_path: ^pft$complete_path,
      path_index: pft$catalog_path_index,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      PUSH p_parent_path: [1 .. UPPERBOUND (path) - 1];
      FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
        p_parent_path^ [path_index] := path [path_index];
      FOREND;
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_path^, charge_id, permit_entry,
            catalog_locator, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      pfp$access_last_object (path, authority, $pft$object_selections [pfc$file_object], catalog_locator,
            permit_entry, p_file_object, p_internal_path^ [UPPERBOUND (path)], status);
    IFEND;

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal AND (p_cycle^.cycle_entry.data_residence = pfc$offline_data) THEN
      p_cycle^.cycle_entry.data_residence := pfc$releasable_data;
      pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_change_res_to_releasable;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_clear_cycle_attachments
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
     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_clear_cycle_attachments; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

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

    syp$push_inhibit_job_recovery;

    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, NOT system_privilege, authority, status);
    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      pfp$clear_cycle_attachments (^path, catalog_locator.p_catalog_file, p_cycle);
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_clear_cycle_attachments;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_define
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         lfn: amt$local_file_name;
         path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         log: pft$log;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
         system_privilege: boolean;
         validation_ring: ost$valid_ring;
         device_class: rmt$device_class;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         p_removable_media_req_info: {input^} ^fmt$removable_media_req_info;
         p_volume_list: {input^} ^rmt$volume_list;
     VAR cycle_number: fst$cycle_number;
     VAR authority: pft$authority;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {server only: i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      VAR
        p_cycle_description: ^fmt$cycle_description,
        p_evaluated_file_reference: ^fst$evaluated_file_reference,
        process_pt_results: bat$process_pt_results;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);

      IF path_table_lock_set THEN
        fmp$unlock_path_table;
        path_table_lock_set := FALSE;
        #SPOIL (path_table_lock_set);
      IFEND;
      {
      { Attempt to clean up BAM tables.
      { Set the cycle_number_valid flag to FALSE after initializing the
      { evaluated_file_reference to prevent an infinite loop if either fmp$
      { interface causes a condition that invokes the handler.
      {
      IF cycle_number_valid THEN
        PUSH p_evaluated_file_reference;
        pfp$convert_pf_to_fs_structure (path, p_evaluated_file_reference^);
        p_evaluated_file_reference^.cycle_reference.specification := fsc$cycle_number;
        p_evaluated_file_reference^.cycle_reference.cycle_number := cycle_number;
        cycle_number_valid := FALSE;
        #SPOIL (cycle_number_valid);
        fmp$process_pt_request (process_pt_work_list, lfn, p_evaluated_file_reference^, p_cycle_description,
              process_pt_results, local_status);
        fmp$delete_path_description (p_evaluated_file_reference^, {implicit_detach} FALSE,
              {return_permanent_file} TRUE, {detachment_options} NIL, local_status);
      IFEND;

      EXIT pfp$r2_define; {----->
    PROCEND initiate_non_local_exit;

    VAR
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_number_valid: boolean,
      date_time: ost$date_time,
      ignore_path_handle: fmt$path_handle,
      ignore_sfid: gft$system_file_identifier,
      local_status: ost$status,
      new_file_index: integer,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      parent_charge_id: pft$charge_id,
      path_table_lock_set: boolean,
      permit_entry: pft$permit_entry,
      physical_object: pft$physical_object,
      process_non_local_exit: boolean,
      usage_selections: pft$usage_selections,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

    cycle_number_valid := FALSE;
    #SPOIL (cycle_number_valid);
    path_table_lock_set := FALSE;
    #SPOIL (path_table_lock_set);
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pmp$get_compact_date_time (date_time, local_status);
    pfp$process_unexpected_status (local_status);
    pfp$get_authority (path, system_privilege, authority, status);
    IF status.normal THEN
      IF family_location = pfc$local_mainframe THEN
        fmp$lock_path_table (status);
        IF NOT status.normal THEN
          syp$pop_inhibit_job_recovery;
          RETURN; {----->
        IFEND;
        path_table_lock_set := TRUE;
      IFEND;

      valid_objects := $pft$object_selections [pfc$free_object, pfc$file_object];
      new_file_index := UPPERBOUND (path);
      PUSH p_internal_cycle_path: [1 .. new_file_index];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_file_object, p_internal_cycle_path^.path, permit_entry, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      IF p_file_object^.object_entry.object_type = pfc$file_object THEN
        {
        { Care must be exercised in adding new cycles. The old information for
        { a file must be left intact, if a cycle cannot be added. If a new
        { cycle causes the creation of a file object, then all items belonging
        { to the file object should be created before the file object is placed
        { in the catalog.
        {
        physical_object := p_file_object^;
        pfp$validate_password (path, authority, password, p_file_object, status);

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

        IF status.normal THEN
          pfp$create_file_object (path [new_file_index], authority, parent_charge_id, password, log,
                physical_object.object_entry);
          p_internal_cycle_path^.path [new_file_index] := physical_object.object_entry.internal_object_name;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (physical_object.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$determine_new_cycle_number (path, p_cycle_list, cycle_selector, cycle_number, status);
      cycle_number_valid := status.normal;
      #SPOIL (cycle_number_valid);
    IFEND;

    IF status.normal THEN
      IF (device_class = rmc$magnetic_tape_device) AND (p_removable_media_req_info^.write_ring =
            rmc$no_write_ring) THEN
        usage_selections := $pft$usage_selections [pfc$read, pfc$execute];
      ELSE
        usage_selections := -$pft$usage_selections [];
      IFEND;

      create_cycle (family_location, mainframe_id, path, cycle_number, lfn, date_time, authority,
            usage_selections, $pft$share_selections [], permit_entry.application_info, validation_ring,
            {enable_media_damage_detection} FALSE, {implicit_attach} FALSE, catalog_cycle_attributes,
            {p_file_label} NIL, device_class, p_mass_storage_request_info, p_removable_media_req_info,
            p_volume_list, catalog_locator.p_catalog_file, p_file_object, p_internal_cycle_path,
            physical_object, p_cycle_list, p_cycle, ignore_sfid, ignore_path_handle, bytes_allocated,
            p_file_server_buffers, status);
      IF NOT status.normal THEN
        pfp$delete_file_object (^path, catalog_locator.p_catalog_file, p_file_object,
              catalog_locator.object_list_descriptor, local_status);
      IFEND;
    IFEND;

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

    IF path_table_lock_set THEN
      fmp$unlock_path_table;
    IFEND;
    pfv$locked_apfid := 0;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_define;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_define_catalog
    (    path: pft$complete_path;
         charge_id: pft$charge_id;
         system_privilege: boolean;
         catalog_type_selected: boolean;
         selected_catalog_type: pft$catalog_types;
         p_mass_storage_request_info: ^fmt$mass_storage_request_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_define_catalog; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_type: pft$catalog_types,
      family_catalog: boolean,
      group: pft$group,
      local_status: ost$status,
      master_catalog: boolean,
      new_catalog_index: integer,
      p_catalog_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /define_catalog/
    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 /define_catalog/; {----->
      IFEND;

      new_catalog_index := UPPERBOUND (path);
      family_catalog := new_catalog_index = pfc$family_path_index;
      master_catalog := new_catalog_index = pfc$master_catalog_path_index;

      IF family_catalog OR master_catalog THEN
        pfp$validate_family_ownership (path [pfc$family_path_index], authority, status);
      ELSE
        pfp$validate_ownership (authority, path, status);
      IFEND;
      IF NOT status.normal THEN
        EXIT /define_catalog/; {----->
      IFEND;

      PUSH p_internal_path: [1 .. new_catalog_index];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$free_object],
            parent_charge_id, catalog_locator, p_catalog_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /define_catalog/; {----->
      IFEND;

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

      IF catalog_type_selected THEN
        catalog_type := selected_catalog_type;
      ELSEIF family_catalog THEN
        catalog_type := pfc$internal_catalog;
      ELSE
        catalog_type := pfc$external_catalog;
      IFEND;

      pfp$create_catalog_object (path, authority, catalog_type, parent_charge_id, charge_id,
            p_mass_storage_request_info, catalog_locator.p_catalog_file, p_catalog_object, status);
      IF status.normal AND master_catalog THEN
        group.group_type := pfc$user;
        group.user_description.family := path [pfc$family_path_index];
        group.user_description.user := path [pfc$master_catalog_path_index];
        replace_permit_description (path, group, -$pft$permit_selections [], $pft$share_requirements [],
              {application_info} osc$null_name, p_catalog_object, catalog_locator.p_catalog_file, status);
      IFEND;
    END /define_catalog/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_define_data
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         lfn: amt$local_file_name;
         path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         update_cycle_statistics: boolean;
         password_selector: pft$password_selector;
         validation_ring: ost$valid_ring;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         p_volume_list: {input} ^array [1 .. * ] of rmt$recorded_vsn;
         purge_cycle_options: pft$purge_cycle_options;
         replace_cycle_data: boolean;
         restore_selections: put$restore_data_selections;
     VAR mandated_modification_time: {i/o} pft$mandated_modification_time;
     VAR data_residence: pft$data_residence;
     VAR authority: pft$authority;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

      VAR
        p_cycle_description: ^fmt$cycle_description,
        p_evaluated_file_reference: ^fst$evaluated_file_reference,
        process_pt_results: bat$process_pt_results;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);

      IF path_table_lock_set THEN
        fmp$unlock_path_table;
        path_table_lock_set := FALSE;
        #SPOIL (path_table_lock_set);
      IFEND;
      {
      { Attempt to clean up BAM tables.
      { Set the cycle_number_valid flag to FALSE after initializing the
      { evaluated_file_reference to prevent an infinite loop if either fmp$
      { interface causes a condition that invokes the handler.
      {
      IF cycle_number_valid THEN
        PUSH p_evaluated_file_reference;
        pfp$convert_pf_to_fs_structure (path, p_evaluated_file_reference^);
        p_evaluated_file_reference^.cycle_reference.specification := fsc$cycle_number;
        p_evaluated_file_reference^.cycle_reference.cycle_number := cycle_number;
        cycle_number_valid := FALSE;
        #SPOIL (cycle_number_valid);
        fmp$process_pt_request (process_pt_work_list, lfn, p_evaluated_file_reference^, p_cycle_description,
              process_pt_results, local_status);
        fmp$delete_path_description (p_evaluated_file_reference^, {implicit_detach} FALSE,
              {return_permanent_file} TRUE, {detachment_options} NIL, local_status);
      IFEND;

      EXIT pfp$r2_define_data; {----->
    PROCEND initiate_non_local_exit;

    CONST
      enable_media_damage_detection = TRUE,
      implicit_attach = TRUE;

    VAR
      apfid_assigned: boolean,
      apfid_in_use: boolean,
      apft_index: pft$attached_pf_table_index,
      bytes_released: amt$file_byte_address,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_number: fst$cycle_number,
      cycle_number_valid: boolean,
      cycle_on_missing_volume: boolean,
      cycle_on_selected_volume: boolean,
      cycle_on_unavailable_volume: boolean,
      define_cycle: boolean,
      device_class: rmt$device_class,
      disk_image_deleted: boolean,
      flush_catalog_pages: boolean,
      fs_path_size: fst$path_size,
      ignore_path_handle: fmt$path_handle,
      internal_cycle_name: pft$internal_name,
      local_status: ost$status,
      modification_times_match: boolean,
      new_cycle_list: boolean,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_cycle: ^pft$physical_cycle,
      p_cycle_description: ^fmt$cycle_description,
      p_cycle_list: ^pft$cycle_list,
      p_data_modification_date_time: ^ost$date_time,
      p_evaluated_file_reference: ^fst$evaluated_file_reference,
      p_file_object: ^pft$physical_object,
      p_free_cycle: ^pft$physical_cycle,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_new_cycle_list: ^pft$cycle_list,
      p_physical_fmd: ^pft$physical_fmd,
      parent_charge_id: pft$charge_id,
      path_description_created: boolean,
      path_handle_name: amt$local_file_name,
      path_name: ost$string,
      path_table_lock_set: boolean,
      permit_entry: pft$permit_entry,
      pf_system_file_id: gft$system_file_identifier,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      process_pt_results: bat$process_pt_results,
      valid_objects: pft$object_selections;

    cycle_number_valid := FALSE;
    #SPOIL (cycle_number_valid);
    define_cycle := FALSE;
    path_table_lock_set := FALSE;
    #SPOIL (path_table_lock_set);
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    p_attached_pf_entry := NIL;
    path_description_created := FALSE;

    syp$push_inhibit_job_recovery;

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      IF family_location = pfc$local_mainframe THEN
        fmp$lock_path_table (status);
        IF NOT status.normal THEN
          syp$pop_inhibit_job_recovery;
          RETURN; {----->
        IFEND;
        path_table_lock_set := TRUE;
      IFEND;

      valid_objects := $pft$object_selections [pfc$file_object];
      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_file_object, p_internal_cycle_path^.path, permit_entry, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      pfp$validate_default_password (path, authority, password_selector, p_file_object, status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF status.normal THEN
        cycle_number := p_cycle^.cycle_entry.cycle_number;
        cycle_number_valid := TRUE;
        #SPOIL (cycle_number_valid);
      IFEND;
    IFEND;

    IF status.normal THEN
      data_residence := p_cycle^.cycle_entry.data_residence;
      IF data_residence = pfc$offline_data THEN
        pfp$validate_file_permission (path, authority, permit_entry, $pft$permit_selections
              [pfc$read, pfc$shorten, pfc$append, pfc$modify, pfc$execute], -$pft$share_selections [],
              status);
      ELSE

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

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

    IF status.normal THEN
      IF replace_cycle_data THEN
        pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
              p_physical_fmd);
        IF p_physical_fmd <> NIL THEN
          locate_cycle_on_selected_volume (^p_physical_fmd^.fmd, p_volume_list, cycle_on_selected_volume,
                status);
          IF status.normal AND (NOT cycle_on_selected_volume) THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$restore_not_selected,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_parameter (osc$status_parameter_delimiter,
                  'REPLACE_CYCLE_DATA=TRUE and not on selected volume(s)', status);
          IFEND;
        IFEND;
      ELSE
        pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
              p_physical_fmd);
        IF (p_physical_fmd <> NIL) AND ((puc$media_missing IN restore_selections) OR
              (puc$volume_unavailable IN restore_selections)) THEN
          locate_cycle_on_selected_volume (^p_physical_fmd^.fmd, p_volume_list, cycle_on_selected_volume,
                status);
          IF status.normal THEN
            IF cycle_on_selected_volume THEN
              locate_cycle_on_active_device (^path, p_cycle, p_physical_fmd^.fmd,
                    catalog_locator.p_catalog_file, cycle_on_missing_volume, cycle_on_unavailable_volume,
                    status);

              IF status.normal THEN
                define_cycle := (cycle_on_missing_volume AND (puc$media_missing IN restore_selections)) OR
                      (cycle_on_unavailable_volume AND (puc$volume_unavailable IN restore_selections));

                IF NOT define_cycle THEN
                  PUSH p_fs_path;
                  pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                  osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$data_already_defined,
                        p_fs_path^ (1, fs_path_size), status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        p_cycle^.cycle_entry.cycle_number, radix, NOT include_radix, status);
                IFEND;
              IFEND;
            ELSE
              PUSH p_fs_path;
              pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$restore_not_selected,
                    p_fs_path^ (1, fs_path_size), status);
              osp$append_status_parameter (osc$status_parameter_delimiter,
                    'RESTORE_EXCLUDED_FILE_CYCLES and not on selected volume(s)', status);
            IFEND;
          IFEND;
        ELSEIF p_physical_fmd <> NIL THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$data_already_defined,
                p_fs_path^ (1, fs_path_size), status);
          osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                radix, NOT include_radix, status);
        ELSE
          IF NOT (puc$no_data_defined IN restore_selections) THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$restore_not_selected,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_parameter (osc$status_parameter_delimiter,
                  'RESTORE_EXCLUDED_FILE_CYCLES and NO_DATA_DEFINED not in RESTORE_OPTIONS', status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal AND ((mandated_modification_time.verify_option = pfc$verify_modification_time) OR
          (mandated_modification_time.verify_option = pfc$replace_modification_time)) THEN
      modification_times_match := ((mandated_modification_time.specified_modification_time =
            p_cycle^.cycle_entry.cycle_statistics.modification_date_time) OR
            (mandated_modification_time.specified_modification_time =
            p_cycle^.cycle_entry.data_modification_date_time));
      IF (mandated_modification_time.verify_option = pfc$verify_modification_time) AND
            NOT modification_times_match THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$modification_time_mismatch,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
              radix, NOT include_radix, status);
      IFEND;
    IFEND;

    IF status.normal AND replace_cycle_data 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;

      IF (mandated_modification_time.verify_option = pfc$replace_modification_time) OR
            (mandated_modification_time.verify_option = pfc$verify_modification_time) THEN
        p_data_modification_date_time := ^mandated_modification_time.specified_modification_time;
      ELSE
        p_data_modification_date_time := NIL;
      IFEND;
      purge_cycle (path, device_class, purge_cycle_options, p_data_modification_date_time, p_cycle,
            catalog_locator.p_catalog_file, p_file_object, catalog_locator.object_list_descriptor,
            disk_image_deleted, bytes_released, local_status);
      IF local_status.normal THEN
        IF (pfc$master_catalog_owner IN authority.ownership) AND (bytes_released > 0) THEN
          sfp$accumulate_file_space (sfc$perm_file_space_limit, -bytes_released);
        IFEND;
      ELSE
        status := local_status;
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$assign_locked_apfid (apft_index, status);
    IFEND;
    apfid_assigned := status.normal;
    pfv$locked_apfid := apft_index;

    IF status.normal THEN
      pfp$create_permanent_file (family_location, lfn, path, p_cycle^.cycle_entry.cycle_number, apft_index,
            -$pft$usage_selections [], $pft$share_selections [], permit_entry.application_info,
            validation_ring, {password_protected} (p_file_object^.object_entry.password <> osc$null_name),
            NOT enable_media_damage_detection, NOT implicit_attach, {recreate_attached_cycle_data} FALSE,
            {p_file_label} NIL, rmc$mass_storage_device, p_mass_storage_request_info,
            {p_removable_media_req_info} NIL, {p_volume_list} NIL, authority, ignore_path_handle,
            pf_system_file_id, internal_cycle_name, bytes_allocated, p_file_server_buffers, status);
    IFEND;
    path_description_created := status.normal;

    IF status.normal AND define_cycle THEN
      {
      { The file is on a selected downed device or a medium is missing.
      {
      IF p_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
        {
        { Logically purge the old cycle and create a new cycle to replace it.
        {
        p_cycle^.cycle_entry.entry_type := pfc$purged_cycle_entry;
        pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);

        pfp$establish_free_cycle_entry (^catalog_locator.p_catalog_file^.catalog_heap, p_cycle_list,
              p_new_cycle_list, new_cycle_list, p_free_cycle, status);
        IF status.normal THEN
          IF new_cycle_list THEN
            pfp$build_cycle_list_locator (p_new_cycle_list, catalog_locator.p_catalog_file,
                  p_file_object^.object_entry.cycle_list_locator);
            pfp$compute_checksum (^p_file_object^.object_entry, #SIZE (pft$object_entry),
                  p_file_object^.checksum);
            p_free_cycle^ := p_cycle^;
            osp$prevalidate_free ((#OFFSET (p_cycle_list) - #OFFSET (^catalog_locator.p_catalog_file^.
                  catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap,
                  prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_cycle_list IN catalog_locator.p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'CYCLE_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_cycle_list));
              p_cycle_list := NIL;
            IFEND;
            p_cycle_list := p_new_cycle_list;
          ELSE
            p_free_cycle^ := p_cycle^;
          IFEND;
          p_cycle := p_free_cycle;
          p_cycle^.cycle_entry.entry_type := pfc$normal_cycle_entry;
          p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
          p_cycle^.cycle_entry.cycle_damage_symptoms := $fst$cycle_damage_symptoms [];
          pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
                p_cycle^.cycle_entry.fmd_locator);
          pfp$build_file_label_locator ({p_file_label} NIL, catalog_locator.p_catalog_file,
                p_cycle^.cycle_entry.file_label_locator);
          pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
        IFEND;
      ELSE
        {
        { Delete all subfiles before re-creating the cycle.
        {
        dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
              local_status);
        osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^catalog_locator.p_catalog_file^.
              catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
                prevalidate_free_result, #OFFSET (p_physical_fmd));
          p_physical_fmd := NIL;
        IFEND;
        pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL, p_cycle^.cycle_entry.fmd_locator);
        pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$record_dm_file_parameters (^path, ^p_cycle^.cycle_entry.cycle_number, pf_system_file_id,
            rmc$mass_storage_device, {p_removable_media_req_info} NIL, {p_volume_list} NIL,
            ^catalog_locator.p_catalog_file^.catalog_heap, p_physical_fmd, status);
    IFEND;

    IF status.normal THEN
      p_internal_cycle_path^.cycle_name := internal_cycle_name;
      build_attached_pf_entry (pf_system_file_id, path, p_cycle^.cycle_entry.cycle_number,
            rmc$mass_storage_device, {update_catalog} TRUE, update_cycle_statistics, -$pft$usage_selections
            [], $pft$share_selections [], {media_image_inconsistent} FALSE,
            {media_damage_detection_enabled} FALSE, $fst$cycle_damage_symptoms [], p_internal_cycle_path^,
            p_attached_pf_entry, status);
    IFEND;
    apfid_in_use := status.normal;

    IF status.normal THEN
      mandated_modification_time.existing_modification_time :=
            p_cycle^.cycle_entry.cycle_statistics.modification_date_time;
      IF (mandated_modification_time.verify_option = pfc$replace_modification_time) AND
            NOT modification_times_match AND NOT replace_cycle_data THEN
        p_cycle^.cycle_entry.cycle_damage_symptoms := $fst$cycle_damage_symptoms
              [fsc$respf_modification_mismatch];
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
              mandated_modification_time.specified_modification_time;
        p_cycle^.cycle_entry.data_modification_date_time :=
              mandated_modification_time.specified_modification_time;
      IFEND;
      p_cycle^.cycle_entry.internal_cycle_name := internal_cycle_name;
      p_cycle^.cycle_entry.device_information.device_class_defined := TRUE;
      p_cycle^.cycle_entry.device_information.device_class := pfc$mass_storage_device;
      IF data_residence <> pfc$offline_data THEN
        p_cycle^.cycle_entry.device_information.eoi := 0;
        p_cycle^.cycle_entry.device_information.bytes_allocated := bytes_allocated;
      IFEND;
      IF replace_cycle_data THEN
        p_cycle^.cycle_entry.global_file_name := internal_cycle_name;
      IFEND;
      pfp$increment_usage_counts (path, -$pft$usage_selections [], $pft$share_selections [], mainframe_id,
            catalog_locator.p_catalog_file, flush_catalog_pages, p_cycle^.cycle_entry, status);
      pfp$build_fmd_locator (p_physical_fmd, catalog_locator.p_catalog_file,
            p_cycle^.cycle_entry.fmd_locator);
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
    IFEND;

    IF NOT status.normal AND path_description_created THEN
      dmp$destroy_file (pf_system_file_id, sfc$no_limit, local_status);

      PUSH p_evaluated_file_reference;
      pfp$convert_pf_to_fs_structure (path, p_evaluated_file_reference^);
      p_evaluated_file_reference^.cycle_reference.specification := fsc$cycle_number;
      p_evaluated_file_reference^.cycle_reference.cycle_number := cycle_number;
      fmp$process_pt_request (process_pt_work_list, lfn, p_evaluated_file_reference^, p_cycle_description,
            process_pt_results, local_status);
      fmp$delete_path_description (p_evaluated_file_reference^, {implicit_detach} FALSE,
            {return_permanent_file} FALSE, {detachment_options} NIL, local_status);

      IF p_attached_pf_entry <> NIL THEN
        IF p_attached_pf_entry^.p_external_path <> NIL THEN
          FREE p_attached_pf_entry^.p_external_path IN pfv$p_p_job_heap^^;
        IFEND;
        FREE p_attached_pf_entry IN pfv$p_p_job_heap^^;
        pfp$release_locked_apfid (apft_index, local_status);
        pfp$process_unexpected_status (local_status);
        apfid_assigned := FALSE;
      IFEND;
    IFEND;

    IF apfid_assigned THEN
      IF apfid_in_use THEN
        pfp$unlock_apfid (apft_index, p_attached_pf_entry, local_status);
      ELSE
        pfp$release_locked_apfid (apft_index, local_status);
      IFEND;
      pfv$locked_apfid := 0;
      pfp$process_unexpected_status (local_status);
    IFEND;

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

    IF path_table_lock_set THEN
      fmp$unlock_path_table;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_define_data;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_delete_all_arch_entries
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
     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_delete_all_arch_entries; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      archive_index: pft$archive_index,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_archive_entry: ^pft$archive_entry,
      p_archive_list: ^pft$archive_list,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_physical_amd: ^pft$physical_amd,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      update_checksum: boolean;

    syp$push_inhibit_job_recovery;

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

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

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

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /delete_archive_list/; {----->
      IFEND;

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

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /delete_archive_list/; {----->
      IFEND;

      IF p_cycle^.cycle_entry.archive_list_locator.archive_count = 0 THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$empty_archive_list,
              p_fs_path^ (1, fs_path_size), status);
        EXIT /delete_archive_list/; {----->
      IFEND;

      update_checksum := TRUE;

      pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator,
            catalog_locator.p_catalog_file, p_archive_list);

      FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
        p_archive_entry := ^p_archive_list^ [archive_index].archive_entry;
        pfp$build_amd_pointer (p_archive_entry^.amd_locator, catalog_locator.p_catalog_file, p_physical_amd);
        IF p_physical_amd <> NIL THEN
          osp$prevalidate_free ((#OFFSET (p_physical_amd) - #OFFSET (^catalog_locator.p_catalog_file^.
                catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_physical_amd IN catalog_locator.p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'ARCHIVE_MEDIA_DESCRIPTOR',
                  'file', prevalidate_free_result, #OFFSET (p_physical_amd));
            p_physical_amd := NIL;
          IFEND;
        IFEND;
      FOREND;

      osp$prevalidate_free ((#OFFSET (p_archive_list) - #OFFSET (^catalog_locator.p_catalog_file^.
            catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_archive_list IN catalog_locator.p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'ARCHIVE_LIST', 'file',
              prevalidate_free_result, #OFFSET (p_archive_list));
        p_archive_list := NIL;
      IFEND;
      pfp$build_archive_list_locator ({p_archive_list} NIL, catalog_locator.p_catalog_file,
            p_cycle^.cycle_entry.archive_list_locator);

    END /delete_archive_list/;

    IF update_checksum THEN
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_delete_archive_entry
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         archive_identification: pft$archive_identification;
     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_delete_archive_entry; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      delete_count: pft$archive_count,
      found: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      new_archive_count: pft$archive_count,
      new_archive_index: pft$archive_index,
      old_archive_index: pft$archive_index,
      p_archive_entry: ^pft$archive_entry,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_new_archive_list: ^pft$archive_list,
      p_old_archive_list: ^pft$archive_list,
      p_physical_amd: ^pft$physical_amd,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      update_checksum: boolean;

    syp$push_inhibit_job_recovery;

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

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

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

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /delete_archive_entry/; {----->
      IFEND;

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

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /delete_archive_entry/; {----->
      IFEND;

      IF p_cycle^.cycle_entry.archive_list_locator.archive_count = 0 THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$empty_archive_list,
              p_fs_path^ (1, fs_path_size), status);
        EXIT /delete_archive_entry/; {----->
      IFEND;

      pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator,
            catalog_locator.p_catalog_file, p_old_archive_list);
      found := FALSE;

      FOR old_archive_index := 1 TO p_cycle^.cycle_entry.archive_list_locator.archive_count DO
        p_archive_entry := ^p_old_archive_list^ [old_archive_index].archive_entry;
        IF (p_archive_entry^.archive_identification.application_identifier =
              archive_identification.application_identifier) THEN
          IF (p_archive_entry^.archive_identification.media_identifier.media_device_class =
                archive_identification.media_identifier.media_device_class) THEN
            IF (p_archive_entry^.archive_identification.media_identifier.media_volume_identifier =
                  archive_identification.media_identifier.media_volume_identifier) THEN
              found := TRUE;
            IFEND;
          IFEND;
        IFEND;
      FOREND;

      IF NOT found THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_archive_ident,
              archive_identification.application_identifier, status);
        EXIT /delete_archive_entry/; {----->
      ELSE
        update_checksum := TRUE;
      IFEND;

      new_archive_count := p_cycle^.cycle_entry.archive_list_locator.archive_count - 1;
      new_archive_index := 1;
      IF new_archive_count = 0 THEN
        p_new_archive_list := NIL;
        p_archive_entry := ^p_old_archive_list^ [1].archive_entry;
        pfp$build_amd_pointer (p_archive_entry^.amd_locator, catalog_locator.p_catalog_file, p_physical_amd);
        IF p_physical_amd <> NIL THEN
          osp$prevalidate_free ((#OFFSET (p_physical_amd) - #OFFSET (^catalog_locator.p_catalog_file^.
                catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_physical_amd IN catalog_locator.p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'ARCHIVE_MEDIA_DESCRIPTOR',
                  'file', prevalidate_free_result, #OFFSET (p_physical_amd));
            p_physical_amd := NIL;
          IFEND;
        IFEND;
      ELSE
        pfp$allocate_archive_list (new_archive_count, ^catalog_locator.p_catalog_file^.catalog_heap,
              p_new_archive_list, status);
        IF NOT status.normal THEN
          EXIT /delete_archive_entry/; {----->
        IFEND;

        found := FALSE;

      /build_new_archive_list/
        FOR old_archive_index := 1 TO UPPERBOUND (p_old_archive_list^) DO
          p_archive_entry := ^p_old_archive_list^ [old_archive_index].archive_entry;
          IF NOT found THEN
            IF (p_archive_entry^.archive_identification.application_identifier =
                  archive_identification.application_identifier) THEN
              IF (p_archive_entry^.archive_identification.media_identifier.media_device_class =
                    archive_identification.media_identifier.media_device_class) THEN
                IF (p_archive_entry^.archive_identification.media_identifier.media_volume_identifier =
                      archive_identification.media_identifier.media_volume_identifier) THEN
                  found := TRUE;
                  pfp$build_amd_pointer (p_archive_entry^.amd_locator, catalog_locator.p_catalog_file,
                        p_physical_amd);
                  IF p_physical_amd <> NIL THEN
                    osp$prevalidate_free ((#OFFSET (p_physical_amd) -
                          #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                          ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
                    IF prevalidate_free_result = osc$heap_free_valid THEN
                      FREE p_physical_amd IN catalog_locator.p_catalog_file^.catalog_heap;
                    ELSE
                      pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number,
                            'ARCHIVE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result,
                            #OFFSET (p_physical_amd));
                      p_physical_amd := NIL;
                    IFEND;
                  IFEND;
                  CYCLE /build_new_archive_list/; {----->
                IFEND;
              IFEND;
            IFEND;
          IFEND;
          p_new_archive_list^ [new_archive_index] := p_old_archive_list^ [old_archive_index];
          new_archive_index := new_archive_index + 1;
        FOREND /build_new_archive_list/;
      IFEND;

      pfp$build_archive_list_locator (p_new_archive_list, catalog_locator.p_catalog_file,
            p_cycle^.cycle_entry.archive_list_locator);

      osp$prevalidate_free ((#OFFSET (p_old_archive_list) -
            #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
            ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_old_archive_list IN catalog_locator.p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'ARCHIVE_LIST', 'file',
              prevalidate_free_result, #OFFSET (p_old_archive_list));
        p_old_archive_list := NIL;
      IFEND;
    END /delete_archive_entry/;

    IF update_checksum THEN
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_delete_catalog_permit
    (    path: pft$complete_path;
         system_privilege: boolean;
         group: pft$group;
     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_delete_catalog_permit; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_alarm_set: boolean,
      catalog_locator: pft$catalog_locator,
      changed_catalog_locator: pft$catalog_locator,
      global_file_name: ost$binary_unique_name,
      ignore_destroy_on_last_detach: boolean,
      local_status: ost$status,
      p_catalog_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /delete_catalog_permit/
    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 /delete_catalog_permit/; {----->
      IFEND;

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

      valid_objects := $pft$object_selections [pfc$catalog_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_catalog_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /delete_catalog_permit/; {----->
      IFEND;

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

      delete_permit_description (path, group, p_catalog_object, catalog_locator.p_catalog_file, status);
      IF NOT status.normal THEN
        EXIT /delete_catalog_permit/; {----->
      IFEND;

      IF p_catalog_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
        global_file_name := p_catalog_object^.object_entry.catalog_object_locator.global_file_name;
      ELSE
        global_file_name := catalog_locator.global_file_name;
      IFEND;
      pfp$check_catalog_alarm (global_file_name, catalog_alarm_set, ignore_destroy_on_last_detach);
      IF NOT catalog_alarm_set THEN
        {
        { Access the changed catalog so that an alarm may be set on it.
        {
        pfp$access_next_catalog (pfc$read_access, catalog_locator, p_catalog_object,
              (path [pfc$family_path_index] <> osv$system_family_name), changed_catalog_locator, status);
        IF status.normal THEN
          IF changed_catalog_locator.object_list_descriptor.catalog_type = pfc$internal_catalog THEN
            {
            { Set alarm on the parent.
            {
            catalog_locator.queuing_info.set_catalog_alarm := TRUE;
          ELSE
            changed_catalog_locator.queuing_info.set_catalog_alarm := TRUE;
            pfp$return_catalog (changed_catalog_locator, status);
            pfp$process_unexpected_status (status);
          IFEND;
        ELSEIF osp$file_access_condition (status) THEN
          pfp$detach_unavail_queued_cat (p_catalog_object^.object_entry.internal_object_name,
                changed_catalog_locator);
          status.normal := TRUE;
        ELSEIF status.condition <> pfe$catalog_access_retry THEN
          pfp$report_unexpected_status (status);
        IFEND;
      IFEND;
    END /delete_catalog_permit/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_delete_permit
    (    path: pft$complete_path;
         system_privilege: boolean;
         group: pft$group;
     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_delete_permit; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /delete_permit/
    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 /delete_permit/; {----->
      IFEND;

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

      valid_objects := $pft$object_selections [pfc$file_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /delete_permit/; {----->
      IFEND;

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

      delete_permit_description (path, group, p_file_object, catalog_locator.p_catalog_file, status);
      syp$hang_if_job_jrt_set (pfc$tjr_delete_permit);
    END /delete_permit/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_detach_reserved_cycles
    (    mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);

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

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

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

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

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

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

        syp$pop_inhibit_job_recovery;

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

        status := local_status;
        initiate_non_local_exit;


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

    PROCEND detach_reserved_cycles_handler;

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);

      IF all_cycles_detached THEN
        FREE pfv$reserved_cycle_info.p_catalog_path IN osv$task_shared_heap^;
        IF pfv$reserved_cycle_info.p_reserved_cycles <> NIL THEN
          FREE pfv$reserved_cycle_info.p_reserved_cycles IN osv$task_shared_heap^;
        IFEND;
        pfv$reserved_cycle_info.number_of_cycles_reserved := 0;
        osp$clear_signature_lock (pfv$reserved_cycle_info.signature_lock, status);
      IFEND;

      EXIT pfp$r2_detach_reserved_cycles; {----->
    PROCEND initiate_non_local_exit;

    VAR
      all_cycles_detached: boolean,
      authority: pft$authority,
      bytes_allocated_change: sft$counter,
      bytes_released: amt$file_byte_address,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      cycle_index: pft$object_index,
      device_class: rmt$device_class,
      disk_image_deleted: boolean,
      file_info: dmt$file_information,
      fmd_modified: boolean,
      i: integer,
      local_status: ost$status,
      lock_status: ost$signature_lock_status,
      object_index: pft$object_index,
      p_complete_path: ^pft$complete_path,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      process_non_local_exit: boolean,
      purge_cycle_options: pft$purge_cycle_options,
      variant_path: pft$variant_path;

    IF pfv$reserved_cycle_info.p_catalog_path = NIL THEN
      RETURN; {----->
    IFEND;

    osp$test_signature_lock (pfv$reserved_cycle_info.signature_lock, lock_status);
    IF lock_status <> osc$sls_locked_by_current_task THEN
      RETURN; {----->
    IFEND;

    syp$push_inhibit_job_recovery;

  /detach_reserved_cycles/
    BEGIN
      bytes_allocated_change := 0;
      catalog_active := FALSE;
      all_cycles_detached := FALSE;
      #SPOIL (all_cycles_detached);
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);

      pfp$get_authority (pfv$reserved_cycle_info.p_catalog_path^, {system_privilege} TRUE, authority, status);
      IF NOT status.normal THEN
        EXIT /detach_reserved_cycles/; {----->
      IFEND;

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

      PUSH p_complete_path: [1 .. UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^) + 1];
      FOR i := 1 TO UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^) DO
        p_complete_path^ [i] := pfv$reserved_cycle_info.p_catalog_path^ [i];
      FOREND;
      p_complete_path^ [UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^) + 1] := 'UNKNOWN_FILE';

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

    /process_cycles/
      FOR object_index := 1 TO pfv$reserved_cycle_info.number_of_cycles_reserved DO
        pfp$locate_object (pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].external_object_name,
              $pft$object_selections [pfc$file_object, pfc$purged_file_object],
              catalog_locator.object_list_descriptor, p_file_object);
        IF (p_file_object = NIL) OR (pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].
              internal_object_name <> p_file_object^.object_entry.internal_object_name) THEN
          pfp$internal_locate_object (catalog_locator.object_list_descriptor.p_object_list,
                pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_object_name,
                p_file_object);
          IF p_file_object = NIL THEN
            CYCLE /process_cycles/; {----->
          IFEND;
        IFEND;

        pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
              catalog_locator.p_catalog_file, p_cycle_list);

        p_cycle := NIL;

      /locate_reserved_cycle/
        FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
          IF ((p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$normal_cycle_entry)
{        } OR (p_cycle_list^ [cycle_index].cycle_entry.entry_type = pfc$purged_cycle_entry))
{       } AND (p_cycle_list^ [cycle_index].cycle_entry.internal_cycle_name =
                pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_cycle_name) THEN

            p_cycle := ^p_cycle_list^ [cycle_index];
            EXIT /locate_reserved_cycle/; {----->
          IFEND;
        FOREND /locate_reserved_cycle/;

{Debug Code
        IF p_cycle = NIL THEN
          syp$increment_rsv_cycle_counter (syc$ircc_detach_nil);
        ELSEIF p_cycle^.cycle_entry.entry_type = pfc$purged_cycle_entry THEN
          syp$increment_rsv_cycle_counter (syc$ircc_detach_purged);
        IFEND;
{End Debug Code

        IF p_cycle <> NIL THEN
          p_complete_path^ [UPPERBOUND (p_complete_path^)] :=
                p_file_object^.object_entry.external_object_name;
          pfp$detach_permanent_file (p_complete_path, pfv$reserved_cycle_info.
                p_reserved_cycles^ [object_index].system_file_id, $pft$usage_selections [pfc$read],
                {catalog_update_allowed} TRUE, p_cycle, catalog_locator.p_catalog_file,
                dmc$df_ignore_file_info, fmd_modified, file_info, local_status);
          IF local_status.normal THEN
            pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_cycle_name :=
                  pfv$null_unique_name;
            decrement_usage_counts ($pft$usage_selections [pfc$read], $pft$share_selections
                  [pfc$read, pfc$execute], mainframe_id, catalog_locator.p_catalog_file,
                  p_cycle^.cycle_entry);
            pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
          IFEND;

          IF (local_status.normal OR NOT osp$file_access_condition (local_status)) AND
                (p_cycle^.cycle_entry.entry_type = pfc$purged_cycle_entry) 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;

            purge_cycle_options.preserve_cycle_entry := FALSE;
            purge_cycle (p_complete_path^, device_class, purge_cycle_options,
                  {p_data_modification_date_time} NIL, p_cycle, catalog_locator.p_catalog_file, p_file_object,
                  catalog_locator.object_list_descriptor, disk_image_deleted, bytes_released, local_status);
            IF local_status.normal THEN
              bytes_allocated_change := bytes_allocated_change - bytes_released;
              pfp$process_unexpected_status (local_status);
            IFEND;
          IFEND;
        IFEND;

        IF (object_index MOD pfv$unlock_catalog_threshold) = 0 THEN
          pfp$unlock_catalog_pages (catalog_locator, status);
          IF NOT status.normal THEN
            EXIT /process_cycles/; {----->
          IFEND;
        IFEND;

      FOREND /process_cycles/;

{Debug Code
      FOR object_index := 1 TO pfv$reserved_cycle_info.number_of_cycles_reserved DO
        IF pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_cycle_name <>
              pfv$null_unique_name THEN
          p_complete_path^ [UPPERBOUND (p_complete_path^)] :=
                pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].external_object_name;
          variant_path.complete_path := TRUE;
          variant_path.p_complete_path := p_complete_path;
          pfp$log_ascii ('***PF Reserved Cycle Info - Device File remains attached***',
                $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
                {critical_message} FALSE, local_status);
          pfp$log_path (variant_path, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
                {critical_message} FALSE, local_status);
        IFEND;
      FOREND;
{End Debug Code

      all_cycles_detached := TRUE;
      #SPOIL (all_cycles_detached);
    END /detach_reserved_cycles/;

    IF all_cycles_detached THEN
      FREE pfv$reserved_cycle_info.p_catalog_path IN osv$task_shared_heap^;
      IF pfv$reserved_cycle_info.p_reserved_cycles <> NIL THEN
        FREE pfv$reserved_cycle_info.p_reserved_cycles IN osv$task_shared_heap^;
      IFEND;
      pfv$reserved_cycle_info.number_of_cycles_reserved := 0;
      osp$clear_signature_lock (pfv$reserved_cycle_info.signature_lock, local_status);
    IFEND;

    IF catalog_active THEN
      IF (pfc$master_catalog_owner IN authority.ownership) AND (bytes_allocated_change < 0) THEN
        sfp$accumulate_file_space (sfc$perm_file_space_limit, bytes_allocated_change);
      IFEND;
      osp$disestablish_cond_handler;
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_detach_reserved_cycles;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_dm_attach_item
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
     VAR sfid: gft$system_file_identifier;
     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_dm_attach_item; {----->
    PROCEND initiate_non_local_exit;

    CONST
      root_size_guess = 0ff(16),
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      device_class: rmt$device_class,
      existing_sft_entry: dmt$existing_sft_entry,
      file_damaged: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_fmd: ^pft$fmd,
      p_fs_path: ^fst$path,
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_internal_path: ^pft$internal_path,
      p_object: ^pft$physical_object,
      p_physical_fmd: ^pft$physical_fmd,
      p_root_container: ^pft$root,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      root_size: pft$root_size,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /dm_attach_item/
    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 /dm_attach_item/; {----->
      IFEND;

      IF NOT (pfc$system_owner IN authority.ownership) THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, ' NOT SYSTEM OWNER',
              status);
        EXIT /dm_attach_item/; {----->
      IFEND;

      IF UPPERBOUND (path) <= pfc$family_path_index THEN
        root_size := root_size_guess;
        PUSH p_root_container: [[REP root_size OF cell]];
        RESET p_root_container;
        stp$get_pf_root (path [pfc$set_path_index], root_size, p_root_container^, status);

        IF status.normal THEN
          RESET p_root_container;
          NEXT p_internal_catalog_name IN p_root_container;
          NEXT p_stored_fmd_size IN p_root_container;
          NEXT p_fmd: [[REP p_stored_fmd_size^ OF cell]] IN p_root_container;
          dmp$attach_file (p_internal_catalog_name^, gfc$fk_catalog, p_fmd^, -pfv$write_usage,
                -$pft$share_selections [], pfc$average_share_history, pfc$maximum_pf_length,
                {restricted_attach} FALSE, {exit_on_unknown_file} FALSE, {server_file} FALSE,
                mmc$null_shared_queue, file_damaged, sfid, existing_sft_entry, status);
        IFEND;
        EXIT /dm_attach_item/; {----->
      IFEND;
      {
      { Process all items other than root catalog.
      {
      valid_objects := $pft$object_selections [pfc$file_object, pfc$catalog_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /dm_attach_item/; {----->
      IFEND;

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

      IF p_object^.object_entry.object_type = pfc$catalog_object THEN
        IF p_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
          pfp$build_fmd_pointer (p_object^.object_entry.catalog_object_locator.fmd_locator,
                catalog_locator.p_catalog_file, p_physical_fmd);
          IF p_physical_fmd = NIL THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, ' NIL CATALOG FMD',
                  status);
          ELSE
            dmp$attach_file (p_object^.object_entry.internal_object_name, gfc$fk_catalog, p_physical_fmd^.
                  fmd, -pfv$write_usage, -$pft$share_selections [], pfc$average_share_history,
                  pfc$maximum_pf_length, {restricted_attach} FALSE, {exit_on_unknown_file} FALSE,
                  {server_file} FALSE, mmc$null_shared_queue, file_damaged, sfid, existing_sft_entry, status);
          IFEND;
        ELSE
          {
          { Currently the only internal catalog is the family catalog,
          { which is handled above.
          {
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, ' INTERNAL CATALOG',
                status);
        IFEND;
      ELSE {file object}
        pfp$build_cycle_list_pointer (p_object^.object_entry.cycle_list_locator,
              catalog_locator.p_catalog_file, p_cycle_list);
        pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);

        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;

        IF status.normal AND (device_class = rmc$mass_storage_device) THEN
          pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
                p_physical_fmd);
          IF p_physical_fmd = NIL THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
                  radix, NOT include_radix, status);
          ELSE
            dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                  p_physical_fmd^.fmd, -pfv$write_usage, -$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, sfid, existing_sft_entry, status);
          IFEND;
        IFEND;
      IFEND;
    END /dm_attach_item/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_flush_catalog
    (    p_complete_path: ^pft$complete_path;
     VAR status: ost$status);

    VAR
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      index: pft$array_index,
      last_catalog_index: pft$array_index,
      local_status: ost$status,
      p_file_object: ^pft$physical_object,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_parent_path: ^pft$complete_path,
      permit_entry: pft$permit_entry;

    syp$push_inhibit_job_recovery;
    pfp$get_authority (p_complete_path^, {system_privilege} FALSE, authority, status);

    IF status.normal THEN
      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (p_complete_path^)];
      pfp$access_object (p_complete_path^, pfc$write_access, authority,
            -$pft$object_selections [pfc$free_object], charge_id, catalog_locator, p_file_object,
            p_internal_cycle_path^.path, permit_entry, status);

      IF status.normal THEN
        pfp$validate_ored_permission (p_complete_path^, authority, permit_entry,
              -$pft$permit_selections [pfc$read, pfc$execute], -$pft$share_selections [], status);
        IF status.normal THEN
          catalog_locator.flush_catalog_pages := TRUE;
          pfp$return_catalog (catalog_locator, status);
          pfp$process_unexpected_status (status);
        ELSE
          catalog_locator.flush_catalog_pages := FALSE;
          pfp$return_catalog (catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      ELSEIF status.condition = pfe$unknown_item THEN
{ The object may have been purged}
        authority.ownership := $pft$ownership [pfc$master_catalog_owner];
        last_catalog_index := UPPERBOUND (p_complete_path^) - 1;
        PUSH p_parent_path: [1 .. last_catalog_index];
        FOR index := 1 TO last_catalog_index DO
          p_parent_path^ [index] := p_complete_path^ [index];
        FOREND;
        pfp$get_catalog (p_parent_path^, pfc$write_access, authority, p_internal_cycle_path^.path, charge_id,
              permit_entry, catalog_locator, status);
        IF status.normal THEN
          catalog_locator.flush_catalog_pages := TRUE;
          pfp$return_catalog (catalog_locator, status);
          pfp$process_unexpected_status (status);
        IFEND;
      IFEND;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_flush_catalog;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_mark_release_candidate
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         validation_ring: ost$valid_ring;
         archive_identification: pft$archive_identification;
     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_mark_release_candidate; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

    VAR
      archive_index: pft$archive_index,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      found: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      mark_date_time: ost$date_time,
      p_archive: ^pft$physical_archive,
      p_archive_list: ^pft$archive_list,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /mark_release_candidate/
    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 /mark_release_candidate/; {----->
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /mark_release_candidate/; {----->
      IFEND;

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

      pfp$validate_file_permission (path, authority, permit_entry, $pft$permit_selections [pfc$control],
            -$pft$share_selections [], status);
      IF NOT status.normal THEN
        EXIT /mark_release_candidate/; {----->
      IFEND;

      pfp$validate_password (path, authority, password, p_file_object, status);
      IF NOT status.normal THEN
        EXIT /mark_release_candidate/; {----->
      IFEND;

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /mark_release_candidate/; {----->
      IFEND;

      IF p_cycle^.cycle_entry.archive_list_locator.archive_count = 0 THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$empty_archive_list,
              p_fs_path^ (1, fs_path_size), status);
        EXIT /mark_release_candidate/; {----->
      IFEND;

      pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator,
            catalog_locator.p_catalog_file, p_archive_list);

      found := FALSE;

      FOR archive_index := 1 TO p_cycle^.cycle_entry.archive_list_locator.archive_count DO
        p_archive := ^p_archive_list^ [archive_index];
        IF (p_archive^.archive_entry.archive_identification.application_identifier =
              archive_identification.application_identifier) THEN
          IF (p_archive^.archive_entry.archive_identification.media_identifier.media_device_class =
                archive_identification.media_identifier.media_device_class) THEN
            IF (p_archive^.archive_entry.archive_identification.media_identifier.media_volume_identifier =
                  archive_identification.media_identifier.media_volume_identifier) THEN
              found := TRUE;
              pmp$get_compact_date_time (mark_date_time, local_status);
              p_archive^.archive_entry.release_candidate.releasable := TRUE;
              p_archive^.archive_entry.release_candidate.mark_date_time := mark_date_time;
              pfp$compute_checksum (#LOC (p_archive^.archive_entry), #SIZE (p_archive^.archive_entry),
                    p_archive^.checksum);
            IFEND;
          IFEND;
        IFEND;
      FOREND;

      IF NOT found THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_archive_ident,
              archive_identification.application_identifier, status);
        EXIT /mark_release_candidate/; {----->
      IFEND;

    END /mark_release_candidate/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_permit
    (    path: pft$complete_path;
         system_privilege: boolean;
         permit_level: pft$permit_level;
         group: pft$group;
         permit_selections: pft$permit_selections;
         share_requirements: pft$share_requirements;
         application_info: pft$application_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_permit; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /permit/
    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 /permit/; {----->
      IFEND;

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

      IF authority.ownership <= $pft$ownership [pfc$master_catalog_owner] THEN
        pfp$check_group_by_permit_level (permit_level, group, status);
        IF NOT status.normal THEN
          EXIT /permit/; {----->
        IFEND;
      IFEND;

      valid_objects := $pft$object_selections [pfc$file_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /permit/; {----->
      IFEND;

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

      replace_permit_description (path, group, permit_selections, share_requirements, application_info,
            p_file_object, catalog_locator.p_catalog_file, status);
      syp$hang_if_job_jrt_set (pfc$tjr_permit);
    END /permit/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_permit_catalog
    (    path: pft$complete_path;
         system_privilege: boolean;
         permit_level: pft$permit_level;
         group: pft$group;
         permit_selections: pft$permit_selections;
         share_requirements: pft$share_requirements;
         application_info: pft$application_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_permit_catalog; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_alarm_set: boolean,
      catalog_locator: pft$catalog_locator,
      changed_catalog_locator: pft$catalog_locator,
      global_file_name: ost$binary_unique_name,
      ignore_destroy_on_last_detach: boolean,
      local_status: ost$status,
      p_catalog_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /permit_catalog/
    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 /permit_catalog/; {----->
      IFEND;

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

      IF authority.ownership <= $pft$ownership [pfc$master_catalog_owner] THEN
        pfp$check_group_by_permit_level (permit_level, group, status);
        IF NOT status.normal THEN
          EXIT /permit_catalog/; {----->
        IFEND;
      IFEND;

      valid_objects := $pft$object_selections [pfc$catalog_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_catalog_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /permit_catalog/; {----->
      IFEND;

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

      replace_permit_description (path, group, permit_selections, share_requirements, application_info,
            p_catalog_object, catalog_locator.p_catalog_file, status);
      IF NOT status.normal THEN
        EXIT /permit_catalog/; {----->
      IFEND;

      IF p_catalog_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog THEN
        global_file_name := p_catalog_object^.object_entry.catalog_object_locator.global_file_name;
      ELSE
        global_file_name := catalog_locator.global_file_name;
      IFEND;
      pfp$check_catalog_alarm (global_file_name, catalog_alarm_set, ignore_destroy_on_last_detach);
      IF NOT catalog_alarm_set THEN
        {
        { Access the changed catalog so that an alarm may be set on it.
        {
        pfp$access_next_catalog (pfc$read_access, catalog_locator, p_catalog_object,
              (path [pfc$family_path_index] <> osv$system_family_name), changed_catalog_locator, status);
        IF status.normal THEN
          IF changed_catalog_locator.object_list_descriptor.catalog_type = pfc$internal_catalog THEN
            {
            { Set alarm on the parent.
            {
            catalog_locator.queuing_info.set_catalog_alarm := TRUE;
          ELSE
            changed_catalog_locator.queuing_info.set_catalog_alarm := TRUE;
            pfp$return_catalog (changed_catalog_locator, status);
            pfp$process_unexpected_status (status);
          IFEND;
        ELSEIF osp$file_access_condition (status) THEN
          pfp$detach_unavail_queued_cat (p_catalog_object^.object_entry.internal_object_name,
                changed_catalog_locator);
          status.normal := TRUE;
        IFEND;
      IFEND;
    END /permit_catalog/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_purge
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         purge_cycle_options: pft$purge_cycle_options;
         system_privilege: boolean;
         validation_ring: ost$valid_ring;
     VAR authority: pft$authority;
     VAR device_class: rmt$device_class;
     VAR bytes_released: amt$file_byte_address;
     VAR status: ost$status);


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

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

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

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

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

        IF catalog_locator.attached THEN
          IF disk_image_deleted THEN
            p_cycle^.cycle_entry.entry_type := pfc$free_cycle_entry;
            catalog_locator.abort_catalog_operation := FALSE;
          ELSE
            catalog_locator.abort_catalog_operation := TRUE;
          IFEND;

          pfp$return_catalog (catalog_locator, local_status);
          IF NOT local_status.normal THEN
            pfp$report_system_error (local_status);
          IFEND;
        IFEND;


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

        status := local_status;
        initiate_non_local_exit;


      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          pfp$log_ascii ('***Recover Files***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
                pmc$msg_origin_system, {critical_message} FALSE, local_status);
          {syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND purge_handler;

    PROCEDURE initiate_non_local_exit;

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

    VAR
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      disk_image_deleted: boolean,
      file_path_index: integer,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_label: ^fmt$file_label,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_stored_file_label: ^pft$physical_file_label,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

    disk_image_deleted := FALSE;
    #SPOIL (disk_image_deleted);
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, system_privilege, authority, status);
    IF status.normal THEN
      valid_objects := $pft$object_selections [pfc$file_object];
      file_path_index := UPPERBOUND (path);
      PUSH p_internal_path: [1 .. file_path_index];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_file_object, p_internal_path^, permit_entry, status);
    IFEND;
    catalog_active := status.normal;

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

    IF status.normal AND purge_cycle_options.enforce_password_validation THEN
      pfp$validate_password (path, authority, password, p_file_object, status);
    IFEND;

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal 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_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, catalog_locator.p_catalog_file,
            p_stored_file_label);
      IF p_stored_file_label = NIL THEN
        p_file_label := NIL;
      ELSE
        p_file_label := ^p_stored_file_label^.file_label;
      IFEND;

      IF purge_cycle_options.enforce_ring_validation THEN
        pfp$validate_ring_access (path, p_file_label, pfv$write_usage, validation_ring, status);
        {
        { Allow an administrator to purge a cycle which has a bad label.
        {
        status.normal := status.normal OR ((status.condition = ame$damaged_file_attributes) AND
              (authority.ownership - $pft$ownership [pfc$master_catalog_owner] <> $pft$ownership []));
      IFEND;
    ELSE
      device_class := rmc$mass_storage_device;
    IFEND;

    IF status.normal THEN
      purge_cycle (path, device_class, purge_cycle_options, {p_data_modification_date_time} NIL, p_cycle,
            catalog_locator.p_catalog_file, p_file_object, catalog_locator.object_list_descriptor,
            disk_image_deleted, bytes_released, status);
    IFEND;

    syp$hang_if_job_jrt_set (pfc$tjr_purge);

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_purge;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_purge_catalog
    (    path: pft$complete_path;
         system_privilege: boolean;
         delete_option: pft$delete_option;
     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_purge_catalog; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_catalog_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;

  /purge_catalog/
    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 /purge_catalog/; {----->
      IFEND;

      IF UPPERBOUND (path) <= pfc$master_catalog_path_index THEN
        pfp$validate_family_ownership (path [pfc$family_path_index], authority, status);
      ELSE
        pfp$validate_ownership (authority, path, status);
      IFEND;
      IF NOT status.normal THEN
        EXIT /purge_catalog/; {----->
      IFEND;

      valid_objects := $pft$object_selections [pfc$catalog_object];
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, valid_objects, parent_charge_id, catalog_locator,
            p_catalog_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /purge_catalog/; {----->
      IFEND;

      pfp$delete_catalog_object (path, delete_option, p_catalog_object, catalog_locator, status);
    END /purge_catalog/;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_purge_catalog;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_purge_object
    (    path: pft$complete_path;
     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_purge_object; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      i: integer,
      local_status: ost$status,
      p_catalog_object: ^pft$physical_object,
      p_catalog_path: ^pft$complete_path,
      p_internal_path: ^pft$internal_path,
      p_physical_object: ^pft$physical_object,
      parent_catalog_index: integer,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      system_privilege: boolean;

    syp$push_inhibit_job_recovery;

  /purge_object/
    BEGIN
      catalog_active := FALSE;
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);
      system_privilege := TRUE;

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

      parent_catalog_index := UPPERBOUND (path) - 1;
      PUSH p_catalog_path: [1 .. parent_catalog_index];
      FOR i := 1 TO parent_catalog_index DO
        p_catalog_path^ [i] := path [i];
      FOREND;

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

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

      pfp$locate_object (path [UPPERBOUND (path)], $pft$object_selections
            [pfc$file_object, pfc$catalog_object], catalog_locator.object_list_descriptor, p_physical_object);
      IF p_physical_object <> NIL THEN
        p_physical_object^.object_entry.object_type := pfc$free_object;
        pfp$compute_checksum (^p_physical_object^.object_entry, #SIZE (pft$object_entry),
              p_physical_object^.checksum);
      IFEND;
    END /purge_object/;

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

?? TITLE := '  [XDCL, #GATE] pfp$r2_recreate_system_catalog', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to re-create the $system master catalog if
{   necessary.
{
{ DESIGN:
{   This procedure will attempt to attach the $system master catalog.  If
{   successful the catalog will be returned and no other action will be taken.
{   If the catalog is found to reside on a volume no longer in the
{   configuration, a new $system master catalog will be created and the
{   catalog_recreated_by_restore field in both the $system family catalog and
{   the $system master catalog will be set to TRUE.

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

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_object_locator: pft$catalog_object_locator,
      family_catalog_active: boolean,
      family_catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      master_catalog_active: boolean,
      master_catalog_locator: pft$catalog_locator,
      new_catalog_locator: pft$catalog_locator,
      p_family_object: ^pft$physical_object,
      p_family_path: ^pft$complete_path,
      p_internal_path: ^pft$internal_path,
      p_master_catalog_object: ^pft$physical_object,
      p_master_catalog_path: ^pft$complete_path,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_physical_fmd: ^pft$physical_fmd,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      valid_objects: pft$object_selections;

    syp$push_inhibit_job_recovery;
    family_catalog_active := FALSE;
    master_catalog_active := FALSE;
    pfv$allow_catalog_write := TRUE;
    catalog_object_locator.catalog_type := pfc$external_catalog;
    PUSH p_master_catalog_path: [1 .. pfc$master_catalog_path_index];
    p_master_catalog_path^ [pfc$set_path_index] := stv$system_set_name;
    p_master_catalog_path^ [pfc$family_path_index] := jmc$system_family;
    p_master_catalog_path^ [pfc$master_catalog_path_index] := jmc$system_user;

    pfp$get_authority (p_master_catalog_path^, system_privilege, authority, status);

    IF status.normal THEN
      pfp$validate_family_ownership (p_master_catalog_path^ [pfc$family_path_index], authority, status);
    IFEND;

    IF status.normal THEN
      valid_objects := $pft$object_selections [pfc$catalog_object];
      PUSH p_internal_path: [1 .. pfc$master_catalog_path_index];
      pfp$access_object (p_master_catalog_path^, pfc$write_access, authority, valid_objects, parent_charge_id,
            family_catalog_locator, p_master_catalog_object, p_internal_path^, permit_entry, status);
    IFEND;
    family_catalog_active := status.normal;

    IF status.normal THEN
      pfp$build_fmd_pointer (p_master_catalog_object^.object_entry.catalog_object_locator.fmd_locator,
            family_catalog_locator.p_catalog_file, p_physical_fmd);

      pfp$attach_catalog (^p_physical_fmd^.fmd, stv$system_set_name,
            p_master_catalog_object^.object_entry.internal_object_name,
            p_master_catalog_object^.object_entry.catalog_object_locator.global_file_name, pfc$write_access,
            {Catalog_remote =} TRUE, master_catalog_locator, status);
    IFEND;
    master_catalog_active := status.normal;


    IF NOT status.normal AND (status.condition = pfe$catalog_volume_not_online) THEN
      {
      { When the $system master catalog cannot be accessed a new catalog will be created
      { and the new fmd will be placed in the master catalogs entry in the family catalog.
      {
      pfp$create_catalog (p_master_catalog_path^, {p_ms_request_info} NIL, authority, {lock_catalog} TRUE,
            new_catalog_locator, status);
      IF status.normal THEN
        pfp$record_dm_file_parameters (p_master_catalog_path, {p_cycle_number} NIL,
              new_catalog_locator.system_file_id, rmc$mass_storage_device, {p_removable_media_req_info} NIL,
              {p_volume_list} NIL, ^family_catalog_locator.p_catalog_file^.catalog_heap, p_new_physical_fmd,
              status);
        IF status.normal THEN
          pfp$build_fmd_locator (p_new_physical_fmd, family_catalog_locator.p_catalog_file,
                catalog_object_locator.fmd_locator);
          catalog_object_locator.global_file_name := new_catalog_locator.global_file_name;
          pfp$return_catalog (new_catalog_locator, status);
        ELSE
          pfp$destroy_catalog (new_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;

      IF status.normal THEN
        osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^family_catalog_locator.p_catalog_file^.
              catalog_heap) - 16), ^family_catalog_locator.p_catalog_file^.catalog_heap,
              prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_physical_fmd IN family_catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (p_master_catalog_path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                'catalog', prevalidate_free_result, #OFFSET (p_physical_fmd));
          p_physical_fmd := NIL;
        IFEND;
        p_master_catalog_object^.object_entry.catalog_recreated_by_restore := TRUE;
        p_master_catalog_object^.object_entry.catalog_object_locator := catalog_object_locator;
        p_master_catalog_object^.object_entry.internal_object_name := catalog_object_locator.global_file_name;
        pfp$compute_checksum (^p_master_catalog_object^.object_entry, #SIZE (pft$object_entry),
              p_master_catalog_object^.checksum);
      IFEND;

      pfp$return_catalog (family_catalog_locator, local_status);
      family_catalog_active := NOT local_status.normal;
      pfp$process_unexpected_status (local_status);
      {
      { Obtain a pointer to the $system family catalog and set the
      { catalog_recreated_by_restore field to TRUE.
      {
      PUSH p_family_path: [1 .. pfc$family_path_index];
      p_family_path^ [pfc$set_path_index] := stv$system_set_name;
      p_family_path^ [pfc$family_path_index] := jmc$system_family;

      IF status.normal THEN
        valid_objects := $pft$object_selections [pfc$catalog_object];
        PUSH p_internal_path: [1 .. pfc$family_path_index];
        pfp$access_object (p_family_path^, pfc$write_access, authority, valid_objects, parent_charge_id,
              family_catalog_locator, p_family_object, p_internal_path^, permit_entry, status);
      IFEND;
      family_catalog_active := status.normal;

      IF status.normal THEN
        p_family_object^.object_entry.catalog_recreated_by_restore := TRUE;
        pfp$compute_checksum (^p_family_object^.object_entry, #SIZE (pft$object_entry),
              p_family_object^.checksum);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$system_catalog_recreated, '', status);
      IFEND;
    IFEND;

    IF master_catalog_active THEN
      pfp$return_catalog (master_catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    IF family_catalog_active THEN
      pfp$return_catalog (family_catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    pfv$allow_catalog_write := FALSE;
    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_recreate_system_catalog;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_release_data
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password: pft$password;
         p_release_data_info: {i/o} ^pft$release_data_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_release_data; {----->
    PROCEND initiate_non_local_exit;

    CONST
      system_privilege = TRUE;

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

    syp$push_inhibit_job_recovery;

  /release_data/
    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 /release_data/; {----->
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /release_data/; {----->
      IFEND;

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

      pfp$validate_file_permission (path, authority, permit_entry, $pft$permit_selections [pfc$control],
            -$pft$share_selections [], status);
      IF NOT status.normal THEN
        EXIT /release_data/; {----->
      IFEND;

      pfp$validate_password (path, authority, password, p_file_object, status);
      IF NOT status.normal THEN
        EXIT /release_data/; {----->
      IFEND;

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /release_data/; {----->
      IFEND;

      release_cycle_data (path, p_cycle, catalog_locator.p_catalog_file, p_release_data_info, status);
      IF NOT status.normal THEN
        EXIT /release_data/; {----->
      IFEND;

    END /release_data/;

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

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

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

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

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

    CONST
      system_privilege = TRUE;

    VAR
      archive_index: pft$archive_index,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      file_path_index: integer,
      found: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_archive: ^pft$physical_archive,
      p_archive_entry: ^pft$archive_entry,
      p_archive_list: ^pft$archive_list,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_old_physical_amd: ^pft$physical_amd,
      parent_charge_id: pft$charge_id,
      path_name: ost$string,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      update_checksum: boolean,
      valid: boolean,
      validated_name: ost$name;

    syp$push_inhibit_job_recovery;

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

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

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

      file_path_index := UPPERBOUND (path);
      PUSH p_internal_path: [1 .. file_path_index];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        EXIT /replace_archive_entry/; {----->
      IFEND;

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

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /replace_archive_entry/; {----->
      IFEND;

      IF p_cycle^.cycle_entry.archive_list_locator.archive_count = 0 THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$empty_archive_list,
              p_fs_path^ (1, fs_path_size), status);
        EXIT /replace_archive_entry/; {----->
      IFEND;

      pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator,
            catalog_locator.p_catalog_file, p_archive_list);
      found := FALSE;

    /search_archive_list/
      FOR archive_index := 1 TO p_cycle^.cycle_entry.archive_list_locator.archive_count DO
        p_archive_entry := ^p_archive_list^ [archive_index].archive_entry;
        IF (p_archive_entry^.archive_identification.application_identifier =
              archive_identification.application_identifier) THEN
          IF (p_archive_entry^.archive_identification.media_identifier.media_device_class =
                archive_identification.media_identifier.media_device_class) THEN
            IF (p_archive_entry^.archive_identification.media_identifier.media_volume_identifier =
                  archive_identification.media_identifier.media_volume_identifier) THEN
              found := TRUE;
              pfp$build_amd_pointer (p_archive_entry^.amd_locator, catalog_locator.p_catalog_file,
                    p_old_physical_amd);
              p_archive := ^p_archive_list^ [archive_index];
              pfp$r2_build_archive_entry (p_archive_array_entry^.archive_identification,
                    p_archive_array_entry, p_amd, catalog_locator.p_catalog_file, p_archive, status);
              IF NOT status.normal THEN
                EXIT /replace_archive_entry/; {----->
              ELSE
                update_checksum := TRUE;
              IFEND;

              IF p_old_physical_amd <> NIL THEN
                osp$prevalidate_free ((#OFFSET (p_old_physical_amd) -
                      #OFFSET (^catalog_locator.p_catalog_file^.catalog_heap) - 16),
                      ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
                IF prevalidate_free_result = osc$heap_free_valid THEN
                  FREE p_old_physical_amd IN catalog_locator.p_catalog_file^.catalog_heap;
                ELSE
                  pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number,
                        'ARCHIVE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result,
                        #OFFSET (p_old_physical_amd));
                  p_old_physical_amd := NIL;
                IFEND;
              IFEND;
              EXIT /search_archive_list/; {----->
            IFEND;
          IFEND;
        IFEND;
      FOREND /search_archive_list/;

      IF NOT found THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_archive_ident,
              archive_identification.application_identifier, status);
        EXIT /replace_archive_entry/; {----->
      IFEND;

    END /replace_archive_entry/;

    IF update_checksum THEN
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_replace_rem_media_fmd
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         replace_existing_rem_media_fmd: boolean;
         p_file_media_descriptor: ^SEQ ( * );
     VAR status: ost$status);

*copy pfp$r2_condition_handler

    PROCEDURE initiate_non_local_exit;

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

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      date_time: ost$date_time,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

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

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
    IFEND;
    catalog_active := status.normal;
    osp$establish_condition_handler (^pfp$r2_condition_handler, {block_exit} TRUE);

    IF status.normal THEN
      pfp$validate_default_password (path, authority, password_selector, p_file_object, status);
    IFEND;

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      pfi$store_file_media_descriptor (p_file_media_descriptor, catalog_locator.p_catalog_file, p_cycle,
            replace_existing_rem_media_fmd, status);
    IFEND;

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_replace_rem_media_fmd;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_resolve_path
    (    path: pft$complete_path;
         system_privilege: boolean;
     VAR cycle_reference: {i/o} fst$cycle_reference;
     VAR path_resolution: fst$path_resolution;
     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_resolve_path; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_number: fst$cycle_number,
      cycle_selector: pft$cycle_selector,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;

  /resolve_path/
    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 /resolve_path/; {----->
      IFEND;

      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, $pft$object_selections
            [pfc$file_object, pfc$catalog_object], parent_charge_id, catalog_locator, p_object,
            p_internal_path^, permit_entry, status);
      catalog_active := status.normal;
      IF NOT status.normal THEN
        CASE status.condition OF
        = pfe$unknown_item =
          CASE cycle_reference.specification OF
          = fsc$cycle_omitted =
            cycle_reference.specification := fsc$cycle_number;
            cycle_reference.cycle_number := 1;
            path_resolution := fsc$path_does_not_exist;
            status.normal := TRUE;

          = fsc$high_cycle, fsc$low_cycle =
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unknown_permanent_file,
                  p_fs_path^ (1, fs_path_size), status);

          = fsc$next_cycle =
            cycle_reference.specification := fsc$cycle_number;
            cycle_reference.cycle_number := 1;
            path_resolution := fsc$new_file_path;
            status.normal := TRUE;

          = fsc$cycle_number =
            {
            { The following IF condition and entire ELSE clause should be removed
            { once pf supports fst$cycle_number.
            {
            IF cycle_reference.cycle_number <= pfc$maximum_cycle_number THEN
              path_resolution := fsc$new_file_path;
              status.normal := TRUE;
            ELSE
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$bad_cycle_number, '', status);
              osp$append_status_integer (osc$status_parameter_delimiter, cycle_reference.cycle_number, 10,
                    FALSE, status);
            IFEND;

          ELSE
            osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$system_error,
                  'Invalid cycle specification.', status);
          CASEND;

        ELSE
          ;
        CASEND;
        EXIT /resolve_path/; {----->
      IFEND;

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

      CASE p_object^.object_entry.object_type OF
      = pfc$file_object =
        pfp$build_cycle_list_pointer (p_object^.object_entry.cycle_list_locator,
              catalog_locator.p_catalog_file, p_cycle_list);
        CASE cycle_reference.specification OF
        = fsc$cycle_omitted, fsc$high_cycle =
          cycle_selector.cycle_option := pfc$highest_cycle;
          pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
          IF status.normal THEN
            cycle_reference.specification := fsc$cycle_number;
            cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
            path_resolution := fsc$cycle_path;
          IFEND;

        = fsc$low_cycle =
          cycle_selector.cycle_option := pfc$lowest_cycle;
          pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
          IF status.normal THEN
            cycle_reference.specification := fsc$cycle_number;
            cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
            path_resolution := fsc$cycle_path;
          IFEND;

        = fsc$next_cycle =
          cycle_selector.cycle_option := pfc$highest_cycle;
          pfp$determine_new_cycle_number (path, p_cycle_list, cycle_selector, cycle_number, status);
          IF status.normal THEN
            cycle_reference.specification := fsc$cycle_number;
            cycle_reference.cycle_number := cycle_number;
            path_resolution := fsc$new_cycle_path;
          IFEND;

        = fsc$cycle_number =
          {
          { The following IF condition and entire ELSE clause should be removed
          { once pf supports fst$cycle_number.
          {
          IF cycle_reference.cycle_number <= pfc$maximum_cycle_number THEN
            cycle_selector.cycle_option := pfc$specific_cycle;
            cycle_selector.cycle_number := cycle_reference.cycle_number;
            pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
            IF status.normal THEN
              path_resolution := fsc$cycle_path;
            ELSEIF status.condition = pfe$unknown_cycle THEN
              path_resolution := fsc$new_cycle_path;
              status.normal := TRUE;
            IFEND;
          ELSE
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$bad_cycle_number, '', status);
            osp$append_status_integer (osc$status_parameter_delimiter, cycle_reference.cycle_number, 10,
                  FALSE, status);
          IFEND;
        ELSE
          osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$system_error,
                'Invalid cycle specification.', status);
        CASEND;

      = pfc$catalog_object =
        IF cycle_reference.specification = fsc$cycle_omitted THEN
          path_resolution := fsc$catalog_path;
        ELSE
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$catalogs_do_not_have_cycles,
                p_fs_path^ (1, fs_path_size), status);
        IFEND;

      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Unexpected object type.', status);
      CASEND;
    END /resolve_path/;

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

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

  PROCEDURE [XDCL, #GATE] pfp$r2_save_released_file_label
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         p_file_label: {input^} ^fmt$file_label;
         validation_ring: ost$valid_ring;
         update_cycle_statistics: boolean;
     VAR p_save_label_audit_info: {i/o} ^pft$save_label_audit_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_save_released_file_label; {----->
    PROCEND initiate_non_local_exit;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      date_time: ost$date_time,
      file_previously_opened: boolean,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      p_static_label_header: ^fmt$static_label_header,
      p_local_file_label: ^fmt$file_label,
      p_physical_file_label: ^pft$physical_file_label,
      p_stored_file_label: ^pft$physical_file_label,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean,
      static_label_attributes: bat$static_label_attributes,
      valid_checksum: boolean;

    syp$push_inhibit_job_recovery;

    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);

    pfp$get_authority (path, {system_privilege} FALSE, authority, status);
    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_path^, permit_entry, status);
    IFEND;
    catalog_active := status.normal;

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

    IF status.normal THEN
      pfp$validate_default_password (path, authority, password_selector, p_file_object, status);
    IFEND;

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

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IFEND;

    IF status.normal THEN
      p_local_file_label := p_file_label;
      RESET p_local_file_label;
      fmp$validate_system_label (p_local_file_label^, validation_ring, valid_checksum, status);

      IF status.normal THEN
        RESET p_local_file_label;
        NEXT p_physical_file_label: [[REP #SIZE (p_local_file_label^) - #SIZE (pft$checksum) OF cell]] IN
              p_local_file_label;

        IF p_save_label_audit_info <> NIL THEN
          IF #SIZE (fmt$static_label_header) <= #SIZE (p_physical_file_label^.file_label) THEN
            p_local_file_label := ^p_physical_file_label^.file_label;
            RESET p_local_file_label;
            NEXT p_static_label_header IN p_local_file_label;

            IF (p_static_label_header = NIL) OR (p_static_label_header^.unique_character <>
                  fmc$unique_label_id) THEN
              p_save_label_audit_info := NIL;
            ELSE
              p_save_label_audit_info^.file_path_count := 0; { The path is available in ring 3.
              p_save_label_audit_info^.cycle_selector.cycle_option := pfc$specific_cycle;
              p_save_label_audit_info^.cycle_selector.cycle_number := p_cycle^.cycle_entry.cycle_number;

              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,
                      p_save_label_audit_info^.device_class);
              ELSE
                p_save_label_audit_info^.device_class := rmc$mass_storage_device;
              IFEND;

              p_save_label_audit_info^.ownership := authority.ownership;

              IF (fmc$file_access_procedure <= p_static_label_header^.highest_attribute_present) AND
                    p_static_label_header^.attribute_present [fmc$file_access_procedure] THEN
                fsp$expand_file_label (p_local_file_label, static_label_attributes, file_previously_opened,
                      local_status);
                IF local_status.normal THEN
                  p_save_label_audit_info^.fap_audit_info.audit := TRUE;
                  p_save_label_audit_info^.fap_audit_info.fap_name :=
                        static_label_attributes.file_access_procedure;
                ELSE
                  p_save_label_audit_info^.fap_audit_info.audit := FALSE;
                IFEND;
              ELSE
                p_save_label_audit_info^.fap_audit_info.audit := FALSE;
              IFEND;

              IF p_static_label_header^.file_previously_opened THEN
                p_save_label_audit_info^.ring_audit_info.audit := TRUE;
                p_save_label_audit_info^.ring_audit_info.ring_attributes :=
                      p_static_label_header^.ring_attributes;
              ELSE
                p_save_label_audit_info^.ring_audit_info.audit := FALSE;
              IFEND;

              IF (NOT p_save_label_audit_info^.fap_audit_info.audit) AND
                    NOT p_save_label_audit_info^.ring_audit_info.audit THEN
                p_save_label_audit_info := NIL;
              IFEND;
            IFEND;
          ELSE
            p_save_label_audit_info := NIL;
          IFEND;
        IFEND;

        IF valid_checksum THEN
          p_stored_file_label := NIL;
          store_file_label (path, ^p_physical_file_label^.file_label, catalog_locator.p_catalog_file, p_cycle,
                p_stored_file_label, status);
        ELSE
          osp$set_status_condition (ame$damaged_file_attributes, status);
        IFEND;
      ELSE
        p_save_label_audit_info := NIL;
      IFEND;
    ELSE
      p_save_label_audit_info := NIL;
    IFEND;

    IF status.normal AND update_cycle_statistics THEN
      pmp$get_compact_date_time (date_time, local_status);
      pfp$process_unexpected_status (local_status);
      p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;

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

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

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_save_released_file_label;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_validate_catalog_exists
    (    catalog_path: pft$complete_path;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      p_internal_path: ^pft$internal_path,
      p_object: ^pft$physical_object,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry;

    syp$push_inhibit_job_recovery;
    pfp$get_authority (catalog_path, NOT system_privilege, authority, status);

    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (catalog_path)];
      pfp$access_object (catalog_path, pfc$read_access, authority, $pft$object_selections
            [pfc$catalog_object], parent_charge_id, catalog_locator, p_object, p_internal_path^, permit_entry,
            status);
    IFEND;

    IF status.normal THEN
      pfp$return_catalog (catalog_locator, status);
    IFEND;
    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_validate_catalog_exists;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_validate_password
    (    path: pft$complete_path;
         password: pft$password;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry;

    syp$push_inhibit_job_recovery;
    pfp$get_authority (path, NOT system_privilege, authority, status);

    IF status.normal AND NOT (pfc$system_owner IN authority.ownership) AND
          NOT (pfc$family_owner IN authority.ownership) THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, $pft$object_selections
            [pfc$file_object, pfc$purged_file_object], parent_charge_id, catalog_locator, p_file_object,
            p_internal_path^, permit_entry, status);
      IF status.normal THEN
        pfp$validate_password (path, authority, password, p_file_object, status);
        pfp$return_catalog (catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$r2_validate_password;

?? TITLE := '  [XDCL] pfp$reattach_permanent_file', EJECT ??
*copy pfh$reattach_permanent_file

  PROCEDURE [XDCL] pfp$reattach_permanent_file
    (    apfid: pft$attached_permanent_file_id;
         device_class: rmt$device_class;
         internal_cycle_name: pft$internal_name;
         mainframe_id: pmt$binary_mainframe_id;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
     VAR new_sfid: gft$system_file_identifier;
     VAR status: ost$status);

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

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

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := p_attached_pf_entry^.p_external_path;

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

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

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

        syp$pop_inhibit_job_recovery;

        IF apfid_locked THEN
          pfp$release_locked_apfid (apfid.attached_pf_table_index, local_status);
        IFEND;

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

        status := local_status;
        initiate_non_local_exit;


      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          pfp$log_ascii ('***Recover Files***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
                pmc$msg_origin_system, {critical_message} FALSE, local_status);
          {syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND reattach_perm_file_handler;

    PROCEDURE initiate_non_local_exit;

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


    CONST
      system_privilege = TRUE;

    VAR
      apfid_locked: boolean,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      charge_id: pft$charge_id,
      cycle_damage_symptoms: fst$cycle_damage_symptoms,
      display_status: ost$status,
      file_damaged: boolean,
      file_info: dmt$file_information,
      flush_catalog_pages: boolean,
      fmd_modified: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      path_string: ost$string,
      permit_entry: pft$permit_entry,
      process_non_local_exit: boolean;

    syp$push_inhibit_job_recovery;
    apfid_locked := FALSE;
    #SPOIL (apfid_locked);
    catalog_active := FALSE;
    process_non_local_exit := FALSE;
    #SPOIL (process_non_local_exit);
    status.normal := TRUE;

    IF apfid.family_location = pfc$server_mainframe THEN
      IF device_class = rmc$mass_storage_device THEN
        pfp$reattach_server_file (apfid, internal_cycle_name, mainframe_id, usage_selections,
              share_selections, new_sfid, status);
      IFEND;
      syp$pop_inhibit_job_recovery;
      RETURN; {----->
    IFEND;

    IF status.normal THEN
      pfp$lock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, status);
      apfid_locked := status.normal;
      #SPOIL (apfid_locked);
    IFEND;

    IF status.normal AND (internal_cycle_name <> p_attached_pf_entry^.internal_cycle_path.cycle_name) THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
            'The global file name (gfn) from FM does not match the gfn in pfp$reattach_permanent_file.',
            status);
    IFEND;

    IF status.normal THEN
      pfp$get_authority (p_attached_pf_entry^.p_external_path^, NOT system_privilege, authority, status);
    IFEND;

    IF status.normal THEN

    /reattach_permanent_file/
      WHILE TRUE DO
        pfp$internal_access_object (p_attached_pf_entry^.p_external_path^ [pfc$set_path_index],
              p_attached_pf_entry^.internal_cycle_path.path, pfc$write_access, authority,
              {extract_permits} TRUE, (p_attached_pf_entry^.p_external_path^ [pfc$family_path_index] <>
              osv$system_family_name), p_file_object, catalog_locator, permit_entry, status);
        IF status.normal OR (status.condition <> pfe$catalog_access_retry) THEN
          EXIT /reattach_permanent_file/; {----->
        ELSE
          syp$pop_inhibit_job_recovery;
          pfp$catalog_access_retry_wait ('PFP$REATTACH_PERMANENT_FILE');
          syp$push_inhibit_job_recovery;
        IFEND;
      WHILEND /reattach_permanent_file/;
    IFEND;
    catalog_active := status.normal;

    IF catalog_active THEN
      osp$establish_condition_handler (^reattach_perm_file_handler, {block_exit} TRUE);
    IFEND;

    IF p_file_object = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
            'Unable to locate file in pfp$reattach_permanent_file.', status);
    IFEND;

    IF status.normal THEN
      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      internal_locate_cycle (p_cycle_list, internal_cycle_name, p_cycle, status);
    IFEND;

    IF status.normal THEN
      check_cycle_damage (p_attached_pf_entry^.p_external_path^, p_cycle^.cycle_entry,
            p_attached_pf_entry^.allowed_exception_conditions, cycle_damage_symptoms, status);
    IFEND;

    IF status.normal AND (device_class = rmc$mass_storage_device) THEN
      dm_attach_file (p_attached_pf_entry^.p_external_path^, catalog_locator.p_catalog_file,
            p_attached_pf_entry^.usage_selections, p_attached_pf_entry^.share_selections, p_cycle, new_sfid,
            file_damaged, status);

      IF status.normal THEN
        IF pfp$share_for_write (p_attached_pf_entry^.share_selections) THEN
          IF file_damaged = p_attached_pf_entry^.media_image_inconsistent THEN
            IF p_attached_pf_entry^.media_damage_detection_enabled THEN
              dmp$enable_damage_detection (new_sfid, internal_cycle_name, status);
            IFEND;
          ELSE
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (p_attached_pf_entry^.p_external_path^, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$media_image_inconsistent,
                  p_fs_path^ (1, fs_path_size), status);
          IFEND;
        ELSE { Attached for exclusive write access.
          IF (NOT file_damaged) OR (fsc$media_image_inconsistent IN
                p_attached_pf_entry^.allowed_exception_conditions) THEN
            dmp$change_sft_damage_detection (new_sfid, p_attached_pf_entry^.media_damage_detection_enabled,
                  internal_cycle_name, status);
            IF status.normal THEN
              IF p_attached_pf_entry^.media_damage_detection_enabled AND
                    NOT p_attached_pf_entry^.media_image_inconsistent THEN
                IF file_damaged THEN
                  dmp$change_sft_file_damaged (new_sfid, {file_damaged} FALSE, internal_cycle_name, status);
                ELSE
                  dmp$enable_damage_detection (new_sfid, internal_cycle_name, status);
                IFEND;
              IFEND;
            IFEND;
          ELSEIF p_attached_pf_entry^.media_damage_detection_enabled AND
                NOT p_attached_pf_entry^.media_image_inconsistent THEN
            dmp$change_sft_file_damaged (new_sfid, {file_damaged} FALSE, internal_cycle_name, status);
            IF status.normal THEN
              dmp$change_sft_damage_detection (new_sfid, p_attached_pf_entry^.media_damage_detection_enabled,
                    internal_cycle_name, status);
            IFEND;
          IFEND;
        IFEND;

        IF NOT status.normal THEN
          pfp$detach_permanent_file (^p_attached_pf_entry^.p_external_path^, new_sfid,
                p_attached_pf_entry^.usage_selections, {catalog_update_allowed} TRUE, p_cycle,
                catalog_locator.p_catalog_file, dmc$df_ignore_file_info, fmd_modified, file_info,
                local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      p_attached_pf_entry^.sfid_status.recovery_state := pfc$attached_pf_normal;
      p_attached_pf_entry^.sfid_status.sfid := new_sfid;
      IF p_attached_pf_entry^.update_catalog THEN
        pfp$increment_usage_counts (p_attached_pf_entry^.p_external_path^,
              p_attached_pf_entry^.usage_selections, p_attached_pf_entry^.share_selections, mainframe_id,
              catalog_locator.p_catalog_file, flush_catalog_pages, p_cycle^.cycle_entry, status);
        pfp$process_unexpected_status (status);
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      IFEND;

      pfp$unlock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, status);
      pfp$process_unexpected_status (status);
    ELSEIF apfid_locked THEN
      IF status.condition = pfe$catalog_access_retry THEN
        pfp$unlock_apfid (apfid.attached_pf_table_index, p_attached_pf_entry, local_status);
        pfp$process_unexpected_status (local_status);
      ELSE
        pfp$convert_cycle_path_to_strng (p_attached_pf_entry^.p_external_path^,
              p_attached_pf_entry^.cycle_number, path_string);
        IF status.condition = pfe$pf_system_error THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, path_string.
                value (1, path_string.size), status);
        ELSE
          osp$log_job_recovery_message (path_string.value (1, path_string.size), display_status);
        IFEND;
        osp$log_job_recovery_status (status, display_status);
        FREE p_attached_pf_entry^.p_external_path IN pfv$p_p_job_heap^^;
        FREE p_attached_pf_entry IN pfv$p_p_job_heap^^;
        pfp$release_locked_apfid (apfid.attached_pf_table_index, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;

    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$reattach_permanent_file;

?? TITLE := '  [XDCL] pfp$reattach_reserved_cycles', EJECT ??

  PROCEDURE [XDCL] pfp$reattach_reserved_cycles
    (    mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      catalog_permit_entry: pft$permit_entry,
      charge_id: pft$charge_id,
      cycle_index: pft$object_index,
      file_damaged: boolean,
      file_info: dmt$file_information,
      fmd_modified: boolean,
      i: pft$catalog_path_index,
      local_status: ost$status,
      new_sfid: gft$system_file_identifier,
      object_index: pft$object_index,
      old_sfid: gft$system_file_identifier,
      p_complete_path: ^pft$complete_path,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_internal_path: ^pft$internal_path;

    IF pfv$reserved_cycle_info.p_catalog_path = NIL THEN
      RETURN; {----->
    IFEND;

    syp$push_inhibit_job_recovery;
    pfp$get_authority (pfv$reserved_cycle_info.p_catalog_path^, {system_privilege} TRUE, authority, status);
    IF status.normal THEN
      PUSH p_internal_path: [1 .. UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^)];
      pfp$get_catalog (pfv$reserved_cycle_info.p_catalog_path^, pfc$write_access, authority, p_internal_path^,
            charge_id, catalog_permit_entry, catalog_locator, status);
      catalog_active := status.normal;
    IFEND;
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    PUSH p_complete_path: [1 .. UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^) + 1];
    FOR i := 1 TO UPPERBOUND (pfv$reserved_cycle_info.p_catalog_path^) DO
      p_complete_path^ [i] := pfv$reserved_cycle_info.p_catalog_path^ [i];
    FOREND;

  /reattach_reserved_cycles/
    FOR object_index := 1 TO pfv$reserved_cycle_info.number_of_cycles_reserved DO
      pfp$locate_object (pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].external_object_name,
            $pft$object_selections [pfc$file_object, pfc$purged_file_object],
            catalog_locator.object_list_descriptor, p_file_object);
      IF (p_file_object = NIL) OR (pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].
            internal_object_name <> p_file_object^.object_entry.internal_object_name) THEN
        pfp$internal_locate_object (catalog_locator.object_list_descriptor.p_object_list,
              pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_object_name, p_file_object);
        IF p_file_object = NIL THEN
{Debug code
{ Note: In this case, we probably still do not purge the device file!!!
          syp$increment_rsv_cycle_counter (syc$ircc_reattach_purged);
{End Debug code
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
                'Unable to locate reserved cycle.', local_status);
          EXIT /reattach_reserved_cycles/; {----->
        IFEND;
      IFEND;

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);

      p_cycle := NIL;

    /locate_reserved_cycle/
      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.internal_cycle_name =
              pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].internal_cycle_name) THEN
          p_cycle := ^p_cycle_list^ [cycle_index];
          EXIT /locate_reserved_cycle/; {----->
        IFEND;
      FOREND /locate_reserved_cycle/;

      IF p_cycle = NIL THEN
{Debug code
        syp$increment_rsv_cycle_counter (syc$ircc_reattach_purged);
{End Debug code
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Unable to locate reserved cycle.', local_status);
        EXIT /reattach_reserved_cycles/; {----->
      ELSE
        p_complete_path^ [UPPERBOUND (p_complete_path^)] := p_file_object^.object_entry.external_object_name;
        dm_attach_file (p_complete_path^, catalog_locator.p_catalog_file, $pft$usage_selections [pfc$read],
              $pft$share_selections [pfc$read, pfc$execute], p_cycle, new_sfid, file_damaged, status);
        IF status.normal THEN
          old_sfid := pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].system_file_id;
          syp$replace_sfid (old_sfid, new_sfid, mmc$sas_allow_access, status);
          IF status.normal THEN
            pfv$reserved_cycle_info.p_reserved_cycles^ [object_index].system_file_id := new_sfid;
            pfp$increment_usage_counts (p_complete_path^, $pft$usage_selections [pfc$read],
                  $pft$share_selections [pfc$read, pfc$execute], mainframe_id, catalog_locator.p_catalog_file,
                  catalog_locator.flush_catalog_pages, p_cycle^.cycle_entry, status);
            pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
          ELSE
            syp$invalidate_open_sfid (old_sfid, local_status);
          IFEND;

          IF NOT status.normal THEN
            {
            {Detach file from device manager.
            {
            pfp$detach_permanent_file ({p_path} NIL, new_sfid, $pft$usage_selections [pfc$read],
                  {catalog_update_allowed} TRUE, p_cycle, catalog_locator.p_catalog_file,
                  dmc$df_ignore_file_info, fmd_modified, file_info, local_status);
          IFEND;
        IFEND;
      IFEND;
    FOREND /reattach_reserved_cycles/;

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

    IF NOT status.normal THEN
      {
      {Upon task termination pfp$detach_reserved_cycles should detach only those
      {cycles that were reattached successfully.
      {
      pfv$reserved_cycle_info.number_of_cycles_reserved := object_index - 1;
      pfp$report_unexpected_status (status);
    IFEND;

    syp$pop_inhibit_job_recovery;
  PROCEND pfp$reattach_reserved_cycles;

?? TITLE := '  [XDCL] pfp$report_invalid_free', EJECT ??

  PROCEDURE [XDCL] pfp$report_invalid_free
    (    p_path: ^pft$complete_path;
         p_cycle_number: ^fst$cycle_number;
         free_object: string ( * <= osc$max_string_size);
         file_or_catalog: string ( * <= osc$max_string_size);
         prevalidate_free_result: ost$prevalidate_free_result;
         catalog_offset: ost$halfword);

    VAR
      free_result_string: ost$string,
      free_status: ost$status,
      fs_path_size: fst$path_size,
      ignore_status: ost$status,
      p_fs_path: ^fst$path,
      p_path_string: ^ost$string;

    osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_free, free_object, free_status);
    osp$append_status_parameter (osc$status_parameter_delimiter, file_or_catalog, free_status);

    IF p_cycle_number <> NIL THEN
      IF p_path <> NIL THEN
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (p_path^, p_cycle_number^, p_path_string^);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_path_string^.
              value (1, p_path_string^.size), free_status);
      ELSE
        osp$append_status_parameter (osc$status_parameter_delimiter, 'of unknown path', free_status);
      IFEND;
    ELSE
      IF p_path <> NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (p_path^, p_fs_path^, fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size),
              free_status);
      ELSE
        osp$append_status_parameter (osc$status_parameter_delimiter, 'of unknown path', free_status);
      IFEND;
    IFEND;

    free_result_string.value := prevalidate_free_result_strings [prevalidate_free_result].value;
    free_result_string.size := prevalidate_free_result_strings [prevalidate_free_result].size;
    osp$append_status_parameter (osc$status_parameter_delimiter, free_result_string.
          value (1, free_result_string.size), free_status);
    osp$append_status_integer (osc$status_parameter_delimiter, catalog_offset, {radix} 16, include_radix,
          free_status);
    osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], free_status, ignore_status);
    pfp$report_unexpected_status (free_status);

  PROCEND pfp$report_invalid_free;


?? TITLE := '  [XDCL] pfp$return_permanent_file', EJECT ??
*copy pfh$return_permanent_file

  PROCEDURE [XDCL] pfp$return_permanent_file
    (    apfid: pft$attached_permanent_file_id;
         system_file_id: gft$system_file_identifier;
         device_class: rmt$device_class;
         usage_selections: pft$usage_selections;
     VAR status: ost$status);

    VAR
      authority: pft$authority,
      bytes_allocated_change: sft$counter,
      mainframe_id: pmt$binary_mainframe_id;

    status.normal := TRUE;

    IF apfid.family_location = pfc$server_mainframe THEN
      pfp$r2_df_client_return (apfid, system_file_id, device_class, usage_selections, authority,
            bytes_allocated_change, status);
    ELSE { local mainframe
      pmp$get_pseudo_mainframe_id (mainframe_id);
      pfp$internal_return_file (apfid.attached_pf_table_index, mainframe_id, authority,
            bytes_allocated_change, status);
    IFEND;

    IF status.normal AND (pfc$master_catalog_owner IN authority.ownership) AND
          (bytes_allocated_change < 0) THEN
      sfp$accumulate_file_space (sfc$perm_file_space_limit, bytes_allocated_change);
    IFEND;

  PROCEND pfp$return_permanent_file;

?? TITLE := '  [XDCL] pfp$save_file_label', EJECT ??
*copy pfh$save_file_label

  PROCEDURE [XDCL] pfp$save_file_label
    (    apfid: pft$attached_permanent_file_id;
         p_file_label: {input} fmt$p_file_label;
         required_permission: pft$permit_options;
     VAR status: ost$status);

    VAR
      p_complete_path: ^pft$complete_path,
      p_save_label_audit_info: ^pft$save_label_audit_info,
      p_save_file_label_audit_seq: ^SEQ ( * ),
      variant_path: pft$variant_path;

    syp$push_inhibit_job_recovery;

    IF sfp$auditing_operation (sfc$ao_fs_change_attribute) THEN
      PUSH p_save_file_label_audit_seq: [[pft$save_label_audit_info,
            REP UPPERVALUE (pft$file_path_count) OF pft$name]];
    ELSE
      p_save_file_label_audit_seq := NIL;
    IFEND;

    IF apfid.family_location = pfc$server_mainframe THEN
      pfp$r2_df_client_save_label (apfid, pfv$system_authority, required_permission, p_file_label,
            p_save_file_label_audit_seq, status);
    ELSE
      pfp$internal_save_file_label (apfid, pfv$system_authority, required_permission, p_file_label,
            p_save_file_label_audit_seq, status);
    IFEND;

    IF p_save_file_label_audit_seq <> NIL THEN
      RESET p_save_file_label_audit_seq;
      NEXT p_save_label_audit_info IN p_save_file_label_audit_seq;

      NEXT p_complete_path: [1 .. p_save_label_audit_info^.file_path_count] IN p_save_file_label_audit_seq;

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := p_complete_path;
      pfp$audit_save_label (variant_path, p_save_label_audit_info, status);
    IFEND;

    syp$pop_inhibit_job_recovery;

  PROCEND pfp$save_file_label;

?? TITLE := '  append_rem_media_vsn', EJECT ??

  PROCEDURE append_rem_media_vsn
    (    path: pft$complete_path;
         volume_descriptor: rmt$volume_descriptor;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
         p_cycle: {i^/o^} pft$p_cycle;
     VAR status: ost$status);

    VAR
      additional_volumes: 0 .. amc$max_vol_number,
      new_stored_fmd_size: dmt$stored_fmd_size,
      number_of_volumes: 0 .. amc$max_vol_number,
      p_fmd: ^pft$fmd,
      p_new_stored_fmd: pft$p_physical_fmd,
      p_old_stored_fmd: pft$p_physical_fmd,
      p_stored_tape_fmd_header: ^dmt$stored_tape_fmd_header,
      p_stored_tape_volume_list: ^dmt$stored_tape_volume_list,
      p_volume_list: ^rmt$volume_list,
      prevalidate_free_result: ost$prevalidate_free_result,
      removable_media_req_info: fmt$removable_media_req_info,
      volume_list_index: integer;

    pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_old_stored_fmd);

    pfp$get_rem_media_req_info (^p_old_stored_fmd^.fmd, ^removable_media_req_info, number_of_volumes, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF number_of_volumes > 0 THEN
      PUSH p_volume_list: [1 .. number_of_volumes];
      pfp$get_rem_media_volume_list (^p_old_stored_fmd^.fmd, p_volume_list, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF (number_of_volumes = 1) AND (p_volume_list^ [1].external_vsn = rmc$unspecified_vsn) AND
          (p_volume_list^ [1].recorded_vsn = rmc$unspecified_vsn) THEN
      additional_volumes := 0;
    ELSE
      additional_volumes := 1;
    IFEND;

    new_stored_fmd_size := #SIZE (p_old_stored_fmd^) + (additional_volumes * #SIZE (rmt$volume_descriptor));

    ALLOCATE p_new_stored_fmd: [[REP new_stored_fmd_size OF cell]] IN p_catalog_file^.catalog_heap;
    IF p_new_stored_fmd = NIL THEN
      osp$set_status_condition (pfe$catalog_full, status);
      RETURN; {----->
    IFEND;

    p_fmd := ^p_new_stored_fmd^.fmd;
    NEXT p_stored_tape_fmd_header IN p_fmd;
    p_stored_tape_fmd_header^.version := dmc$stored_tape_fmd_version_1;
    pfp$convert_density_to_dm (removable_media_req_info.density, p_stored_tape_fmd_header^.density);
    p_stored_tape_fmd_header^.removable_media_group := removable_media_req_info.removable_media_group;
    p_stored_tape_fmd_header^.volume_count := number_of_volumes + additional_volumes;
    p_stored_tape_fmd_header^.volume_overflow_allowed := removable_media_req_info.volume_overflow_allowed;
    p_stored_tape_fmd_header^.reserved_tape_fmd_header_space := pfv$null_tape_fmd_header_space;

    NEXT p_stored_tape_volume_list: [1 .. (number_of_volumes + additional_volumes)] IN p_fmd;

    IF number_of_volumes > 0 THEN
      FOR volume_list_index := 1 TO UPPERBOUND (p_volume_list^) DO
        p_stored_tape_volume_list^ [volume_list_index].external_vsn :=
              p_volume_list^ [volume_list_index].external_vsn;
        p_stored_tape_volume_list^ [volume_list_index].recorded_vsn :=
              p_volume_list^ [volume_list_index].recorded_vsn;
      FOREND;
    IFEND;

    p_stored_tape_volume_list^ [(number_of_volumes + additional_volumes)].external_vsn :=
          volume_descriptor.external_vsn;
    p_stored_tape_volume_list^ [(number_of_volumes + additional_volumes)].recorded_vsn :=
          volume_descriptor.recorded_vsn;

    pfp$compute_checksum (#LOC (p_new_stored_fmd^.fmd), #SIZE (p_new_stored_fmd^.fmd),
          p_new_stored_fmd^.checksum);

    pfp$build_fmd_locator (p_new_stored_fmd, p_catalog_file, p_cycle^.cycle_entry.fmd_locator);
    pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IF p_old_stored_fmd <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_old_stored_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_old_stored_fmd IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
              prevalidate_free_result, #OFFSET (p_old_stored_fmd));
        p_old_stored_fmd := NIL;
      IFEND;
    IFEND;

  PROCEND append_rem_media_vsn;

?? TITLE := '  attach_cycle', EJECT ??

  PROCEDURE attach_cycle
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         path: pft$complete_path;
         lfn: amt$local_file_name;
         device_class: rmt$device_class;
         date_time: ost$date_time;
         authority: pft$authority;
         update_catalog: boolean;
         update_cycle_statistics: boolean;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         application_info: pft$application_info;
         validation_ring: ost$valid_ring;
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
         enable_media_damage_detection: boolean;
         implicit_attach: boolean;
         p_file_label: {input} ^fmt$file_label;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_file_object: {i^/o^} ^pft$physical_object;
         p_internal_cycle_path: {i^/o^} ^pft$internal_cycle_path;
         p_physical_cycle: {i^/o^} ^pft$physical_cycle;
     VAR flush_catalog_pages: {i/o} boolean;
     VAR path_handle: {client only} fmt$path_handle;
     VAR cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR p_file_server_buffers: {server only: i^/o^} ^pft$file_server_buffers;
     VAR status: ost$status);

    VAR
      apft_entry_assigned: boolean,
      apft_entry_in_use: boolean,
      archive_date_time: ost$date_time,
      archive_index: pft$archive_index,
      attached_pf_table_index: pft$attached_pf_table_index,
      comparison_result: pmt$comparison_result,
      data_modification_date_time: ost$date_time,
      file_damaged: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      new_log_list: boolean,
      p_archive_list: ^pft$archive_list,
      p_attached_pf_entry: ^pft$attached_pf_entry,
      p_fs_path: ^fst$path,
      p_log_list: ^pft$log_list,
      p_new_log_list: ^pft$log_list,
      prevalidate_free_result: ost$prevalidate_free_result,
      sfid: gft$system_file_identifier,
      valid_archive_entry_exists: boolean;

    set_flush_catalog_pages (usage_selections, p_physical_cycle, flush_catalog_pages);
    pfp$assign_locked_apfid (attached_pf_table_index, status);
    apft_entry_assigned := status.normal;
    pfv$locked_apfid := attached_pf_table_index;

    IF status.normal THEN
      check_cycle_damage (path, p_physical_cycle^.cycle_entry, allowed_cycle_damage_symptoms,
            cycle_damage_symptoms, status);
    IFEND;

    IF status.normal THEN
      pfp$attach_permanent_file (family_location, mainframe_id, lfn, path, attached_pf_table_index,
            usage_selections, share_selections, application_info, validation_ring,
            (p_file_object^.object_entry.password <> osc$null_name), allowed_cycle_damage_symptoms,
            enable_media_damage_detection, implicit_attach, update_catalog, authority, p_file_label,
            p_catalog_file, p_physical_cycle, sfid, file_damaged, flush_catalog_pages, path_handle,
            p_file_server_buffers, status);
    IFEND;
    apft_entry_in_use := status.normal;

    IF status.normal THEN
      p_internal_cycle_path^.cycle_name := p_physical_cycle^.cycle_entry.internal_cycle_name;
      build_attached_pf_entry (sfid, path, p_physical_cycle^.cycle_entry.cycle_number, device_class,
            update_catalog, update_cycle_statistics, usage_selections, share_selections, file_damaged,
            enable_media_damage_detection, allowed_cycle_damage_symptoms, p_internal_cycle_path^,
            p_attached_pf_entry, status);
    IFEND;

    IF status.normal AND update_catalog AND (p_file_object^.object_entry.logging_selection = pfc$log) THEN
      flush_catalog_pages := pfv$flush_catalogs;
      pfp$build_log_list_pointer (p_file_object^.object_entry.log_list_locator, p_catalog_file, p_log_list);
      update_access_log (date_time, authority, p_physical_cycle^.cycle_entry.cycle_number,
            ^p_catalog_file^.catalog_heap, p_log_list, p_new_log_list, new_log_list, status);

      IF status.normal AND new_log_list THEN
        pfp$build_log_list_locator (p_new_log_list, p_catalog_file,
              p_file_object^.object_entry.log_list_locator);
        pfp$compute_checksum (#LOC (p_file_object^.object_entry), #SIZE (pft$object_entry),
              p_file_object^.checksum);
        IF p_log_list <> NIL THEN
          osp$prevalidate_free ((#OFFSET (p_log_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_log_list IN p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'LOG_LIST', 'file',
                  prevalidate_free_result, #OFFSET (p_log_list));
            p_log_list := NIL;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal AND update_catalog THEN
      pfp$increment_usage_counts (path, usage_selections, share_selections, mainframe_id, p_catalog_file,
            flush_catalog_pages, p_physical_cycle^.cycle_entry, status);

      IF status.normal THEN
        IF update_cycle_statistics THEN
          update_access_date (p_physical_cycle^.cycle_entry.cycle_statistics, date_time, usage_selections,
                share_selections, p_physical_cycle^.cycle_entry.cycle_statistics);
          IF usage_selections * pfv$write_usage <> $pft$usage_selections [] THEN
            p_physical_cycle^.cycle_entry.data_modification_date_time := date_time;
          IFEND;
        ELSE {utility attach}
          { Set a job recovery test.
          syp$hang_if_job_jrt_set (pfc$tjr_utility_attach);
        IFEND;

        pfp$compute_checksum (#LOC (p_physical_cycle^.cycle_entry), #SIZE (pft$cycle_entry),
              p_physical_cycle^.checksum);
      IFEND;
    IFEND;

    IF apft_entry_assigned THEN
      IF apft_entry_in_use THEN
        pfp$unlock_apfid (attached_pf_table_index, p_attached_pf_entry, local_status);
      ELSE
        pfp$release_locked_apfid (attached_pf_table_index, local_status);
      IFEND;
      pfp$process_unexpected_status (local_status);
    IFEND;
  PROCEND attach_cycle;

?? TITLE := '  build_attached_pf_entry', EJECT ??

  PROCEDURE build_attached_pf_entry
    (    system_file_id: gft$system_file_identifier;
         external_path: pft$complete_path;
         cycle_number: fst$cycle_number;
         device_class: rmt$device_class;
         update_catalog: boolean;
         update_cycle_statistics: boolean;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         media_image_inconsistent: boolean;
         media_damage_detection_enabled: boolean;
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
         internal_cycle_path: pft$internal_cycle_path;
     VAR p_attached_pf_entry: pft$p_attached_pf_entry;
     VAR status: ost$status);

    ALLOCATE p_attached_pf_entry: [1 .. UPPERBOUND (internal_cycle_path.path)] IN pfv$p_p_job_heap^^;
    IF p_attached_pf_entry = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
            'Too many attached files - p_attached_pf_entry', status);
    ELSE
      ALLOCATE p_attached_pf_entry^.p_external_path: [1 .. UPPERBOUND (external_path)] IN pfv$p_p_job_heap^^;
      IF p_attached_pf_entry^.p_external_path = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Too many attached files - p_external_path', status);
      ELSE
        status.normal := TRUE;
        p_attached_pf_entry^.sfid_status.recovery_state := pfc$attached_pf_normal;
        p_attached_pf_entry^.sfid_status.sfid := system_file_id;
        p_attached_pf_entry^.update_catalog := update_catalog;
        p_attached_pf_entry^.update_cycle_statistics := update_cycle_statistics;
        p_attached_pf_entry^.usage_selections := usage_selections;
        p_attached_pf_entry^.share_selections := share_selections;
        p_attached_pf_entry^.media_image_inconsistent := media_image_inconsistent;
        p_attached_pf_entry^.media_damage_detection_enabled := media_damage_detection_enabled;
        IF update_cycle_statistics THEN
          p_attached_pf_entry^.allowed_exception_conditions := allowed_cycle_damage_symptoms;
        ELSE
          p_attached_pf_entry^.allowed_exception_conditions := $fst$cycle_damage_symptoms [];
        IFEND;
        p_attached_pf_entry^.p_external_path^ := external_path;
        p_attached_pf_entry^.cycle_number := cycle_number;
        p_attached_pf_entry^.device_class := device_class;
        p_attached_pf_entry^.internal_cycle_path := internal_cycle_path;
      IFEND;
    IFEND;
  PROCEND build_attached_pf_entry;

?? TITLE := '  build_damage_symptoms_string', EJECT ??

  PROCEDURE build_damage_symptoms_string
    (    cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR cycle_damage_symptoms_string: pft$selections_string);

    VAR
      cycle_damage_symptom: fst$cycle_damage_symptom,
      first_match: boolean;

    IF cycle_damage_symptoms = $fst$cycle_damage_symptoms [] THEN
      cycle_damage_symptoms_string.value := 'null set';
      cycle_damage_symptoms_string.size := 8;
    ELSE
      first_match := TRUE;

      FOR cycle_damage_symptom := fsc$media_image_inconsistent TO fsc$parent_catalog_restored DO
        IF cycle_damage_symptom IN cycle_damage_symptoms THEN
          CASE cycle_damage_symptom OF
          = fsc$media_image_inconsistent =
            cycle_damage_symptoms_string.value (1, 29) := '[fsc$media_image_inconsistent';
            cycle_damage_symptoms_string.size := 29;
            first_match := FALSE;

          = fsc$respf_modification_mismatch =
            IF first_match THEN
              cycle_damage_symptoms_string.value (1, 32) := '[fsc$respf_modification_mismatch';
              cycle_damage_symptoms_string.size := 32;
              first_match := FALSE;
            ELSE
              STRINGREP (cycle_damage_symptoms_string.value, cycle_damage_symptoms_string.size,
                    cycle_damage_symptoms_string.value (1, cycle_damage_symptoms_string.size),
                    ', fsc$respf_modification_mismatch');
            IFEND;

          = fsc$parent_catalog_restored =
            IF first_match THEN
              cycle_damage_symptoms_string.value (1, 27) := '[fsc$parent_catalog_restored';
              cycle_damage_symptoms_string.size := 27;
              first_match := FALSE;
            ELSE
              STRINGREP (cycle_damage_symptoms_string.value, cycle_damage_symptoms_string.size,
                    cycle_damage_symptoms_string.value (1, cycle_damage_symptoms_string.size),
                    ', fsc$parent_catalog_restored');
            IFEND;

          ELSE
            ;
          CASEND;
        IFEND;
      FOREND;

      STRINGREP (cycle_damage_symptoms_string.value, cycle_damage_symptoms_string.size,
            cycle_damage_symptoms_string.value (1, cycle_damage_symptoms_string.size), ']');
    IFEND;
  PROCEND build_damage_symptoms_string;

?? TITLE := '  check_cycle_damage', EJECT ??

  PROCEDURE check_cycle_damage
    (    path: pft$complete_path;
         cycle_entry: pft$cycle_entry;
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR cycle_damage_symptoms: fst$cycle_damage_symptoms;
     VAR status: ost$status);

    VAR
      date_string: ost$date,
      local_status: ost$status,
      path_string: ost$string,
      time_string: ost$time;

    cycle_damage_symptoms := cycle_entry.cycle_damage_symptoms;
    IF cycle_entry.cycle_damage_symptoms <= allowed_cycle_damage_symptoms THEN
      status.normal := TRUE;
    ELSE { Cycle contains damage symptoms NOT allowed.
      IF fsc$respf_modification_mismatch IN cycle_entry.cycle_damage_symptoms THEN
        pfp$convert_cycle_path_to_strng (path, cycle_entry.cycle_number, path_string);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$respf_modification_mismatch,
              path_string.value (1, path_string.size), status);
        pmp$format_compact_date (cycle_entry.cycle_statistics.modification_date_time, osc$mdy_date,
              date_string, local_status);
        pfp$process_unexpected_status (local_status);
        osp$append_status_parameter (osc$status_parameter_delimiter, date_string.mdy, status);
        pmp$format_compact_time (cycle_entry.cycle_statistics.modification_date_time, osc$millisecond_time,
              time_string, local_status);
        pfp$process_unexpected_status (local_status);
        osp$append_status_parameter (osc$status_parameter_delimiter, time_string.millisecond, status);
      ELSEIF fsc$parent_catalog_restored IN cycle_entry.cycle_damage_symptoms THEN
        pfp$convert_cycle_path_to_strng (path, cycle_entry.cycle_number, path_string);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$parent_catalog_restored,
              path_string.value (1, path_string.size), status);
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error,
              'Unexpected damage condition.', status);
      IFEND;
    IFEND;
  PROCEND check_cycle_damage;

?? TITLE := '  check_mainframe_usage', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is  determine is a cycle is to be considered
{   busy, due to usage by another mainframe.  If another mainframe is writing the cycle,
{   or if this mainframe desires to write the cycle, but another mainframe is
{   using the cycle, then the cycle is considered busy.

  PROCEDURE check_mainframe_usage
    (    path: pft$complete_path;
         mainframe_id: pmt$binary_mainframe_id;
         usage_intentions: pft$permit_selections;
         p_catalog_file: {input^} ^pft$catalog_file;
         cycle_entry: pft$cycle_entry;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      mainframe: pft$mainframe_count,
      p_mainframe_usage_list: ^pft$mainframe_usage_list;

    status.normal := TRUE;
    pfp$build_mainfram_list_pointer (cycle_entry.mainframe_usage_list_locator, p_catalog_file,
          p_mainframe_usage_list);

    {
    { Check for another mainframe writing the file.
    {
    IF other_mainframe_writer (mainframe_id, cycle_entry, p_mainframe_usage_list) THEN
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, 10, FALSE, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, pfc$another_mainframe_writer, status);
      RETURN; {----->
    IFEND;

    IF (usage_intentions * $pft$permit_selections [pfc$shorten, pfc$append,
          pfc$modify]) <> $pft$permit_selections [] THEN
      {
      { Check if another mainframe is using the file.
      {
      IF other_mainframe_using (mainframe_id, cycle_entry, p_mainframe_usage_list) THEN
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, 10, FALSE,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$another_mainframe_user, status);
        RETURN; {----->
      IFEND;
    IFEND;
  PROCEND check_mainframe_usage;

?? TITLE := '  check_path_table_cycle_number', EJECT ??

  PROCEDURE check_path_table_cycle_number
    (    catalog_cycle_number: fst$cycle_number;
         cycle_selector: pft$cycle_selector;
         path_table_cycle_number: fst$cycle_number;
     VAR fetch_new_cycle_info: boolean);


    CASE cycle_selector.cycle_option OF
    = pfc$specific_cycle =
      fetch_new_cycle_info := FALSE;

    = pfc$highest_cycle =
      IF path_table_cycle_number = catalog_cycle_number THEN
        fetch_new_cycle_info := FALSE;
      ELSEIF path_table_cycle_number > catalog_cycle_number THEN
        {
        { The highest cycle attached within the job has been deleted from
        { the catalog. The path table must be searched for a cycle entry
        { corresponding to the highest cycle in the catalog.
        {
        fetch_new_cycle_info := TRUE;
      ELSE { path_table_cycle_number < catalog_cycle_number
        {
        { The highest cycle attached within the job is lower than the highest
        { cycle in the catalog. The path table need not be searched.
        {
        fetch_new_cycle_info := FALSE;
      IFEND;

    = pfc$lowest_cycle =
      IF path_table_cycle_number = catalog_cycle_number THEN
        fetch_new_cycle_info := FALSE;
      ELSEIF path_table_cycle_number > catalog_cycle_number THEN
        {
        { The lowest cycle attached within the job is higher than the lowest
        { cycle in the catalog. The path table need not be searched.
        {
        fetch_new_cycle_info := FALSE;
      ELSE { path_table_cycle_number < catalog_cycle_number
        {
        { The lowest cycle attached within the job has been deleted from the
        { catalog.  The path table must be searched for a cycle entry
        { corresponding to the lowest cycle in the catalog.
        {
        fetch_new_cycle_info := TRUE;
      IFEND;
    ELSE
      ;
    CASEND;
  PROCEND check_path_table_cycle_number;

?? TITLE := '  contract_cycle_list', EJECT ??
{       CONTRACT_CYCLE_LIST
{
{   The purpose of this procedure is to analyze a cycle list and conditionally
{ contract it based on some algorithm.  If it is necessary to contract the cycle
{ list, a new, smaller cycle list is created and the old list is copied to the
{ new list.  The algorithm can be chosen to determine the performance of the
{ permanent file system relative to a changing number of cycles.  The current
{ algorithm is a very simple one that contracts the cycle list if the free cycle
{ count equals or exceeds a threshold.

  PROCEDURE contract_cycle_list
    (    path: pft$complete_path;
         p_file_object: {output^} pft$p_object;
         p_catalog_file: {output^} pft$p_catalog_file;
     VAR status: ost$status);

    VAR
      cycle_index: pft$cycle_index,
      free_physical_cycle: pft$physical_cycle,
      high_cycle_index: pft$cycle_index,
      new_cycle_count: pft$cycle_count,
      new_cycle_index: pft$cycle_index,
      p_cycle_list: pft$p_cycle_list,
      p_new_cycle_list: pft$p_cycle_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    status.normal := TRUE;

    pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
          p_cycle_list);
    IF p_cycle_list <> NIL THEN
      high_cycle_index := UPPERBOUND (p_cycle_list^);

      IF pfc$cycle_contraction_count <= high_cycle_index THEN
        new_cycle_count := 0;

        FOR cycle_index := 1 TO high_cycle_index DO
          IF p_cycle_list^ [cycle_index].cycle_entry.entry_type <> pfc$free_cycle_entry THEN
            new_cycle_count := new_cycle_count + 1;
          IFEND;
        FOREND;

        IF pfc$cycle_contraction_count <= high_cycle_index - new_cycle_count THEN
          pfp$allocate_cycle_list (new_cycle_count, ^p_catalog_file^.catalog_heap, p_new_cycle_list, status);
          IF status.normal THEN
            new_cycle_index := 1;

            FOR cycle_index := 1 TO high_cycle_index DO
              IF p_cycle_list^ [cycle_index].cycle_entry.entry_type <> pfc$free_cycle_entry THEN
                p_new_cycle_list^ [new_cycle_index] := p_cycle_list^ [cycle_index];
                new_cycle_index := new_cycle_index + 1;
              IFEND;
            FOREND;

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

            FOR new_cycle_index := new_cycle_index TO UPPERBOUND (p_new_cycle_list^) DO
              p_new_cycle_list^ [new_cycle_index] := free_physical_cycle;
            FOREND;
            {
            { To make the catalog crash resistant, the new cycle list should be
            { written to permanent storage, the file object owning the new
            { cycle list written to permanent storage, and the old cycle list
            { released.
            {
            pfp$build_cycle_list_locator (p_new_cycle_list, p_catalog_file,
                  p_file_object^.object_entry.cycle_list_locator);
            pfp$compute_checksum (#LOC (p_file_object^.object_entry), #SIZE (pft$object_entry),
                  p_file_object^.checksum);
            osp$prevalidate_free ((#OFFSET (p_cycle_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                  ^p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_cycle_list IN p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'CYCLE_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_cycle_list));
              p_cycle_list := NIL;
            IFEND;
          ELSEIF status.condition = pfe$catalog_full THEN
            status.normal := TRUE;
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND contract_cycle_list;

?? TITLE := '  contract_permit_list', EJECT ??

  PROCEDURE contract_permit_list
    (    path: pft$complete_path;
         p_object: {output^} pft$p_object;
         p_catalog_file: {output^} pft$p_catalog_file;
     VAR status: ost$status);

    VAR
      free_physical_permit: pft$physical_permit,
      high_permit_index: pft$permit_index,
      new_permit_count: pft$permit_count,
      new_permit_index: pft$permit_index,
      p_new_permit_list: pft$p_permit_list,
      p_permit_list: pft$p_permit_list,
      permit_index: pft$permit_index,
      prevalidate_free_result: ost$prevalidate_free_result;

    status.normal := TRUE;

    pfp$build_permit_list_pointer (p_object^.object_entry.permit_list_locator, p_catalog_file, p_permit_list);
    IF p_permit_list <> NIL THEN
      high_permit_index := UPPERBOUND (p_permit_list^);

      IF pfc$permit_contraction_count <= high_permit_index THEN
        new_permit_count := 0;

        FOR permit_index := 1 TO high_permit_index DO
          IF p_permit_list^ [permit_index].permit_entry.entry_type <> pfc$free_permit_entry THEN
            new_permit_count := new_permit_count + 1;
          IFEND;
        FOREND;

        IF pfc$permit_contraction_count <= high_permit_index - new_permit_count THEN
          pfp$allocate_permit_list (new_permit_count, ^p_catalog_file^.catalog_heap, p_new_permit_list,
                status);
          IF status.normal THEN
            new_permit_index := 1;

            FOR permit_index := 1 TO high_permit_index DO
              IF p_permit_list^ [permit_index].permit_entry.entry_type <> pfc$free_permit_entry THEN
                p_new_permit_list^ [new_permit_index] := p_permit_list^ [permit_index];
                new_permit_index := new_permit_index + 1;
              IFEND;
            FOREND;

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

            FOR new_permit_index := new_permit_index TO UPPERBOUND (p_new_permit_list^) DO
              p_new_permit_list^ [new_permit_index] := free_physical_permit;
            FOREND;
            {
            { To make the catalog crash resistant, write the new permit list to
            { permanent storage, update the pointer to the new permit list, and
            { free the old permit list.
            {
            pfp$build_permit_list_locator (p_new_permit_list, p_catalog_file,
                  p_object^.object_entry.permit_list_locator);
            pfp$compute_checksum (#LOC (p_object^.object_entry), #SIZE (pft$object_entry),
                  p_object^.checksum);
            osp$prevalidate_free ((#OFFSET (p_permit_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                  ^p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_permit_list IN p_catalog_file^.catalog_heap;
            ELSE
              IF p_object^.object_entry.object_type = pfc$file_object THEN
                pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'PERMIT_LIST', 'file',
                      prevalidate_free_result, #OFFSET (p_permit_list));
              ELSE
                pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'PERMIT_LIST', 'catalog',
                      prevalidate_free_result, #OFFSET (p_permit_list));
              IFEND;
              p_permit_list := NIL;
            IFEND;
          ELSEIF status.condition = pfe$catalog_full THEN
            status.normal := TRUE;
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND contract_permit_list;

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

  PROCEDURE [INLINE] convert_group_type_to_string
    (    group_type: pft$group_types;
     VAR group_type_string: string (maximum_group_type_string_size);
     VAR group_type_string_size: 1 .. maximum_group_type_string_size);

    CASE group_type OF
    = pfc$public =
      group_type_string := 'public';
      group_type_string_size := 6;
    = pfc$family =
      group_type_string := 'family';
      group_type_string_size := 6;
    = pfc$account =
      group_type_string := 'account';
      group_type_string_size := 7;
    = pfc$project =
      group_type_string := 'project';
      group_type_string_size := 7;
    = pfc$user =
      group_type_string := 'user';
      group_type_string_size := 4;
    = pfc$user_account =
      group_type_string := 'user_account';
      group_type_string_size := 12;
    = pfc$member =
      group_type_string := 'member';
      group_type_string_size := 6;
    ELSE
      group_type_string := '?';
      group_type_string_size := 1;
    CASEND;
  PROCEND convert_group_type_to_string;

?? TITLE := '  create_cycle', EJECT ??

  PROCEDURE create_cycle
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         path: pft$complete_path;
         cycle_number: fst$cycle_number;
         lfn: amt$local_file_name;
         date_time: ost$date_time;
         authority: pft$authority;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         application_info: pft$application_info;
         validation_ring: ost$valid_ring;
         enable_media_damage_detection: boolean;
         implicit_attach: boolean;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
         p_file_label: {input} fmt$p_file_label;
         device_class: rmt$device_class,
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         p_removable_media_req_info: {input} ^fmt$removable_media_req_info;
         p_volume_list: {input} ^rmt$volume_list;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
         p_file_object: {i^/o^} pft$p_object;
         p_internal_cycle_path: {i^/o^} pft$p_internal_cycle_path;
     VAR physical_file_object: {i/o} pft$physical_object;
     VAR p_cycle_list: {i/o} pft$p_cycle_list;
     VAR p_cycle: {output} pft$p_cycle;
     VAR sfid: gft$system_file_identifier;
     VAR path_handle: {client only} fmt$path_handle;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {server only: i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

    VAR
      apft_index: pft$attached_pf_table_index,
      apfid_assigned: boolean,
      apfid_in_use: boolean,
      flush_catalog_pages: boolean,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      ignore_status: ost$status,
      internal_cycle_name: pft$internal_name,
      local_status: ost$status,
      new_cycle_list: boolean,
      new_log_list: boolean,
      p_attached_pf_entry: pft$p_attached_pf_entry,
      p_catalog_heap: pft$p_catalog_heap,
      p_data_value: ^clt$data_value,
      p_evaluated_file_reference: ^fst$evaluated_file_reference,
      p_log_list: pft$p_log_list,
      p_new_cycle_list: pft$p_cycle_list,
      p_new_log_list: pft$p_log_list,
      p_new_stored_fmd: pft$p_physical_fmd,
      p_parent_path: ^pft$complete_path,
      path_description_created: boolean,
      path_index: pft$catalog_path_index,
      pf_device_class: pft$device_class,
      physical_cycle: pft$physical_cycle,
      prevalidate_free_result: ost$prevalidate_free_result,
      shared_queue: pft$shared_queue;

    pfp$assign_locked_apfid (apft_index, status);
    apfid_assigned := status.normal;
    apfid_in_use := FALSE;
    path_description_created := FALSE;
    pfv$locked_apfid := apft_index;

    IF status.normal THEN
      IF (device_class = rmc$magnetic_tape_device) AND (authority.ownership = $pft$ownership []) THEN
        PUSH p_parent_path: [1 .. (UPPERBOUND (path) - 1)];
        FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
          p_parent_path^ [path_index] := path [path_index];
        FOREND;
        pfp$convert_pf_path_to_fs_path (p_parent_path^, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$non_owner_tape_file_create,
              fs_path (1, fs_path_size), status);
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$create_permanent_file (family_location, lfn, path, cycle_number, apft_index, usage_selections,
            share_selections, application_info, validation_ring, {password_protected}
            (physical_file_object.object_entry.password <> osc$null_name), enable_media_damage_detection,
            implicit_attach, {recreate_attached_cycle_data} FALSE, p_file_label, device_class,
            p_mass_storage_request_info, p_removable_media_req_info, p_volume_list, authority, path_handle,
            sfid, internal_cycle_name, bytes_allocated, p_file_server_buffers, status);
    IFEND;
    apfid_in_use := status.normal;
    path_description_created := status.normal;

    IF status.normal THEN
      p_catalog_heap := ^p_catalog_file^.catalog_heap;
      pfp$record_dm_file_parameters (^path, ^cycle_number, sfid, device_class, p_removable_media_req_info,
            p_volume_list, p_catalog_heap, p_new_stored_fmd, status);
    IFEND;

    p_attached_pf_entry := NIL;
    IF status.normal THEN
      create_cycle_entry (cycle_number, catalog_cycle_attributes, date_time, bytes_allocated, device_class,
            physical_cycle.cycle_entry);
      physical_cycle.cycle_entry.internal_cycle_name := internal_cycle_name;
      physical_cycle.cycle_entry.device_information.device_class_defined := TRUE;
      pfp$convert_device_class_to_pf (device_class, pf_device_class);
      physical_cycle.cycle_entry.device_information.device_class := pf_device_class;
      IF (p_mass_storage_request_info <> NIL) AND (p_mass_storage_request_info^.shared_queue <>
            pfc$null_shared_queue) THEN
        physical_cycle.cycle_entry.shared_queue_info.defined := TRUE;
        physical_cycle.cycle_entry.shared_queue_info.shared_queue :=
              p_mass_storage_request_info^.shared_queue;

      ELSEIF pfv$honor_scl_var_create_file THEN
        clp$get_variable_value ('RMV$SHARED_QUEUE', p_data_value, local_status);
        IF local_status.normal AND (p_data_value <> NIL) THEN
          IF p_data_value^.kind = clc$name THEN
            pfp$convert_shared_queue_to_ord (p_data_value^.name_value, shared_queue, local_status);
            IF local_status.normal THEN
              physical_cycle.cycle_entry.shared_queue_info.defined := TRUE;
              physical_cycle.cycle_entry.shared_queue_info.shared_queue := shared_queue;
            ELSE
              pmp$log_ascii ('Invalid value for variable RMV$SHARED_QUEUE ignored.',
                    $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
            IFEND;
          ELSE
            pmp$log_ascii ('Invalid type for variable RMV$SHARED_QUEUE ignored.',
                  $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
          IFEND;
        IFEND;
      IFEND;
      physical_cycle.cycle_entry.device_information.eoi := 0;
      physical_cycle.cycle_entry.device_information.bytes_allocated := bytes_allocated;
      physical_cycle.cycle_entry.global_file_name := internal_cycle_name;
      pfp$build_fmd_locator (p_new_stored_fmd, p_catalog_file, physical_cycle.cycle_entry.fmd_locator);
      pfp$increment_usage_counts (path, usage_selections, share_selections, mainframe_id, p_catalog_file,
            flush_catalog_pages, physical_cycle.cycle_entry, status);
      pfp$compute_checksum (#LOC (physical_cycle.cycle_entry), #SIZE (physical_cycle.cycle_entry),
            physical_cycle.checksum);
      syp$hang_if_job_jrt_set (pfc$tjr_define);
      p_internal_cycle_path^.cycle_name := internal_cycle_name;
      build_attached_pf_entry (sfid, path, cycle_number, device_class, {update_catalog} TRUE,
            {update_cycle_statistics} TRUE, usage_selections, share_selections,
            {media_image_inconsistent} FALSE, enable_media_damage_detection, $fst$cycle_damage_symptoms [],
            p_internal_cycle_path^, p_attached_pf_entry, status);
    IFEND;

    IF status.normal THEN
      new_log_list := FALSE;
      IF physical_file_object.object_entry.logging_selection = pfc$log THEN
        pfp$build_log_list_pointer (physical_file_object.object_entry.log_list_locator, p_catalog_file,
              p_log_list);
        update_access_log (date_time, authority, cycle_number, p_catalog_heap, p_log_list, p_new_log_list,
              new_log_list, status);
      IFEND;

      IF status.normal THEN
        pfp$establish_free_cycle_entry (p_catalog_heap, p_cycle_list, p_new_cycle_list, new_cycle_list,
              p_cycle, status);

        IF status.normal THEN
          p_cycle^ := physical_cycle;

          IF new_cycle_list THEN
            pfp$build_cycle_list_locator (p_new_cycle_list, p_catalog_file,
                  physical_file_object.object_entry.cycle_list_locator);
          IFEND;

          IF new_log_list THEN
            pfp$build_log_list_locator (p_new_log_list, p_catalog_file,
                  physical_file_object.object_entry.log_list_locator);
          IFEND;

          IF new_cycle_list OR new_log_list THEN
            pfp$compute_checksum (#LOC (physical_file_object.object_entry), #SIZE (pft$object_entry),
                  physical_file_object.checksum);
            p_file_object^ := physical_file_object;
          IFEND;

          IF new_cycle_list AND (p_cycle_list <> NIL) THEN
            osp$prevalidate_free ((#OFFSET (p_cycle_list) - #OFFSET (p_catalog_heap) - 16), p_catalog_heap,
                  prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_cycle_list IN p_catalog_heap^;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'CYCLE_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_cycle_list));
              p_cycle_list := NIL;
            IFEND;
          IFEND;

          IF new_log_list AND (p_log_list <> NIL) THEN
            osp$prevalidate_free ((#OFFSET (p_log_list) - #OFFSET (p_catalog_heap) - 16), p_catalog_heap,
                  prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_log_list IN p_catalog_heap^;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'LOG_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_log_list));
              p_log_list := NIL;
            IFEND;
          IFEND;
        ELSE
          IF new_log_list THEN
            osp$prevalidate_free ((#OFFSET (p_new_log_list) - #OFFSET (p_catalog_heap) - 16),
                  p_catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_new_log_list IN p_catalog_heap^;
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'LOG_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_new_log_list));
              p_new_log_list := NIL;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF NOT status.normal AND path_description_created THEN
      dmp$destroy_file (sfid, sfc$no_limit, local_status);

      PUSH p_evaluated_file_reference;
      pfp$convert_pf_to_fs_structure (path, p_evaluated_file_reference^);
      p_evaluated_file_reference^.path_handle_info.path_handle_present := TRUE;
      p_evaluated_file_reference^.path_handle_info.path_handle := path_handle;
      fmp$delete_path_description (p_evaluated_file_reference^, {implicit_detach} FALSE,
            {return_permanent_file} FALSE, {detachment_options} NIL, local_status);

      IF p_attached_pf_entry <> NIL THEN
        IF p_attached_pf_entry^.p_external_path <> NIL THEN
          FREE p_attached_pf_entry^.p_external_path IN pfv$p_p_job_heap^^;
        IFEND;
        FREE p_attached_pf_entry IN pfv$p_p_job_heap^^;
        pfp$release_locked_apfid (apft_index, local_status);
        pfp$process_unexpected_status (local_status);
        apfid_assigned := FALSE;
      IFEND;
    IFEND;

    IF apfid_assigned THEN
      IF apfid_in_use THEN
        pfp$unlock_apfid (apft_index, p_attached_pf_entry, local_status);
      ELSE
        pfp$release_locked_apfid (apft_index, local_status);
      IFEND;
      pfp$process_unexpected_status (local_status);
    IFEND;
  PROCEND create_cycle;

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

  PROCEDURE [INLINE] create_cycle_entry
    (    cycle_number: fst$cycle_number;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
         date_time: ost$date_time;
         bytes_allocated: amt$file_byte_address;
         device_class: rmt$device_class;
     VAR cycle_entry: pft$cycle_entry);

    VAR
      pf_device_class: pft$device_class;

    cycle_entry.entry_type := pfc$normal_cycle_entry;
    cycle_entry.cycle_number := cycle_number;
    cycle_entry.cycle_statistics.creation_date_time := date_time;
    cycle_entry.cycle_statistics.modification_date_time := date_time;
    cycle_entry.cycle_statistics.access_date_time := date_time;
    cycle_entry.data_modification_date_time := date_time;
    cycle_entry.cycle_statistics.access_count := 0;
    form_expiration_date_time (date_time, catalog_cycle_attributes.retention,
          cycle_entry.expiration_date_time);
    cycle_entry.attach_status := pfv$unattached_status;
    cycle_entry.cycle_damage_symptoms := $fst$cycle_damage_symptoms [];
    cycle_entry.device_information.device_class_defined := TRUE;
    pfp$convert_device_class_to_pf (device_class, pf_device_class);
    cycle_entry.device_information.device_class := pf_device_class;
    cycle_entry.shared_queue_info.defined := FALSE;
    cycle_entry.shared_queue_info.shared_queue := pfc$null_shared_queue;
    cycle_entry.retrieve_option := catalog_cycle_attributes.retrieve_option;
    cycle_entry.site_backup_option := catalog_cycle_attributes.site_backup_option;
    cycle_entry.site_archive_option := catalog_cycle_attributes.site_archive_option;
    cycle_entry.site_release_option := catalog_cycle_attributes.site_release_option;
    cycle_entry.device_information.eoi := 0;
    cycle_entry.device_information.bytes_allocated := bytes_allocated;
    pfp$build_fmd_locator (NIL, NIL, cycle_entry.fmd_locator);
    pfp$build_file_label_locator (NIL, NIL, cycle_entry.file_label_locator);
    pfp$build_archive_list_locator (NIL, NIL, cycle_entry.archive_list_locator);
    cycle_entry.data_residence := pfc$unreleasable_data;
    cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
    pfp$build_mainfram_list_locator (NIL, NIL, cycle_entry.mainframe_usage_list_locator);
    cycle_entry.reserved_cycle_entry_space := pfv$null_cycle_entry_space;

  PROCEND create_cycle_entry;

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

  FUNCTION [INLINE] cycle_busy_due_to_sharing
    (    attach_status: pft$attach_status;
         share_intentions: pft$share_selections): boolean;

    VAR
      share_option: pft$share_options;

    FOR share_option := LOWERVALUE (share_option) TO UPPERVALUE (share_option) DO
      IF NOT (share_option IN share_intentions) AND (attach_status.usage_counts [share_option] > 0) THEN
        cycle_busy_due_to_sharing := TRUE;
        RETURN; {----->
      IFEND;
    FOREND;

    cycle_busy_due_to_sharing := FALSE;

  FUNCEND cycle_busy_due_to_sharing;
?? TITLE := '  [INLINE] cycle_busy_due_to_usage', EJECT ??

  FUNCTION [INLINE] cycle_busy_due_to_usage
    (    attach_status: pft$attach_status;
         usage_intentions: pft$permit_selections): boolean;

    VAR
      usage_option: pft$usage_options;

    FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
      IF (usage_option IN usage_intentions) AND (attach_status.prevent_usage_counts [usage_option] > 0) THEN
        cycle_busy_due_to_usage := TRUE;
        RETURN; {----->
      IFEND;
    FOREND;

    cycle_busy_due_to_usage := FALSE;

  FUNCEND cycle_busy_due_to_usage;
?? TITLE := '  [INLINE] decrement_attach_status', EJECT ??
{       DECREMENT_ATTACH_STATUS
{
{   The purpose of this procedure is to decrement the attach status to reflect
{ that the activity, as indicated by the usage_selections and share_selections
{ parameters, has stopped.

  PROCEDURE [INLINE] decrement_attach_status
    (    old_attach_status: pft$attach_status;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
     VAR new_attach_status: pft$attach_status);

    VAR
      share_option: pft$share_options,
      usage_option: pft$usage_options;

    new_attach_status := old_attach_status;
    new_attach_status.attach_count := new_attach_status.attach_count - 1;

    FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
      IF usage_option IN usage_selections THEN
        new_attach_status.usage_counts [usage_option] := new_attach_status.usage_counts [usage_option] - 1;
      IFEND;
    FOREND;

    FOR share_option := LOWERVALUE (share_option) TO UPPERVALUE (share_option) DO
      IF NOT (share_option IN share_selections) THEN
        new_attach_status.prevent_usage_counts [share_option] :=
              new_attach_status.prevent_usage_counts [share_option] - 1;
      IFEND;
    FOREND;
  PROCEND decrement_attach_status;

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

{ PURPOSE:
{   This procedure updates the mainframe usage to reflect that the specified
{   usage is no longer in effect.

  PROCEDURE [INLINE] decrement_mainframe_usage
    (    usage_selections: pft$usage_selections;
     VAR mainframe_usage {input, output} : pft$mainframe_usage_entry);

    mainframe_usage.attach_count := mainframe_usage.attach_count - 1;
    IF (usage_selections * pfv$write_usage) <> $pft$usage_selections [] THEN
      mainframe_usage.write_count := mainframe_usage.write_count - 1;
    IFEND;
  PROCEND decrement_mainframe_usage;

?? TITLE := '  decrement_usage_counts', EJECT ??

{ PURPOSE:
{   This procedure decrements the attach status and the mainframe usage
{   to reflect that the cycle is no longer used for the specified access and
{   share.

  PROCEDURE decrement_usage_counts
    (    usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         mainframe_id: pmt$binary_mainframe_id;
         p_catalog_file: {input^} ^pft$catalog_file;
     VAR cycle_entry: {input, output} pft$cycle_entry);

    VAR
      first_mainframe: boolean,
      mainframe_found: boolean,
      p_physical_mainframe_usage: ^pft$physical_mainframe_usage;

    decrement_attach_status (cycle_entry.attach_status, usage_selections, share_selections,
          cycle_entry.attach_status);

    locate_mainframe_usage (mainframe_id, cycle_entry, p_catalog_file, mainframe_found, first_mainframe,
          p_physical_mainframe_usage);
    IF mainframe_found THEN
      IF first_mainframe THEN
        decrement_mainframe_usage (usage_selections, cycle_entry.first_mainframe_usage_entry);
      ELSE
        decrement_mainframe_usage (usage_selections, p_physical_mainframe_usage^.mainframe_usage);
        pfp$compute_checksum (#LOC (p_physical_mainframe_usage^.mainframe_usage),
              #SIZE (p_physical_mainframe_usage^.mainframe_usage), p_physical_mainframe_usage^.checksum);
      IFEND;
    IFEND;
  PROCEND decrement_usage_counts;

?? TITLE := '  delete_permit_description', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to delete the permit description for a
{   specified group from a permit list.
{
{ DESIGN:
{   If no permit description is found, a warning level abnormal status is
{   returned.  If the permit list is contracted as a result of deleting the
{   permit description, a new, smaller permit list is created and the old
{   permit list is copied to the new list.

  PROCEDURE delete_permit_description
    (    path: pft$complete_path;
         group: pft$group;
         p_object: {i^/o^} pft$p_object;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR status: ost$status);

    VAR
      p_permit: pft$p_permit;

    locate_group (p_object^.object_entry.permit_list_locator, p_catalog_file, group, p_permit);
    IF p_permit = NIL THEN
      osp$set_status_condition (pfe$no_permit_deleted, status);
    ELSE
      p_permit^.permit_entry.entry_type := pfc$free_permit_entry;
      pfp$compute_checksum (#LOC (p_permit^.permit_entry), #SIZE (pft$permit_entry), p_permit^.checksum);
      contract_permit_list (path, p_object, p_catalog_file, status);
    IFEND;
  PROCEND delete_permit_description;

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

{ PURPOSE:
{   This procedure determines the user's share requirements based on
{   the user's permit and also defaults the share selections if either
{   fsc$determine_from_access_modes or fsc$required_share_modes was
{   specified.  This procedure takes into account usage by other jobs when
{   determining fsc$required_share_modes.

  PROCEDURE [INLINE] determine_share_with_fs_select
    (    usage_selections: pft$usage_selections;
         share_modes: fst$share_modes;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
         cycle_entry: pft$cycle_entry;
         device_class: rmt$device_class;
     VAR sharing_required: pft$share_selections;
     VAR share_selections: pft$share_selections);

    VAR
      share_option: pft$share_options;

    IF device_class = rmc$mass_storage_device THEN
      IF (pfc$system_owner IN authority.ownership) OR (pfc$family_owner IN authority.ownership) THEN
        sharing_required := $pft$share_selections [];
      ELSE
        sharing_required := permit_entry.share_requirements;
      IFEND;

      CASE share_modes.selector OF
      = fsc$determine_from_access_modes =
        IF (usage_selections * pfv$write_usage) = $pft$usage_selections [] THEN
          share_selections := $pft$share_selections [pfc$execute, pfc$read];
        ELSE
          share_selections := $pft$share_selections [];
        IFEND;

      = fsc$required_share_modes =
        share_selections := sharing_required;

      /determine_share_selections/
        FOR share_option := LOWERVALUE (share_option) TO UPPERVALUE (share_option) DO
          IF cycle_entry.attach_status.usage_counts [share_option] > 0 THEN
            share_selections := share_selections + $pft$share_selections [share_option];
          IFEND;
        FOREND /determine_share_selections/;

      = fsc$specific_share_modes =
        #UNCHECKED_CONVERSION (share_modes.value, share_selections);
      CASEND;

    ELSEIF device_class = rmc$mass_storage_device THEN
      sharing_required := $pft$share_selections [];
      share_selections := $pft$share_selections [];
    IFEND;

  PROCEND determine_share_with_fs_select;

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

{ PURPOSE:
{   This procedure determines the user's share requirements based on
{   the user's permit and also determines the share selections based upon
{   the share option selected, either pfc$specific_share_option, or
{   pfc$default_share_option.

  PROCEDURE [INLINE] determine_share_with_pf_option
    (    share_selector: pft$share_selector;
         permit_entry: pft$permit_entry;
         usage_selections: pft$usage_selections;
     VAR share_selections: pft$share_selections;
     VAR required_share_selections: pft$share_selections);

    IF permit_entry.entry_type = pfc$normal_permit_entry THEN
      required_share_selections := permit_entry.share_requirements;
    ELSE
      required_share_selections := -$pft$share_selections [];
    IFEND;

    IF share_selector.option = pfc$specific_share_option THEN
      share_selections := share_selector.share_selections;
    ELSE {pfc$default_share_option
      IF (usage_selections * pfv$write_usage) = $pft$usage_selections [] THEN
        share_selections := $pft$share_selections [pfc$read, pfc$execute];
      ELSE
        share_selections := $pft$share_selections [];
      IFEND;
    IFEND;
  PROCEND determine_share_with_pf_option;

?? TITLE := '  determine_usage_allowed', EJECT ??

{ PURPOSE:
{   This procedure determines the user's allowed usage.
{
{ DESIGN:
{   If fsc$permitted_access_modes was specified, the usage is determined based
{   upon the user's permit, upon sharing allowed in other jobs, and upon usage
{   on other mainframes.

  PROCEDURE determine_usage_allowed
    (    path: pft$complete_path;
         cycle_reference: fst$cycle_reference;
         mainframe_id: pmt$binary_mainframe_id;
         access_modes: fst$access_modes;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
         cycle_entry: pft$cycle_entry;
         p_catalog_file: {input^} ^pft$catalog_file;
     VAR usage_allowed: pft$usage_selections;
     VAR usage_selections: pft$usage_selections;
     VAR multiple_job_usage_selections: pft$usage_selections;
     VAR status: ost$status);

    VAR
      fs_path_size: fst$path_size,
      p_fs_path: ^fst$path,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      selections_string: pft$selections_string,
      usage_option: pft$usage_options;

    status.normal := TRUE;
    IF access_modes.selector = fsc$permitted_access_modes THEN
      IF (pfc$system_owner IN authority.ownership) OR (pfc$family_owner IN authority.ownership) THEN
        usage_allowed := -$pft$usage_selections [];
        usage_selections := $pft$usage_selections [];

      /determine_usage_selections/
        FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
          IF cycle_entry.attach_status.prevent_usage_counts [usage_option] = 0 THEN
            usage_selections := usage_selections + $pft$usage_selections [usage_option];
          IFEND;
        FOREND /determine_usage_selections/;
      ELSEIF permit_entry.usage_permissions <= $pft$permit_selections [pfc$cycle, pfc$control] THEN
        usage_selections := $pft$usage_selections [];
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$usage_not_permitted,
              p_fs_path^ (1, fs_path_size), status);
        pfp$build_permit_selections_str (permit_entry.usage_permissions, selections_string);
        osp$append_status_parameter (osc$status_parameter_delimiter, selections_string.
              value (1, selections_string.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'null set', status);
        IF permit_entry.usage_permissions = $pft$permit_selections [] THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, pfc$usage_self_denied, status);
        IFEND;
        RETURN; {----->
      ELSE
        usage_allowed := $pft$usage_selections [];
        usage_selections := $pft$usage_selections [];

      /determine_permitted_and_usage/
        FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
          IF usage_option IN permit_entry.usage_permissions THEN
            usage_allowed := usage_allowed + $pft$usage_selections [usage_option];
            IF cycle_entry.attach_status.prevent_usage_counts [usage_option] = 0 THEN
              usage_selections := usage_selections + $pft$usage_selections [usage_option];
            IFEND;
          IFEND;
        FOREND /determine_permitted_and_usage/;
      IFEND;

      multiple_job_usage_selections := usage_selections;
      {
      { If another mainframe is using the cycle remove write usage.
      {
      IF (usage_selections * pfv$write_usage <> $pft$usage_selections []) AND
            (cycle_entry.attach_status.attach_count > 0) THEN
        pfp$build_mainfram_list_pointer (cycle_entry.mainframe_usage_list_locator, p_catalog_file,
              p_mainframe_usage_list);
        IF other_mainframe_using (mainframe_id, cycle_entry, p_mainframe_usage_list) THEN
          usage_selections := usage_selections - pfv$write_usage;
        IFEND;
      IFEND;
    ELSE {fsc$specific_access_modes}
      #UNCHECKED_CONVERSION (access_modes.value, usage_selections);
      multiple_job_usage_selections := usage_selections;
      IF (pfc$system_owner IN authority.ownership) OR (pfc$family_owner IN authority.ownership) THEN
        usage_allowed := -$pft$usage_selections [];
      ELSE
        usage_allowed := $pft$usage_selections [];

      /determine_permitted_usage/
        FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
          IF usage_option IN permit_entry.usage_permissions THEN
            usage_allowed := usage_allowed + $pft$usage_selections [usage_option];
          IFEND;
        FOREND /determine_permitted_usage/;
      IFEND;
    IFEND;
  PROCEND determine_usage_allowed;

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

{ PURPOSE:
{   This procedure determines the users selected usage based either on
{   specifically requested usage, or based on the usage permitted.  This
{   procedure also determines the users permitted usage.

  PROCEDURE [INLINE] determine_usage_permitted
    (    usage_selector: pft$usage_selector;
         permit_entry: pft$permit_entry;
     VAR usage_selections: pft$usage_selections;
     VAR permitted_usage_selections: pft$usage_selections);

    VAR
      usage_option: pft$usage_options;

    permitted_usage_selections := $pft$usage_selections [];

    IF permit_entry.entry_type = pfc$normal_permit_entry THEN
      FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
        IF usage_option IN permit_entry.usage_permissions THEN
          permitted_usage_selections := permitted_usage_selections + $pft$usage_selections [usage_option];
        IFEND;
      FOREND;
    IFEND;

    IF usage_selector.option = pfc$specific_usage_option THEN
      usage_selections := usage_selector.usage_selections;
    ELSE {pfc$allowed_usage_option
      usage_selections := permitted_usage_selections;
    IFEND;
  PROCEND determine_usage_permitted;

?? TITLE := '  dm_attach_file', EJECT ??
{ This routine will call device manager to attach a permanent_file.
{ If the fmd requires reconciliation it will performed.
{ When dmp$attach encounters a file that was attached by pfp$restricted_attach
{ it does not attach the file and returns the value dmc$restricted_attach_entry
{ in the EXISTING_SFT_ENTRY parameter. If this value is returned the FMD
{ will be reconciled and dmp$attach_file will be called again.
{ Since this routine is used to attach all files during job recovery
{ this is the only attach that should encounter a file previously
{ attached by restricted attach.

  PROCEDURE dm_attach_file
    (    path: pft$complete_path;
         p_catalog_file: {input^} pft$p_catalog_file;
         usage_intentions: pft$usage_selections;
         share_selections: pft$share_selections;
         p_cycle: {i^/o^} pft$p_cycle;
     VAR system_file_id: gft$system_file_identifier;
     VAR file_damaged: boolean;
     VAR status: ost$status);

    CONST
      update_catalog = TRUE;

    VAR
      existing_sft_entry: dmt$existing_sft_entry,
      exit_on_unknown_file: boolean,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      p_physical_fmd: pft$p_physical_fmd,
      recorded_vsn: rmt$recorded_vsn;

    pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
    IF p_physical_fmd = NIL THEN
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data, fs_path (1, fs_path_size),
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number, 10, FALSE,
            status);
    ELSE
      {exit_on_unknown_file := cycle attached for write access
      exit_on_unknown_file := (p_cycle^.cycle_entry.attach_status.attach_count > 0) AND
            ((p_cycle^.cycle_entry.attach_status.usage_counts [pfc$shorten] > 0) OR
            (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$append] > 0) OR
            (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$modify] > 0));

      dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
            p_physical_fmd^.fmd, usage_intentions, 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, share_selections), file_damaged,
            system_file_id, existing_sft_entry, status);
      IF status.normal THEN
        pfp$reconcile_fmd (^path, p_cycle^.cycle_entry.internal_cycle_name, existing_sft_entry,
              update_catalog, p_catalog_file, p_cycle, p_physical_fmd, status);
        IF status.normal AND ((existing_sft_entry = dmc$restricted_attach_entry) OR
              (exit_on_unknown_file AND (existing_sft_entry = dmc$entry_not_found))) THEN
          dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                p_physical_fmd^.fmd, usage_intentions, 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,
                share_selections), file_damaged, system_file_id, existing_sft_entry, status);
        IFEND;
      IFEND;

      IF NOT status.normal THEN
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        IF status.condition = dme$volume_unavailable THEN
          recorded_vsn := status.text.value (2, 6);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_unavailable,
                fs_path (1, fs_path_size), status);
          osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
        ELSEIF status.condition = dme$some_volumes_not_online THEN
          recorded_vsn := status.text.value (2, 6);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_not_online,
                fs_path (1, fs_path_size), status);
          osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      IFEND;
    IFEND;
  PROCEND dm_attach_file;

?? TITLE := '  establish_free_log_entry', EJECT ??
{       ESTABLISH_FREE_LOG_ENTRY
{
{   The purpose of this procedure is to establish a free log entry in a log
{ list.  This is accomplished by either finding an existing free entry or by
{ expanding the log list to create a free entry.  If it is necessary to expand
{ the log list, a new, larger log list is created and the old list is copied to
{ the new list.  NOTE: It is the responsibility of the caller to FREE the old
{ log list if a new log list has been created.

  PROCEDURE establish_free_log_entry
    (    p_catalog_heap: {output^} pft$p_catalog_heap;
     VAR p_log_list: {i/o} pft$p_log_list;
     VAR p_new_log_list: {output} pft$p_log_list;
     VAR new_log_list: boolean;
     VAR p_log: {output} pft$p_log;
     VAR status: ost$status);

    VAR
      free_physical_log: pft$physical_log,
      log_index: pft$log_index;


    PROCEDURE [INLINE] locate_free_log_entry
      (    p_log_list: {input} pft$p_log_list;
       VAR p_log: {output} pft$p_log);

      VAR
        log_index: pft$log_index;

      IF p_log_list <> NIL THEN
        FOR log_index := 1 TO UPPERBOUND (p_log_list^) DO
          IF p_log_list^ [log_index].log_entry.entry_type = pfc$free_log_entry THEN
            p_log := ^p_log_list^ [log_index];
            RETURN; {----->
          IFEND;
        FOREND;
      IFEND;

      p_log := NIL;
    PROCEND locate_free_log_entry;


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

    locate_free_log_entry (p_log_list, p_log);
    IF p_log = NIL THEN
      IF p_log_list = NIL THEN
        pfp$allocate_log_list (0, p_catalog_heap, p_new_log_list, status);
        IF status.normal THEN
          free_physical_log.log_entry.entry_type := pfc$free_log_entry;
          pfp$compute_checksum (#LOC (free_physical_log.log_entry), #SIZE (pft$log_entry),
                free_physical_log.checksum);

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

          p_log := ^p_new_log_list^ [1];
          new_log_list := TRUE;
        IFEND;
      ELSE { A log list already exists.
        pfp$allocate_log_list (UPPERBOUND (p_log_list^), p_catalog_heap, p_new_log_list, status);
        IF status.normal THEN
          i#move (#LOC (p_log_list^), #LOC (p_new_log_list^), #SIZE (p_log_list^));

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

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

          p_log := ^p_new_log_list^ [UPPERBOUND (p_log_list^) + 1];
          new_log_list := TRUE;
        IFEND;
      IFEND;
    IFEND;
  PROCEND establish_free_log_entry;

?? TITLE := '  establish_free_mainframe_entry', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to establish a free mainframe entry.
{   If this is the first mainframe using the cycle, then the mainframe entry
{   in the cycle entry will be used, and first_mainframe will be returned as
{   TRUE, and the p_physical_mainframe_entry parameter is not initialized.
{   If the mainframe entry in the cycle entry is not free, then the
{   mainframe usage list is searched for a free entry, and optionally a new
{   list is allocated. In this case a pointer to the mainframe entry is
{   returned.
{   This procedure assumes that the cycle entry checksum will be recomputed
{   subsequent to this call.

  PROCEDURE establish_free_mainframe_entry
    (    path: pft$complete_path;
         p_catalog_file: {input^, output^} ^pft$catalog_file;
     VAR cycle_entry: {input, output} pft$cycle_entry;
     VAR first_mainframe: boolean;
     VAR p_physical_mainframe_entry: ^pft$physical_mainframe_usage;
     VAR status: ost$status);

    VAR
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_new_mainframe_usage_list: ^pft$mainframe_usage_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    status.normal := TRUE;

    IF cycle_entry.first_mainframe_usage_entry.entry_type = pfc$free_mainframe_entry THEN
      first_mainframe := TRUE;
    ELSE
      first_mainframe := FALSE;
      pfp$build_mainfram_list_pointer (cycle_entry.mainframe_usage_list_locator, p_catalog_file,
            p_mainframe_usage_list);
      IF p_mainframe_usage_list = NIL THEN
        ALLOCATE p_mainframe_usage_list: [1 .. 1] IN p_catalog_file^.catalog_heap;
        IF p_mainframe_usage_list = NIL THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'mainframe list', status);
        ELSE
          p_physical_mainframe_entry := ^p_mainframe_usage_list^ [1];
          pfp$build_mainfram_list_locator (p_mainframe_usage_list, p_catalog_file,
                cycle_entry.mainframe_usage_list_locator);
        IFEND;
      ELSE { A mainframe list already exists
        locate_free_mainframe_entry (p_mainframe_usage_list, p_physical_mainframe_entry);
        IF p_physical_mainframe_entry = NIL THEN
          ALLOCATE p_new_mainframe_usage_list: [1 .. (UPPERBOUND (p_mainframe_usage_list^) + 1)] IN
                p_catalog_file^.catalog_heap;
          IF p_new_mainframe_usage_list = NIL THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'New mainframe list',
                  status);
          ELSE
            i#move (#LOC (p_mainframe_usage_list^), #LOC (p_new_mainframe_usage_list^),
                  #SIZE (p_mainframe_usage_list^));
            p_physical_mainframe_entry := ^p_new_mainframe_usage_list^
                  [UPPERBOUND (p_new_mainframe_usage_list^)];
            pfp$build_mainfram_list_locator (p_new_mainframe_usage_list, p_catalog_file,
                  cycle_entry.mainframe_usage_list_locator);
            osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) -
                  #OFFSET (^p_catalog_file^.catalog_heap) - 16), ^p_catalog_file^.catalog_heap,
                  prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_mainframe_usage_list IN p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, ^cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
              p_mainframe_usage_list := NIL;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND establish_free_mainframe_entry;

?? TITLE := '  establish_free_permit_entry', EJECT ??

  PROCEDURE establish_free_permit_entry
    (    path: pft$complete_path;
         p_object: {i^/o^} pft$p_object;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR p_permit: {output} pft$p_permit;
     VAR status: ost$status);

    VAR
      free_physical_permit: pft$physical_permit,
      p_new_permit_list: pft$p_permit_list,
      p_permit_list: pft$p_permit_list,
      permit_index: pft$permit_index,
      prevalidate_free_result: ost$prevalidate_free_result;


    PROCEDURE [INLINE] locate_free_permit_entry
      (    p_permit_list: {input} pft$p_permit_list;
       VAR p_permit: {output} pft$p_permit);

      VAR
        permit_index: pft$permit_index;

      IF p_permit_list <> NIL THEN
        FOR permit_index := 1 TO UPPERBOUND (p_permit_list^) DO
          IF p_permit_list^ [permit_index].permit_entry.entry_type = pfc$free_permit_entry THEN
            p_permit := ^p_permit_list^ [permit_index];
            RETURN; {----->
          IFEND;
        FOREND;
      IFEND;

      p_permit := NIL;
    PROCEND locate_free_permit_entry;


    status.normal := TRUE;

    pfp$build_permit_list_pointer (p_object^.object_entry.permit_list_locator, p_catalog_file, p_permit_list);
    locate_free_permit_entry (p_permit_list, p_permit);
    IF p_permit = NIL THEN
      IF p_permit_list = NIL THEN
        pfp$allocate_permit_list (0, ^p_catalog_file^.catalog_heap, p_new_permit_list, status);
        IF status.normal THEN
          free_physical_permit.permit_entry.entry_type := pfc$free_permit_entry;
          pfp$compute_checksum (#LOC (free_physical_permit.permit_entry), #SIZE (pft$permit_entry),
                free_physical_permit.checksum);

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

          p_permit := ^p_new_permit_list^ [1];
          {
          { To make the catalog crash resistant, write the new permit list to
          { permanent storage and then update the object that owns the new
          { permit list.
          {
          pfp$build_permit_list_locator (p_new_permit_list, p_catalog_file,
                p_object^.object_entry.permit_list_locator);
          pfp$compute_checksum (#LOC (p_object^.object_entry), #SIZE (pft$object_entry), p_object^.checksum);
        IFEND;
      ELSE { A permit list already exists.
        pfp$allocate_permit_list (UPPERBOUND (p_permit_list^), ^p_catalog_file^.catalog_heap,
              p_new_permit_list, status);
        IF status.normal THEN
          i#move (#LOC (p_permit_list^), #LOC (p_new_permit_list^), #SIZE (p_permit_list^));

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

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

          p_permit := ^p_new_permit_list^ [UPPERBOUND (p_permit_list^) + 1];
          {
          { To make the catalog crash resistant, write the new permit list to
          { permanent storage, update the object that owns the new permit
          { list, and then free the old permit list.
          {
          pfp$build_permit_list_locator (p_new_permit_list, p_catalog_file,
                p_object^.object_entry.permit_list_locator);
          pfp$compute_checksum (#LOC (p_object^.object_entry), #SIZE (pft$object_entry), p_object^.checksum);
          osp$prevalidate_free ((#OFFSET (p_permit_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_permit_list IN p_catalog_file^.catalog_heap;
          ELSE
            IF p_object^.object_entry.object_type = pfc$file_object THEN
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'PERMIT_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_permit_list));
            ELSE
              pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'PERMIT_LIST', 'catalog',
                    prevalidate_free_result, #OFFSET (p_permit_list));
            IFEND;
            p_permit_list := NIL;
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND establish_free_permit_entry;

?? TITLE := '  find_family_location', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to determine on which mainframe the
{   specified family resides.

  PROCEDURE find_family_location
    (    family_name: ost$family_name;
     VAR served_family: boolean;
     VAR served_family_locator: pft$served_family_locator);

    VAR
      p_queue_interface_table: dft$p_queue_interface_table,
      queue_index: dft$queue_index,
      self_serving: boolean,
      server_state: dft$server_state;

    served_family_locator.server_location.server_location_selector := dfc$served_family_table_index;
    dfp$locate_served_family (family_name, served_family, served_family_locator.served_family_table_index,
          served_family_locator.server_mainframe_id, p_queue_interface_table, queue_index, server_state);
    IF served_family THEN
      served_family_locator.server_location.served_family_table_index :=
            served_family_locator.served_family_table_index;
      dfp$check_self_serving_job (served_family_locator.server_mainframe_id, self_serving);
      served_family := NOT self_serving;
    IFEND;

  PROCEND find_family_location;

?? TITLE := '  form_expiration_date_time', EJECT ??
{
{   The purpose of this procedure is to form the expiration date and time from
{ the current date and time and the retention period.

  PROCEDURE form_expiration_date_time
    (    current_date: ost$date_time;
         fs_retention: fst$retention;
     VAR expiration_date: ost$date_time);

    VAR
      local_expiration_date: ost$date_time,
      local_status: ost$status,
      time_increment: pmt$time_increment;

    local_expiration_date := current_date;

    CASE fs_retention.selector OF
    = fsc$retention_day_increment =
      local_expiration_date.hour := 23;
      local_expiration_date.minute := 59;
      local_expiration_date.second := 59;
      local_expiration_date.millisecond := 999;
      IF fs_retention.day_increment = UPPERVALUE (pft$retention) THEN
        local_expiration_date.year := UPPERVALUE (local_expiration_date.year);
        local_expiration_date.month := 12;
        local_expiration_date.day := 31;
      ELSE
        time_increment.year := 0;
        time_increment.month := 0;
        time_increment.day := fs_retention.day_increment;
        time_increment.hour := 0;
        time_increment.minute := 0;
        time_increment.second := 0;
        time_increment.millisecond := 0;
        pmp$compute_date_time (current_date, time_increment, local_expiration_date, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;

    = fsc$retention_time_increment =
      time_increment := fs_retention.time_increment;
      pmp$compute_date_time (current_date, time_increment, local_expiration_date, local_status);
      pfp$process_unexpected_status (local_status);

    = fsc$retention_expiration_date =
      local_expiration_date := fs_retention.expiration_date;
    CASEND;

    expiration_date := local_expiration_date;

  PROCEND form_expiration_date_time;

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

{       INCREMENT_ATTACH_STATUS
{
{   The purpose of this procedure is to increment attach status to reflect the
{ additional activity indicated by the usage_selections and share_selections
{ parameters.

  PROCEDURE [INLINE] increment_attach_status
    (    old_attach_status: pft$attach_status;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
     VAR new_attach_status: pft$attach_status);

    VAR
      share_option: pft$share_options,
      usage_option: pft$usage_options;

    new_attach_status := old_attach_status;
    new_attach_status.attach_count := new_attach_status.attach_count + 1;

    FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
      IF usage_option IN usage_selections THEN
        new_attach_status.usage_counts [usage_option] := new_attach_status.usage_counts [usage_option] + 1;
      IFEND;
    FOREND;

    FOR share_option := LOWERVALUE (share_option) TO UPPERVALUE (share_option) DO
      IF NOT (share_option IN share_selections) THEN
        new_attach_status.prevent_usage_counts [share_option] :=
              new_attach_status.prevent_usage_counts [share_option] + 1;
      IFEND;
    FOREND;
  PROCEND increment_attach_status;

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

{ PURPOSE:
{   This procedure updates the mainframe usage to reflect the additional usage.

  PROCEDURE [INLINE] increment_mainframe_usage
    (    usage_selections: pft$usage_selections;
     VAR mainframe_usage {input, output} : pft$mainframe_usage_entry);

    mainframe_usage.attach_count := mainframe_usage.attach_count + 1;
    IF (usage_selections * pfv$write_usage) <> $pft$usage_selections [] THEN
      mainframe_usage.write_count := mainframe_usage.write_count + 1;
    IFEND;
  PROCEND increment_mainframe_usage;

?? TITLE := '  internal_locate_cycle', EJECT ??
{       INTERNAL_LOCATE_CYCLE
{
{   The purpose of this routine is to locate the specified cycle for the
{ specified file object.  If the selected cycle cannot be found, an error
{ status is returned.

  PROCEDURE internal_locate_cycle
    (    p_cycle_list: {input} pft$p_cycle_list;
         internal_cycle_name: pft$internal_name;
     VAR p_cycle: {output} pft$p_cycle;
     VAR status: ost$status);

    VAR
      cycle_index: pft$cycle_index;

    status.normal := TRUE;
    p_cycle := NIL;

    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$free_cycle_entry) AND
              (p_cycle_list^ [cycle_index].cycle_entry.internal_cycle_name = internal_cycle_name) THEN
          p_cycle := ^p_cycle_list^ [cycle_index];
          RETURN; {----->
        IFEND;
      FOREND;
    IFEND;

    IF p_cycle = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$pf_system_error, '', status);
    IFEND;

  PROCEND internal_locate_cycle;

?? TITLE := '  locate_cycle_on_active_device', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to determine whether or not a cycle exists
{   on an active volume.
{
{ DESIGN:
{   An attempt to attach the cycle is made using dmp$attach_file.  If abnormal
{   status is returned, the status condition will be examined to determine the
{   current status of the volumes on which the cycle resides.

  PROCEDURE locate_cycle_on_active_device
    (    p_path: ^pft$complete_path;
         p_cycle: {i^/o^} pft$p_cycle;
         fmd: pft$fmd;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR cycle_on_missing_volume: boolean;
     VAR cycle_on_unavailable_volume: boolean;
     VAR status: ost$status);

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

    cycle_on_missing_volume := FALSE;
    cycle_on_unavailable_volume := FALSE;

    dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file, 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,
          sfid, existing_sft_entry, status);
    IF status.normal THEN
      pfp$detach_permanent_file (p_path, sfid, $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);
    ELSEIF status.condition = dme$some_volumes_not_online THEN
      cycle_on_missing_volume := TRUE;
      status.normal := TRUE;
    ELSEIF status.condition = dme$volume_unavailable THEN
      cycle_on_unavailable_volume := TRUE;
      status.normal := TRUE;
    ELSE
      pfp$report_unexpected_status (status);
    IFEND;
  PROCEND locate_cycle_on_active_device;

?? TITLE := '  locate_cycle_on_selected_volume', EJECT ??
{         LOCATE_CYCLE_ON_SELECTED_VOLUME
{
{ The purpose of this procedure is to determine if any portion of a
{ specific cycle exists on the volumes specfied by a previous
{ INCLUDE_VOLUMES subcommand.

  PROCEDURE locate_cycle_on_selected_volume
    (    p_fmd: {input} pft$p_fmd;
         p_included_volume_list: {input} ^pft$volume_list;
     VAR cycle_on_selected_volume: boolean;
     VAR status: ost$status);

    VAR
      fmd_header: pft$fmd_header,
      fmd_volume_index: dmt$subfile_index,
      included_volume_index: dmt$subfile_index,
      p_fmd_volume_list: ^pft$volume_list,
      p_stored_fmd: ^dmt$stored_fmd;

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

    IF p_included_volume_list = NIL THEN
      cycle_on_selected_volume := TRUE;
    ELSE
      p_stored_fmd := p_fmd;
      RESET p_stored_fmd;

      dmp$get_stored_fmd_header_info (p_stored_fmd, fmd_header, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

      IF fmd_header.number_of_subfiles > 0 THEN
        PUSH p_fmd_volume_list: [1 .. fmd_header.number_of_subfiles];
        dmp$get_stored_fmd_volume_list (p_stored_fmd, p_fmd_volume_list, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;

      FOR fmd_volume_index := 1 TO fmd_header.number_of_subfiles DO
        FOR included_volume_index := 1 TO UPPERBOUND (p_included_volume_list^) DO
          IF p_fmd_volume_list^ [fmd_volume_index] = p_included_volume_list^ [included_volume_index] THEN
            cycle_on_selected_volume := TRUE;
            RETURN; {----->
          IFEND;
        FOREND;
      FOREND;
    IFEND;
  PROCEND locate_cycle_on_selected_volume;

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

{ PURPOSE:
{   This procedure searches a mainframe usage list looking for a free mainframe
{   usage list entry.  If no free entry is found p_physical_mainframe_usage is
{   returned as NIL.

  PROCEDURE [INLINE] locate_free_mainframe_entry
    (    p_mainframe_usage_list: {input^} ^pft$mainframe_usage_list;
     VAR p_physical_mainframe_usage: ^pft$physical_mainframe_usage);

    VAR
      mainframe: pft$mainframe_count;

  /search_mainframe_list/
    FOR mainframe := 1 TO UPPERBOUND (p_mainframe_usage_list^) DO
      IF p_mainframe_usage_list^ [mainframe].mainframe_usage.entry_type = pfc$free_mainframe_entry THEN
        p_physical_mainframe_usage := ^p_mainframe_usage_list^ [mainframe];
        RETURN; {----->
      IFEND;
    FOREND /search_mainframe_list/;
    p_physical_mainframe_usage := NIL;
  PROCEND locate_free_mainframe_entry;

?? TITLE := '  locate_group', EJECT ??
{       LOCATE_GROUP
{
{   The purpose of this procedure is to search a permit list and return a
{ pointer to the permit entry that applies to the specified group.  If no
{ permit entry that applies to the group is found, a NIL pointer is returned.

  PROCEDURE locate_group
    (    permit_list_locator: pft$permit_list_locator;
         p_catalog_file: {input^} pft$p_catalog_file;
         group: pft$group;
     VAR p_permit: pft$p_permit);

    VAR
      group_found: boolean,
      p_permit_list: pft$p_permit_list,
      permit_group: pft$group,
      permit_index: pft$permit_index;

    pfp$build_permit_list_pointer (permit_list_locator, p_catalog_file, p_permit_list);
    IF p_permit_list = NIL THEN
      p_permit := NIL;
    ELSE
      FOR permit_index := 1 TO UPPERBOUND (p_permit_list^) DO
        p_permit := ^p_permit_list^ [permit_index];
        IF (p_permit^.permit_entry.entry_type = pfc$normal_permit_entry) AND
              (p_permit^.permit_entry.group.group_type = group.group_type) THEN
          permit_group := p_permit^.permit_entry.group;
          CASE permit_group.group_type OF
          = pfc$public =
            group_found := TRUE;
          = pfc$family =
            group_found := (permit_group.family_description = group.family_description);
          = pfc$account =
            group_found := (permit_group.account_description = group.account_description);
          = pfc$project =
            group_found := (permit_group.project_description = group.project_description);
          = pfc$user =
            group_found := (permit_group.user_description = group.user_description);
          = pfc$user_account =
            group_found := (permit_group.user_account_description = group.user_account_description);
          = pfc$member =
            group_found := (permit_group.member_description = group.member_description);
          ELSE
            group_found := FALSE;
          CASEND;

          IF group_found THEN
            RETURN; {----->
          IFEND;
        IFEND;
      FOREND;

      p_permit := NIL;
    IFEND;
  PROCEND locate_group;

?? TITLE := '  locate_mainframe_usage', EJECT ??

{ PURPOSE:
{   This procedure locates a mainframe in the list of mainframes using the cycle.
{   IF the mainframe is found AND it's the first mainframe, THEN the p_physical_mainframe_usage
{   is not set, and the mainframe was found in the cycle entry. IF the mainframe is found
{   AND it's NOT the first mainframe, then the p_physical_mainframe_usage
{   points to the particular entry in the mainframe usage list.

  PROCEDURE locate_mainframe_usage
    (    mainframe_id: pmt$binary_mainframe_id;
         cycle_entry: pft$cycle_entry;
         p_catalog_file: {input} pft$p_catalog_file;
     VAR mainframe_found: boolean;
     VAR first_mainframe: boolean;
     VAR p_physical_mainframe_usage: ^pft$physical_mainframe_usage);

    VAR
      mainframe_index: pft$mainframe_count,
      p_mainframe_usage_list: ^pft$mainframe_usage_list;

    IF (cycle_entry.first_mainframe_usage_entry.entry_type = pfc$normal_mainframe_entry) AND
          (cycle_entry.first_mainframe_usage_entry.mainframe_id = mainframe_id) THEN
      mainframe_found := TRUE;
      first_mainframe := TRUE;
      RETURN; {----->
    IFEND;

    pfp$build_mainfram_list_pointer (cycle_entry.mainframe_usage_list_locator, p_catalog_file,
          p_mainframe_usage_list);

    IF p_mainframe_usage_list <> NIL THEN

    /search_mainframes/
      FOR mainframe_index := 1 TO UPPERBOUND (p_mainframe_usage_list^) DO
        IF (p_mainframe_usage_list^ [mainframe_index].mainframe_usage.entry_type =
              pfc$normal_mainframe_entry) AND (p_mainframe_usage_list^ [mainframe_index].mainframe_usage.
              mainframe_id = mainframe_id) THEN
          mainframe_found := TRUE;
          first_mainframe := FALSE;
          p_physical_mainframe_usage := ^p_mainframe_usage_list^ [mainframe_index];
          RETURN; {----->
        IFEND;
      FOREND /search_mainframes/;
    IFEND;

    mainframe_found := FALSE;
  PROCEND locate_mainframe_usage;

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

{ PURPOSE:
{   The purpose of this function is to determine is a mainframe other
{   than the specified mainframe has the cycle attached.

  FUNCTION [INLINE] other_mainframe_using
    (    mainframe_id: pmt$binary_mainframe_id;
         cycle_entry: pft$cycle_entry;
         p_mainframe_usage_list: {input^} ^pft$mainframe_usage_list): boolean;

    VAR
      mainframe: pft$mainframe_count;

    IF (cycle_entry.first_mainframe_usage_entry.entry_type = pfc$normal_mainframe_entry) AND
          (cycle_entry.first_mainframe_usage_entry.mainframe_id <> mainframe_id) AND
          (cycle_entry.first_mainframe_usage_entry.attach_count > 0) THEN
      other_mainframe_using := TRUE;
    ELSE
      IF p_mainframe_usage_list <> NIL THEN

      /locate_other_mainframe_using/
        FOR mainframe := 1 TO UPPERBOUND (p_mainframe_usage_list^) DO
          IF (p_mainframe_usage_list^ [mainframe].mainframe_usage.entry_type = pfc$normal_mainframe_entry) AND
                (mainframe_id <> p_mainframe_usage_list^ [mainframe].mainframe_usage.mainframe_id) AND
                (p_mainframe_usage_list^ [mainframe].mainframe_usage.attach_count > 0) THEN
            other_mainframe_using := TRUE;
            RETURN; {----->
          IFEND;
        FOREND /locate_other_mainframe_using/;
      IFEND;
      other_mainframe_using := FALSE;
    IFEND;
  FUNCEND other_mainframe_using;

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

{ PURPOSE:
{   The purpose of this function is to determine if a mainframe other than the
{   specified mainframe has the file attached for write usage.

  FUNCTION [INLINE] other_mainframe_writer
    (    mainframe_id: pmt$binary_mainframe_id;
         cycle_entry: pft$cycle_entry;
         p_mainframe_usage_list: ^pft$mainframe_usage_list): boolean;

    VAR
      mainframe: pft$mainframe_count;

    IF (cycle_entry.first_mainframe_usage_entry.entry_type = pfc$normal_mainframe_entry) AND
          (cycle_entry.first_mainframe_usage_entry.mainframe_id <> mainframe_id) AND
          (cycle_entry.first_mainframe_usage_entry.write_count > 0) THEN
      other_mainframe_writer := TRUE;
    ELSE
      IF p_mainframe_usage_list <> NIL THEN

      /locate_other_mainframe_writer/
        FOR mainframe := 1 TO UPPERBOUND (p_mainframe_usage_list^) DO
          IF (p_mainframe_usage_list^ [mainframe].mainframe_usage.entry_type = pfc$normal_mainframe_entry) AND
                (mainframe_id <> p_mainframe_usage_list^ [mainframe].mainframe_usage.mainframe_id) AND
                (p_mainframe_usage_list^ [mainframe].mainframe_usage.write_count > 0) THEN
            other_mainframe_writer := TRUE;
            RETURN; {----->
          IFEND;
        FOREND /locate_other_mainframe_writer/;
      IFEND;
      other_mainframe_writer := FALSE;
    IFEND;
  FUNCEND other_mainframe_writer;

?? TITLE := '  pick_modes_for_attach', EJECT ??

  PROCEDURE pick_modes_for_attach
    (    path: pft$complete_path;
         cycle_reference: fst$cycle_reference;
         mainframe_id: pmt$binary_mainframe_id;
         authority: pft$authority;
         p_attachment_options: {input} ^fst$attachment_options;
         setfa_access_modes: fst$access_modes;
         device_class: rmt$device_class;
         permit_entry: pft$permit_entry;
         cycle_entry: pft$cycle_entry;
         p_old_file_label: {input} fmt$p_file_label;
         p_new_file_label: {input} fmt$p_file_label;
         validation_ring: ost$valid_ring;
         p_catalog_file: {input^} ^pft$catalog_file;
     VAR usage_allowed: pft$usage_selections; {phase 1}
     VAR usage_selections: pft$usage_selections;
     VAR sharing_required: pft$share_selections; {phase 1}
     VAR share_selections: pft$share_selections;
     VAR save_file_label: boolean;
     VAR status: ost$status);

    VAR
      access_and_share_modes_found: boolean,
      access_modes: fst$access_modes,
      cycle_formerly_opened_info: fmt$cycle_formerly_opened_info,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      label_status: ost$status,
      options_index: ost$non_negative_integers,
      options_specified: ost$non_negative_integers,
      permitted_access_modes_failure: boolean,
      ring_attributes: amt$ring_attributes,
      ring_attributes_source: amt$attribute_source,
      share_modes: fst$share_modes,
      usage_intentions: pft$permit_selections,
      valid_ring: boolean;

    options_index := 0;
    IF p_attachment_options = NIL THEN
      options_specified := 0;
    ELSE
      options_specified := UPPERBOUND (p_attachment_options^);
    IFEND;
    access_and_share_modes_found := FALSE;
    save_file_label := FALSE;

    IF (p_old_file_label = NIL) AND (pfc$control IN permit_entry.usage_permissions) THEN
      fmi$get_ring_attributes (p_new_file_label, cycle_formerly_opened_info, label_status);
      save_file_label := (label_status.normal AND (p_new_file_label <> NIL));
    ELSE
      fmi$get_ring_attributes (p_old_file_label, cycle_formerly_opened_info, label_status);
      save_file_label := FALSE;
    IFEND;

    REPEAT
      IF p_attachment_options <> NIL THEN
        REPEAT
          options_index := options_index + 1;
        UNTIL (p_attachment_options^ [options_index].selector = fsc$access_and_share_modes) OR
              (options_index = options_specified);
      IFEND;

      IF (p_attachment_options <> NIL) AND (p_attachment_options^ [options_index].selector =
            fsc$access_and_share_modes) THEN
        access_and_share_modes_found := TRUE;
        access_modes := p_attachment_options^ [options_index].access_modes;
        IF device_class = rmc$mass_storage_device THEN
          share_modes := p_attachment_options^ [options_index].share_modes;
        ELSEIF device_class = rmc$magnetic_tape_device THEN
          share_modes.selector := fsc$specific_share_modes;
          share_modes.value := $fst$file_access_options [];
        IFEND;
        status.normal := TRUE;
      ELSEIF NOT access_and_share_modes_found THEN
        {
        { Use setfa access modes and default share modes. (If access
        { modes were not specified via a setfa, they will default to
        { fsc$permitted_access_modes.)
        {
        access_modes := setfa_access_modes;
        IF device_class = rmc$mass_storage_device THEN
          share_modes.selector := fsc$determine_from_access_modes;
        ELSEIF device_class = rmc$magnetic_tape_device THEN
          share_modes.selector := fsc$specific_share_modes;
          share_modes.value := $fst$file_access_options [];
        IFEND;
        status.normal := TRUE;
      IFEND;

      IF status.normal THEN
        validate_permission_and_sharing (path, cycle_reference, mainframe_id, access_modes, share_modes,
              authority, permit_entry, cycle_entry, device_class,
              cycle_formerly_opened_info.cycle_previously_opened, p_catalog_file, usage_allowed { phase 1} ,
              usage_selections, sharing_required {phase 1} , share_selections, status);
      IFEND;
      permitted_access_modes_failure := (access_modes.selector = fsc$permitted_access_modes) AND
            (usage_selections = $pft$usage_selections []);

      IF status.normal THEN
        IF label_status.normal THEN
          ring_vote_selected_access (access_modes.selector, cycle_formerly_opened_info, validation_ring,
                usage_selections, valid_ring);
          IF (NOT valid_ring) AND (usage_selections <> $pft$usage_selections []) THEN
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_ring_access,
                  fs_path (1, fs_path_size), status);
            save_file_label := FALSE;
            permitted_access_modes_failure := (access_modes.selector = fsc$permitted_access_modes);
          IFEND;
        ELSE
          status := label_status;
        IFEND;
      IFEND;
    UNTIL status.normal OR (options_index = options_specified) OR permitted_access_modes_failure OR
          ((status.condition <> pfe$cycle_busy) AND (status.condition <> pfe$usage_not_permitted) AND
          (status.condition <> pfe$unknown_cycle) AND (status.condition <> ame$new_file_requires_append) AND
          (status.condition <> pfe$sharing_not_permitted) AND (status.condition <> pfe$invalid_ring_access));
  PROCEND pick_modes_for_attach;

?? TITLE := '  pick_modes_for_create', EJECT ??

  PROCEDURE pick_modes_for_create
    (    path: pft$complete_path;
         p_attachment_options: {input} ^fst$attachment_options;
         setfa_access_modes: fst$access_modes;
         ownership: pft$ownership;
         permit_entry: pft$permit_entry;
     VAR usage_allowed: pft$usage_selections;
     VAR usage_selections: pft$usage_selections;
     VAR sharing_required: pft$share_selections;
     VAR share_selections: pft$share_selections;
     VAR status: ost$status);

    VAR
      access_and_share_modes_found: boolean,
      access_modes: fst$access_modes,
      fs_path_size: fst$path_size,
      options_index: ost$non_negative_integers,
      options_specified: ost$non_negative_integers,
      p_fs_path: ^fst$path,
      share_modes: fst$share_modes,
      usage_option: pft$usage_options;

    options_index := 0;
    IF p_attachment_options = NIL THEN
      options_specified := 0;
    ELSE
      options_specified := UPPERBOUND (p_attachment_options^);
    IFEND;
    access_and_share_modes_found := FALSE;

    REPEAT
      IF p_attachment_options <> NIL THEN
        REPEAT
          options_index := options_index + 1;
        UNTIL (p_attachment_options^ [options_index].selector = fsc$access_and_share_modes) OR
              (options_index = options_specified);
      IFEND;

      IF (p_attachment_options <> NIL) AND (p_attachment_options^ [options_index].selector =
            fsc$access_and_share_modes) THEN
        access_and_share_modes_found := TRUE;
        access_modes := p_attachment_options^ [options_index].access_modes;
        share_modes := p_attachment_options^ [options_index].share_modes;
        status.normal := TRUE;
      ELSEIF NOT access_and_share_modes_found THEN
        {
        { Use setfa access modes and default share modes. (If access
        { modes were not specified via a setfa, they will default to
        { fsc$permitted_access_modes.)
        {
        access_modes := setfa_access_modes;
        share_modes.selector := fsc$determine_from_access_modes;
        status.normal := TRUE;
      IFEND;

      IF status.normal THEN
        IF access_modes.selector = fsc$permitted_access_modes THEN
          usage_selections := -$pft$usage_selections [];
        ELSE
          #UNCHECKED_CONVERSION (access_modes.value, usage_selections);
          IF NOT (fsc$append IN access_modes.value) THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, ame$new_file_requires_append,
                  p_fs_path^ (1, fs_path_size), status);
          IFEND;
        IFEND;
      IFEND;

      IF status.normal THEN
        CASE share_modes.selector OF
        = fsc$determine_from_access_modes, fsc$required_share_modes =
          share_selections := $pft$share_selections [];
        = fsc$specific_share_modes =
          #UNCHECKED_CONVERSION (share_modes.value, share_selections);
        ELSE
          osp$set_status_condition (fse$system_error, status);
        CASEND;
      IFEND;
    UNTIL status.normal OR (options_index = options_specified);

    IF status.normal THEN
      IF (pfc$system_owner IN ownership) OR (pfc$family_owner IN ownership) THEN
        usage_allowed := -$pft$usage_selections [];
        sharing_required := $pft$share_selections [];
      ELSEIF (permit_entry.entry_type = pfc$normal_permit_entry) AND
            NOT (permit_entry.usage_permissions <= $pft$permit_selections [pfc$cycle, pfc$control]) THEN
        usage_allowed := $pft$usage_selections [];
        FOR usage_option := LOWERVALUE (usage_option) TO UPPERVALUE (usage_option) DO
          IF usage_option IN permit_entry.usage_permissions THEN
            usage_allowed := usage_allowed + $pft$usage_selections [usage_option];
          IFEND;
        FOREND;
        sharing_required := permit_entry.share_requirements;
      ELSE {unpermitted}
        usage_allowed := $pft$usage_selections [];
        sharing_required := -$pft$share_selections [];
      IFEND;
    IFEND;
  PROCEND pick_modes_for_create;

?? TITLE := '  process_change_list', EJECT ??
{ NOTE:
{   Modifiers of this procedure may also need to modify procedures
{   change_path_table and validate_path_table_change in module
{   pfm$r2_df_client_requests.

  PROCEDURE process_change_list
    (    family_location: pft$family_location;
         path: pft$complete_path;
         device_class: rmt$device_class;
         change_list: pft$change_list;
         date_time: ost$date_time;
         p_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
         p_cycle: {i^/o^} ^pft$physical_cycle;
     VAR p_file_object: {i^/o} ^pft$physical_object;
     VAR object_list_descriptor: {i/o} pft$object_list_descriptor;
     VAR change_index: ost$non_negative_integers;
     VAR status: ost$status);

    VAR
      cycle_reference: fst$cycle_reference,
      detach_status: ost$status,
      dm_file_info: dmt$file_information,
      evaluated_file_reference: fst$evaluated_file_reference,
      fs_retention: fst$retention,
      file_damaged: boolean,
      fmd_modified: boolean,
      found: boolean,
      new_cycle_entry: boolean,
      new_name: fst$path_element,
      new_object_entry: boolean,
      p_cycle_list: ^pft$cycle_list,
      p_path_string: ^ost$string,
      path_index: fst$path_index,
      sfid: gft$system_file_identifier,
      space_index: 1 .. fsc$max_path_element_size + 1;

    status.normal := TRUE;

    FOR change_index := 1 TO UPPERBOUND (change_list) DO
      CASE change_list [change_index].change_type OF
      = pfc$pf_name_change =
        validate_object_name_change (path, change_list [change_index].pfn, object_list_descriptor,
              p_catalog_file, authority, permit_entry, status);
        IF status.normal THEN
          pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
                p_cycle_list);
        IFEND;

      = pfc$cycle_number_change =
        pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
              p_cycle_list);
        validate_cycle_number_change (path, p_cycle^.cycle_entry.cycle_number,
              change_list [change_index].cycle_number, p_cycle_list, status);

      ELSE
        ;
      CASEND;

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

    new_object_entry := FALSE;
    new_cycle_entry := FALSE;

  /make_changes/
    FOR change_index := 1 TO UPPERBOUND (change_list) DO
      CASE change_list [change_index].change_type OF
      = pfc$pf_name_change =
        IF family_location = pfc$local_mainframe THEN
          IF NOT new_cycle_entry THEN
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
          IFEND;
          new_name.value := change_list [change_index].pfn;
          #SCAN (pfv$space_character, change_list [change_index].pfn, space_index, found);
          new_name.size := space_index - 1;
          fmp$change_recorded_file_name (evaluated_file_reference, new_name, status);
          IF status.normal THEN
            #SCAN (pfv$space_character, path [UPPERBOUND (path)], space_index, found);
            path_index := evaluated_file_reference.path_structure_size - space_index + 1;
            evaluated_file_reference.path_structure (path_index) := $CHAR (new_name.size);
            evaluated_file_reference.path_structure (path_index + 1, new_name.size) := new_name.value;
            evaluated_file_reference.path_structure_size := path_index + new_name.size;
          ELSE
            IF status.condition <> pfe$name_already_used THEN
              pfp$report_unexpected_status (status);
            IFEND;
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        pfp$change_object_name (^path, change_list [change_index].pfn, p_catalog_file, p_file_object,
              object_list_descriptor, status);
        IF NOT status.normal THEN
          EXIT /make_changes/; {----->
        IFEND;
        {
        { Update the modification date and time of all cycles so they will appear
        { to have been modified and, thus, will be backed-up on a partial backup.
        {
        update_all_cycles_modif_date (date_time, p_cycle_list);
        new_object_entry := TRUE;

      = pfc$password_change =
        p_file_object^.object_entry.password := change_list [change_index].password;
        new_object_entry := TRUE;

      = pfc$cycle_number_change =
        IF family_location = pfc$local_mainframe THEN
          IF NOT new_object_entry THEN
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
          IFEND;
          evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
          evaluated_file_reference.cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
          fmp$change_recorded_cycle_num (evaluated_file_reference, change_list [change_index].cycle_number,
                status);
          IF status.normal THEN
            evaluated_file_reference.cycle_reference.cycle_number := change_list [change_index].cycle_number;
          ELSE
            IF status.condition <> pfe$duplicate_cycle THEN
              pfp$report_unexpected_status (status);
            IFEND;
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        p_cycle^.cycle_entry.cycle_number := change_list [change_index].cycle_number;
        {
        { Update the modification date and time of the cycle so it will appear
        { to have been modified and, thus, will be backed-up on a partial backup.
        { The data_modification_date_time is not updated as that would make the
        { the off-line data for the cycle obsolete.
        {
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = pfc$retention_change =
        fs_retention.selector := fsc$retention_day_increment;
        fs_retention.day_increment := change_list [change_index].retention;
        form_expiration_date_time (date_time, fs_retention, p_cycle^.cycle_entry.expiration_date_time);
        new_cycle_entry := TRUE;

      = pfc$log_change =
        p_file_object^.object_entry.logging_selection := change_list [change_index].log;
        new_object_entry := TRUE;

      = pfc$charge_change =
        p_file_object^.object_entry.charge_id.account := authority.account;
        p_file_object^.object_entry.charge_id.project := authority.project;
        new_object_entry := TRUE;

      = pfc$delete_damage_change =
        p_cycle^.cycle_entry.cycle_damage_symptoms := p_cycle^.cycle_entry.cycle_damage_symptoms -
              change_list [change_index].delete_damage_condition;
        new_cycle_entry := TRUE;
        IF fsc$media_image_inconsistent IN change_list [change_index].delete_damage_condition THEN
          file_damaged := FALSE;
          IF p_cycle^.cycle_entry.attach_status.attach_count = 0 THEN
            IF (device_class = rmc$mass_storage_device) AND (p_cycle^.cycle_entry.data_residence <>
                  pfc$offline_data) THEN
              dm_attach_file (path, p_catalog_file, $pft$usage_selections [pfc$read],
                    -$pft$share_selections [], p_cycle, sfid, file_damaged, status);
              IF status.normal THEN
                IF file_damaged THEN
                  dmp$change_file_damaged (sfid, {file_damaged} FALSE,
                        p_cycle^.cycle_entry.internal_cycle_name, status);
                IFEND;
                pfp$detach_permanent_file (^path, sfid, $pft$usage_selections [pfc$read],
                      {catalog_update_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_file_info,
                      fmd_modified, dm_file_info, detach_status);
                IF NOT detach_status.normal THEN
                  pfp$report_unexpected_status (detach_status);
                IFEND;
              ELSEIF status.condition = pfe$undefined_data THEN
                status.normal := TRUE;
              IFEND;
            IFEND;
          IFEND;
          IF status.normal AND (NOT file_damaged) THEN
            PUSH p_path_string;
            pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$no_media_image_inconsistent,
                  p_path_string^.value (1, p_path_string^.size), status);
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        IF NOT status.normal THEN
          IF (status.condition <> pfe$no_media_image_inconsistent) THEN
            pfp$report_unexpected_status (status);
          IFEND;
          EXIT /make_changes/; {----->
        IFEND;
      ELSE
        ;
      CASEND;
    FOREND /make_changes/;

    IF change_index > UPPERBOUND (change_list) THEN
      change_index := UPPERBOUND (change_list);
    IFEND;

    IF new_cycle_entry THEN
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

    IF new_object_entry THEN
      pfp$compute_checksum (#LOC (p_file_object^.object_entry), #SIZE (pft$object_entry),
            p_file_object^.checksum);
    IFEND;
  PROCEND process_change_list;

?? TITLE := '  process_file_changes', EJECT ??
{ NOTE:
{   Modifiers of this procedure may also need to modify procedures
{   change_path_table and validate_path_table_change in module
{   pfm$r2_df_client_requests.

  PROCEDURE process_file_changes
    (    family_location: pft$family_location;
         path: pft$complete_path;
         device_class: rmt$device_class;
         file_changes: ^fst$file_changes;
         date_time: ost$date_time;
         p_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
         p_cycle: {i^/o^} ^pft$physical_cycle;
     VAR p_file_object: {i^/o} ^pft$physical_object;
     VAR object_list_descriptor: {i/o} pft$object_list_descriptor;
     VAR change_index: ost$non_negative_integers;
     VAR status: ost$status);

    VAR
      cycle_reference: fst$cycle_reference,
      detach_status: ost$status,
      dm_file_info: dmt$file_information,
      evaluated_file_reference: fst$evaluated_file_reference,
      file_damaged: boolean,
      fmd_modified: boolean,
      found: boolean,
      local_expiration_date: ost$date_time,
      new_cycle_entry: boolean,
      new_name: fst$path_element,
      new_object_entry: boolean,
      p_cycle_list: ^pft$cycle_list,
      p_path_string: ^ost$string,
      path_index: fst$path_index,
      sfid: gft$system_file_identifier,
      shared_queue: pft$shared_queue,
      space_index: 1 .. fsc$max_path_element_size + 1,
      time_increment: pmt$time_increment;

    status.normal := TRUE;

    FOR change_index := 1 TO UPPERBOUND (file_changes^) DO
      CASE file_changes^ [change_index].selector OF
      = fsc$cycle_number_change =
        pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
              p_cycle_list);
        validate_cycle_number_change (path, p_cycle^.cycle_entry.cycle_number,
              file_changes^ [change_index].cycle_number, p_cycle_list, status);

      = fsc$pf_name_change =
        validate_object_name_change (path, file_changes^ [change_index].pfn, object_list_descriptor,
              p_catalog_file, authority, permit_entry, status);
        IF status.normal THEN
          pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator, p_catalog_file,
                p_cycle_list);
        IFEND;

      = fsc$retention_change =
        CASE file_changes^ [change_index].retention.selector OF
        = fsc$retention_day_increment =
          time_increment.year := 0;
          time_increment.month := 0;
          time_increment.day := file_changes^ [change_index].retention.day_increment;
          time_increment.hour := 0;
          time_increment.minute := 0;
          time_increment.second := 0;
          time_increment.millisecond := 0;
          clp$verify_time_increment (time_increment, status);
          IF status.normal THEN
            pmp$compute_date_time (date_time, time_increment, local_expiration_date, status);
          IFEND;

        = fsc$retention_time_increment =
          time_increment := file_changes^ [change_index].retention.time_increment;
          clp$verify_time_increment (time_increment, status);
          IF status.normal THEN
            pmp$compute_date_time (date_time, time_increment, local_expiration_date, status);
          IFEND;
          pmp$compute_date_time (date_time, time_increment, local_expiration_date, status);

        = fsc$retention_expiration_date =
          time_increment.year := 0;
          time_increment.month := 0;
          time_increment.day := 0;
          time_increment.hour := 0;
          time_increment.minute := 0;
          time_increment.second := 0;
          time_increment.millisecond := 0;
          pmp$compute_date_time (file_changes^ [change_index].retention.expiration_date, time_increment,
                local_expiration_date, status);
        CASEND;

      = fsc$retrieve_option_change =
        IF ((p_cycle^.cycle_entry.retrieve_option = pfc$admin_retrieve_only) AND
              (file_changes^ [change_index].retrieve_option <> pfc$admin_retrieve_only) AND
              (NOT ((pfc$system_owner IN authority.ownership) OR (pfc$family_owner IN authority.ownership))))
              THEN
          IF file_changes^ [change_index].retrieve_option = pfc$always_retrieve THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$change_requires_privilege,
                  'ALWAYS_RETRIEVE', status);
          ELSEIF file_changes^ [change_index].retrieve_option = pfc$explicit_retrieve_only THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$change_requires_privilege,
                  'EXPLICIT_RETRIEVE_ONLY', status);
          IFEND;
        IFEND;

      = fsc$shared_queue_change =
        pfp$convert_shared_queue_to_ord (file_changes^ [change_index].shared_queue, shared_queue, status);

      ELSE
        ;
      CASEND;

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

    new_object_entry := FALSE;
    new_cycle_entry := FALSE;

  /make_changes/
    FOR change_index := 1 TO UPPERBOUND (file_changes^) DO
      CASE file_changes^ [change_index].selector OF
      = fsc$charge_change =
        p_file_object^.object_entry.charge_id.account := authority.account;
        p_file_object^.object_entry.charge_id.project := authority.project;
        new_object_entry := TRUE;

      = fsc$cycle_number_change =
        IF family_location = pfc$local_mainframe THEN
          IF NOT new_object_entry THEN
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
          IFEND;
          evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
          evaluated_file_reference.cycle_reference.cycle_number := p_cycle^.cycle_entry.cycle_number;
          fmp$change_recorded_cycle_num (evaluated_file_reference, file_changes^ [change_index].cycle_number,
                status);
          IF status.normal THEN
            evaluated_file_reference.cycle_reference.cycle_number := file_changes^ [change_index].
                  cycle_number;
          ELSE
            IF status.condition <> pfe$duplicate_cycle THEN
              pfp$report_unexpected_status (status);
            IFEND;
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        p_cycle^.cycle_entry.cycle_number := file_changes^ [change_index].cycle_number;
        {
        { Update the modification date and time of the cycle so it will appear
        { to have been modified and, thus, will be backed-up on a partial backup.
        { The data_modification_date_time is not updated as that would make the
        { the off-line data for the cycle obsolete.
        {
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = fsc$delete_damage_change =
        p_cycle^.cycle_entry.cycle_damage_symptoms := p_cycle^.cycle_entry.cycle_damage_symptoms -
              file_changes^ [change_index].delete_damage_condition;
        new_cycle_entry := TRUE;
        IF fsc$media_image_inconsistent IN file_changes^ [change_index].delete_damage_condition THEN
          file_damaged := FALSE;
          IF p_cycle^.cycle_entry.attach_status.attach_count = 0 THEN
            IF (device_class = rmc$mass_storage_device) AND (p_cycle^.cycle_entry.data_residence <>
                  pfc$offline_data) THEN
              dm_attach_file (path, p_catalog_file, $pft$usage_selections [pfc$read],
                    -$pft$share_selections [], p_cycle, sfid, file_damaged, status);
              IF status.normal THEN
                IF file_damaged THEN
                  dmp$change_file_damaged (sfid, {file_damaged} FALSE,
                        p_cycle^.cycle_entry.internal_cycle_name, status);
                IFEND;
                pfp$detach_permanent_file (^path, sfid, $pft$usage_selections [pfc$read],
                      {catalog_update_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_file_info,
                      fmd_modified, dm_file_info, detach_status);
                IF NOT detach_status.normal THEN
                  pfp$report_unexpected_status (detach_status);
                IFEND;
              ELSEIF status.condition = pfe$undefined_data THEN
                status.normal := TRUE;
              IFEND;
            IFEND;
          IFEND;
          IF status.normal AND (NOT file_damaged) THEN
            PUSH p_path_string;
            pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$no_media_image_inconsistent,
                  p_path_string^.value (1, p_path_string^.size), status);
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        IF NOT status.normal THEN
          IF (status.condition <> pfe$no_media_image_inconsistent) THEN
            pfp$report_unexpected_status (status);
          IFEND;
          EXIT /make_changes/; {----->
        IFEND;

      = fsc$log_change =
        p_file_object^.object_entry.logging_selection := file_changes^ [change_index].log;
        new_object_entry := TRUE;

      = fsc$null_file_change =
        ;

      = fsc$password_change =
        p_file_object^.object_entry.password := file_changes^ [change_index].password;
        new_object_entry := TRUE;

      = fsc$pf_name_change =
        IF family_location = pfc$local_mainframe THEN
          IF NOT new_cycle_entry THEN
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
          IFEND;
          new_name.value := file_changes^ [change_index].pfn;
          #SCAN (pfv$space_character, file_changes^ [change_index].pfn, space_index, found);
          new_name.size := space_index - 1;
          fmp$change_recorded_file_name (evaluated_file_reference, new_name, status);
          IF status.normal THEN
            #SCAN (pfv$space_character, path [UPPERBOUND (path)], space_index, found);
            path_index := evaluated_file_reference.path_structure_size - space_index + 1;
            evaluated_file_reference.path_structure (path_index) := $CHAR (new_name.size);
            evaluated_file_reference.path_structure (path_index + 1, new_name.size) := new_name.value;
            evaluated_file_reference.path_structure_size := path_index + new_name.size;
          ELSE
            IF status.condition <> pfe$name_already_used THEN
              pfp$report_unexpected_status (status);
            IFEND;
            EXIT /make_changes/; {----->
          IFEND;
        IFEND;
        pfp$change_object_name (^path, file_changes^ [change_index].pfn, p_catalog_file, p_file_object,
              object_list_descriptor, status);
        IF NOT status.normal THEN
          EXIT /make_changes/; {----->
        IFEND;
        {
        { Update the modification date and time of all cycles so they will appear
        { to have been modified and, thus, will be backed-up on a partial backup.
        {
        update_all_cycles_modif_date (date_time, p_cycle_list);
        new_object_entry := TRUE;

      = fsc$retention_change =
        form_expiration_date_time (date_time, file_changes^ [change_index].retention,
              p_cycle^.cycle_entry.expiration_date_time);
        new_cycle_entry := TRUE;

      = fsc$retrieve_option_change =
        p_cycle^.cycle_entry.retrieve_option := file_changes^ [change_index].retrieve_option;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = fsc$shared_queue_change =
        IF shared_queue = pfc$null_shared_queue THEN
          p_cycle^.cycle_entry.shared_queue_info.defined := FALSE;
        ELSE
          p_cycle^.cycle_entry.shared_queue_info.defined := TRUE;
          p_cycle^.cycle_entry.shared_queue_info.shared_queue := shared_queue;
        IFEND;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = fsc$site_archive_option_change =
        p_cycle^.cycle_entry.site_archive_option := file_changes^ [change_index].site_archive_option;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = fsc$site_backup_option_change =
        p_cycle^.cycle_entry.site_backup_option := file_changes^ [change_index].site_backup_option;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      = fsc$site_release_option_change =
        p_cycle^.cycle_entry.site_release_option := file_changes^ [change_index].site_release_option;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := date_time;
        new_cycle_entry := TRUE;

      ELSE
        ;
      CASEND;
    FOREND /make_changes/;

    IF change_index > UPPERBOUND (file_changes^) THEN
      change_index := UPPERBOUND (file_changes^);
    IFEND;

    IF new_cycle_entry THEN
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;

    IF new_object_entry THEN
      pfp$compute_checksum (#LOC (p_file_object^.object_entry), #SIZE (pft$object_entry),
            p_file_object^.checksum);
    IFEND;
  PROCEND process_file_changes;

?? TITLE := '  purge_cycle', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to purge the specified cycle entry for a
{   file object.  This includes deleting the file described by the cycle entry.
{   If the file is busy, it is flagged so that it will be deleted when it is
{   detached.  If the specified cycle is not found, an error status is
{   returned.  If the cycle list is contracted as a result of deleting the
{   cycle entry, a new, smaller cycle list is created and the old list is
{   copied to the new list.

  PROCEDURE purge_cycle
    (    path: pft$complete_path;
         device_class: rmt$device_class;
         purge_cycle_options: pft$purge_cycle_options;
         p_data_modification_date_time: ^ost$date_time;
         p_cycle: {i^/o^} pft$p_cycle;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR p_file_object: {i^/o^} pft$p_object;
     VAR object_list_descriptor: {i/o} pft$object_list_descriptor;
     VAR disk_image_deleted: boolean;
     VAR bytes_released: amt$file_byte_address;
     VAR status: ost$status);

    CONST
      update_catalog = TRUE;

    VAR
      archive_index: pft$archive_index,
      authority: pft$authority,
      delete_cycle: boolean,
      existing_sft_entry: dmt$existing_sft_entry,
      file_info: dmt$file_information,
      local_status: ost$status,
      matching_archive_entry: boolean,
      p_archive_list: ^pft$archive_list,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_physical_fmd: ^pft$physical_fmd,
      p_physical_media: ^pft$physical_amd,
      p_stored_file_label: ^pft$physical_file_label,
      path_name: ost$string,
      prevalidate_free_result: ost$prevalidate_free_result,
      sfid: gft$system_file_identifier;

    bytes_released := 0;
    delete_cycle := TRUE;
    status.normal := TRUE;

    IF purge_cycle_options.preserve_cycle_entry AND (p_cycle^.cycle_entry.attach_status.attach_count > 0) THEN
      pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, path_name);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$replace_cycle_data_busy, path_name.
            value (1, path_name.size), status);
      RETURN; {----->
    IFEND;

    pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);

    IF (p_cycle^.cycle_entry.attach_status.attach_count <> 0) AND (p_physical_fmd <> NIL) THEN
      IF device_class = rmc$mass_storage_device THEN
        dmp$locate_existing_sft_entry (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
              existing_sft_entry, file_info, status);

        IF status.normal THEN
          IF (existing_sft_entry = dmc$normal_entry) OR (existing_sft_entry = dmc$restricted_attach_entry)
                THEN
            delete_cycle := FALSE;
            p_cycle^.cycle_entry.entry_type := pfc$purged_cycle_entry;
            pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
          ELSEIF pfp$cycle_attached_for_write (p_cycle) THEN
            pfp$reconcile_fmd (^path, p_cycle^.cycle_entry.internal_cycle_name, existing_sft_entry,
                  update_catalog, p_catalog_file, p_cycle, p_physical_fmd, status);
            pfp$process_unexpected_status (status);
          IFEND;
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      ELSEIF device_class = rmc$magnetic_tape_device THEN
        delete_cycle := FALSE;
        p_cycle^.cycle_entry.entry_type := pfc$purged_cycle_entry;
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      IFEND;
    IFEND;

    IF delete_cycle THEN
      IF p_physical_fmd <> NIL THEN
        IF device_class = rmc$mass_storage_device THEN
          dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
                local_status);
          disk_image_deleted := local_status.normal;
          #SPOIL (disk_image_deleted);
          pfp$process_unexpected_status (local_status);

          bytes_released := p_cycle^.cycle_entry.device_information.bytes_allocated;
          {
          { Despite a dmp$destroy_permanent_file failure, remove the file from
          { the permanent file base. This makes the permanent file manager
          { somewhat fault tolerant and allows the user to continue. Recovery
          { of the set will make the files known to device management and to
          { permanent file management consistent.
          {
          osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_physical_fmd IN p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR',
                  'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
            p_physical_fmd := NIL;
          IFEND;
          pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
                p_cycle^.cycle_entry.fmd_locator);
        ELSEIF device_class = rmc$magnetic_tape_device THEN
          disk_image_deleted := TRUE;
          #SPOIL (disk_image_deleted);
          osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_physical_fmd IN p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR',
                  'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
            p_physical_fmd := NIL;
          IFEND;
          pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
                p_cycle^.cycle_entry.fmd_locator);
        IFEND;
      IFEND;

      IF (NOT purge_cycle_options.preserve_cycle_entry) OR
            ((purge_cycle_options.preserve_cycle_entry) AND (NOT purge_cycle_options.preserve_file_label))
            THEN
        pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, p_catalog_file,
              p_stored_file_label);
        IF p_stored_file_label <> NIL THEN
          osp$prevalidate_free ((#OFFSET (p_stored_file_label) - #OFFSET (^p_catalog_file^.catalog_heap) -
                16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_stored_file_label IN p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_LABEL', 'file',
                  prevalidate_free_result, #OFFSET (p_stored_file_label));
            p_stored_file_label := NIL;
          IFEND;
          pfp$build_file_label_locator ({p_file_label} NIL, {p_catalog_file} NIL,
                p_cycle^.cycle_entry.file_label_locator);
        IFEND;
      IFEND;

      IF (purge_cycle_options.preserve_cycle_entry) AND (NOT purge_cycle_options.
            preserve_modification_date_time) THEN
        p_cycle^.cycle_entry.data_modification_date_time := pfv$null_date_time;
        p_cycle^.cycle_entry.cycle_statistics.modification_date_time := pfv$null_date_time;
      IFEND;

      IF p_cycle^.cycle_entry.archive_list_locator.archive_count > 0 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
          matching_archive_entry := FALSE;
          IF p_data_modification_date_time <> NIL THEN
            FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
              matching_archive_entry := matching_archive_entry OR
                    (p_archive_list^ [archive_index].archive_entry.modification_date_time =
                    p_data_modification_date_time^);
            FOREND;
          IFEND;
          IF (NOT purge_cycle_options.preserve_cycle_entry) OR
                (purge_cycle_options.preserve_cycle_entry AND (NOT purge_cycle_options.
                preserve_archive_info)) OR (purge_cycle_options.preserve_cycle_entry AND
                purge_cycle_options.preserve_archive_info AND (p_data_modification_date_time <> NIL) AND
                (NOT matching_archive_entry)) THEN
            FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
              pfp$build_amd_pointer (p_archive_list^ [archive_index].archive_entry.amd_locator,
                    p_catalog_file, p_physical_media);
              IF p_physical_media <> NIL THEN
                osp$prevalidate_free ((#OFFSET (p_physical_media) - #OFFSET (^p_catalog_file^.catalog_heap) -
                      16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
                IF prevalidate_free_result = osc$heap_free_valid THEN
                  FREE p_physical_media IN p_catalog_file^.catalog_heap;
                ELSE
                  pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number,
                        'ARCHIVE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result,
                        #OFFSET (p_physical_media));
                  p_physical_media := NIL;
                IFEND;
              IFEND;
            FOREND;

            osp$prevalidate_free ((#OFFSET (p_archive_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                  ^p_catalog_file^.catalog_heap, prevalidate_free_result);
            IF prevalidate_free_result = osc$heap_free_valid THEN
              FREE p_archive_list IN p_catalog_file^.catalog_heap;
            ELSE
              pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'ARCHIVE_LIST', 'file',
                    prevalidate_free_result, #OFFSET (p_archive_list));
              p_archive_list := NIL;
            IFEND;
            pfp$build_archive_list_locator ({p_archive_list} NIL, {p_catalog_file} NIL,
                  p_cycle^.cycle_entry.archive_list_locator);
          IFEND;
        IFEND;
      IFEND;

      pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator, p_catalog_file,
            p_mainframe_usage_list);
      IF p_mainframe_usage_list <> NIL THEN
        osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) - #OFFSET (^p_catalog_file^.catalog_heap) -
              16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_mainframe_usage_list IN p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST', 'file',
                prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
          p_mainframe_usage_list := NIL;
        IFEND;
      IFEND;
      p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
      pfp$build_mainfram_list_locator ({p_mainframe_list} NIL, {p_catalog_file} NIL,
            p_cycle^.cycle_entry.mainframe_usage_list_locator);
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);

      IF NOT purge_cycle_options.preserve_cycle_entry THEN
        p_cycle^.cycle_entry.entry_type := pfc$free_cycle_entry;
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
        pfp$delete_file_object (^path, p_catalog_file, p_file_object, object_list_descriptor, status);
        IF status.normal AND (p_file_object^.object_entry.object_type <> pfc$free_object) THEN
          contract_cycle_list (path, p_file_object, p_catalog_file, status);
        IFEND;
      IFEND;
    ELSE
      IF NOT purge_cycle_options.preserve_cycle_entry THEN
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
        pfp$delete_file_object (^path, p_catalog_file, p_file_object, object_list_descriptor, status);
      IFEND;
    IFEND;
  PROCEND purge_cycle;

?? TITLE := '  recreate_cycle_data', EJECT ??

  PROCEDURE recreate_cycle_data
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         path: pft$complete_path;
         authority: pft$authority;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         application_info: pft$application_info;
         validation_ring: ost$valid_ring;
         password_protected: boolean;
         enable_media_damage_detection: boolean;
         apft_index: pft$attached_pf_table_index;
         p_file_label: {input} fmt$p_file_label;
         p_cycle_description: {i^/o^} ^fmt$cycle_description;
         catalog_locator: {i^/o^} pft$catalog_locator;
         p_cycle: {i^/o^} ^pft$physical_cycle;
         p_internal_cycle_path: {i^/o^} ^pft$internal_cycle_path;
         p_attached_pf_entry: {i^/o^} ^pft$attached_pf_entry;
     VAR evaluated_file_reference: fst$evaluated_file_reference;
     VAR new_global_file_name: ost$binary_unique_name;
     VAR new_remote_sfid: gft$system_file_identifier;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {server only: i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

    VAR
      fmd_header_info: pft$fmd_header,
      ignore_flush_catalog_pages: boolean,
      ignore_status: ost$status,
      internal_cycle_name: pft$internal_name,
      local_apft_index: pft$attached_pf_table_index,
      local_status: ost$status,
      mass_storage_request_info: fmt$mass_storage_request_info,
      new_apfid_assigned: boolean,
      new_apfid_in_use: boolean,
      p_catalog_heap: pft$p_catalog_heap,
      p_local_attached_pf_entry: ^pft$attached_pf_entry,
      p_mass_storage_request_info: ^fmt$mass_storage_request_info,
      p_new_stored_fmd: ^pft$physical_fmd,
      p_physical_fmd: ^pft$physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      sfid: gft$system_file_identifier,
      shared_queue: pft$shared_queue;

    status.normal := TRUE;
    new_apfid_assigned := FALSE;
    new_global_file_name := dmv$null_global_file_name;
    new_remote_sfid := gfv$null_sfid;

    IF p_attached_pf_entry <> NIL THEN
      local_apft_index := apft_index;
      IF p_cycle_description <> NIL THEN
        evaluated_file_reference.path_handle_info.path_handle := p_cycle_description^.path_handle;
      IFEND;
    ELSE
      pfp$assign_locked_apfid (local_apft_index, status);
      IF status.normal THEN
        new_apfid_assigned := TRUE;
        pfv$locked_apfid := local_apft_index;
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
            p_physical_fmd);
      p_mass_storage_request_info := NIL;
      IF p_physical_fmd <> NIL THEN
        dmp$get_stored_fmd_header_info (^p_physical_fmd^.fmd, fmd_header_info, status);
        IF status.normal THEN
          IF p_cycle^.cycle_entry.shared_queue_info.defined THEN
            shared_queue := p_cycle^.cycle_entry.shared_queue_info.shared_queue;
          ELSE
            shared_queue := pfc$null_shared_queue;
          IFEND;

          rmp$build_mass_storage_info (fmd_header_info.requested_allocation_size, rmc$unspecified_file_size,
                fmd_header_info.requested_volume.recorded_vsn, fmd_header_info.requested_class, shared_queue,
                fmd_header_info.requested_transfer_size, fmd_header_info.overflow_allowed,
                {ring_of_caller} osc$tmtr_ring, ^mass_storage_request_info, status);
          IF status.normal THEN
            p_mass_storage_request_info := ^mass_storage_request_info;
          IFEND;
        IFEND;
      IFEND;

      pfp$create_permanent_file (family_location, {lfn} osc$null_name, path,
            p_cycle^.cycle_entry.cycle_number, local_apft_index, usage_selections, share_selections,
            application_info, validation_ring, password_protected, enable_media_damage_detection,
            {implicit_attach} (p_attached_pf_entry = NIL), {recreate_attached_cycle_data}
            (p_attached_pf_entry <> NIL), p_file_label, {device_class} rmc$mass_storage_device,
            p_mass_storage_request_info, {p_removable_media_req_info} NIL, {p_volume_list} NIL, authority,
            evaluated_file_reference.path_handle_info.path_handle, sfid, internal_cycle_name, bytes_allocated,
            p_file_server_buffers, status);
    IFEND;
    new_apfid_in_use := (p_attached_pf_entry = NIL) AND status.normal;

    IF status.normal THEN
      IF p_physical_fmd <> NIL THEN
        dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
              local_status);
        pfp$process_unexpected_status (local_status);
        osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^catalog_locator.p_catalog_file^.
              catalog_heap) - 16), ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
                prevalidate_free_result, #OFFSET (p_physical_fmd));
          p_physical_fmd := NIL;
        IFEND;
      IFEND;

      p_catalog_heap := ^catalog_locator.p_catalog_file^.catalog_heap;
      pfp$record_dm_file_parameters (^path, ^p_cycle^.cycle_entry.cycle_number, sfid,
            {device_class} rmc$mass_storage_device, {p_removable_media_req_info} NIL, {p_volume_list} NIL,
            p_catalog_heap, p_new_stored_fmd, status);
      IF NOT status.normal THEN
        fmp$delete_path_description (evaluated_file_reference, {implicit_detach} FALSE,
              {return_permanent_file} FALSE, {detachment_options} NIL, ignore_status);
        dmp$destroy_file (sfid, sfc$no_limit, ignore_status);
        new_apfid_in_use := FALSE;
      IFEND;
    IFEND;

    IF status.normal THEN
      p_cycle^.cycle_entry.internal_cycle_name := internal_cycle_name;
      p_cycle^.cycle_entry.global_file_name := internal_cycle_name;
      p_cycle^.cycle_entry.device_information.eoi := 0;
      p_cycle^.cycle_entry.device_information.bytes_allocated := bytes_allocated;
      p_cycle^.cycle_entry.data_residence := pfc$unreleasable_data;
      pfp$build_fmd_locator (p_new_stored_fmd, catalog_locator.p_catalog_file,
            p_cycle^.cycle_entry.fmd_locator);
      IF p_attached_pf_entry = NIL THEN
        p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
        pfp$increment_usage_counts (path, usage_selections, share_selections, mainframe_id,
              catalog_locator.p_catalog_file, ignore_flush_catalog_pages, p_cycle^.cycle_entry, status);
      IFEND;
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (p_cycle^.cycle_entry), p_cycle^.checksum);
      syp$hang_if_job_jrt_set (pfc$tjr_define);
      p_internal_cycle_path^.cycle_name := internal_cycle_name;
      IF p_attached_pf_entry <> NIL THEN
        IF p_cycle_description <> NIL THEN
          p_cycle_description^.system_file_id := sfid;
        ELSE
          new_global_file_name := p_cycle^.cycle_entry.global_file_name;
          new_remote_sfid := sfid;
        IFEND;
        p_attached_pf_entry^.internal_cycle_path.cycle_name := internal_cycle_name;
        p_attached_pf_entry^.sfid_status.sfid := sfid;
      ELSE
        build_attached_pf_entry (sfid, path, p_cycle^.cycle_entry.cycle_number,
              {device_class} rmc$mass_storage_device, {update_catalog} TRUE, {update_cycle_statistics} TRUE,
              usage_selections, share_selections, {media_image_inconsistent} FALSE,
              enable_media_damage_detection, $fst$cycle_damage_symptoms [], p_internal_cycle_path^,
              p_local_attached_pf_entry, status);
      IFEND;
    IFEND;

    IF (p_attached_pf_entry = NIL) AND new_apfid_assigned THEN
      IF new_apfid_in_use THEN
        pfp$unlock_apfid (local_apft_index, p_local_attached_pf_entry, status);
      ELSE
        pfp$release_locked_apfid (local_apft_index, status);
      IFEND;
      pfp$process_unexpected_status (status);
    IFEND;

  PROCEND recreate_cycle_data;

?? TITLE := '  release_cycle_data', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to release mass storage data for a
{   specified file cycle.
{
{ NOTES:
{   Releasing mass storage data does not cause the file label to be released.
{   If the file cycle is busy, mass storage will be released when the file
{   cycle is detached.  If the mass storage data has been modified since the
{   most recent archive entry was created, the mass storage data will not be
{   released.

  PROCEDURE release_cycle_data
    (    path: pft$complete_path;
         p_physical_cycle: {i^/o^} ^pft$physical_cycle;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_release_data_info: {i/o} ^pft$release_data_info;
     VAR status: ost$status);

    VAR
      archive_date_time: ost$date_time,
      archive_index: pft$archive_index,
      comparison_result: pmt$comparison_result,
      data_modification_date_time: ost$date_time,
      local_status: ost$status,
      p_archive_entry: ^pft$archive_entry,
      p_archive_list: ^pft$archive_list,
      p_physical_fmd: ^pft$physical_fmd,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      prevalidate_free_result: ost$prevalidate_free_result,
      release_data_info: pft$release_data_info,
      release_date_time: ost$date_time,
      variant_path: pft$variant_path;

    status.normal := TRUE;

    IF p_release_data_info = NIL THEN
      release_data_info.perform_changes := TRUE;
      release_data_info.release_attached_cycle_data := TRUE;
      release_data_info.update_last_release_date_time := TRUE;
      release_data_info.valid_archive_entry_required := TRUE;
    ELSE
      release_data_info := p_release_data_info^;
    IFEND;
    release_data_info.cycle_attached := FALSE;

    pfp$build_archive_list_pointer (p_physical_cycle^.cycle_entry.archive_list_locator, p_catalog_file,
          p_archive_list);
    IF p_archive_list = NIL THEN
      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;
      pfp$set_status_abnormal (variant_path, pfe$empty_archive_list, status);
      RETURN; {----->
    IFEND;
    {
    { Locate most recently created archive entry.
    {
    p_archive_entry := ^p_archive_list^ [1].archive_entry;
    archive_date_time := p_archive_entry^.archive_date_time;

  /search_archive_list/
    FOR archive_index := 2 TO UPPERBOUND (p_archive_list^) DO
      pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.archive_date_time,
            archive_date_time, comparison_result, status);
      IF NOT status.normal THEN
        CYCLE /search_archive_list/; {----->
      IFEND;
      IF comparison_result = pmc$left_is_greater THEN
        archive_date_time := p_archive_list^ [archive_index].archive_entry.archive_date_time;
        p_archive_entry := ^p_archive_list^ [archive_index].archive_entry;
      IFEND;
    FOREND /search_archive_list/;
    {
    { The archive entry will be considered a valid archive entry if it was created after
    { the cycle was last modified.
    {
    data_modification_date_time := p_physical_cycle^.cycle_entry.data_modification_date_time;
    pmp$date_time_compare (archive_date_time, data_modification_date_time, comparison_result, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;
    release_data_info.valid_archive_entry_found := (comparison_result = pmc$left_is_greater);
    {
    { If the release_data_info specified that a valid archive entry must exist and a valid archive
    { entry does not exist, the release request will be rejected.
    {
    IF release_data_info.valid_archive_entry_required AND NOT release_data_info.valid_archive_entry_found THEN
      p_physical_cycle^.cycle_entry.data_residence := pfc$unreleasable_data;
      pfp$compute_checksum (^p_physical_cycle^.cycle_entry, #SIZE (pft$cycle_entry),
            p_physical_cycle^.checksum);

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;
      pfp$set_status_abnormal (variant_path, pfe$data_not_releasable, status);
      osp$append_status_integer (osc$status_parameter_delimiter, p_physical_cycle^.cycle_entry.cycle_number,
            radix, NOT include_radix, status);
      RETURN; {----->
    IFEND;

    IF NOT release_data_info.valid_archive_entry_found THEN
      release_data_info.old_data_modification_date_time := data_modification_date_time;
      release_data_info.new_data_modification_date_time := p_archive_entry^.modification_date_time;
    IFEND;
    {
    { Exit here with the output parameter containing the correct data but before the catalog
    { is modified, if indicated in the release_data_info.
    {
    IF NOT release_data_info.perform_changes THEN
      IF p_physical_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
        release_data_info.cycle_attached := TRUE;
      IFEND;
      IF p_release_data_info <> NIL THEN
        p_release_data_info^ := release_data_info;
      IFEND;
      RETURN; {----->
    IFEND;
    {
    { For cycles currently attached to this or other jobs the data residence will be
    { set to indicate that the cycle should be released when the attach count goes to
    { zero.  The new data residence will also specify what type of release to execute.
    {
    IF p_physical_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
      release_data_info.cycle_attached := TRUE;
      IF release_data_info.release_attached_cycle_data THEN
        p_physical_cycle^.cycle_entry.data_residence := pfc$release_data_requested;
        IF (NOT release_data_info.valid_archive_entry_found) AND
              (data_modification_date_time <> p_archive_entry^.modification_date_time) THEN
          p_physical_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
                p_archive_entry^.modification_date_time;
          p_physical_cycle^.cycle_entry.data_modification_date_time :=
                p_archive_entry^.modification_date_time;
          p_physical_cycle^.cycle_entry.cycle_damage_symptoms :=
                p_physical_cycle^.cycle_entry.cycle_damage_symptoms +
                $fst$cycle_damage_symptoms [fsc$respf_modification_mismatch];
        IFEND;

        IF release_data_info.update_last_release_date_time THEN
          pmp$get_compact_date_time (release_date_time, local_status);

        /set_attached_release_date_time/
          FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
            pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.modification_date_time,
                  p_physical_cycle^.cycle_entry.data_modification_date_time, comparison_result, local_status);
            IF NOT local_status.normal THEN
              CYCLE /set_attached_release_date_time/; {----->
            IFEND;
            IF comparison_result = pmc$equal THEN
              p_archive_list^ [archive_index].archive_entry.last_release_date_time := release_date_time;
              pfp$compute_checksum (^p_archive_list^ [archive_index].archive_entry, #SIZE (pft$archive_entry),
                    p_archive_list^ [archive_index].checksum);
            IFEND;
          FOREND /set_attached_release_date_time/;
        IFEND;

        pfp$compute_checksum (^p_physical_cycle^.cycle_entry, #SIZE (pft$cycle_entry),
              p_physical_cycle^.checksum);
      IFEND;
      IF p_release_data_info <> NIL THEN
        p_release_data_info^ := release_data_info;
      IFEND;
      RETURN; {----->
    IFEND;

    pfp$build_fmd_pointer (p_physical_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
    IF p_physical_fmd <> NIL THEN
      dmp$destroy_permanent_file (p_physical_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
            status);
      IF NOT status.normal THEN
        pfp$report_unexpected_status (status);
        status.normal := TRUE;
      IFEND;
      {
      { Release the file_media_descriptor even if there is a failure in
      { releasing the mass storage for the file cycle.  This makes the
      { system more fault tolerant and allows the user to continue.
      { Recovery of the set will make the files known to both device
      { management and permanent file management.
      {
      osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_physical_fmd IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_physical_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR',
              'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
        p_physical_fmd := NIL;
      IFEND;
      pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
            p_physical_cycle^.cycle_entry.fmd_locator);
    IFEND;

    pfp$build_mainfram_list_pointer (p_physical_cycle^.cycle_entry.mainframe_usage_list_locator,
          p_catalog_file, p_mainframe_usage_list);
    IF p_mainframe_usage_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_mainframe_usage_list IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_physical_cycle^.cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST',
              'file', prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
        p_mainframe_usage_list := NIL;
      IFEND;
    IFEND;
    pfp$build_mainfram_list_locator ({p_mainframe_list} NIL, {p_catalog_file} NIL,
          p_physical_cycle^.cycle_entry.mainframe_usage_list_locator);

    p_physical_cycle^.cycle_entry.attach_status := pfv$unattached_status;
    p_physical_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
    p_physical_cycle^.cycle_entry.data_residence := pfc$offline_data;

    IF (NOT release_data_info.valid_archive_entry_found) AND
          (data_modification_date_time <> p_archive_entry^.modification_date_time) THEN
      p_physical_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
            p_archive_entry^.modification_date_time;
      p_physical_cycle^.cycle_entry.data_modification_date_time := p_archive_entry^.modification_date_time;
      p_physical_cycle^.cycle_entry.cycle_damage_symptoms :=
            p_physical_cycle^.cycle_entry.cycle_damage_symptoms +
            $fst$cycle_damage_symptoms [fsc$respf_modification_mismatch];
    IFEND;

    IF release_data_info.update_last_release_date_time THEN
      pmp$get_compact_date_time (release_date_time, local_status);

    /set_release_date_time/
      FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
        pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.modification_date_time,
              p_physical_cycle^.cycle_entry.data_modification_date_time, comparison_result, local_status);
        IF NOT local_status.normal THEN
          CYCLE /set_release_date_time/; {----->
        IFEND;
        IF comparison_result = pmc$equal THEN
          p_archive_list^ [archive_index].archive_entry.last_release_date_time := release_date_time;
          pfp$compute_checksum (^p_archive_list^ [archive_index].archive_entry, #SIZE (pft$archive_entry),
                p_archive_list^ [archive_index].checksum);
        IFEND;
      FOREND /set_release_date_time/;
    IFEND;

    pfp$compute_checksum (^p_physical_cycle^.cycle_entry, #SIZE (pft$cycle_entry),
          p_physical_cycle^.checksum);

    IF p_release_data_info <> NIL THEN
      p_release_data_info^ := release_data_info;
    IFEND;
  PROCEND release_cycle_data;

?? TITLE := '  replace_permit_description', EJECT ??
{       REPLACE_PERMIT_DESCRIPTION
{
{   The purpose of this procedure is to replace the permit description for a
{ specified group that may exist in a permit list.  If no permit description
{ currently exists for the group, a new one is created.  If the permit list is
{ expanded as a result of adding a new permit description, a new, larger permit
{ list is created and the old list is copied to the new list.

  PROCEDURE replace_permit_description
    (    path: pft$complete_path;
         group: pft$group;
         permit_selections: pft$permit_selections;
         share_requirements: pft$share_requirements;
         application_info: pft$application_info;
         p_object: {i^/o^} pft$p_object;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR status: ost$status);

    VAR
      p_permit: pft$p_permit;

    status.normal := TRUE;

    locate_group (p_object^.object_entry.permit_list_locator, p_catalog_file, group, p_permit);
    IF p_permit = NIL THEN
      establish_free_permit_entry (path, p_object, p_catalog_file, p_permit, status);
      IF status.normal THEN
        p_permit^.permit_entry.entry_type := pfc$normal_permit_entry;
        p_permit^.permit_entry.group := group;
      ELSE
        RETURN; {----->
      IFEND;
    IFEND;

    p_permit^.permit_entry.usage_permissions := permit_selections;
    p_permit^.permit_entry.share_requirements := share_requirements;
    p_permit^.permit_entry.application_info := application_info;
    pfp$compute_checksum (#LOC (p_permit^.permit_entry), #SIZE (pft$permit_entry), p_permit^.checksum);
  PROCEND replace_permit_description;

?? TITLE := '  ring_vote_selected_access', EJECT ??

  PROCEDURE ring_vote_selected_access
    (    access_mode_choice: fst$access_mode_choices;
         cycle_formerly_opened_info: fmt$cycle_formerly_opened_info;
         validation_ring: ost$valid_ring;
     VAR usage_selections: {i/o} pft$usage_selections;
     VAR valid_ring: boolean);

    valid_ring := fmf$ring_attributes_valid (cycle_formerly_opened_info, usage_selections, validation_ring);

    WHILE NOT valid_ring AND (access_mode_choice = fsc$permitted_access_modes) AND
          (usage_selections <> $pft$usage_selections []) DO
      IF (usage_selections * pfv$write_usage) <> $pft$usage_selections [] THEN
        usage_selections := usage_selections - pfv$write_usage;
      ELSEIF pfc$read IN usage_selections THEN
        usage_selections := usage_selections - $pft$usage_selections [pfc$read];
      ELSE
        usage_selections := $pft$usage_selections [];
      IFEND;

      IF usage_selections <> $pft$usage_selections [] THEN
        valid_ring := fmf$ring_attributes_valid (cycle_formerly_opened_info, usage_selections,
              validation_ring);
      IFEND;
    WHILEND;

  PROCEND ring_vote_selected_access;

?? TITLE := '  set_flush_catalog_pages', EJECT ??

  { DESIGN:
  {   This procedure will inhibit catalog flushing under certain conditions.
  {   The flush_catalog_pages field of the catalog_locator is set to TRUE when the catalog
  {   is opened and should not be modified prior to passing the value to this procedure.
  {   The following rules for flushing catalog pages are used:
  {      Flush catalog pages on the first attach for write access.
  {      Flush catalog pages when cycle_entry spans an allocation unit boundary.
  {      Do not flush catalog pages when the file is being attached for read access.
  {
  {   IF cycle_not_currently_attached_for_write AND this_attach_is_for_write THEN
  {     flush_catalog_pages := TRUE
  {   ELSE
  {     flush_catalog_pages := FALSE;
  {   IFEND;
  {

  PROCEDURE [INLINE] set_flush_catalog_pages
    (    usage_selections: pft$usage_selections;
         p_cycle: {input} pft$p_cycle;
     VAR flush_catalog_pages: boolean);

    IF pfv$restrict_catalog_flushing THEN
      flush_catalog_pages := (NOT pfp$cycle_attached_for_write (p_cycle)) AND
            ((usage_selections * $pft$usage_selections [pfc$shorten, pfc$append,
            pfc$modify]) <> $pft$usage_selections []) AND pfv$flush_catalogs;

      {
      { Force flushing of catalog pages if the cycle_entry crosses an allocation unit boundary
      { and flushing was set to FALSE.
      {
      IF NOT flush_catalog_pages THEN
        flush_catalog_pages := (((#OFFSET (p_cycle) MOD pfc$catalog_allocation_size) +
              #SIZE (pft$physical_cycle)) > pfc$catalog_allocation_size) AND pfv$flush_catalogs;
      IFEND;
    IFEND;
  PROCEND set_flush_catalog_pages;

?? TITLE := '  store_file_label', EJECT ??

  PROCEDURE store_file_label
    (    path: pft$complete_path;
         p_file_label: {input} fmt$p_file_label;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
         p_cycle: {i^/o^} pft$p_cycle;
     VAR p_old_stored_file_label: {i/o} pft$p_stored_file_label;
     VAR status: ost$status);

    VAR
      label_replaced: boolean,
      p_new_stored_file_label: pft$p_stored_file_label,
      prevalidate_free_result: ost$prevalidate_free_result;

    update_file_label (p_file_label, p_old_stored_file_label, ^p_catalog_file^.catalog_heap,
          p_new_stored_file_label, label_replaced, status);

    IF status.normal AND label_replaced THEN
      pfp$build_file_label_locator (p_new_stored_file_label, p_catalog_file,
            p_cycle^.cycle_entry.file_label_locator);
      pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);

      IF p_old_stored_file_label <> NIL THEN
        osp$prevalidate_free ((#OFFSET (p_old_stored_file_label) - #OFFSET (^p_catalog_file^.catalog_heap) -
              16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_old_stored_file_label IN p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_LABEL', 'file',
                prevalidate_free_result, #OFFSET (p_old_stored_file_label));
          p_old_stored_file_label := NIL;
        IFEND;
      IFEND;
    IFEND;
  PROCEND store_file_label;

?? TITLE := '  [INLINE] update_access_date', EJECT ??
{       UPDATE_ACCESS_DATE
{
{   The purpose of this procedure is to update the cycle statistics to reflect
{ the file access indicated by the usage_intentions and share_intentions
{ parameters.  This does NOT update usage count.

  PROCEDURE [INLINE] update_access_date
    (    old_cycle_statistics: pft$cycle_statistics;
         date_time: ost$date_time;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
     VAR new_cycle_statistics: pft$cycle_statistics);

    new_cycle_statistics := old_cycle_statistics;
    new_cycle_statistics.access_date_time := date_time;
    IF (usage_selections * pfv$write_usage) <> $pft$usage_selections [] THEN
      new_cycle_statistics.modification_date_time := date_time;
    IFEND;
  PROCEND update_access_date;

?? TITLE := '  update_access_log', EJECT ??
{       UPDATE_ACCESS_LOG
{
{   The purpose of this procedure is to locate the log entry for the specified
{ user in the log list and update it.  If no log entry is found for the user, a
{ new one is created.  If the log list is expanded as a result of adding a new
{ log entry, a new, larger log list is created and the old list is copied to
{ the new list.

  PROCEDURE update_access_log
    (    date_time: ost$date_time;
         authority: pft$authority;
         cycle_number: fst$cycle_number;
         p_catalog_heap: {output^} pft$p_catalog_heap;
     VAR p_log_list: {i/o} pft$p_log_list;
     VAR p_new_log_list: {output} pft$p_log_list;
     VAR new_log_list: boolean;
     VAR status: ost$status);

    VAR
      p_log: pft$p_log,
      physical_log: pft$physical_log,
      user_id: ost$user_identification;

    status.normal := TRUE;
    new_log_list := FALSE;
    user_id.family := authority.family;
    user_id.user := authority.user;

    pfp$locate_log_entry (p_log_list, user_id, p_log);
    IF p_log = NIL THEN
      establish_free_log_entry (p_catalog_heap, p_log_list, p_new_log_list, new_log_list, p_log, status);
      IF status.normal THEN
        physical_log.log_entry.entry_type := pfc$normal_log_entry;
        physical_log.log_entry.user_id := user_id;
        physical_log.log_entry.access_count := 0;
      ELSE
        RETURN; {----->
      IFEND;
    ELSE
      physical_log := p_log^;
    IFEND;

    physical_log.log_entry.access_date_time := date_time;
    physical_log.log_entry.access_count := physical_log.log_entry.access_count + 1;
    physical_log.log_entry.last_cycle := cycle_number;
    pfp$compute_checksum (#LOC (physical_log.log_entry), #SIZE (pft$log_entry), physical_log.checksum);
    p_log^ := physical_log;
  PROCEND update_access_log;

?? TITLE := '  update_all_cycles_modif_date', EJECT ??
{       UPDATE_ALL_CYCLES_MODIF_DATE
{
{   The purpose of this procedure is to update the cycle modification date of all
{ cycles of a file to indicate that the cycles are modified.  It is neccessary
{ for all cycles to appear modified after a pf name change, so that the cycles
{ will be backed-up on a partial backup.  New checksums are computed for each
{ cycle.

  PROCEDURE [INLINE] update_all_cycles_modif_date
    (    date_time: ost$date_time;
         p_cycle_list: {i/o^} pft$p_cycle_list);

    VAR
      cycle_p: ^pft$cycle_entry,
      cycle_index: pft$cycle_index;

    IF p_cycle_list <> NIL THEN
      FOR cycle_index := 1 TO UPPERBOUND (p_cycle_list^) DO
        cycle_p := ^p_cycle_list^ [cycle_index].cycle_entry;
        IF cycle_p^.entry_type = pfc$normal_cycle_entry THEN
          cycle_p^.cycle_statistics.modification_date_time := date_time;
          pfp$compute_checksum (#LOC (cycle_p^), #SIZE (pft$cycle_entry), p_cycle_list^ [cycle_index].
                checksum);
        IFEND;
      FOREND;
    IFEND;
  PROCEND update_all_cycles_modif_date;

?? TITLE := '  [INLINE] update_cycle_statistics', EJECT ??
{       UPDATE_CYCLE_STATISTICS
{
{   The purpose of this procedure is to update the cycle statistics to reflect
{ the file access indicated by the usage_intentions and share_intentions
{ parameters.

  PROCEDURE [INLINE] update_cycle_statistics
    (    old_cycle_statistics: pft$cycle_statistics;
         date_time: ost$date_time;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
     VAR new_cycle_statistics: pft$cycle_statistics;
     VAR new_data_modification_date_time: ost$date_time);

    update_access_date (old_cycle_statistics, date_time, usage_selections, share_selections,
          new_cycle_statistics);
    IF (usage_selections * pfv$write_usage) <> $pft$usage_selections [] THEN
      new_data_modification_date_time := date_time;
    IFEND;
    new_cycle_statistics.access_count := old_cycle_statistics.access_count + 1;

  PROCEND update_cycle_statistics;

?? TITLE := '  update_file_label', EJECT ??

  PROCEDURE [INLINE] update_file_label
    (    p_file_label: {input} fmt$p_file_label;
         p_old_stored_file_label: {i/o^} pft$p_stored_file_label;
         p_catalog_heap: {output^} pft$p_catalog_heap;
     VAR p_new_stored_file_label: {output} pft$p_stored_file_label;
     VAR new_stored_file_label: boolean;
     VAR status: ost$status);

    IF (p_old_stored_file_label = NIL) OR (#SIZE (p_file_label^) <>
          #SIZE (p_old_stored_file_label^.file_label)) THEN
      ALLOCATE p_new_stored_file_label: [[REP (#SIZE (p_file_label^)) OF cell]] IN p_catalog_heap^;
      IF p_new_stored_file_label = NIL THEN
        new_stored_file_label := FALSE;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, '', status);
      ELSE
        p_new_stored_file_label^.file_label := p_file_label^;
        pfp$compute_checksum (#LOC (p_file_label^), #SIZE (p_file_label^), p_new_stored_file_label^.checksum);
        new_stored_file_label := TRUE;
        status.normal := TRUE;
      IFEND;
    ELSE
      p_old_stored_file_label^.file_label := p_file_label^;
      pfp$compute_checksum (#LOC (p_file_label^), #SIZE (p_file_label^), p_old_stored_file_label^.checksum);
      new_stored_file_label := FALSE;
      status.normal := TRUE;
    IFEND;
  PROCEND update_file_label;

?? TITLE := '  update_mainframe_usage', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is update the mainframe usage to reflect
{   the addition of this usage.  If required, a new mainframe entry will be added
{   to the cycle entry.  If the mainframe already is recorded in the cycle entry,
{   the entry for the mainframe is incremented to indicate this additional attach.

  PROCEDURE update_mainframe_usage
    (    path: pft$complete_path;
         mainframe_id: pmt$binary_mainframe_id;
         usage_selections: pft$usage_selections;
         p_catalog_file: pft$p_catalog_file;
     VAR flush_catalog_pages: boolean;
     VAR cycle_entry: {input, output} pft$cycle_entry;
     VAR status: ost$status);

    VAR
      first_mainframe: boolean,
      mainframe_found: boolean,
      p_physical_mainframe_usage: ^pft$physical_mainframe_usage;


    locate_mainframe_usage (mainframe_id, cycle_entry, p_catalog_file, mainframe_found, first_mainframe,
          p_physical_mainframe_usage);
    IF mainframe_found THEN
      status.normal := TRUE;
      IF first_mainframe THEN
        increment_mainframe_usage (usage_selections, cycle_entry.first_mainframe_usage_entry);
      ELSE
        increment_mainframe_usage (usage_selections, p_physical_mainframe_usage^.mainframe_usage);
        pfp$compute_checksum (^p_physical_mainframe_usage^.mainframe_usage,
              #SIZE (p_physical_mainframe_usage^.mainframe_usage), p_physical_mainframe_usage^.checksum);
      IFEND;
    ELSE
      establish_free_mainframe_entry (path, p_catalog_file, cycle_entry, first_mainframe,
            p_physical_mainframe_usage, status);
      IF status.normal THEN
        flush_catalog_pages := pfv$flush_catalogs;
        IF first_mainframe THEN
          cycle_entry.first_mainframe_usage_entry.entry_type := pfc$normal_mainframe_entry;
          cycle_entry.first_mainframe_usage_entry.mainframe_id := mainframe_id;
          cycle_entry.first_mainframe_usage_entry.attach_count := 0;
          cycle_entry.first_mainframe_usage_entry.write_count := 0;
          increment_mainframe_usage (usage_selections, cycle_entry.first_mainframe_usage_entry);
        ELSE
          p_physical_mainframe_usage^.mainframe_usage.entry_type := pfc$normal_mainframe_entry;
          p_physical_mainframe_usage^.mainframe_usage.mainframe_id := mainframe_id;
          p_physical_mainframe_usage^.mainframe_usage.attach_count := 0;
          p_physical_mainframe_usage^.mainframe_usage.write_count := 0;
          increment_mainframe_usage (usage_selections, p_physical_mainframe_usage^.mainframe_usage);
          pfp$compute_checksum (^p_physical_mainframe_usage^.mainframe_usage,
                #SIZE (p_physical_mainframe_usage^.mainframe_usage), p_physical_mainframe_usage^.checksum);
        IFEND;
      IFEND;
    IFEND;
  PROCEND update_mainframe_usage;

?? TITLE := '  validate_access_and_share_modes', EJECT ??

  PROCEDURE validate_access_and_share_modes
    (    evaluated_file_reference: fst$evaluated_file_reference;
         last_access_and_share_modes: boolean;
         access_modes: fst$access_modes;
         share_modes: fst$share_modes;
         allowed_access: fst$file_access_options;
         required_sharing: fst$file_access_options;
         initial_open: boolean;
         create_file: boolean;
         device_class: rmt$device_class;
     VAR access_selections: fst$file_access_options;
     VAR share_selections: fst$file_access_options;
     VAR permitted_access_modes_failure: boolean;
     VAR status: ost$status);

    CONST
      include_open_position = TRUE;

    VAR
      p_fs_path: ^fst$path,
      fs_path_size: fst$path_size,
      local_status: ost$status;

    IF access_modes.selector = fsc$permitted_access_modes THEN
      IF allowed_access = $fst$file_access_options [] THEN
        permitted_access_modes_failure := TRUE;
        PUSH p_fs_path;
        clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
              fs_path_size, local_status);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, p_fs_path^ (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              evaluated_file_reference.cycle_reference.cycle_number, radix, NOT include_radix, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$current_job_usage_conflict, status);
      ELSE
        access_selections := allowed_access;
        permitted_access_modes_failure := FALSE;
        status.normal := TRUE;
      IFEND;
{   ELSEIF access_modes.value = $fst$file_access_options [] THEN
{     permitted_access_modes_failure := FALSE;
{     PUSH p_fs_path;
{     clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
{           fs_path_size, status);
{     osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$null_access_not_allowed,
{           p_fs_path^ (1, fs_path_size), status);
    ELSEIF access_modes.value <= allowed_access THEN
      access_selections := access_modes.value;
      permitted_access_modes_failure := FALSE;
      status.normal := TRUE;
    ELSE
      permitted_access_modes_failure := FALSE;
      IF last_access_and_share_modes THEN
        PUSH p_fs_path;
        clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
              fs_path_size, local_status);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, p_fs_path^ (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter,
              evaluated_file_reference.cycle_reference.cycle_number, radix, NOT include_radix, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$current_job_usage_conflict, status);
      ELSE
        osp$set_status_condition (pfe$cycle_busy, status);
      IFEND;
    IFEND;

    IF status.normal THEN
      CASE share_modes.selector OF
      = fsc$determine_from_access_modes =
        IF (access_selections * $fst$file_access_options [fsc$shorten, fsc$append,
              fsc$modify]) = $fst$file_access_options [] THEN
          share_selections := $fst$file_access_options [fsc$execute, fsc$read];
        ELSE
          share_selections := $fst$file_access_options [];
        IFEND;
        IF NOT (required_sharing <= share_selections) THEN
          IF last_access_and_share_modes THEN
            PUSH p_fs_path;
            clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
                  fs_path_size, local_status);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
                  p_fs_path^ (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter,
                  evaluated_file_reference.cycle_reference.cycle_number, radix, NOT include_radix, status);
            osp$append_status_parameter (osc$status_parameter_delimiter, pfc$current_job_share_conflict,
                  status);
          ELSE
            osp$set_status_condition (pfe$cycle_busy, status);
          IFEND;
        IFEND;

      = fsc$required_share_modes =
        share_selections := required_sharing;

      = fsc$specific_share_modes =
        IF required_sharing <= share_modes.value THEN
          share_selections := share_modes.value;
        ELSEIF last_access_and_share_modes THEN
          PUSH p_fs_path;
          clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
                fs_path_size, local_status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
                p_fs_path^ (1, fs_path_size), status);
          osp$append_status_integer (osc$status_parameter_delimiter,
                evaluated_file_reference.cycle_reference.cycle_number, radix, NOT include_radix, status);
          osp$append_status_parameter (osc$status_parameter_delimiter, pfc$current_job_share_conflict,
                status);
        ELSE
          osp$set_status_condition (pfe$cycle_busy, status);
        IFEND;

      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$system_error, '', status);
      CASEND;
    IFEND;

    IF status.normal AND initial_open AND (((NOT (fsc$append IN access_selections)) AND
          (device_class = rmc$mass_storage_device)) OR (access_selections = $fst$file_access_options [])) THEN

      IF last_access_and_share_modes THEN
        PUSH p_fs_path;
        clp$convert_file_ref_to_string (evaluated_file_reference, NOT include_open_position, p_fs_path^,
              fs_path_size, local_status);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, ame$new_file_requires_append,
              p_fs_path^ (1, fs_path_size), status);
      ELSE
        osp$set_status_condition (ame$new_file_requires_append, status);
      IFEND;
    IFEND;
  PROCEND validate_access_and_share_modes;

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

  PROCEDURE [INLINE] validate_cycle_number_change
    (    path: pft$complete_path;
         old_cycle_number: fst$cycle_number;
         new_cycle_number: fst$cycle_number;
         p_cycle_list: {input} pft$p_cycle_list;
     VAR status: ost$status);

    VAR
      cycle_selector: pft$cycle_selector,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      p_cycle: pft$p_cycle;

    cycle_selector.cycle_option := pfc$specific_cycle;
    cycle_selector.cycle_number := new_cycle_number;
    pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
    IF status.normal THEN
      IF new_cycle_number <> old_cycle_number THEN
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_cycle,
              fs_path (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, new_cycle_number, 10, FALSE, status);
      IFEND;
    ELSE { New cycle number does not already exist.
      status.normal := TRUE;
    IFEND;
  PROCEND validate_cycle_number_change;

?? TITLE := '  validate_object_name_change', EJECT ??

  PROCEDURE validate_object_name_change
    (    path: pft$complete_path;
         new_object_name: pft$name;
         object_list_descriptor: pft$object_list_descriptor;
         p_catalog_file: {input^} pft$p_catalog_file;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      last_name_index: integer,
      new_permit_entry: pft$permit_entry,
      p_new_path: pft$p_complete_path,
      p_object: pft$p_object,
      p_permit_list: pft$p_permit_list,
      path_index: integer;

    status.normal := TRUE;

    IF path [UPPERBOUND (path)] <> new_object_name THEN
      pfp$locate_object (new_object_name, $pft$object_selections [pfc$file_object, pfc$catalog_object],
            object_list_descriptor, p_object);
      IF p_object <> NIL THEN
        IF authority.ownership = $pft$ownership [] THEN
          pfp$build_permit_list_pointer (p_object^.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);

          IF (new_permit_entry.entry_type = pfc$free_permit_entry) OR
                (new_permit_entry.usage_permissions = $pft$permit_selections []) THEN
            last_name_index := UPPERBOUND (path);
            PUSH p_new_path: [1 .. last_name_index];
            FOR path_index := 1 TO last_name_index - 1 DO
              p_new_path^ [path_index] := path [path_index];
            FOREND;
            p_new_path^ [last_name_index] := new_object_name;
            pfp$convert_pf_path_to_fs_path (p_new_path^, fs_path, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$name_already_used,
                  fs_path (1, fs_path_size), status);
          IFEND;
        IFEND;

        IF status.normal THEN
          last_name_index := UPPERBOUND (path);
          PUSH p_new_path: [1 .. last_name_index];
          FOR path_index := 1 TO last_name_index - 1 DO
            p_new_path^ [path_index] := path [path_index];
          FOREND;
          p_new_path^ [last_name_index] := new_object_name;
          pfp$convert_pf_path_to_fs_path (p_new_path^, fs_path, fs_path_size);
          IF p_object^.object_entry.object_type = pfc$file_object THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$name_already_permanent_file,
                  fs_path (1, fs_path_size), status);
          ELSEIF (last_name_index = pfc$family_path_index) THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_family_catalog,
                  fs_path (1, fs_path_size), status);
          ELSEIF (last_name_index = pfc$master_catalog_path_index) THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_master_catalog,
                  fs_path (1, fs_path_size), status);
          ELSE
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$name_already_subcatalog,
                  fs_path (1, fs_path_size), status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND validate_object_name_change;

?? TITLE := '  validate_permission_and_sharing', EJECT ??

  PROCEDURE validate_permission_and_sharing
    (    path: pft$complete_path;
         cycle_reference: fst$cycle_reference;
         mainframe_id: pmt$binary_mainframe_id;
         access_modes: fst$access_modes;
         share_modes: fst$share_modes;
         authority: pft$authority;
         permit_entry: pft$permit_entry;
         cycle_entry: pft$cycle_entry;
         device_class: rmt$device_class;
         cycle_previously_opened: boolean;
         p_catalog_file: {input^} ^pft$catalog_file;
     VAR usage_allowed: pft$usage_selections;
     VAR usage_selections: pft$usage_selections;
     VAR sharing_required: pft$share_selections;
     VAR share_selections: pft$share_selections;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      multiple_job_usage_selections: pft$usage_selections,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      usage_intentions: pft$permit_selections;

    determine_usage_allowed (path, cycle_reference, mainframe_id, access_modes, authority, permit_entry,
          cycle_entry, p_catalog_file, usage_allowed, usage_selections, multiple_job_usage_selections,
          status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    determine_share_with_fs_select (usage_selections, share_modes, authority, permit_entry, cycle_entry,
          device_class, sharing_required, share_selections);

    IF (access_modes.selector <> fsc$permitted_access_modes) OR
          (share_modes.selector <> fsc$required_share_modes) THEN
      pfp$map_usage_selections (usage_selections, usage_intentions);
      pfp$validate_file_permission (path, authority, permit_entry, usage_intentions, share_selections,
            status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    { Determine if the cycle is busy, and if so why.

    { Check for conflicts between jobs.
    {
    IF access_modes.selector = fsc$permitted_access_modes THEN
      IF multiple_job_usage_selections = $pft$usage_selections [] THEN
        {
        { If there is no usage because of multimainframes, catch it later.
        {
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, radix,
              NOT include_radix, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict, status);
      IFEND;
    ELSE {fsc$specific_access_modes}
      IF (cycle_entry.attach_status.attach_count > 0) AND cycle_busy_due_to_usage
            (cycle_entry.attach_status, usage_intentions) THEN
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, radix,
              NOT include_radix, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict, status);
      IFEND;
    IFEND;

    IF (share_modes.selector <> fsc$required_share_modes) AND (cycle_entry.attach_status.attach_count > 0) AND
          cycle_busy_due_to_sharing (cycle_entry.attach_status, share_selections) THEN
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, radix,
            NOT include_radix, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_share_conflict, status);
    IFEND;

    { Check for multimainframe conflicts.
    {
    IF status.normal THEN
      IF access_modes.selector = fsc$permitted_access_modes THEN
        IF usage_selections = $pft$usage_selections [] THEN
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
                status);
          osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, radix,
                NOT include_radix, status);
          osp$append_status_parameter (osc$status_parameter_delimiter, pfc$another_mainframe_user, status);
        ELSEIF cycle_entry.attach_status.attach_count > 0 THEN
          pfp$build_mainfram_list_pointer (cycle_entry.mainframe_usage_list_locator, p_catalog_file,
                p_mainframe_usage_list);
          IF other_mainframe_writer (mainframe_id, cycle_entry, p_mainframe_usage_list) THEN
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy, fs_path (1, fs_path_size),
                  status);
            osp$append_status_integer (osc$status_parameter_delimiter, cycle_entry.cycle_number, radix,
                  NOT include_radix, status);
            osp$append_status_parameter (osc$status_parameter_delimiter, pfc$another_mainframe_writer,
                  status);
          IFEND;
        IFEND;
      ELSEIF cycle_entry.attach_status.attach_count > 0 THEN
        check_mainframe_usage (path, mainframe_id, usage_intentions, p_catalog_file, cycle_entry, status);
      IFEND;
    IFEND;

    { Append access is required if the file has never been opened and has a disk image.
    IF status.normal AND (NOT cycle_previously_opened) AND (usage_selections <> $pft$usage_selections []) AND
          (NOT (pfc$append IN usage_selections)) AND (device_class = rmc$mass_storage_device) AND
          (((cycle_entry.data_residence = pfc$releasable_data) OR
          (cycle_entry.data_residence = pfc$unreleasable_data)) AND (cycle_entry.fmd_locator.fmd_size > 0))
          THEN
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, ame$new_file_requires_append,
            fs_path (1, fs_path_size), status);
    IFEND;
  PROCEND validate_permission_and_sharing;

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