*copyc osd$default_pragmats
?? RIGHT := 110 ??
?? NEWTITLE := ' NOS/VE Backup/Restore Utilities:  restore_file ' ??
MODULE pum$restore_file;

?? NEWTITLE := '   Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$ring_validation_errors
*copyc osc$nosve_system_set
*copyc osc$space_unavailable_condition
*copyc osd$virtual_address
*copyc osk$keypoint_class_codes
*copyc ost$caller_identifier
*copyc pfc$null_shared_queue
*copyc pue$error_condition_codes
*copyc rme$request_mass_storage
?? POP ??
*copyc amp$close
*copyc amp$get_segment_pointer
*copyc amp$return
*copyc amp$set_segment_eoi
*copyc avp$family_administrator
*copyc avp$system_administrator
*copyc clp$evaluate_file_reference
*copyc clp$evaluate_parameters
*copyc dmp$get_stored_fmd_header_info
*copyc fsp$change_cycle_date_time
*copyc mmp$close_segment
*copyc mmp$open_segment
*copyc mmp$set_segment_length
*copyc osp$append_status_file
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$enforce_exception_policies
*copyc osp$establish_condition_handler
*copyc osp$file_access_condition
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osv$initial_exception_context
*copyc pfp$change_res_to_releasable
*copyc pfp$convert_pf_cy_path_to_strng
*copyc pfp$convert_pft$path_to_fs_path
*copyc pfp$define_data
*copyc pfp$delete_cycle_data
*copyc pfp$get_family_set
*copyc pfp$purge
*copyc pfp$put_cycle_info
*copyc pfp$r3_change_cycle_date_time
*copyc pfp$r3_release_data
*copyc pfp$replace_rem_media_fmd
*copyc pfp$save_released_file_label
*copyc pfp$validate_site_options
*copyc pmp$cause_task_condition
*copyc pmp$continue_to_cause
*copyc pmp$get_unique_name
*copyc pue$error_condition_codes
*copyc pup$advised_get_part
*copyc pup$build_catalog_header
*copyc pup$build_entry
*copyc pup$check_cycle_access
*copyc pup$close_backup_file
*copyc pup$compare_paths
*copyc pup$crack_backup_file
*copyc pup$crack_pf_file_reference
*copyc pup$display_blank_lines
*copyc pup$display_integer
*copyc pup$format_date_time
*copyc pup$get_backup_cycle_info
*copyc pup$get_next_hierarchy_list
*copyc pup$get_next_record_header
*copyc pup$get_part
*copyc pup$get_summary_status
*copyc pup$initialize_restore_listing
*copyc pup$open_backup_file
*copyc pup$restore_file_info
*copyc pup$restore_sub_levels
*copyc pup$set_restore_subcmd_defaults
*copyc pup$skip_logical_partition
*copyc pup$validate_n_n_minus_1
*copyc pup$write_cycle_display
*copyc pup$write_os_status
*copyc pup$write_status_to_listing
*copyc puv$create_objects
*copyc puv$free_behind_selected
*copyc puv$mass_storage_info
*copyc puv$p_included_volumes
*copyc puv$purge_cycle_options
*copyc puv$replace_cycle_data
*copyc puv$require_modification_match
*copyc puv$restore_archive_information
*copyc puv$trace_selected
*copyc puv$update_cycle_statistics
*copyc rmp$build_mass_storage_info
*copyc rmp$validate_mass_storage_info
*copyc srp$store_system_label

?? TITLE := '    Global Variables', EJECT ??

  CONST
    include_radix = TRUE,
    radix = 10;

  VAR
    number_of_cycles_restored: integer := 0,
    total_cycle_data_restored: integer := 0;

?? TITLE := '    [XDCL] pup$display_restore_totals ', EJECT ??

  PROCEDURE [XDCL] pup$display_restore_totals;

    VAR
      local_status: ost$status;

    pup$display_blank_lines (3, local_status);
    pup$display_line (' RESTORE SUMMARY: ', local_status);
    pup$display_integer ('   NUMBER OF CYCLES RESTORED: ', number_of_cycles_restored, local_status);
    number_of_cycles_restored := 0;
    pup$display_integer ('   TOTAL CYCLE DATA RESTORED: ', total_cycle_data_restored, local_status);
    total_cycle_data_restored := 0;
  PROCEND pup$display_restore_totals;

?? TITLE := '    [XDCL] pup$initialize_restore_totals ', EJECT ??

  PROCEDURE [XDCL] pup$initialize_restore_totals;

    total_cycle_data_restored := 0;
    number_of_cycles_restored := 0;
  PROCEND pup$initialize_restore_totals;

?? TITLE := '    [XDCL, INLINE] pup$open_file_for_seg_access ', EJECT ??
*copyc puh$open_file_for_seg_access

  PROCEDURE [XDCL, INLINE] pup$open_file_for_seg_access
    (    lfn: amt$local_file_name;
     VAR segment_pointer: mmt$segment_pointer;
     VAR status: ost$status);

   VAR
      seg_attribute: array [1 .. 1] OF mmt$attribute_descriptor;

    display (' mmp$open_segment users file');
    IF puv$free_behind_selected THEN
      seg_attribute[1].keyword := mmc$kw_software_attributes;
      seg_attribute[1].software_attri_set :=
            $mmt$software_attribute_set [mmc$sa_free_behind];
      mmp$open_segment (lfn, ^seg_attribute, mmc$sequence_pointer, segment_pointer, status);
    ELSE
      mmp$open_segment (lfn, NIL, mmc$sequence_pointer, segment_pointer, status);
    IFEND;

    RESET segment_pointer.seq_pointer;

  PROCEND pup$open_file_for_seg_access;

?? TITLE := '    [XDCL] pup$restore_cycle_content ', EJECT ??

  PROCEDURE [XDCL] pup$restore_cycle_content (
        new_file_name_path: pft$path;
        new_file_name_cycle_selector: pft$cycle_selector;
        password_selector: pft$password_selector;
        record_header: put$backup_file_record_header;
        label_exists: boolean;
        p_label: ^SEQ ( * );
        p_fmd: ^SEQ ( * );
        restore_selections: put$restore_data_selections;
    VAR mandated_modification_time: pft$mandated_modification_time;
    VAR backup_file_id: put$file_identifier;
    VAR file_position: put$file_position;
    VAR cycle_length: amt$file_length;
    VAR status: ost$status);

    VAR
      local_status: ost$status;

    status.normal := TRUE;

    CASE file_position OF
    = puc$mid_partition =
      IF record_header.kind = puc$backup_cycle_data THEN
        display_integer (' define_cycle_contents puc$mid_partition; size = ', record_header.size);
        cycle_length := record_header.size;
        define_cycle_contents (new_file_name_path, new_file_name_cycle_selector, password_selector,
              label_exists, p_label^, p_fmd, restore_selections, record_header.size,
              mandated_modification_time, backup_file_id, file_position, status);
      ELSE
        osp$set_status_abnormal (puc$pf_utility_id, pue$unexpected_item_requested, ' cycle data ', status);
        display_status (status);
        pup$display_line (' FILE DATA OR ATTRIBUTES POSSIBLY LOST.', local_status);
      IFEND;
    = puc$partition_boundary =
      display (' define_cycle_contents puc$partition_boundary; size = 0 (data_released or magnetic_tape}');
      cycle_length := puc$released_cycle_size;
      define_released_cycle (new_file_name_path, new_file_name_cycle_selector, password_selector,
            label_exists, p_label, status);
    ELSE
      osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, 'unexpected file position',
            status);
      display_status (status);
      pup$display_line (' FILE DATA OR ATTRIBUTES POSSIBLY LOST.', local_status);
    CASEND;
  PROCEND pup$restore_cycle_content;

?? TITLE := '    [XDCL] pup$restore_cycle_item ', EJECT ??
*copyc puh$restore_cycle_item

  PROCEDURE [XDCL] pup$restore_cycle_item
    (    file_entry: put$entry;
         new_file_name_path: pft$path;
         new_file_name_cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         p_cycle_array_extended_record: pft$p_info_record;
         p_cycle_directory_array: pft$p_cycle_directory_array;
     VAR backup_file_id: put$file_identifier;
     VAR file_position: put$file_position;
     VAR status: ost$status);

    VAR
      cycle_array_entry: pft$cycle_array_entry_version_2,
      cycle_defined: boolean,
      cycle_included: boolean,
      cycle_length: amt$file_length,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      label_exists: boolean,
      local_access_date_time: fst$date_time,
      local_creation_date_time: fst$date_time,
      local_mod_date_time: fst$date_time,
      local_status: ost$status,
      mandated_modification_time: pft$mandated_modification_time,
      new_file_entry: put$entry,
      p_fmd: ^SEQ ( * ),
      p_label: ^ seq (*),
      p_path_string: ^ost$string,
      password: pft$password,
      record_header: put$backup_file_record_header,
      restore_selections: [STATIC, READ] put$restore_data_selections := [puc$no_data_defined],
      update_cycle_stats_status_p: ^ost$status;

    update_cycle_stats_status_p := NIL;
    pup$build_entry (new_file_name_path [UPPERBOUND (new_file_name_path)], new_file_name_cycle_selector,
          puc$valid_cycle_entry, new_file_entry);
{
{   input cycle array entry
    cycle_defined := FALSE;
    pup$get_backup_cycle_info (backup_file_id, file_position, cycle_array_entry, p_fmd, status);
{
    IF status.normal THEN
      pup$check_cycle_access (cycle_array_entry, cycle_included);
      IF cycle_included THEN
        IF file_position = puc$mid_partition THEN
          IF (puv$require_modification_match) AND (NOT puv$replace_cycle_data) THEN
            mandated_modification_time.verify_option := pfc$verify_modification_time;
          ELSE
            mandated_modification_time.verify_option := pfc$replace_modification_time;
          IFEND;
          mandated_modification_time.specified_modification_time :=
                cycle_array_entry.data_modification_date_time;
          mandated_modification_time.existing_modification_time :=
                cycle_array_entry.data_modification_date_time;
          pup$restore_label (record_header, label_exists, p_label, backup_file_id, file_position, status);
          IF status.normal THEN
            IF file_position = puc$partition_boundary THEN
              IF puv$restore_archive_information THEN
                cycle_length := puc$released_cycle_size;
              ELSE
                PUSH p_path_string;
                pfp$convert_pf_cy_path_to_strng (new_file_name_path,
                      new_file_name_cycle_selector.cycle_number, p_path_string^);
                osp$set_status_abnormal (puc$pf_utility_id, pue$released_cycle_rai_false,
                      p_path_string^.value (1, p_path_string^.size), status);
              IFEND;
            IFEND;
            IF status.normal AND (puv$restore_archive_information OR (file_position <> puc$partition_boundary)
                  OR (cycle_array_entry.device_class = rmc$magnetic_tape_device)) THEN
              IF (puv$mass_storage_info.shared_queue <> pfc$null_shared_queue) AND
                    (cycle_array_entry.device_class = rmc$mass_storage_device) THEN
                cycle_array_entry.shared_queue_info.defined := TRUE;
                cycle_array_entry.shared_queue_info.shared_queue := puv$mass_storage_info.shared_queue;
              IFEND;
              IF puv$create_objects THEN
                IF cycle_array_entry.site_archive_option <> pfc$null_site_archive_option THEN
                  pfp$validate_site_options (new_file_name_path [pfc$family_name_index],
                        cycle_array_entry.site_archive_option, pfc$null_site_backup_option,
                        pfc$null_site_release_option, status);
                  IF NOT status.normal THEN
                    pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
                    osp$set_status_abnormal (puc$pf_utility_id, pue$site_option_ignored,
                          fs_path (1, fs_path_size), status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          new_file_name_cycle_selector.cycle_number, radix, NOT include_radix, status);
                    osp$append_status_parameter (osc$status_parameter_delimiter, 'SITE_ARCHIVE_OPTION',
                          status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          cycle_array_entry.site_archive_option, radix, NOT include_radix, status);
                    pup$write_os_status (status, local_status);
                    cycle_array_entry.site_archive_option := pfc$null_site_archive_option;
                  IFEND;
                IFEND;
                IF cycle_array_entry.site_backup_option <> pfc$null_site_backup_option THEN
                  pfp$validate_site_options (new_file_name_path [pfc$family_name_index],
                        pfc$null_site_archive_option, cycle_array_entry.site_backup_option,
                        pfc$null_site_release_option, status);
                  IF NOT status.normal THEN
                    pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
                    osp$set_status_abnormal (puc$pf_utility_id, pue$site_option_ignored,
                          fs_path (1, fs_path_size), status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          new_file_name_cycle_selector.cycle_number, radix, NOT include_radix, status);
                    osp$append_status_parameter (osc$status_parameter_delimiter, 'SITE_BACKUP_OPTION',
                          status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          cycle_array_entry.site_backup_option, radix, NOT include_radix, status);
                    pup$write_os_status (status, local_status);
                    cycle_array_entry.site_backup_option := pfc$null_site_backup_option;
                  IFEND;
                IFEND;
                IF cycle_array_entry.site_release_option <> pfc$null_site_release_option THEN
                  pfp$validate_site_options (new_file_name_path [pfc$family_name_index],
                        pfc$null_site_archive_option, pfc$null_site_backup_option,
                        cycle_array_entry.site_release_option, status);
                  IF NOT status.normal THEN
                    pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
                    osp$set_status_abnormal (puc$pf_utility_id, pue$site_option_ignored,
                          fs_path (1, fs_path_size), status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          new_file_name_cycle_selector.cycle_number, radix, NOT include_radix, status);
                    osp$append_status_parameter (osc$status_parameter_delimiter, 'SITE_RELEASE_OPTION',
                          status);
                    osp$append_status_integer (osc$status_parameter_delimiter,
                          cycle_array_entry.site_release_option, radix, NOT include_radix, status);
                    pup$write_os_status (status, local_status);
                    cycle_array_entry.site_release_option := pfc$null_site_release_option;
                  IFEND;
                IFEND;
                pfp$put_cycle_info (new_file_name_path, new_file_name_cycle_selector, password_selector,
                      cycle_array_entry, status);
                cycle_defined := status.normal;
                IF NOT status.normal AND ((status.condition = pfe$duplicate_cycle) OR
                      (status.condition = pfe$duplicate_offline_cycle)) THEN
                  status.normal := TRUE;
                IFEND;
              IFEND;
              IF status.normal THEN
                pup$restore_cycle_content (new_file_name_path, new_file_name_cycle_selector,
                      password_selector, record_header, label_exists, p_label, p_fmd, restore_selections,
                      mandated_modification_time, backup_file_id, file_position, cycle_length, status);
              IFEND;
 {Update the cycle statistics to those on the backup in case of replaced cycles
              IF status.normal AND (NOT puv$update_cycle_statistics) AND puv$replace_cycle_data THEN
                IF password_selector.password_specified = pfc$specific_password_option THEN
                  password := password_selector.password;
                ELSE
                  password := osc$null_name;
                IFEND;
                local_access_date_time.value_specified := TRUE;
                local_access_date_time.date_time :=  cycle_array_entry.cycle_statistics.access_date_time;
                local_creation_date_time.value_specified := TRUE;
                local_creation_date_time.date_time :=  cycle_array_entry.cycle_statistics.creation_date_time;
                local_mod_date_time.value_specified := TRUE;
                local_mod_date_time.date_time := cycle_array_entry.cycle_statistics.modification_date_time;
                PUSH p_path_string;
                PUSH update_cycle_stats_status_p;
                pfp$convert_pf_cy_path_to_strng (new_file_name_path,
                      new_file_name_cycle_selector.cycle_number, p_path_string^);
                update_replaced_cycle_stats (p_path_string^.value (1, p_path_string^.size),
                      password, ^local_access_date_time, ^local_creation_date_time,
                      ^local_mod_date_time, update_cycle_stats_status_p^);
              IFEND;
              IF status.normal AND (cycle_array_entry.device_class = rmc$magnetic_tape_device)
                    AND (p_fmd <> NIL) THEN
                pfp$replace_rem_media_fmd (new_file_name_path, new_file_name_cycle_selector,
                      password_selector, puv$replace_cycle_data, p_fmd, status);
                IF NOT status.normal THEN
                  IF (status.condition = pfe$duplicate_cycle) AND (NOT puv$replace_cycle_data) THEN
                    status.normal := TRUE;
                  ELSE
                    pup$display_line (' REMOVABLE MEDIA ATTRIBUTES PROBABLY LOST - UNUSABLE FILE ',
                          local_status);
                    pup$write_os_status (status, local_status);
                  IFEND;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
          IF p_label <> NIL THEN
            FREE p_label;
          IFEND;
          IF p_fmd <> NIL THEN
            FREE p_fmd;
          IFEND;
        ELSE
          osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, ' unexpected file position',
                status);
        IFEND;
      IFEND;
    IFEND;
    IF status.normal THEN
      IF cycle_included THEN
        pup$write_cycle_display (new_file_entry, cycle_array_entry, cycle_length,
              puv$unknown_global_file_name, {recorded vsns} NIL, p_cycle_array_extended_record,
              p_cycle_directory_array, status);
        IF ((NOT puv$require_modification_match) OR puv$replace_cycle_data) AND
              (cycle_array_entry.cycle_statistics.modification_date_time <>
              mandated_modification_time.existing_modification_time) THEN
          IF puv$replace_cycle_data THEN
            display_date_time ('  -- Restore replaced data, modification date/time of previous data: ',
                  mandated_modification_time.existing_modification_time);
          ELSE
            display_date_time ('  -- Restore replaced modification, Previous modification time: ',
                  mandated_modification_time.existing_modification_time);
          IFEND;
        IFEND;
        IF (update_cycle_stats_status_p <> NIL) AND (not update_cycle_stats_status_p^.normal) THEN
          pup$display_line (' -- Unable to update cycle date_time attributes due to the following error:',
                local_status);
          pup$write_os_status (update_cycle_stats_status_p^, local_status);
        IFEND;
      IFEND;
    ELSE
      IF (NOT puv$create_objects) AND ((status.condition = pfe$unknown_permanent_file) OR
            (status.condition = pfe$unknown_cycle) OR (status.condition = pfe$unknown_last_subcatalog) OR
            (status.condition = pfe$unknown_nth_subcatalog)) THEN
        status.normal := TRUE;
      ELSE
        pup$write_status_to_listing (new_file_entry, status, local_status);
      IFEND;
    IFEND;
    IF cycle_defined AND NOT status.normal THEN
      pup$display_line (' cycle_defined and NOT status.normal, delete_file required', local_status);
    IFEND;
  PROCEND pup$restore_cycle_item;

?? TITLE := '    [XDCL] pup$restore_file_command ', EJECT ??

  PROCEDURE [XDCL] pup$restore_file_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      backup_file: amt$local_file_name,
      backup_file_id: put$file_identifier,
      cycle_entry: put$entry,
      cycle_selector: pft$cycle_selector,
      cycle_specified: boolean,
      dummy_cycle_selector: pft$cycle_selector,
      entry_type: put$entry_type,
      file_entry: put$entry,
      file_path_container: clt$path_container,
      local_status: ost$status,
      new_cycle_selector: pft$cycle_selector,
      new_cycle_specified: boolean,
      new_file_path_container: clt$path_container,
      p_catalog_header: ^put$catalog_header,
      p_file_path: ^pft$path,
      p_new_catalog_header: ^put$catalog_header,
      p_new_file_path: ^pft$path,
      p_selected_cycles: ^array [1 .. *] of put$selected_cycle_info,
      password: pft$password,
      password_specified: boolean,
      path_1_above_path_2: boolean,
      paths_equal: boolean;

    crack_restore_file (parameter_list, file_path_container, p_file_path, cycle_specified, cycle_selector,
          password, new_file_path_container, p_new_file_path, new_cycle_specified, new_cycle_selector,
          backup_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH p_selected_cycles: [1 .. 1];

    IF cycle_specified THEN
      p_selected_cycles ^[1].selected_cycle.cycle_specified := TRUE;
      p_selected_cycles ^[1].selected_cycle.cycle_selector := cycle_selector;
    ELSE
      p_selected_cycles ^[1].selected_cycle.cycle_specified := FALSE;
    IFEND;

    IF new_cycle_specified THEN
      p_selected_cycles ^[1].new_selected_cycle.cycle_specified := TRUE;
      p_selected_cycles ^[1].new_selected_cycle.cycle_selector := new_cycle_selector;
      IF NOT cycle_specified THEN
        cycle_specified := TRUE;
        cycle_selector.cycle_option := pfc$highest_cycle;
        p_selected_cycles ^[1].selected_cycle.cycle_specified := TRUE;
        p_selected_cycles ^[1].selected_cycle.cycle_selector := cycle_selector;
      IFEND;
    ELSE
      p_selected_cycles ^[1].new_selected_cycle.cycle_specified := FALSE;
    IFEND;

    pup$build_entry (p_file_path^ [UPPERBOUND (p_file_path^)], cycle_selector, puc$valid_pf_entry,
          file_entry);
    PUSH p_catalog_header: [1 .. UPPERBOUND (p_file_path^)];
    pup$build_catalog_header (osc$nosve_system_set, p_file_path, p_catalog_header^);
    PUSH p_new_catalog_header: [1 .. UPPERBOUND (p_new_file_path^)];
    pup$build_catalog_header (osc$nosve_system_set, p_new_file_path, p_new_catalog_header^);
    pup$validate_n_n_minus_1 (p_new_file_path^, puc$valid_pf_entry, dummy_cycle_selector, status);
    IF (cycle_specified OR new_cycle_specified) AND (NOT status.normal) AND
          (status.condition = pue$new_file_already_exists) THEN
      { Allow the cycle to be restored when the file already exists.
      status.normal := TRUE;
      password_specified := TRUE;
    ELSE
      password_specified := FALSE;
      password := osc$null_name;
    IFEND;
    IF status.normal THEN
      pup$open_backup_file (backup_file, puc$restore_permanent_files, amc$open_at_boi, backup_file_id,
            status);
      IF status.normal THEN
        IF cycle_specified THEN
          pup$build_entry (p_file_path^ [UPPERBOUND (p_file_path^)], cycle_selector,
                puc$valid_cycle_entry, cycle_entry);
          IF new_cycle_specified THEN
            pup$initialize_restore_listing ('RESTORE FILE CYCLE:', p_catalog_header^, cycle_entry,
                  p_new_file_path^, new_cycle_selector, status);
          ELSE
            pup$initialize_restore_listing ('RESTORE FILE CYCLE:', p_catalog_header^, cycle_entry,
                  p_new_file_path^, cycle_selector, status);
          IFEND;
        ELSE
          IF new_cycle_specified THEN
            pup$build_entry (p_file_path^ [UPPERBOUND (p_file_path^)], cycle_selector,
                  puc$valid_cycle_entry, cycle_entry);
            pup$initialize_restore_listing (' RESTORE FILE CYCLE: ', p_catalog_header^, cycle_entry,
                  p_new_file_path^, new_cycle_selector, status);
          ELSE
            pup$initialize_restore_listing (' RESTORE FILE: ', p_catalog_header^, file_entry,
                  p_new_file_path^, cycle_selector, status);
          IFEND;
        IFEND;
        IF status.normal THEN
          pup$set_restore_subcmd_defaults (NOT (avp$system_administrator() OR avp$family_administrator()));
          pup$restore_sub_levels (file_entry, p_catalog_header^, password_specified, password,
                p_new_catalog_header^, {restore_n_levels} TRUE, p_selected_cycles, backup_file_id, status);
        IFEND;
        pup$close_backup_file (backup_file_id, local_status);
        IF status.normal THEN
          status := local_status;
        IFEND;
        pup$display_restore_totals;
        pup$get_summary_status (status);
      IFEND;
    IFEND;
    pup$write_os_status (status, local_status);

  PROCEND pup$restore_file_command;

?? TITLE := '    [XDCL] pup$restore_label ', EJECT ??

  PROCEDURE [XDCL] pup$restore_label (
    VAR record_header: put$backup_file_record_header;
    VAR label_exists: boolean;
    VAR p_label: { output } ^SEQ ( * );
    VAR backup_file_id: put$file_identifier;
    VAR file_position: put$file_position;
    VAR status: ost$status);

    VAR
      local_status: ost$status,
      transfer_count: amt$file_length;

{   input system label
    p_label := NIL;
    pup$get_next_record_header (backup_file_id, record_header, file_position, status);
    IF status.normal THEN
      IF file_position = puc$mid_partition THEN
        IF record_header.kind = puc$backup_system_label THEN
          label_exists := record_header.size > 0;
          IF label_exists THEN
            ALLOCATE p_label: [[REP record_header.size OF cell]];
            RESET p_label;
            pup$get_part (backup_file_id, ^p_label^, #SIZE (p_label^), file_position, transfer_count,
                  status);
          ELSE
            ALLOCATE p_label: [[REP 5 OF cell]];
          IFEND;
        ELSE
          osp$set_status_abnormal (puc$pf_utility_id, pue$unexpected_item_requested, ' label ', status);
        IFEND;
      ELSE
        osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, 'unexpected file position',
              status);
      IFEND;
    IFEND;
{
    IF status.normal THEN
      IF file_position = puc$mid_partition THEN
        pup$skip_hierarchy_list (backup_file_id, file_position, status);
      ELSE
        osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, ' unexpected file position',
              status);
      IFEND;
    IFEND;
{  input cycle data
    IF status.normal THEN
      IF file_position = puc$mid_partition THEN
        pup$get_next_record_header (backup_file_id, record_header, file_position, status);
        IF file_position = puc$partition_boundary THEN
          display (' puc$partition_boundary');
          status.normal := TRUE;
        ELSEIF NOT status.normal THEN
          pup$display_line (' FILE DATA OR ATTRIBUTES POSSIBLY LOST.', local_status);
        IFEND;
        display_status (status);
      ELSE
        osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, 'unexpected file position',
              status);
      IFEND;
    IFEND;
  PROCEND pup$restore_label;

?? TITLE := '    [XDCL] pup$skip_hierarchy_list ', EJECT ??

  PROCEDURE [XDCL] pup$skip_hierarchy_list
    (VAR backup_file_id: put$file_identifier;
     VAR file_position: put$file_position;
     VAR status: ost$status);

    VAR
      p_hierarchy_list: ^put$hierarchy_list,
      record_header: put$backup_file_record_header;

    pup$get_next_record_header (backup_file_id, record_header, file_position, status);
    IF status.normal THEN
      IF file_position = puc$mid_partition THEN
        IF (record_header.kind = puc$backup_hierarchy_list) AND (record_header.size >= 1) THEN
          PUSH p_hierarchy_list: [1 .. record_header.size];
          pup$get_next_hierarchy_list (backup_file_id, p_hierarchy_list^, file_position, status);
        ELSE
          osp$set_status_abnormal (puc$pf_utility_id, pue$unexpected_item_requested, ' hierarchy list',
                status);
        IFEND;
      ELSE
        osp$set_status_abnormal (puc$pf_utility_id, pue$unusable_restore_file, 'unexpected file position',
              status);
      IFEND;
    IFEND;
  PROCEND pup$skip_hierarchy_list;

?? TITLE := '    crack_restore_file ', EJECT ??

  PROCEDURE crack_restore_file
    (    parameter_list: clt$parameter_list;
     VAR file_path_container: clt$path_container;
     VAR p_file_path: ^pft$path;
     VAR cycle_specified: boolean;
     VAR cycle_selector: pft$cycle_selector;
     VAR password: pft$password;
     VAR new_file_path_container: clt$path_container;
     VAR p_new_file_path: ^pft$path;
     VAR new_cycle_specified: boolean;
     VAR new_cycle_selector: pft$cycle_selector;
     VAR backup_file: amt$local_file_name;
     VAR status: ost$status);

{ PROCEDURE (osm$resf) restore_file, resf (
{   file, f: file = $required
{   backup_file, bf: file = $required
{   password, pw: (SECURE) any of
{       key
{         none
{       keyend
{       name
{     anyend = none
{   new_file_name, nfn: file = $optional
{   status)

?? PUSH (LISTEXT := ON) ??

    VAR
      pdt: [STATIC, READ, cls$declaration_section] record
        header: clt$pdt_header,
        names: array [1 .. 9] of clt$pdt_parameter_name,
        parameters: array [1 .. 5] of clt$pdt_parameter,
        type1: record
          header: clt$type_specification_header,
        recend,
        type2: record
          header: clt$type_specification_header,
        recend,
        type3: record
          header: clt$type_specification_header,
          qualifier: clt$union_type_qualifier,
          type_size_1: clt$type_specification_size,
          element_type_spec_1: record
            header: clt$type_specification_header,
            qualifier: clt$keyword_type_qualifier,
            keyword_specs: array [1 .. 1] of clt$keyword_specification,
          recend,
          type_size_2: clt$type_specification_size,
          element_type_spec_2: record
            header: clt$type_specification_header,
            qualifier: clt$name_type_qualifier,
          recend,
          default_value: string (4),
        recend,
        type4: record
          header: clt$type_specification_header,
        recend,
        type5: record
          header: clt$type_specification_header,
        recend,
      recend := [[1, [87, 10, 20, 12, 57, 54, 434], clc$command, 9, 5, 2, 0, 0, 0, 5, 'OSM$RESF'],
            [['BACKUP_FILE                    ', clc$nominal_entry, 2],
            ['BF                             ', clc$abbreviation_entry, 2],
            ['F                              ', clc$abbreviation_entry, 1],
            ['FILE                           ', clc$nominal_entry, 1],
            ['NEW_FILE_NAME                  ', clc$nominal_entry, 4],
            ['NFN                            ', clc$abbreviation_entry, 4],
            ['PASSWORD                       ', clc$nominal_entry, 3],
            ['PW                             ', clc$abbreviation_entry, 3],
            ['STATUS                         ', clc$nominal_entry, 5]], [
{ PARAMETER 1
      [4, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 3, clc$required_parameter, 0, 0],
{ PARAMETER 2
      [1, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 3, clc$required_parameter, 0, 0],
{ PARAMETER 3
      [7, clc$normal_usage_entry, clc$secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 69, clc$optional_default_parameter, 0, 4],
{ PARAMETER 4
      [5, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 3, clc$optional_parameter, 0, 0],
{ PARAMETER 5
      [9, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods [clc$specify_by_name],
            clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
            clc$optional_parameter, 0, 0]],
{ PARAMETER 1
      [[1, 0, clc$file_type]],
{ PARAMETER 2
      [[1, 0, clc$file_type]],
{ PARAMETER 3
      [[1, 0, clc$union_type], [[clc$keyword_type, clc$name_type], FALSE, 2], 44,
            [[1, 0, clc$keyword_type], [1], [['NONE                           ', clc$nominal_entry,
            clc$normal_usage_entry, 1]]], 5, [[1, 0, clc$name_type], [1, osc$max_name_size]], 'none'],
{ PARAMETER 4
      [[1, 0, clc$file_type]],
{ PARAMETER 5
      [[1, 0, clc$status_type]]];

?? POP ??

    CONST
      p$file = 1,
      p$backup_file = 2,
      p$password = 3,
      p$new_file_name = 4,
      p$status = 5;

    VAR
      pvt: array [1 .. 5] of clt$parameter_value;

    VAR
      evaluated_file_reference: fst$evaluated_file_reference;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pup$crack_pf_file_reference (pvt [p$file].value^.file_value^,
          $put$cycle_reference_selections [puc$cycle_omitted, puc$lowest_cycle, puc$highest_cycle,
          puc$specific_cycle], 'FILE', file_path_container, p_file_path, cycle_specified, cycle_selector,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pup$crack_backup_file (pvt [p$backup_file].value^.file_value^, backup_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF pvt [p$password].value^.kind = clc$name THEN
      password := pvt [p$password].value^.name_value;
    ELSE {keyword = NONE}
      password := osc$null_name;
    IFEND;

    IF pvt [p$new_file_name].specified THEN
      pup$crack_pf_file_reference (pvt [p$new_file_name].value^.file_value^,
            $put$cycle_reference_selections [puc$cycle_omitted, puc$specific_cycle, puc$next_highest_cycle],
            'NEW_FILE_NAME', new_file_path_container, p_new_file_path, new_cycle_specified,
            new_cycle_selector, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF new_cycle_specified THEN
        clp$evaluate_file_reference (pvt [p$new_file_name].value^.file_value^,
              $clt$file_ref_parsing_options [], {resolve_cycle_number} TRUE, evaluated_file_reference,
              status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        new_cycle_selector.cycle_option := pfc$specific_cycle;
        new_cycle_selector.cycle_number := evaluated_file_reference.cycle_reference.cycle_number;
      IFEND;
    ELSE
      new_cycle_specified := FALSE;
      p_new_file_path := p_file_path;
    IFEND;

  PROCEND crack_restore_file;

?? TITLE := '    define_cycle_contents', EJECT ??

  PROCEDURE define_cycle_contents
    (    new_file_name_path: pft$path;
         new_file_name_cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         label_exists: boolean;
         label: SEQ ( * );
         p_fmd: ^SEQ ( * );
         restore_selections: put$restore_data_selections;
         cycle_length: amt$file_length;
     VAR mandated_modification_time: pft$mandated_modification_time;
     VAR backup_file_id: put$file_identifier;
     VAR file_position: { input, output } put$file_position;
     VAR status: ost$status);

{ This routine restores a cycle's label and contents.

  PROCEDURE restore_abort_handler
    (    condition: pmt$condition;
         condition_information: ^pmt$condition_information;
         save_area: ^ost$stack_frame_save_area;
     VAR handler_status: ost$status);

    VAR
      exception_information: ^ost$condition_information,
      condition_status: ost$status,
      construction_status: ost$status,
      display_status: ost$status;

    CASE condition.selector OF
    = pmc$system_conditions, mmc$segment_access_condition =
      {
      { Display the reason for the condition.
      {
      pup$display_line (' Condition occurred in restoring cycle.', display_status);
      osp$set_status_from_condition (puc$pf_utility_id, condition, save_area, condition_status,
            construction_status);
      IF construction_status.normal THEN
        pup$write_os_status (condition_status, display_status);
      ELSE
        pup$write_os_status (construction_status, display_status);
      IFEND;
      osp$set_status_abnormal (puc$pf_utility_id, pue$restore_condition, '', status);
      current_pf_lfn_usable := FALSE;
      EXIT define_cycle_contents;
    = pmc$user_defined_condition =
      {
      { Process file exception conditions that occur on the call to pfp$define_data or
      { during segment access.  The raised_conditions set is initialized so no condition is
      { raised by osp$enforce_exception_policies should the policy be to wait; this would cause
      { a death spiral of recursion.  If the policy is to wait, we simply exit this handler to
      { retry whatever we were doing.  Otherwise, we exit the restore with abnormal status.
      {

      IF (condition.user_condition_name = osc$volume_unavailable_cond) OR (condition.user_condition_name =
           osc$space_unavailable_condition) THEN

        exception_information := condition_information;
        IF exception_information <> NIL THEN
          context^.condition_status := exception_information^.exception_status;
        ELSEIF condition.user_condition_name = osc$space_unavailable_condition THEN
          osp$set_status_condition (ame$space_unavailable, context^.condition_status);
        ELSEIF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$set_status_condition (pfe$volume_unavailable, context^.condition_status);
        IFEND;

        osp$enforce_exception_policies (context^);
        #SPOIL (context^);

        IF (NOT osp$file_access_condition (context^.condition_status)) OR (NOT context^.wait) THEN
          {
          { Display the reason for the condition.
          {
          pup$display_line (' Condition occurred in restoring cycle.', display_status);
          pup$write_os_status (context^.condition_status, display_status);
          osp$set_status_abnormal (puc$pf_utility_id, pue$restore_condition, '', status);

          current_pf_lfn_usable := FALSE;
          EXIT define_cycle_contents;
        IFEND;
      IFEND;
    ELSE
      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
    CASEND;
  PROCEND restore_abort_handler;

?? EJECT ??

    VAR
      allocation_size: rmt$allocation_size,
      caller_id: ost$caller_identifier,
      context: ^ost$ecp_exception_context,
      current_pf_lfn_usable: [STATIC] boolean := FALSE,
      data_residence: pft$data_residence,
      externalized_info: ost$condition_information,
      fmd_header_info: pft$fmd_header,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      ignore_status: ost$status,
      initial_volume: rmt$recorded_vsn,
      local_label_exists: boolean,
      local_status: ost$status,
      mass_storage_class: rmt$mass_storage_class,
      mass_storage_class_string: string (1),
      mass_storage_request_info: fmt$mass_storage_request_info,
      new_pf_lfn: [STATIC] amt$local_file_name,
      p_release_data_info: ^pft$release_data_info,
      password: pft$password,
      pu_status: ost$status,
      set_name: stt$set_name,
      transfer_count: amt$file_length,
      transfer_size: fst$transfer_size,
      validate_mass_storage_info: boolean,
      volume_overflow_allowed: boolean;

    #CALLER_ID (caller_id);

    PUSH context;
    context^ := osv$initial_exception_context;
    context^.file.selector := osc$ecp_pf_path;
    context^.file.pf_path := ^new_file_name_path;
    context^.file.cycle_selector := new_file_name_cycle_selector;
    context^.raised_conditions := -$fst$file_access_conditions [];
    IF password_selector.password_specified = pfc$specific_password_option THEN
      context^.password := password_selector.password;
    IFEND;
    #SPOIL (context^);

    osp$establish_condition_handler (^restore_abort_handler, { block_exit = } FALSE);

    IF NOT current_pf_lfn_usable THEN
      pmp$get_unique_name (new_pf_lfn, ignore_status);
    IFEND;

    mass_storage_request_info := puv$mass_storage_info;
    validate_mass_storage_info := FALSE;

    IF p_fmd <> NIL THEN
      dmp$get_stored_fmd_header_info (p_fmd, fmd_header_info, status);
      IF status.normal THEN

        allocation_size := puv$mass_storage_info.allocation_size;
        IF puv$mass_storage_info.allocation_size = rmc$unspecified_allocation_size THEN
          allocation_size := fmd_header_info.requested_allocation_size;
        IFEND;

        transfer_size := puv$mass_storage_info.transfer_size;
        IF puv$mass_storage_info.transfer_size = rmc$unspecified_transfer_size THEN
          transfer_size := fmd_header_info.requested_transfer_size;
        IFEND;

        mass_storage_class := puv$mass_storage_info.mass_storage_class;
        IF puv$mass_storage_info.mass_storage_class = rmc$unspecified_file_class THEN
          mass_storage_class := fmd_header_info.requested_class;
          IF (NOT avp$system_administrator ())
                AND (fmd_header_info.requested_class <> rmc$msc_user_permanent_files) THEN
            validate_mass_storage_info := TRUE;
          IFEND;
        IFEND;

        initial_volume := puv$mass_storage_info.initial_volume;
        IF puv$mass_storage_info.initial_volume = rmc$unspecified_vsn THEN
          IF fmd_header_info.requested_volume.recorded_vsn <> rmc$unspecified_vsn THEN
            pfp$get_family_set (new_file_name_path [pfc$family_name_index], set_name, status);
            IF status.normal AND (set_name= fmd_header_info.requested_volume.setname) THEN
              initial_volume := fmd_header_info.requested_volume.recorded_vsn;
              validate_mass_storage_info := TRUE;
            IFEND;
          IFEND;
        IFEND;

        volume_overflow_allowed := puv$mass_storage_info.volume_overflow_allowed;
        IF avp$system_administrator () AND puv$mass_storage_info.volume_overflow_allowed THEN
            volume_overflow_allowed := fmd_header_info.overflow_allowed;
        IFEND;
      IFEND;

      IF status.normal THEN
        display (' rmp$build_mass_storage_info');
        rmp$build_mass_storage_info (allocation_size, rmc$unspecified_file_size, initial_volume,
              mass_storage_class, puv$mass_storage_info.shared_queue, transfer_size,
              volume_overflow_allowed, caller_id.ring, ^mass_storage_request_info, status);
      IFEND;
    IFEND;

    IF NOT status.normal THEN
      pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
      osp$set_status_abnormal (puc$pf_utility_id, pue$original_ms_attr_ignored,
            fs_path (1, fs_path_size), pu_status);
      pup$write_os_status (pu_status, ignore_status);
      pup$write_os_status (status, ignore_status);
      mass_storage_request_info := puv$mass_storage_info;
      validate_mass_storage_info := FALSE;
    IFEND;

    IF validate_mass_storage_info THEN
      display (' rmp$validate_mass_storage_info');
      pfp$get_family_set (new_file_name_path [pfc$family_name_index], set_name, status);
      IF status.normal THEN
        rmp$validate_mass_storage_info (set_name, {object_permanent} TRUE,
              {object_type} pfc$file_object, ^mass_storage_request_info, status);
      IFEND;
      IF NOT status.normal THEN
        IF (status.condition = rme$unknown_volume)
              OR (status.condition = rme$vsn_not_part_of_set) THEN
          pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
          osp$set_status_abnormal (puc$pf_utility_id, pue$original_init_vol_ignored,
                fs_path (1, fs_path_size), pu_status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                mass_storage_request_info.initial_volume, pu_status);
          pup$write_os_status (pu_status, ignore_status);
          pup$write_os_status (status, ignore_status);
          mass_storage_request_info := puv$mass_storage_info;
        ELSEIF  status.condition = rme$file_class_not_valid THEN
          pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
          osp$set_status_abnormal (puc$pf_utility_id, pue$original_file_class_ignored,
                fs_path (1, fs_path_size), pu_status);
          mass_storage_class_string := mass_storage_request_info.mass_storage_class;
          osp$append_status_parameter (osc$status_parameter_delimiter, mass_storage_class_string, pu_status);
          pup$write_os_status (pu_status, ignore_status);
          pup$write_os_status (status, ignore_status);
          mass_storage_request_info := puv$mass_storage_info;
        ELSE
          pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
          osp$set_status_abnormal (puc$pf_utility_id, pue$original_ms_attr_ignored,
                fs_path (1, fs_path_size), pu_status);
          pup$write_os_status (pu_status, ignore_status);
          IF status.condition <> rme$job_not_valid THEN
            pup$write_os_status (status, ignore_status);
          IFEND;
          mass_storage_request_info := puv$mass_storage_info;
        IFEND;
      IFEND;
    IFEND;

    display (' pfp$define_data');
  /define_data/
    WHILE TRUE DO
      pfp$define_data (new_pf_lfn, new_file_name_path, new_file_name_cycle_selector,
            puv$update_cycle_statistics, password_selector, ^mass_storage_request_info,
            puv$p_included_volumes, puv$purge_cycle_options, puv$replace_cycle_data, restore_selections,
            {wait_on_volume} (mass_storage_request_info.initial_volume = rmc$unspecified_vsn),
            mandated_modification_time, data_residence, status);
      IF NOT status.normal THEN
        IF ((status.condition = pfe$volume_unavailable) OR (status.condition = pfe$volume_not_online)) THEN
          {
          { This case only occurs if the INITIAL_VOLUME option was chosen
          {
          pfp$convert_pft$path_to_fs_path (new_file_name_path, fs_path, fs_path_size);
          osp$set_status_abnormal (puc$pf_utility_id, pue$original_init_vol_ignored,
                fs_path (1, fs_path_size), pu_status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                mass_storage_request_info.initial_volume, pu_status);
          pup$write_os_status (pu_status, ignore_status);
          pup$write_os_status (status, ignore_status);
          mass_storage_request_info.initial_volume := rmc$unspecified_vsn;
          CYCLE /define_data/;
        ELSEIF osp$file_access_condition (status) THEN
          {
          { The most likely condition is space unavailable but we do not assume
          { it.  We merely choose it as a representative file access condition
          { to raise.  This invokes the restore_abort_handler to process this
          { condition from pfp$define_data in the same manner as would occur
          { during data access.  If a wait policy is in effect, the wait occurs
          { in the handler defined for this procedure.  After the wait, we
          { retry pfp$define_data.  If no wait is to occur, we exit
          { DEFINE_CYCLE_DATA from the restore_abort_handler and do not return
          { here.
          {

          externalized_info.when_handler_status := TRUE;
          externalized_info.exception_status := status;
          pmp$cause_task_condition (osc$space_unavailable_condition, ^externalized_info,
                {notify_scl} TRUE, {notify_debug} FALSE, {propagate_to_parent} TRUE,
                {call_default_handler} FALSE, ignore_status);
          CYCLE /define_data/;
        IFEND;
      IFEND;
      EXIT /define_data/;
    WHILEND;

    IF status.normal THEN
    { While retrieving a file, the label is not restored,
    { because the label in the catalog may be more current.
      local_label_exists := label_exists AND (puv$replace_cycle_data OR (data_residence <> pfc$offline_data));
      input_cycle_contents (cycle_length, data_residence, new_pf_lfn, local_label_exists, label,
            new_file_name_path, new_file_name_cycle_selector, password_selector, backup_file_id,
            file_position, transfer_count, status);
      IF status.normal THEN
        number_of_cycles_restored := number_of_cycles_restored + 1;
        total_cycle_data_restored := total_cycle_data_restored + transfer_count;
      ELSE
        display_status (status);
        IF status.condition <> ame$ring_validation_error THEN
          pup$display_line (' FILE DATA OR ATTRIBUTES POSSIBLY LOST.', ignore_status);
        IFEND;
      IFEND;

      display (' Amp$return user''s new permanent file.');
      amp$return (new_pf_lfn, local_status);
      IF puv$trace_selected THEN
        IF NOT local_status.normal THEN
          IF status.normal THEN
            status := local_status;
          IFEND;
          pup$write_os_status (local_status, ignore_status);
        IFEND;
      IFEND;
    IFEND;

    IF (data_residence = pfc$offline_data) AND (NOT puv$update_cycle_statistics) THEN
      IF status.normal AND (transfer_count = cycle_length) THEN
        pfp$change_res_to_releasable (new_file_name_path, new_file_name_cycle_selector, ignore_status);
      ELSE
        IF password_selector.password_specified = pfc$default_password_option THEN
          password := osc$null_name;
        ELSE
          password := password_selector.password;
        IFEND;

        PUSH p_release_data_info;
        p_release_data_info^.perform_changes := TRUE;
        p_release_data_info^.release_attached_cycle_data := TRUE;
        p_release_data_info^.update_last_release_date_time := FALSE;
        p_release_data_info^.valid_archive_entry_required := TRUE;

        REPEAT
          pfp$r3_release_data (new_file_name_path, new_file_name_cycle_selector, password,
                p_release_data_info, local_status);
          IF NOT local_status.normal THEN
            context^ := osv$initial_exception_context;
            context^.file.selector := osc$ecp_pf_path;
            context^.file.pf_path := ^new_file_name_path;
            context^.file.cycle_selector := new_file_name_cycle_selector;
            context^.password := password;
            context^.condition_status := local_status;
            osp$enforce_exception_policies (context^);
            local_status := context^.condition_status;
          IFEND;
        UNTIL local_status.normal OR (NOT osp$file_access_condition (local_status)) OR (NOT context^.wait);
      IFEND;
    IFEND;

    current_pf_lfn_usable := status.normal;
  PROCEND define_cycle_contents;

?? TITLE := '    define_released_cycle', EJECT ??

  PROCEDURE define_released_cycle
    (    new_file_name_path: pft$path;
         new_file_name_cycle_selector: pft$cycle_selector;
         password_selector: pft$password_selector;
         label_exists: boolean;
         p_label: ^SEQ ( * );
     VAR status: ost$status);

  PROCEDURE released_restore_abort_handler
    (    condition: pmt$condition;
         condition_information: ^pmt$condition_information;
         save_area: ^ost$stack_frame_save_area;
     VAR handler_status: ost$status);

    VAR
      condition_status: ost$status,
      construction_status: ost$status,
      display_status: ost$status;

    IF (condition.selector = pmc$system_conditions) OR (condition.selector = mmc$segment_access_condition)
          THEN
      { Display the reason for the condition.
      pup$display_line (' Condition occurred in restoring cycle.', display_status);
      osp$set_status_from_condition (puc$pf_utility_id, condition, save_area, condition_status,
            construction_status);
      IF construction_status.normal THEN
        pup$write_os_status (condition_status, display_status);
      ELSE
        pup$write_os_status (construction_status, display_status);
      IFEND;
      osp$set_status_abnormal (puc$pf_utility_id, pue$restore_condition, '', status);
      EXIT define_released_cycle;
    ELSE
      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
    IFEND;
  PROCEND released_restore_abort_handler;

?? EJECT ??

    VAR
      local_status: ost$status;

    osp$establish_condition_handler (^released_restore_abort_handler, { block_exit } FALSE);

    status.normal := TRUE;
    IF label_exists THEN
      input_cycle_label (new_file_name_path, new_file_name_cycle_selector, password_selector, p_label,
            status);
    IFEND;
    IF status.normal THEN
      number_of_cycles_restored := number_of_cycles_restored + 1;
    ELSEIF puv$create_objects THEN
      display_status (status);
      pup$display_line (' FILE ATTRIBUTES POSSIBLY LOST.', local_status);
    IFEND;
  PROCEND define_released_cycle;

?? TITLE := '    display_date_time ', EJECT ??

  PROCEDURE display_date_time
    (    descriptor: string ( * <= 90);
         date_time: ost$date_time);

    VAR
      status: ost$status,
      working_string: string (120),
      date_time_string: string (30);

    working_string := descriptor;
    pup$format_date_time (date_time, date_time_string);
    working_string ((STRLENGTH (descriptor) + 1), * ) := date_time_string;
    pup$display_line (working_string (1, (STRLENGTH (descriptor) + 30)), status);
  PROCEND display_date_time;

?? TITLE := '    input_cycle_contents ', EJECT ??

  PROCEDURE input_cycle_contents
    (   file_length: amt$file_length;
        data_residence: pft$data_residence;
        new_pf_lfn: amt$local_file_name;
        label_exists: boolean;
        label: SEQ ( * );
        path: pft$path;
        cycle_selector: pft$cycle_selector;
        password_selector: pft$password_selector;
    VAR backup_file_id: put$file_identifier;
    VAR file_position: put$file_position;
    VAR transfer_count: amt$file_length;
    VAR status: ost$status);

{  This routine reads in the cycle data and label into a defined file.

    VAR
      caller_id: ost$caller_identifier,
      cycle_segment: mmt$segment_pointer,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      password: pft$password,
      purge_cycle_options: pft$purge_cycle_options,
      restore_label_status: ost$status;

    status.normal := TRUE;
    transfer_count := 0;

    IF file_length > 0 THEN
      pup$open_file_for_seg_access (new_pf_lfn, cycle_segment, status);
      IF status.normal THEN
        restore_label_status.normal := TRUE;
        #CALLER_ID (caller_id);

      /store_label_and_data/
        BEGIN
          IF label_exists THEN

            { The restore label is done here since the restore label routine enforces that the
            { file must have an eoi of 0. IF the restore_label was done prior to the open, the
            { open would prevent restoring a file with rings lower than the running ring.
            {
            { NOTE:  the restore_label will prevent restoring files with r1 lower than
            { the user's minimum valid ring UNLESS one is the SYSTEM ADMINISTRATOR.

            display (' srp$store_system_label');
            srp$store_system_label (new_pf_lfn, label, restore_label_status);
            display_status (restore_label_status);
            IF NOT restore_label_status.normal THEN
              IF restore_label_status.condition = ame$ring_validation_error THEN
                status := restore_label_status;
                amp$return (new_pf_lfn, local_status);
                purge_cycle_options.enforce_password_validation := FALSE;
                purge_cycle_options.enforce_ring_validation := FALSE;
                purge_cycle_options.preserve_cycle_entry := FALSE;
                pfp$delete_cycle_data (path, cycle_selector, {password} osc$null_name,
                      purge_cycle_options, local_status);
                osp$set_status_abnormal (amc$access_method_id, ame$ring_validation_error,
                      '', status);
                pfp$convert_pft$path_to_fs_path (path, fs_path, fs_path_size);
                osp$append_status_file (osc$status_parameter_delimiter,
                      fs_path (1, fs_path_size), status);
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      'restore', status);
                EXIT /store_label_and_data/;
              ELSE
                pup$display_line (' FILE ATTRIBUTES PROBABLY LOST - RESTORING DATA', local_status);
                pup$write_os_status (restore_label_status, local_status);
              IFEND;
            IFEND;
          IFEND;
          display_integer (' get the user''s file data restored:', file_length);
          pup$advised_get_part (backup_file_id, cycle_segment.seq_pointer, file_length,
                file_position, transfer_count, status);
          display_integer (' pup$advised_get_part complete:', transfer_count);
          IF (data_residence = pfc$offline_data) AND (NOT puv$update_cycle_statistics) THEN
            mmp$set_segment_length (cycle_segment.seq_pointer, caller_id.ring, file_length, local_status);
            display_integer (' mmp$set_segment_length complete:', file_length);
          ELSE
            mmp$set_segment_length (cycle_segment.seq_pointer, caller_id.ring, transfer_count, local_status);
            display_integer (' mmp$set_segment_length complete:', transfer_count);
          IFEND;
          IF NOT local_status.normal THEN
            pup$write_os_status (local_status, local_status);
          IFEND;
        END /store_label_and_data/;

        mmp$close_segment (cycle_segment, caller_id.ring, local_status);
        IF NOT local_status.normal THEN
          pup$write_os_status (local_status, local_status);
        IFEND;
        IF status.normal THEN
          IF restore_label_status.normal THEN
            status := local_status;
          ELSE
            status := restore_label_status;
          IFEND;
        IFEND;
      IFEND;

    ELSE { No data in file
      IF label_exists THEN
        input_cycle_label (path, cycle_selector, password_selector, ^label, status);
      IFEND;
    IFEND;
  PROCEND input_cycle_contents;

?? TITLE := '    input_cycle_label ', EJECT ??

  PROCEDURE input_cycle_label
    (   path: pft$path;
        cycle_selector: pft$cycle_selector;
        password_selector: pft$password_selector;
        p_label: fmt$p_file_label;
    VAR status: ost$status);

    VAR
      local_status: ost$status;

    display (' pfp$save_released_file_label');
    pfp$save_released_file_label (path, cycle_selector, puv$update_cycle_statistics, password_selector,
          p_label, status);
    IF NOT status.normal AND puv$create_objects THEN
      pup$display_line (' FILE ATTRIBUTES PROBABLY LOST - EMPTY FILE ', local_status);
      pup$write_os_status (status, local_status);
    IFEND;
  PROCEND input_cycle_label;

?? TITLE := 'update_replaced_cycle_stats', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to update the cycle statistics of a
{   replaced cycle
{

  PROCEDURE update_replaced_cycle_stats
    (    file: fst$file_reference;
         password: pft$password;
         p_new_access_date_time: ^fst$date_time;
         p_new_creation_date_time: ^fst$date_time;
         p_new_modification_date_time: ^fst$date_time;
     VAR status: ost$status);

    VAR
      context: ^ost$ecp_exception_context;

    context := NIL;

    REPEAT
      pfp$r3_change_cycle_date_time (file, password, p_new_access_date_time, p_new_creation_date_time,
            p_new_modification_date_time, status);
      IF NOT status.normal THEN
        IF context = NIL THEN
          PUSH context;
          context^ := osv$initial_exception_context;
          context^.file.selector := osc$ecp_file_reference;
          context^.file.file_reference := ^file;
          context^.password := password;
        IFEND;
        context^.condition_status := status;
        osp$enforce_exception_policies (context^);
        status := context^.condition_status;
      IFEND;
    UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);

  PROCEND update_replaced_cycle_stats;

MODEND pum$restore_file;
