?? RIGHT := 110 ??
?? TITLE := 'NOS/VE Permanent Files : Catalog Maintenance' ??
MODULE pfm$catalog_maintenance_manager;

{ PURPOSE:
{   This module contains the procedures to perform pf recovery during a
{   continuation deadstart.

?? NEWTITLE := '  Global Declarations Referenced by this Module' ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc pfc$average_share_history
*copyc pfc$maximum_pf_length
*copyc osd$integer_limits
*copyc mme$condition_codes
*copyc pfe$error_condition_codes
*copyc pfe$internal_error_conditions
*copyc ste$error_condition_codes
*copyc fmt$mass_storage_request_info
*copyc fst$cycle_damage_symptoms
*copyc ost$prevalidate_free_result
*copyc pft$overhaul_choices
*copyc pft$p_archive
*copyc pft$p_complete_path
?? POP ??
*copyc dmp$allocate_file_space_r1
*copyc dmp$attach_file
*copyc dmp$build_sorted_dfl
*copyc dmp$destroy_permanent_file
*copyc dmp$dev_mgmt_table_update
*copyc dmp$device_file_list_update
*copyc dmp$get_reconciled_fmd
*copyc dmp$get_stored_fmd
*copyc dmp$get_stored_fmd_size
*copyc dmp$reconcile_fmd
*copyc dpp$get_next_line
*copyc dpp$put_next_line
*copyc dmv$ds_msg_update_interval
*copyc dmv$reconcile_locator
*copyc dpv$system_core_display
*copyc i#move
*copyc mmp$create_scratch_segment
*copyc mmp$delete_scratch_segment
*copyc mmp$get_segment_length
*copyc mmp$set_segment_length
*copyc mmp$write_modified_pages
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$prevalidate_free
*copyc osp$reset_heap
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$verify_heap
*copyc osv$lower_to_upper
*copyc osv$system_family_name
*copyc pfp$access_next_catalog
*copyc pfp$access_object
*copyc pfp$attach_catalog
*copyc pfp$attach_root_catalog
*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_object_list_pointer
*copyc pfp$build_permit_list_locator
*copyc pfp$build_permit_list_pointer
*copyc pfp$check_archive_entries
*copyc pfp$compute_checksum
*copyc pfp$convert_device_class_to_rm
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$create_catalog
*copyc pfp$cycle_attached_for_write
*copyc pfp$destroy_catalog
*copyc pfp$detach_all_catalogs
*copyc pfp$detach_permanent_file
*copyc pfp$display_memory_to_log
*copyc pfp$get_authority
*copyc pfp$get_family_set
*copyc pfp$get_restore_status
*copyc pfp$log_ascii
*copyc pfp$log_error
*copyc pfp$process_unexpected_status
*copyc pfp$record_dm_file_parameters
*copyc pfp$report_invalid_free
*copyc pfp$report_unexpected_status
*copyc pfp$return_catalog
*copyc pfp$set_restore_status
*copyc pfp$set_status_abnormal
*copyc pfp$sort_object_list
*copyc pfp$system_path
*copyc pfp$update_obj_list_descriptor
*copyc pfp$update_object_list_locator
*copyc pfp$update_stale_cycle_entry
*copyc pfp$validate_ownership
*copyc pfp$validate_set_owner
*copyc pfv$sort_catalog_object_list
*copyc pfv$space_character
*copyc pmp$continue_to_cause
*copyc pmp$convert_binary_unique_name
*copyc pmp$delay
*copyc pmp$date_time_compare
*copyc pmp$format_compact_time
*copyc pmp$get_compact_date_time
*copyc pmp$get_date_time_at_timestamp
*copyc stp$clear_root_recreated
*copyc stp$get_pf_root
*copyc stp$get_pf_root_size
*copyc stp$get_volumes_in_set
*copyc stp$store_pf_root
*copyc syp$invoke_system_debugger
*copyc syp$process_deadstart_status
*copyc syv$nosve_internal_operations
?? OLDTITLE ??
?? NEWTITLE := '  Global Declarations Declared by this Module', EJECT ??

  CONST
    include_radix = TRUE,
    radix = 10;

  TYPE
    pft$catalog_or_cycle = record
      case cycle_specified: boolean of
      = FALSE =
        ,
      = TRUE =
        cycle_number: fst$cycle_number,
      casend,
    recend,

    pft$string = record
      size: integer,
      value: string (osc$max_string_size + fsc$max_path_size),
    recend;

  VAR
    pfv$catalogs_missing_media: [XDCL] ost$non_negative_integers := 0,
    pfv$catalogs_moved: [XDCL] ost$non_negative_integers := 0,
    pfv$catalogs_not_in_set: [XDCL] ost$non_negative_integers := 0,
    pfv$clear_catalog_recreated: [XDCL] boolean := FALSE,
    pfv$cycles_missing_media: [XDCL] ost$non_negative_integers := 0,
    pfv$cycles_not_in_set: [XDCL] ost$non_negative_integers := 0,
    pfv$immovable_catalogs: [XDCL] ost$non_negative_integers := 0,
    pfv$overhaul_catalog_options: [XDCL] pft$set_overhaul_choices := $pft$set_overhaul_choices[],
    pfv$overhaul_errors: [XDCL] ost$non_negative_integers := 0,
    pfv$overhaul_set_options: [XDCL] pft$set_overhaul_choices := $pft$set_overhaul_choices[],
    pfv$purged_catalogs_deleted: [XDCL] ost$non_negative_integers := 0,
    pfv$recreated_catalogs_cleared: [XDCL] ost$non_negative_integers := 0,
    pfv$reinstalled_device_cycles: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_catalogs: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_cats_deleted: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_cycle_data_del: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_cycle_released: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_cycle_retained: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_cycles_deleted: [XDCL] ost$non_negative_integers := 0,
    pfv$unreconciled_files: [XDCL] ost$non_negative_integers := 0,
    pfv$unreorganized_catalogs: [XDCL] ost$non_negative_integers := 0;

  VAR
    ascii_logset: pmt$ascii_logset,
    catalog_moved: boolean := FALSE,
    critical_message: boolean := FALSE,
    message_origin: pmt$log_msg_origin := pmc$msg_origin_system,
    out_of_space: boolean := FALSE,
    previous_master_catalog: pft$name := osc$null_name,
    previous_timestamp: integer;

?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] pfp$r2_overhaul_catalog', EJECT ??

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

    CONST
      block_exit = TRUE,
      catalog_remote = TRUE,
      system_privilege = TRUE,
      validation_ring = 2;

    VAR
      authority: pft$authority,
      catalog_overhaul_option: pft$catalog_overhaul_options,
      catalog_segment_length: ost$segment_length,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      moved_or_destroyed_child: boolean,
      new_catalog_locator: pft$catalog_locator,
      old_catalog_accessed: boolean,
      old_catalog_locator: pft$catalog_locator,
      p_fs_path: ^fst$path,
      p_internal_path: ^pft$internal_path,
      p_physical_catalog_object: ^pft$physical_object,
      p_physical_fmd: ^pft$physical_fmd,
      parent_accessed: boolean,
      parent_catalog_locator: pft$catalog_locator,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      scratch_segment_pointer: amt$segment_pointer,
      set_overhaul_choices: pft$set_overhaul_choices,
      text: pft$string,
      variant_path: pft$variant_path;

?? NEWTITLE := 'CONDITION_HANDLER', EJECT ??

    PROCEDURE condition_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;

      IF (condition.selector = pmc$system_conditions) OR
            (condition.selector = mmc$segment_access_condition) THEN
        osp$set_status_from_condition (pfc$permanent_file_manager_id, condition, p_sfsa, status,
              local_status);
        IF local_status.normal THEN
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
        ELSE
          pfp$log_error (local_status, ascii_logset, message_origin, critical_message);
          status := local_status;
        IFEND;

        pfv$overhaul_errors := pfv$overhaul_errors + 1;
        osp$set_status_condition (pfe$recovery_summary, status);
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$overhaul_errors, radix,
              NOT include_radix, status);
        IF pfv$overhaul_errors = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'error', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'errors', status);
        IFEND;
        {
        { Return accessed catalogs.
        {
        IF old_catalog_accessed THEN
          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF parent_accessed THEN
          pfp$return_catalog (parent_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

        EXIT pfp$r2_overhaul_catalog;
      ELSE
        {
        { Ignore the condition.
        {
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;

    PROCEND condition_handler;
?? OLDTITLE ??
?? EJECT ??

    parent_accessed := FALSE;
    old_catalog_accessed := FALSE;
    ascii_logset := $pmt$ascii_logset [pmc$job_log];

    #SPOIL (parent_accessed, old_catalog_accessed);
    osp$establish_condition_handler (^condition_handler, NOT block_exit);

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

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

    IF status.normal THEN
      set_overhaul_choices := $pft$set_overhaul_choices [];
      FOR catalog_overhaul_option := LOWERVALUE (catalog_overhaul_option)
            TO UPPERVALUE (catalog_overhaul_option) DO
        IF catalog_overhaul_option IN catalog_overhaul_choices THEN
          set_overhaul_choices := set_overhaul_choices + $pft$set_overhaul_choices [catalog_overhaul_option];
        IFEND;
      FOREND;
      validate_overhaul_choices (set_overhaul_choices, authority.ownership, set_overhaul_choices, status);
    IFEND;

    IF status.normal THEN
      pfv$overhaul_catalog_options := set_overhaul_choices;
      pfp$log_ascii (' *  overhaul catalog options: ', ascii_logset, message_origin, critical_message,
             local_status);
      log_overhaul_options (set_overhaul_choices, local_status);
      PUSH p_internal_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$read_access, authority, $pft$object_selections [pfc$catalog_object],
            parent_charge_id, parent_catalog_locator, p_physical_catalog_object, p_internal_path^,
            permit_entry, status);
    IFEND;

    IF status.normal THEN
      #SPOIL (parent_catalog_locator);
      parent_accessed := TRUE;
      #SPOIL (parent_accessed);

      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        pfp$access_next_catalog (pfc$write_access, parent_catalog_locator, p_physical_catalog_object,
              NOT catalog_remote, old_catalog_locator, status);
      ELSE
        pfp$access_next_catalog (pfc$read_access, parent_catalog_locator, p_physical_catalog_object,
              NOT catalog_remote, old_catalog_locator, status);
      IFEND;

      IF status.normal THEN
        old_catalog_accessed := TRUE;
        #SPOIL (old_catalog_accessed);
        previous_timestamp := #free_running_clock (0);

        overhaul_physical_catalog (set_overhaul_choices, path, dmv$reconcile_locator, authority,
              old_catalog_locator, new_catalog_locator, moved_or_destroyed_child, status);
        scratch_segment_pointer.kind := amc$cell_pointer;
        scratch_segment_pointer.cell_pointer := new_catalog_locator.p_catalog_file;

        IF status.normal OR (status.condition = pfe$recovery_summary) THEN
          IF NOT status.normal THEN
            osp$append_status_integer (osc$status_parameter_delimiter, pfv$overhaul_errors, radix,
                  NOT include_radix, status);
            IF pfv$overhaul_errors = 1 THEN
              osp$append_status_parameter (osc$status_parameter_delimiter, 'error', status);
            ELSE
              osp$append_status_parameter (osc$status_parameter_delimiter, 'errors', status);
            IFEND;
            pfp$log_error (status, ascii_logset, message_origin, critical_message);
          IFEND;

          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          old_catalog_accessed := FALSE;
          #SPOIL (old_catalog_accessed);
        ELSE
          {
          { The catalog could not be successfully overhauled because of a
          { system error, because permanent storage was unavailable, or
          { because of a system or segment access condition. The old catalog
          { will continue to be used and the new catalog will be destroyed.
          {
          IF status.condition = pfe$pf_system_error THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path ( path, p_fs_path^, fs_path_size);
            STRINGREP (text.value, text.size, ' System error while overhauling catalog ',
                  p_fs_path^(1, fs_path_size));
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
                  local_status);
          IFEND;
          IF (pfc$reorganize_catalogs IN set_overhaul_choices) AND
            (scratch_segment_pointer.cell_pointer <> NIL) THEN
             mmp$delete_scratch_segment (scratch_segment_pointer, local_status);
             pfp$process_unexpected_status (local_status);
          IFEND;
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          #SPOIL (old_catalog_accessed);
          old_catalog_accessed := FALSE;
          #SPOIL (old_catalog_accessed);
          variant_path.complete_path := TRUE;
          variant_path.p_complete_path := ^path;
          pfp$set_status_abnormal (variant_path, pfe$overhaul_catalog_failed, status);
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
        IFEND;
      IFEND;

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

  PROCEND pfp$r2_overhaul_catalog;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] pfp$r2_overhaul_set', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_overhaul_set
    (    set_name: stt$set_name;
         set_overhaul_choices: pft$set_overhaul_choices;
     VAR status: ost$status);

    CONST
      block_exit = TRUE,
      fatal_status = TRUE,
      purge_catalog = TRUE,
      system_privilege = TRUE,
      validation_ring = 2;

    VAR
      authority: pft$authority,
      catalog_segment_length: ost$segment_length,
      found: boolean,
      fs_path_size: fst$path_size,
      getsl_wrimc_status: ost$status,
      local_status: ost$status,
      mass_storage_classes: dmt$class,
      moved_or_destroyed_child: boolean,
      new_catalog_locator: pft$catalog_locator,
      new_set_overhaul_choices: pft$set_overhaul_choices,
      old_catalog_locator: pft$catalog_locator,
      p_fs_path: ^fst$path,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_root_fmd: ^pft$fmd,
      path: array [1 .. pfc$set_path_index] of pft$name,
      resides_on_system_device: boolean,
      root_size: pft$root_size,
      scratch_segment_pointer: amt$segment_pointer,
      space_index: 1 .. osc$max_name_size + 1,
      text: pft$string;

?? NEWTITLE := 'CONDITION_HANDLER', EJECT ??

    PROCEDURE condition_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;

      IF (condition.selector = pmc$system_conditions) OR
            (condition.selector = mmc$segment_access_condition) THEN
        osp$set_status_from_condition (pfc$permanent_file_manager_id, condition, p_sfsa, status,
              local_status);
        IF local_status.normal THEN
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
        ELSE
          pfp$log_error (local_status, ascii_logset, message_origin, critical_message);
          status := local_status;
        IFEND;

        EXIT pfp$r2_overhaul_set;
      ELSE
        {
        { Ignore the condition.
        {
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;

    PROCEND condition_handler;
?? OLDTITLE ??
?? EJECT ??

    ascii_logset := - $pmt$ascii_logset [];

    path [pfc$set_path_index] := set_name;
    pfp$get_authority (path, NOT system_privilege, authority, status);

    IF status.normal THEN
      pfp$validate_set_owner (set_name, authority, status);
    IFEND;

    IF status.normal THEN
      validate_overhaul_choices (set_overhaul_choices, authority.ownership, new_set_overhaul_choices, status);
    IFEND;

    IF status.normal THEN
      pfv$overhaul_set_options := new_set_overhaul_choices;
      pfp$log_ascii (' *  overhaul set options: ', ascii_logset, message_origin, {critical_message} FALSE,
             local_status);
      log_overhaul_options (new_set_overhaul_choices, local_status);
      stp$get_pf_root_size (set_name, root_size, status);
      IF NOT status.normal THEN
        IF status.condition = ste$pf_root_not_stored THEN
          create_root_catalog (set_name, authority, status);
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      ELSE
        pfp$get_restore_status (pfv$clear_catalog_recreated);
        IF pfc$reconcile_fmds IN new_set_overhaul_choices THEN
          attach_reconciled_root_catalog (set_name, NOT purge_catalog, pfc$write_access, p_root_fmd,
                resides_on_system_device, mass_storage_classes, old_catalog_locator, status);
        ELSE
          pfp$attach_root_catalog (set_name, pfc$read_access, old_catalog_locator, status);
        IFEND;

        IF status.normal THEN
          IF pfc$reconcile_fmds IN new_set_overhaul_choices THEN
            message_origin := pmc$msg_origin_recovery;
            critical_message := TRUE;

            IF NOT (pfc$reorganize_catalogs IN new_set_overhaul_choices) THEN
              osp$establish_condition_handler (^condition_handler, NOT block_exit);
              osp$verify_heap (^old_catalog_locator.p_catalog_file^.catalog_heap, status.normal);
              osp$disestablish_cond_handler;
            IFEND;
          IFEND;

          IF status.normal THEN
            previous_timestamp := #free_running_clock (0);
            IF pfv$clear_catalog_recreated THEN
              stp$clear_root_recreated (set_name, local_status);
              pfp$process_unexpected_status (local_status);
            IFEND;
            overhaul_physical_catalog (new_set_overhaul_choices, path, dmv$reconcile_locator,
                  authority, old_catalog_locator, new_catalog_locator, moved_or_destroyed_child, status);
          ELSE
            #SCAN (pfv$space_character, set_name, space_index, found);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$bad_catalog_heap,
                  set_name (1, space_index - 1), status);
            pfp$log_ascii ('* * * * * * * * * * * * * * * * * * * * *', ascii_logset, message_origin,
                  {critical_message} FALSE, local_status);
            pfp$log_ascii ('* The heap for the set is damaged.', ascii_logset, message_origin,
                  critical_message, local_status);
            pfp$log_ascii ('* REDEADSTART using System Core Command:', ascii_logset, message_origin,
                  critical_message, local_status);
            pfp$log_ascii ('* SETSA REORGANIZE_PERMANENT_FILES 1', ascii_logset, message_origin,
                  critical_message, local_status);
            pfp$log_ascii ('* * * * * * * * * * * * * * * * * * * * *', ascii_logset, message_origin,
                  {critical_message} FALSE, local_status);
          IFEND;

          IF status.normal OR (status.condition = pfe$recovery_summary) THEN
            pfp$set_restore_status ({restore_missing_catalogs_done} FALSE, local_status);
            pfp$process_unexpected_status (local_status);

            IF pfc$reconcile_fmds IN new_set_overhaul_choices THEN
              IF pfc$reorganize_catalogs IN new_set_overhaul_choices THEN
                mmp$get_segment_length (new_catalog_locator.p_catalog_file, validation_ring,
                      catalog_segment_length, getsl_wrimc_status);
                IF getsl_wrimc_status.normal THEN
                  {
                  { The root/set catalog can never grow as a result of
                  { reconciliation, because it contains no files.  Thus
                  { preallocation is unnecessary.
                  {
                  { Rewrite the "old" catalog with the reorganized, scratch
                  { catalog.
                  {
                  mmp$set_segment_length (old_catalog_locator.p_catalog_file, validation_ring,
                         {segment_length} 0, local_status);
                  IF NOT local_status.normal THEN
                    pfp$process_unexpected_status (local_status);
                  IFEND;
                  i#move (new_catalog_locator.p_catalog_file, old_catalog_locator.p_catalog_file,
                        catalog_segment_length);
                IFEND;
              ELSE
                mmp$get_segment_length (old_catalog_locator.p_catalog_file, validation_ring,
                      catalog_segment_length, getsl_wrimc_status);
              IFEND;

              IF getsl_wrimc_status.normal THEN
                {
                { Force the "new" catalog to be written to disk now.
                {
                write_modified_catalog (set_overhaul_choices, path, resides_on_system_device,
                      mass_storage_classes, catalog_segment_length, dmv$reconcile_locator,
                      p_root_fmd, authority, {p_parent_catalog_file} NIL, {p_catalog_object} NIL,
                      p_new_physical_fmd, old_catalog_locator, catalog_moved, getsl_wrimc_status);
                IF NOT getsl_wrimc_status.normal THEN
                  pfp$log_ascii (('Unable to flush the root catalog to disk.  An initialization deadstart' CAT
                        ' followed by a full reload of the permanent file base must be performed.'),
                        ascii_logset, message_origin, critical_message, local_status);
                IFEND;
              ELSEIF moved_or_destroyed_child THEN
                pfp$log_error (getsl_wrimc_status, ascii_logset, message_origin, {critical_message} FALSE);
                pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset, message_origin,
                      {critical_message} FALSE, local_status);
                pfp$log_ascii (('Unable to flush the root catalog to disk.  An initialization deadstart' CAT
                      ' followed by a full reload of the permanent file base must be performed.'),
                      ascii_logset, message_origin, critical_message, local_status);
              ELSEIF pfc$reorganize_catalogs IN new_set_overhaul_choices THEN
                pfp$log_error (local_status, ascii_logset, message_origin, {critical_message} FALSE);
                pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset, message_origin,
                      {critical_message} FALSE, local_status);
                pfp$log_ascii ('Unable to reorganize the root catalog.', ascii_logset, message_origin,
                      {critical_message} FALSE, local_status);
                pfv$unreorganized_catalogs := pfv$unreorganized_catalogs + 1;
                getsl_wrimc_status.normal := TRUE;
              ELSE
                pfp$log_error (local_status, ascii_logset, message_origin, {critical_message} FALSE);
                pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset, message_origin,
                      {critical_message} FALSE, local_status);
                pfp$log_ascii ('Reverting to unmodified root catalog.', ascii_logset, message_origin,
                      {critical_message} FALSE, local_status);
                getsl_wrimc_status.normal := TRUE;
              IFEND;

              IF pfc$reorganize_catalogs IN new_set_overhaul_choices THEN
                scratch_segment_pointer.kind := amc$cell_pointer;
                scratch_segment_pointer.cell_pointer := new_catalog_locator.p_catalog_file;
                mmp$delete_scratch_segment (scratch_segment_pointer, local_status);
                pfp$process_unexpected_status (local_status);
              IFEND;

              IF pfc$delete_unreconciled_objects IN new_set_overhaul_choices THEN
                dmp$device_file_list_update (set_name, local_status);
                pfp$process_unexpected_status (local_status);
              IFEND;
              {
              { Rebuild the sorted dfl so it contains the correct entries for
              { the catalogs that have moved as a result of reorganization.
              {
              IF catalog_moved THEN
                dmp$build_sorted_dfl (set_name, dmv$reconcile_locator, local_status);
                pfp$process_unexpected_status (local_status);
              IFEND;

              log_recovery_summary_status (status);
              IF NOT getsl_wrimc_status.normal THEN
                status := getsl_wrimc_status;
              IFEND;
            ELSE
              log_recovery_summary_status (status);
            IFEND;

          ELSEIF status.condition = pfe$bad_root_catalog_header THEN
            {
            { Force the deadstart to hang so the root catalog will still be in
            { memory, in case a dump is taken.
            {
            syp$process_deadstart_status (('The root catalog is damaged.  An initialization deadstart' CAT
                  ' followed by a full reload of the permanent file base must be performed.'), fatal_status,
                  status);
          IFEND;

          IF status.condition = pfe$pf_system_error THEN
            STRINGREP (text.value, text.size, ' System error while overhauling set ', set_name);
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin,
                  {critical_message} FALSE, local_status);
          IFEND;
          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          pfp$detach_all_catalogs;

          IF pfc$reconcile_fmds IN new_set_overhaul_choices THEN
            message_origin := pmc$msg_origin_system;
            critical_message := FALSE;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND pfp$r2_overhaul_set;
?? OLDTITLE ??
?? NEWTITLE := '  attach_reconciled_root_catalog', EJECT ??

  PROCEDURE attach_reconciled_root_catalog
    (    set_name: stt$set_name;
         purge_catalog: boolean;
         access_kind: pft$access_kind;
     VAR p_fmd: ^pft$fmd;
     VAR resides_on_system_device: boolean;
     VAR mass_storage_classes: dmt$class;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    CONST
      best_root_size_estimate = 0ff(16),
      catalog_remote = TRUE;

    VAR
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_root_container: ^pft$root,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      root_size: pft$root_size;

    root_size := best_root_size_estimate;

    REPEAT
      PUSH p_root_container: [[REP root_size OF cell]];
      RESET p_root_container;
      stp$get_pf_root (set_name, root_size, p_root_container^, status);
    UNTIL status.normal OR (status.condition <> ste$incorrect_root_size);

    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$reconcile_fmd (dmv$reconcile_locator, p_internal_catalog_name^, p_fmd^, purge_catalog,
            mass_storage_classes, p_stored_fmd_size^, resides_on_system_device, status);
      IF status.normal THEN
        pfp$attach_catalog (p_fmd, set_name, p_internal_catalog_name^, p_internal_catalog_name^,
              access_kind, NOT catalog_remote, catalog_locator, status);
      IFEND;
    ELSE
      pfp$report_unexpected_status (status);
    IFEND;
  PROCEND attach_reconciled_root_catalog;

?? TITLE := '  create_root_catalog', EJECT ??

  PROCEDURE create_root_catalog
    (    set_name: stt$set_name;
         authority: pft$authority;
     VAR status: ost$status);

    VAR
      catalog_locator: pft$catalog_locator,
      local_status: ost$status,
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_root: ^pft$root,
      p_stored_fmd: ^dmt$stored_fmd,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      set_path: array [1 .. 1] of pft$name,
      stored_fmd_size: dmt$stored_fmd_size;

    set_path[1] := set_name;
    pfp$create_catalog (set_path, {p_mass_storage_request_info} NIL, authority, {lock_catalog} FALSE,
          catalog_locator, status);

    IF status.normal THEN
      {
      { The design assumes that the file media descriptor does not change for
      { the catalog while the system is up.
      {
      dmp$get_stored_fmd_size (catalog_locator.system_file_id, stored_fmd_size, status);
      IF status.normal THEN
        PUSH p_root: [[REP 1 OF pft$internal_catalog_name, REP 1 OF dmt$stored_fmd_size,
              REP stored_fmd_size OF cell]];
        RESET p_root;
        NEXT p_internal_catalog_name IN p_root;
        p_internal_catalog_name^ := catalog_locator.global_file_name;
        NEXT p_stored_fmd_size IN p_root;
        p_stored_fmd_size^ := stored_fmd_size;
        NEXT p_stored_fmd: [[REP stored_fmd_size OF cell]] IN p_root;
        dmp$get_stored_fmd (catalog_locator.system_file_id, p_stored_fmd^, status);
        IF status.normal THEN
          stp$store_pf_root (set_name, p_root^, status);
          IF status.normal THEN
            pfp$return_catalog (catalog_locator, status);
          ELSE
            pfp$destroy_catalog (catalog_locator, local_status);
            pfp$process_unexpected_status (local_status);
          IFEND;
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    ELSE
      pfp$report_unexpected_status (status);
    IFEND;
  PROCEND create_root_catalog;

?? TITLE := '  delete_catalog_object', EJECT ??

  PROCEDURE delete_catalog_object
    (    p_path: ^pft$complete_path;
         p_catalog_object: {i^/o^} ^pft$physical_object;
     VAR new_parent_catalog_locator: {i/o} pft$catalog_locator;
     VAR p_permit_list: {i/o} ^pft$permit_list);

    VAR
      prevalidate_free_result: ost$prevalidate_free_result;

    pfp$update_obj_list_descriptor (p_catalog_object, new_parent_catalog_locator.object_list_descriptor);
    p_catalog_object^.object_entry.object_type := pfc$free_object;
    pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (pft$object_entry),
          p_catalog_object^.checksum);
    IF p_permit_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET(p_permit_list) -
            #OFFSET(^new_parent_catalog_locator.p_catalog_file^.catalog_heap) - 16),
            ^new_parent_catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_permit_list IN new_parent_catalog_locator.p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'PERMIT_LIST', 'catalog',
              prevalidate_free_result, #OFFSET(p_permit_list));
        p_permit_list := NIL;
      IFEND;
    IFEND;
  PROCEND delete_catalog_object;

?? TITLE := '  initialize_catalog_locator', EJECT ??

  PROCEDURE initialize_catalog_locator
    (    old_catalog_locator: pft$catalog_locator;
         p_cell: {input} ^cell;
     VAR new_catalog_locator: pft$catalog_locator);

    CONST
      algorithm = 0,
      lock = TRUE;

    new_catalog_locator.set_name := old_catalog_locator.set_name;
    new_catalog_locator.new_catalog := TRUE;
    new_catalog_locator.queuing_info.set_catalog_alarm := FALSE;
    new_catalog_locator.queuing_info.attach_queued := FALSE;
    new_catalog_locator.internal_catalog_name := old_catalog_locator.internal_catalog_name;
    new_catalog_locator.attached := TRUE;
    new_catalog_locator.open := TRUE;
    new_catalog_locator.locked := TRUE;
    {
    { The "new" catalog is not actually locked, but the fields within the
    { "locked" subrecord are to be used.
    {
    new_catalog_locator.access_kind := pfc$write_access;
    new_catalog_locator.p_catalog_file := p_cell;
    osp$reset_heap (^new_catalog_locator.p_catalog_file^.catalog_heap,
          #SIZE (new_catalog_locator.p_catalog_file^.catalog_heap), NOT lock, algorithm);
    new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.valid :=
          old_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.valid;
    new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.version :=
          old_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.version;
    new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.
          reserved_catalog_header_space := old_catalog_locator.p_catalog_file^.physical_catalog_header.
          catalog_header.reserved_catalog_header_space;
    pfp$build_object_list_locator ({sorted_object_count} 0, {free_sorted_object_count} 0, {p_object_list} NIL,
          {p_catalog_file} NIL, new_catalog_locator.p_catalog_file^.physical_catalog_header.
          catalog_header.object_list_locator);
    pfp$compute_checksum (#LOC (new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header),
          #SIZE (pft$catalog_header), new_catalog_locator.p_catalog_file^.physical_catalog_header.checksum);
    new_catalog_locator.object_list_descriptor.p_object_list := NIL;
    new_catalog_locator.object_list_descriptor.sorted_object_count := 0;
    new_catalog_locator.object_list_descriptor.free_sorted_object_count := 0;
    new_catalog_locator.object_list_descriptor.catalog_type := pfc$external_catalog;
    new_catalog_locator.object_list_descriptor.p_physical_catalog_header :=
          ^new_catalog_locator.p_catalog_file^.physical_catalog_header;
    new_catalog_locator.flush_catalog_pages := TRUE;
    new_catalog_locator.abort_catalog_operation := FALSE;
  PROCEND initialize_catalog_locator;

?? TITLE := '  log_deleted_catalog_object', EJECT ??

  PROCEDURE log_deleted_catalog_object
    (    path: pft$complete_path;
         critical_message: boolean;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
    STRINGREP (text.value, text.size, 'Catalog ', fs_path (1, fs_path_size), ' deleted.');
    pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
    osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
  PROCEND log_deleted_catalog_object;

?? TITLE := '  log_overhaul_options', EJECT ??

  PROCEDURE log_overhaul_options
    (    overhaul_options: pft$set_overhaul_choices;
     VAR status: ost$status);

    VAR
      overhaul_choices: pft$set_overhaul_options,
      overhaul_options_string: ost$string;


    FOR overhaul_choices := LOWERVALUE(pft$set_overhaul_options) TO UPPERVALUE(pft$set_overhaul_options) DO
      IF overhaul_choices IN overhaul_options THEN
        CASE overhaul_choices OF
          = pfc$all_catalogs =
            overhaul_options_string.size := 22;
            overhaul_options_string.value := ' *    pfc$all_catalogs';
          = pfc$recover_purged_files =
            overhaul_options_string.size := 30;
            overhaul_options_string.value := ' *    pfc$recover_purged_files';
          = pfc$validate_files=
            overhaul_options_string.size := 24;
            overhaul_options_string.value := ' *    pfc$validate_files';
          = pfc$reorganize_catalogs =
            overhaul_options_string.size := 29;
            overhaul_options_string.value := ' *    pfc$reorganize_catalogs';
          = pfc$reconcile_fmds =
            overhaul_options_string.size := 24;
            overhaul_options_string.value := ' *    pfc$reconcile_fmds';
          = pfc$delete_unreconciled_objects =
            overhaul_options_string.size := 37;
            overhaul_options_string.value := ' *    pfc$delete_unreconciled_objects';
        ELSE
        CASEND;
        pfp$log_ascii (overhaul_options_string.value (1, overhaul_options_string.size),
              ascii_logset, message_origin, {critical_message} FALSE, status);
      IFEND;
    FOREND;

  PROCEND log_overhaul_options;
?? TITLE := '  log_recovery_summary_status', EJECT ??

  PROCEDURE log_recovery_summary_status
    (VAR status: ost$status);

    IF status.normal AND ((pfv$catalogs_missing_media > 0) OR (pfv$catalogs_moved > 0) OR
          (pfv$catalogs_not_in_set > 0) OR (pfv$cycles_missing_media > 0) OR (pfv$cycles_not_in_set > 0) OR
          (pfv$immovable_catalogs > 0) OR (pfv$overhaul_errors > 0) OR (pfv$purged_catalogs_deleted > 0) OR
          (pfv$recreated_catalogs_cleared > 0) OR (pfv$reinstalled_device_cycles > 0) OR
          (pfv$unreconciled_cats_deleted > 0) OR (pfv$unreconciled_cycles_deleted > 0) OR
          (pfv$unreconciled_catalogs > 0) OR (pfv$unreconciled_files > 0) OR
          (pfv$unreconciled_cats_deleted > 0) OR (pfv$unreconciled_cycle_data_del > 0) OR
          (pfv$unreconciled_cycle_released > 0) OR (pfv$unreconciled_cycle_retained > 0) OR
          (pfv$unreconciled_cycles_deleted > 0)  OR (pfv$unreorganized_catalogs > 0)) THEN

      osp$set_status_condition (pfe$recovery_summary, status);
    IFEND;

    IF (NOT status.normal) AND (status.condition = pfe$recovery_summary) THEN
      osp$append_status_integer (osc$status_parameter_delimiter, pfv$overhaul_errors, radix,
            NOT include_radix, status);
      IF pfv$overhaul_errors = 1 THEN
        osp$append_status_parameter (osc$status_parameter_delimiter, 'error', status);
      ELSE
        osp$append_status_parameter (osc$status_parameter_delimiter, 'errors', status);
      IFEND;

      IF pfv$catalogs_missing_media > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$catalogs_missing_media, radix,
              NOT include_radix, status);
        IF pfv$catalogs_missing_media = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalog resides on an unavailable device.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalogs reside on one or more unavailable devices.', status);
        IFEND;
      IFEND;

      IF pfv$cycles_missing_media > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$cycles_missing_media, radix,
              NOT include_radix, status);
        IF pfv$cycles_missing_media = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycle resides on an unavailable device.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycles reside on one or more unavailable devices.', status);
        IFEND;
      IFEND;

      IF pfv$catalogs_moved > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$catalogs_moved, radix,
              NOT include_radix, status);
        IF pfv$catalogs_moved = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalog was moved from a non catalog device to a catalog device.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, ('catalogs were moved from one or' CAT
                ' more non catalog devices to one or more catalog devices.'), status);
        IFEND;
      IFEND;

      IF pfv$immovable_catalogs > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$immovable_catalogs, radix,
              NOT include_radix, status);
        IF pfv$immovable_catalogs = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalog could not be moved from a non catalog device to a catalog device.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, ('catalogs could not be moved from' CAT
                ' one or more non catalog devices to one or more catalog devices.'), status);
        IFEND;
      IFEND;

      IF pfv$catalogs_not_in_set > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$catalogs_not_in_set, radix,
              NOT include_radix, status);
        IF pfv$catalogs_not_in_set = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalog resides on a volume which is not a member of any set.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'catalogs reside on one or more volumes which are not members of any set.', status);
        IFEND;
      IFEND;

      IF pfv$cycles_not_in_set > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$cycles_not_in_set, radix,
              NOT include_radix, status);
        IF pfv$cycles_not_in_set = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycle resides on a volume which is not a member of any set.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycles reside on one or more volumes which are not members of any set.', status);
        IFEND;
      IFEND;

      IF pfv$unreorganized_catalogs > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreorganized_catalogs, radix,
              NOT include_radix, status);
        IF pfv$unreorganized_catalogs = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog could not be reorganized.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'catalogs could not be reorganized.',
                status);
        IFEND;
      IFEND;

      IF pfv$purged_catalogs_deleted > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$purged_catalogs_deleted, radix,
              NOT include_radix, status);
        IF pfv$purged_catalogs_deleted = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'purged catalog was deleted.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'purged catalogs were deleted.',
                status);
        IFEND;
      IFEND;

      IF pfv$recreated_catalogs_cleared > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$recreated_catalogs_cleared, radix,
              NOT include_radix, status);
        IF pfv$recreated_catalogs_cleared = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 're-created catalog was cleared.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 're-created catalogs were cleared.',
                status);
        IFEND;
      IFEND;

      IF pfv$reinstalled_device_cycles > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$reinstalled_device_cycles, radix,
              NOT include_radix, status);
        IF pfv$reinstalled_device_cycles = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycle resides on one or more reinstalled devices.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycles reside on one or more reinstalled devices.', status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_catalogs > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_catalogs, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_catalogs = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled catalog was detected.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled catalogs were detected.',
                status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_cats_deleted > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_cats_deleted, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_cats_deleted = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled catalog was deleted.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled catalogs were deleted.',
                status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_cycles_deleted > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_cycles_deleted, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_cycles_deleted = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled cycle was deleted.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled cycles were deleted.',
                status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_cycle_released > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_cycle_released, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_cycle_released = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled cycle was released.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled cycles were released.',
                status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_cycle_retained > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_cycle_retained, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_cycle_retained = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'unreconciled cycle with archive images for older version was retained.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'unreconciled cycles with archive images for older version were retained.',
                status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_cycle_data_del > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_cycle_data_del, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_cycle_data_del = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycle with data lost due to recovery without image.', status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter,
                'cycles with data lost due to recovery without image.', status);
        IFEND;
      IFEND;

      IF pfv$unreconciled_files > 0 THEN
        osp$append_status_integer (osc$status_parameter_delimiter, pfv$unreconciled_files, radix,
              NOT include_radix, status);
        IF pfv$unreconciled_files = 1 THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled file was detected.',
                status);
        ELSE
          osp$append_status_parameter (osc$status_parameter_delimiter, 'unreconciled files were detected.',
                status);
        IFEND;
      IFEND;
      pfp$log_error (status, ascii_logset, message_origin, critical_message);
    IFEND;
  PROCEND log_recovery_summary_status;

?? TITLE := '  overhaul_archive_list', EJECT ??

  PROCEDURE overhaul_archive_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         cycle_number: fst$cycle_number;
         p_old_catalog_file: {input^} pft$p_catalog_file;
         p_new_catalog_file: {i^/o^} pft$p_catalog_file;
     VAR p_old_archive_list: {i^/o} pft$p_archive_list;
     VAR p_new_archive_list: {output} pft$p_archive_list;
     VAR status: ost$status);

    VAR
      archive_index: pft$archive_index,
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      new_archive_index: pft$archive_index,
      p_catalog_path: pft$p_complete_path,
      p_new_amd: pft$p_physical_amd,
      p_new_catalog_heap: pft$p_catalog_heap,
      p_old_amd: pft$p_physical_amd,
      path_index: pft$catalog_path_index,
      prevalidate_free_result: ost$prevalidate_free_result,
      text: pft$string,
      valid_archive_count: pft$archive_count,
      valid_archive_entry: boolean,
      validation_status: ost$status;

    status.normal := TRUE;
    p_new_catalog_heap := ^p_new_catalog_file^.catalog_heap;

    IF pfc$validate_files IN set_overhaul_choices THEN
      FOR archive_index := 1 TO UPPERBOUND (p_old_archive_list^) DO
        validate_archive_entry (path, cycle_number, ^p_old_archive_list^ [archive_index], validation_status);
        IF NOT validation_status.normal THEN
          IF status.normal THEN
            status := validation_status;
          IFEND;
        ELSE
          pfp$build_amd_pointer (p_old_archive_list^ [archive_index].archive_entry.amd_locator,
                p_old_catalog_file, p_old_amd);
          validate_amd (path, cycle_number, p_old_amd, validation_status);
          IF (NOT validation_status.normal) AND status.normal THEN
            status := validation_status;
          IFEND;
        IFEND;
      FOREND;
    IFEND;

    IF pfc$reconcile_fmds IN set_overhaul_choices THEN
      valid_archive_count := 0;

      FOR archive_index := 1 TO UPPERBOUND (p_old_archive_list^) DO
        pfp$compute_checksum (#LOC (p_old_archive_list^ [archive_index].archive_entry),
              #SIZE (pft$archive_entry), checksum);
        IF checksum = p_old_archive_list^ [archive_index].checksum THEN
          pfp$build_amd_pointer (p_old_archive_list^ [archive_index].archive_entry.amd_locator,
                p_old_catalog_file, p_old_amd);
          IF p_old_amd <> NIL THEN
            pfp$compute_checksum (#LOC (p_old_amd^.amd), #SIZE (p_old_amd^.amd), checksum);
            IF checksum = p_old_amd^.checksum THEN
              valid_archive_count := valid_archive_count + 1;
            IFEND;
          IFEND;
        IFEND;
      FOREND;

      IF valid_archive_count = 0 THEN
        p_new_archive_list := NIL;
      ELSE
        ALLOCATE p_new_archive_list: [1 .. valid_archive_count] IN p_new_catalog_heap^;

        IF p_new_archive_list = NIL THEN
          PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
          FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
            p_catalog_path^ [path_index] := path [path_index];
          FOREND;
          pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
                status);
          RETURN;
        IFEND;

        new_archive_index := 1;
        FOR archive_index := 1 TO UPPERBOUND (p_old_archive_list^) DO
          pfp$compute_checksum (#LOC (p_old_archive_list^ [archive_index].archive_entry),
                #SIZE (pft$archive_entry), checksum);

          IF checksum = p_old_archive_list^ [archive_index].checksum THEN
            pfp$build_amd_pointer (p_old_archive_list^ [archive_index].archive_entry.amd_locator,
                  p_old_catalog_file, p_old_amd);

            IF p_old_amd <> NIL THEN
              pfp$compute_checksum (#LOC (p_old_amd^.amd), #SIZE (p_old_amd^.amd), checksum);

              IF checksum = p_old_amd^.checksum THEN
                p_new_archive_list^ [new_archive_index] := p_old_archive_list^ [archive_index];
                ALLOCATE p_new_amd: [[REP (#SIZE (p_old_amd^.amd)) OF cell]] IN p_new_catalog_heap^;

                IF p_new_amd = NIL THEN
                  PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
                  FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
                    p_catalog_path^ [path_index] := path [path_index];
                  FOREND;
                  pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
                  osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full,
                        fs_path (1, fs_path_size), status);
                  RETURN;
                IFEND;

                p_new_amd^ := p_old_amd^;
                pfp$build_amd_locator (p_new_amd, p_new_catalog_file,
                      p_new_archive_list^ [new_archive_index].archive_entry.amd_locator);
                pfp$compute_checksum (#LOC (p_new_archive_list^ [new_archive_index].archive_entry),
                      #SIZE (pft$archive_entry), p_new_archive_list^ [new_archive_index].checksum);
                new_archive_index := new_archive_index + 1;
              IFEND;
            IFEND;
          IFEND;
        FOREND;
      IFEND;

      FOR archive_index := 1 TO UPPERBOUND (p_old_archive_list^) DO
        valid_archive_entry := FALSE;

        pfp$compute_checksum (#LOC (p_old_archive_list^ [archive_index].archive_entry),
              #SIZE (pft$archive_entry), checksum);
        IF checksum = p_old_archive_list^ [archive_index].checksum THEN
          pfp$build_amd_pointer (p_old_archive_list^ [archive_index].archive_entry.amd_locator,
                p_old_catalog_file, p_old_amd);
          IF p_old_amd <> NIL THEN
            pfp$compute_checksum (#LOC (p_old_amd^.amd), #SIZE (p_old_amd^.amd), checksum);
            IF checksum = p_old_amd^.checksum THEN
              valid_archive_entry := TRUE;
            IFEND;

            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              osp$prevalidate_free ((#OFFSET(p_old_amd) - #OFFSET(p_new_catalog_heap) - 16),
                    p_new_catalog_heap, prevalidate_free_result);
              IF prevalidate_free_result = osc$heap_free_valid THEN
                FREE p_old_amd IN p_new_catalog_heap^;
              ELSE
                pfp$report_invalid_free (^path, ^cycle_number, 'ARCHIVE_MEDIA_DESCRIPTOR', 'file',
                      prevalidate_free_result, #OFFSET(p_old_amd));
                p_old_amd := NIL;
              IFEND;
            IFEND;
          IFEND;
        IFEND;

        IF NOT valid_archive_entry THEN
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, 'Archive entry deleted for cycle ', fs_path (1, fs_path_size),
                cycle_number, '.');
          text.value (33 + fs_path_size) := '.';
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
        IFEND;
      FOREND;

      IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
        osp$prevalidate_free ((#OFFSET(p_old_archive_list) - #OFFSET(p_new_catalog_heap) - 16),
              p_new_catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_old_archive_list IN p_new_catalog_heap^;
        ELSE
          pfp$report_invalid_free (^path, ^cycle_number, 'ARCHIVE_LIST', 'file', prevalidate_free_result,
                #OFFSET(p_old_archive_list));
          p_old_archive_list := NIL;
        IFEND;
      IFEND;
    IFEND;
  PROCEND overhaul_archive_list;

?? TITLE := '  overhaul_catalog_content', EJECT ??

  PROCEDURE overhaul_catalog_content
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_old_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
     VAR object_list_descriptor: {i/o} pft$object_list_descriptor;
     VAR new_catalog_locator: pft$catalog_locator;
     VAR moved_or_destroyed_child: {i/o} boolean;
     VAR p_new_object_list: ^pft$object_list;
     VAR status: ost$status);

    VAR
      catalog_status: ost$status,
      fs_path_size: fst$path_size,
      new_path_index: pft$file_path_index,
      object_index: pft$object_index,
      p_fs_path: ^fst$path,
      p_new_path: ^pft$complete_path,
      p_object: ^pft$physical_object,
      path_index: pft$catalog_path_index,
      temp_set_overhaul_choices: pft$set_overhaul_choices,
      text: pft$string;

    temp_set_overhaul_choices := set_overhaul_choices + $pft$set_overhaul_choices [pfc$recover_purged_files];
    IF (object_list_descriptor.sorted_object_count > 0) OR pfv$sort_catalog_object_list OR
          (pfc$object_sort_threshold <= UPPERBOUND (object_list_descriptor.p_object_list^)) THEN
      overhaul_sorted_object_list (temp_set_overhaul_choices, path, object_list_descriptor,
            new_catalog_locator, p_new_object_list, status);
    ELSE
      new_catalog_locator.object_list_descriptor.sorted_object_count := 0;
      new_catalog_locator.object_list_descriptor.free_sorted_object_count := 0;
      overhaul_object_list (temp_set_overhaul_choices, path, object_list_descriptor, new_catalog_locator,
            p_new_object_list, status);
    IFEND;

    IF (NOT status.normal) AND (status.condition = pfe$catalog_full) THEN
      p_new_object_list := NIL;
      RETURN;
    IFEND;
    {
    { The new object list now contains objects with pointers to items in the
    { old catalog. The processing will be done from the new object list,
    { because in the case of reorganization the new object list is known to be
    { valid, but the old object list may contain invalid objects.
    {
    new_path_index := UPPERBOUND (path) + 1;
    PUSH p_new_path: [1 .. new_path_index];
    FOR path_index := 1 TO UPPERBOUND (path) DO
      p_new_path^ [path_index] := path [path_index];
    FOREND;

  /overhaul_objects/
    FOR object_index := 1 TO UPPERBOUND (p_new_object_list^) DO
      p_object := ^p_new_object_list^ [object_index];
      CASE p_object^.object_entry.object_type OF
      = pfc$free_object =
        {
        { Do nothing.
        {

      = pfc$file_object, pfc$purged_file_object =
        p_new_path^ [new_path_index] := p_object^.object_entry.external_object_name;
        overhaul_file_object (set_overhaul_choices, p_new_path^, reconcile_locator, p_old_catalog_file,
              p_object, new_catalog_locator, moved_or_destroyed_child, catalog_status);
        IF NOT catalog_status.normal THEN
          status := catalog_status;
          IF (status.condition = pfe$catalog_full) OR (status.condition = pfe$pf_system_error) THEN
            EXIT /overhaul_objects/;
          IFEND;
        IFEND;

      = pfc$catalog_object, pfc$purged_catalog_object =
        p_new_path^ [new_path_index] := p_object^.object_entry.external_object_name;
        overhaul_catalog_object (set_overhaul_choices, p_new_path^, reconcile_locator, p_old_catalog_file,
              authority, p_object, new_catalog_locator, moved_or_destroyed_child, catalog_status);
        IF NOT catalog_status.normal THEN
          status := catalog_status;
          IF (status.condition = pfe$bad_catalog_heap) OR (status.condition = pfe$catalog_full) OR
                (status.condition = pfe$pf_system_error) THEN
            EXIT /overhaul_objects/;
          IFEND;
        IFEND;

      ELSE { An invalid object type passed the checksum validation test.
        p_new_path^ [new_path_index] := p_object^.object_entry.external_object_name;
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (p_new_path^, p_fs_path^, fs_path_size);
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          p_object^.object_entry.object_type := pfc$free_object;
          pfp$compute_checksum (#LOC (p_object^.object_entry), #SIZE (pft$object_entry), p_object^.checksum);
          STRINGREP (text.value, text.size, 'Invalid object type; catalog/file ',
                p_fs_path^ (1, fs_path_size), ' deleted.');
          IF object_index <= new_catalog_locator.object_list_descriptor.sorted_object_count THEN
            new_catalog_locator.object_list_descriptor.free_sorted_object_count :=
                  new_catalog_locator.object_list_descriptor.free_sorted_object_count + 1;
          IFEND;
        ELSE
          STRINGREP (text.value, text.size, 'Invalid object type for catalog/file ',
                p_fs_path^ (1, fs_path_size), '.');
        IFEND;
        pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
        osp$set_status_condition (pfe$recovery_summary, status);
        pfv$overhaul_errors := pfv$overhaul_errors + 1;
      CASEND;
    FOREND /overhaul_objects/;
  PROCEND overhaul_catalog_content;

?? TITLE := '  overhaul_catalog_object', EJECT ??

  PROCEDURE overhaul_catalog_object
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_old_parent_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
         p_new_catalog_object: {i^/o^} ^pft$physical_object;
     VAR new_parent_catalog_locator: pft$catalog_locator;
     VAR moved_or_destroyed_child: {i/o} boolean;
     VAR status: ost$status);

    VAR
      local_status: ost$status,
      p_new_permit_list: ^pft$permit_list,
      p_old_permit_list: ^pft$permit_list,
      p_physical_fmd: ^pft$physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      temp_set_overhaul_choices: pft$set_overhaul_choices;

    status.normal := TRUE;
    p_new_permit_list := NIL;

    pfp$build_permit_list_pointer (p_new_catalog_object^.object_entry.permit_list_locator,
          p_old_parent_catalog_file, p_old_permit_list);
    IF p_old_permit_list = NIL THEN
      IF pfv$clear_catalog_recreated AND p_new_catalog_object^.object_entry.catalog_recreated_by_restore THEN
        pfv$recreated_catalogs_cleared := pfv$recreated_catalogs_cleared + 1;
        p_new_catalog_object^.object_entry.catalog_recreated_by_restore := FALSE;
        pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
              p_new_catalog_object^.checksum);
      IFEND;
    ELSE
      IF p_new_catalog_object^.object_entry.object_type = pfc$catalog_object THEN
        overhaul_permit_list (set_overhaul_choices, path, p_new_catalog_object^.object_entry.object_type,
              p_old_permit_list, ^new_parent_catalog_locator.p_catalog_file^.catalog_heap, p_new_permit_list,
              status);
      IFEND;
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        IF status.normal THEN
          pfp$build_permit_list_locator (p_new_permit_list, new_parent_catalog_locator.p_catalog_file,
                p_new_catalog_object^.object_entry.permit_list_locator);
          IF pfv$clear_catalog_recreated AND
                p_new_catalog_object^.object_entry.catalog_recreated_by_restore THEN
            pfv$recreated_catalogs_cleared := pfv$recreated_catalogs_cleared + 1;
            p_new_catalog_object^.object_entry.catalog_recreated_by_restore := FALSE;
          IFEND;
          pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
                p_new_catalog_object^.checksum);
        ELSEIF status.condition = pfe$catalog_full THEN
          RETURN;
        ELSE
          {
          { A permit entry is defective. Remove the catalog so that
          { unauthorized users may not access the file. (Because permit groups
          { have precedence over catalog/file permit hierarchies, either all
          { permits in the subtree of the highest level, permit containing
          { catalog in the path must be deleted, or this catalog must be
          { deleted. The latter option has been chosen.)
          {
          IF p_new_catalog_object^.object_entry.catalog_object_locator.catalog_type = pfc$external_catalog
                THEN
            pfp$build_fmd_pointer (p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator,
                  p_old_parent_catalog_file, p_physical_fmd);
            IF p_physical_fmd <> NIL THEN
              IF NOT (pfc$delete_unreconciled_objects IN set_overhaul_choices) THEN
                dmp$destroy_permanent_file (new_parent_catalog_locator.global_file_name,
                      p_physical_fmd^.fmd, local_status);
                IF local_status.normal THEN
                  moved_or_destroyed_child := TRUE;
                  out_of_space := FALSE;
                IFEND;
              IFEND;
              IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                {
                { The fmd still exists in the "new", parent catalog. (It will not
                { have been allocated in the new, parent catalog when reorganizing.)
                {
                osp$prevalidate_free ((#OFFSET(p_physical_fmd) -
                      #OFFSET(^new_parent_catalog_locator.p_catalog_file^.catalog_heap) - 16),
                      ^new_parent_catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
                IF prevalidate_free_result = osc$heap_free_valid THEN
                  FREE p_physical_fmd IN new_parent_catalog_locator.p_catalog_file^.catalog_heap;
                ELSE
                  pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR', 'catalog',
                        prevalidate_free_result, #OFFSET(p_physical_fmd));
                  p_physical_fmd := NIL;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
          delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator, p_new_permit_list);
          log_deleted_catalog_object (path, critical_message, status);
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      CASE p_new_catalog_object^.object_entry.catalog_object_locator.catalog_type OF
      = pfc$internal_catalog =
        overhaul_internal_catalog (set_overhaul_choices, path, reconcile_locator, p_old_parent_catalog_file,
              authority, p_new_catalog_object, new_parent_catalog_locator, moved_or_destroyed_child, status);

      = pfc$external_catalog =
        IF pfc$all_catalogs IN set_overhaul_choices THEN
          overhaul_external_catalog (set_overhaul_choices, path, reconcile_locator, p_old_parent_catalog_file,
                authority, p_new_catalog_object, new_parent_catalog_locator, p_new_permit_list,
                moved_or_destroyed_child, status);
        IFEND;

      ELSE
        pfp$log_ascii ('Invalid catalog type.', ascii_logset, message_origin, critical_message, status);
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator, p_new_permit_list);
          log_deleted_catalog_object (path, critical_message, status);
        ELSE
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
        IFEND;
        pfv$overhaul_errors := pfv$overhaul_errors + 1;
      CASEND;
    IFEND;
  PROCEND overhaul_catalog_object;

?? TITLE := '  overhaul_cycle_list', EJECT ??

  PROCEDURE overhaul_cycle_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_cycle_list: {input} ^pft$cycle_list;
         p_old_catalog_file: {input^} ^pft$catalog_file;
         p_new_catalog_file: {i^/o^} ^pft$catalog_file;
         p_catalog_heap: {i/o^} ^pft$catalog_heap;
     VAR cycle_destroyed: {i/o} boolean;
     VAR p_new_cycle_list: ^pft$cycle_list;
     VAR empty_cycle_list: boolean;
     VAR normal_or_recovered_cycles: boolean;
     VAR status: ost$status);

    CONST
      cycle_expansion_count = 1,
      purge_cycle = TRUE;

    VAR
      cycle_count: pft$cycle_count,
      cycle_index: pft$cycle_index,
      cycle_status: ost$status,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      high_cycle_index: pft$cycle_index,
      new_cycle_index: pft$cycle_index,
      p_catalog_path: ^pft$complete_path,
      p_old_physical_fmd: ^pft$physical_fmd,
      path_index: pft$catalog_path_index,
      physical_cycle: pft$physical_cycle,
      text: pft$string;

    high_cycle_index := UPPERBOUND (p_cycle_list^);

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      cycle_count := 0;

      FOR cycle_index := 1 TO high_cycle_index DO
        CASE p_cycle_list^ [cycle_index].cycle_entry.entry_type OF
        = pfc$free_cycle_entry =
          {
          { Do nothing.
          {

        = pfc$normal_cycle_entry =
          cycle_count := cycle_count + 1;

        = pfc$purged_cycle_entry =
          {
          { It is possible for a purged cycle entry to have an attach count of
          { zero during a running system, if all jobs which wished to reattach
          { the cycle during the previous recovery were unrecoverable.
          {
          IF (pfc$recover_purged_files IN set_overhaul_choices) AND
                (p_cycle_list^ [cycle_index].cycle_entry.attach_status.attach_count > 0) THEN
            cycle_count := cycle_count + 1;
          IFEND;

        ELSE
          {
          { Do nothing. This error will be processed later.
          {
        CASEND;
      FOREND;

      IF cycle_count + cycle_expansion_count < high_cycle_index THEN
        ALLOCATE p_new_cycle_list: [1 .. cycle_count + cycle_expansion_count] IN p_catalog_heap^;
      ELSE
        ALLOCATE p_new_cycle_list: [1 .. high_cycle_index] IN p_catalog_heap^;
      IFEND;

      IF p_new_cycle_list = NIL THEN
        PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
        FOR path_index := 1 TO UPPERBOUND (p_catalog_path^) DO
          p_catalog_path^ [path_index] := path [path_index];
        FOREND;
        pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      ELSE
        status.normal := TRUE;
      IFEND;
    ELSE
      p_new_cycle_list := p_cycle_list;
      status.normal := TRUE;
    IFEND;

    empty_cycle_list := status.normal AND (pfc$reconcile_fmds IN set_overhaul_choices);
    normal_or_recovered_cycles := NOT empty_cycle_list;

    IF status.normal THEN
      new_cycle_index := 1;

      FOR cycle_index := 1 TO high_cycle_index DO
        cycle_status.normal := TRUE;

        CASE p_cycle_list^ [cycle_index].cycle_entry.entry_type OF
        = pfc$free_cycle_entry =
          {
          { Do nothing.
          {

        = pfc$normal_cycle_entry =
          IF pfc$validate_files IN set_overhaul_choices THEN
            validate_cycle_entry (set_overhaul_choices, path, ^p_cycle_list^ [cycle_index], cycle_status);
          IFEND;
          IF cycle_status.normal THEN
            IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
              p_new_cycle_list^ [new_cycle_index] := p_cycle_list^ [cycle_index];
              overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, NOT purge_cycle,
                    p_old_catalog_file, p_new_catalog_file, ^p_new_cycle_list^ [new_cycle_index],
                    cycle_destroyed, empty_cycle_list, normal_or_recovered_cycles, cycle_status);
              new_cycle_index := new_cycle_index + 1;
            ELSE
              overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, NOT purge_cycle,
                    p_old_catalog_file, p_new_catalog_file, ^p_cycle_list^ [cycle_index], cycle_destroyed,
                    empty_cycle_list, normal_or_recovered_cycles, cycle_status);
            IFEND;
            IF NOT cycle_status.normal THEN
              status := cycle_status;
              IF status.condition = pfe$catalog_full THEN
                RETURN;
              IFEND;
            IFEND;
          ELSE
            IF pfc$reconcile_fmds IN set_overhaul_choices THEN
              pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
              STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                    p_cycle_list^ [cycle_index].cycle_entry.cycle_number, ' deleted.');
              text.value (7 + fs_path_size) := '.';
              IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                p_cycle_list^ [cycle_index].cycle_entry.entry_type := pfc$free_cycle_entry;
                pfp$compute_checksum (#LOC (p_cycle_list^ [cycle_index].cycle_entry), #SIZE (pft$cycle_entry),
                      p_cycle_list^ [cycle_index].checksum);
              IFEND;
              pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
                    status);
            IFEND;
            status := cycle_status;
          IFEND;

        = pfc$purged_cycle_entry =
          IF pfc$validate_files IN set_overhaul_choices THEN
            validate_cycle_entry (set_overhaul_choices, path, ^p_cycle_list^ [cycle_index], cycle_status);
          IFEND;
          IF cycle_status.normal THEN
            IF (pfc$recover_purged_files IN set_overhaul_choices) AND
                  (p_cycle_list^ [cycle_index].cycle_entry.attach_status.attach_count > 0) THEN
              IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                p_new_cycle_list^ [new_cycle_index] := p_cycle_list^ [cycle_index];
                overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, NOT purge_cycle,
                      p_old_catalog_file, p_new_catalog_file, ^p_new_cycle_list^ [new_cycle_index],
                      cycle_destroyed, empty_cycle_list, normal_or_recovered_cycles, cycle_status);
                new_cycle_index := new_cycle_index + 1;
              ELSE
                overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, NOT purge_cycle,
                      p_old_catalog_file, p_new_catalog_file, ^p_cycle_list^ [cycle_index], cycle_destroyed,
                      empty_cycle_list, normal_or_recovered_cycles, cycle_status);
              IFEND;
              IF NOT cycle_status.normal THEN
                status := cycle_status;
                IF status.condition = pfe$catalog_full THEN
                  RETURN;
                IFEND;
              IFEND;
            ELSE
              IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                p_new_cycle_list^ [new_cycle_index] := p_cycle_list^ [cycle_index];
                overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, purge_cycle,
                      p_old_catalog_file, p_new_catalog_file, ^p_new_cycle_list^ [new_cycle_index],
                      cycle_destroyed, empty_cycle_list, normal_or_recovered_cycles, cycle_status);
              ELSE
                overhaul_file_cycle (set_overhaul_choices, path, reconcile_locator, purge_cycle,
                      p_old_catalog_file, p_new_catalog_file, ^p_cycle_list^ [cycle_index], cycle_destroyed,
                      empty_cycle_list, normal_or_recovered_cycles, cycle_status);
                IF pfc$reconcile_fmds IN set_overhaul_choices THEN
                  p_cycle_list^ [cycle_index].cycle_entry.entry_type := pfc$free_cycle_entry;
                  pfp$compute_checksum (#LOC (p_cycle_list^ [cycle_index].cycle_entry),
                        #SIZE (pft$cycle_entry), p_cycle_list^ [cycle_index].checksum);
                IFEND;
              IFEND;
              IF NOT cycle_status.normal THEN
                status := cycle_status;
              IFEND;
            IFEND;
          ELSE
            IF pfc$reconcile_fmds IN set_overhaul_choices THEN
              pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
              STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                    p_cycle_list^ [cycle_index].cycle_entry.cycle_number, ' deleted.');
              text.value (7 + fs_path_size) := '.';
              IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                p_cycle_list^ [cycle_index].cycle_entry.entry_type := pfc$free_cycle_entry;
                pfp$compute_checksum (#LOC (p_cycle_list^ [cycle_index].cycle_entry), #SIZE (pft$cycle_entry),
                      p_cycle_list^ [cycle_index].checksum);
              IFEND;
              pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
                    status);
            IFEND;
            status := cycle_status;
          IFEND;

        ELSE
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          IF pfc$reconcile_fmds IN set_overhaul_choices THEN
            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              p_cycle_list^ [cycle_index].cycle_entry.entry_type := pfc$free_cycle_entry;
              pfp$compute_checksum (#LOC (p_cycle_list^ [cycle_index].cycle_entry), #SIZE (pft$cycle_entry),
                    p_cycle_list^ [cycle_index].checksum);
            IFEND;
            STRINGREP (text.value, text.size, 'Invalid cycle entry type; cycle ', fs_path (1, fs_path_size),
                  '.? deleted.');
          ELSE
            STRINGREP (text.value, text.size, 'Invalid cycle entry type for cycle ',
                  fs_path (1, fs_path_size), '.?.');
          IFEND;
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
          pfv$overhaul_errors := pfv$overhaul_errors + 1;
        CASEND;
      FOREND;

      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        {
        { Initialize remaining cycle entries.
        {
        physical_cycle.cycle_entry.entry_type := pfc$free_cycle_entry;
        pfp$compute_checksum (#LOC (physical_cycle.cycle_entry), #SIZE (pft$cycle_entry),
              physical_cycle.checksum);
        FOR cycle_index := new_cycle_index TO UPPERBOUND (p_new_cycle_list^) DO
          p_new_cycle_list^ [cycle_index] := physical_cycle;
        FOREND;
      IFEND;
    IFEND;
  PROCEND overhaul_cycle_list;

?? TITLE := '  overhaul_external_catalog', EJECT ??

  PROCEDURE overhaul_external_catalog
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_old_parent_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
         p_new_catalog_object: {i^/o^} ^pft$physical_object;
     VAR new_parent_catalog_locator: {i/o} pft$catalog_locator;
     VAR p_new_permit_list: {i/o} ^pft$permit_list;
     VAR moved_or_destroyed_catalog: {i/o} boolean;
     VAR status: ost$status);

    CONST
      block_exit = TRUE,
      byte_address = 0,
      catalog_remote = TRUE,
      chapter = 0,
      max_reply_length = 119,
      purge_catalog = TRUE,
      validation_ring = 2;

    TYPE
      pft$previous_reorganization = record
        case operator_already_queried: boolean of
        = FALSE =
          ,
        = TRUE =
          already_attempted: boolean,
        casend,
      recend;

    VAR
      catalog_or_cycle: pft$catalog_or_cycle,
      catalog_segment_length: ost$segment_length,
      conditions: pmt$condition,
      established_handler: pmt$established_handler,
      fs_path_size: fst$path_size,
      getsl_allfs_status: ost$status,
      ignore_unreconciled_file: boolean,
      global_file_name: ost$binary_unique_name,
      internal_catalog_name: pft$internal_catalog_name,
      line_received: boolean,
      local_status: ost$status,
      mass_storage_classes: dmt$class,
      moved_or_destroyed_child: boolean,
      new_catalog_locator: pft$catalog_locator,
      old_catalog_locator: pft$catalog_locator,
      p_fs_path: ^fst$path,
      p_new_parent_catalog_file: ^pft$catalog_file,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_old_physical_fmd: ^pft$physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      previous_reorganization: [STATIC] pft$previous_reorganization := [FALSE],
      reply: string (max_reply_length),
      resides_on_system_device: boolean,
      scratch_segment_pointer: amt$segment_pointer,
      temp_set_overhaul_choices: pft$set_overhaul_choices,
      text: pft$string,
      uc_reply: string (max_reply_length),
      verify_heap: boolean;


    PROCEDURE condition_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;

      IF (condition.selector = pmc$system_conditions) OR
            (condition.selector = mmc$segment_access_condition) THEN
        osp$set_status_from_condition (pfc$permanent_file_manager_id, condition, p_sfsa, status,
              local_status);
        IF local_status.normal THEN
          pfp$log_error (status, ascii_logset, message_origin,
                (critical_message OR syv$nosve_internal_operations));
        ELSE
          pfp$log_error (local_status, ascii_logset, message_origin,
                (critical_message OR syv$nosve_internal_operations));
          status := local_status;
        IFEND;

        IF NOT verify_heap THEN
          IF syv$nosve_internal_operations THEN
            pfp$log_ascii (('Invoking system core debugger, from overhaul_external_catalog, due to unexpected'
                  CAT ' condition.'), ascii_logset, message_origin, {critical_message} TRUE, local_status);
            pfp$log_ascii ('Contact PF project.', ascii_logset, message_origin, {critical_message} TRUE,
                  local_status);
            syp$invoke_system_debugger ('', 0, local_status);
          IFEND;

          IF pfc$reconcile_fmds IN set_overhaul_choices THEN
            delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                  p_new_permit_list);
            log_deleted_catalog_object (path, critical_message, status);
          IFEND;

          pfv$overhaul_errors := pfv$overhaul_errors + 1;
          previous_timestamp := #free_running_clock (0);
          EXIT overhaul_external_catalog;
        IFEND;
      ELSE
        {
        { Ignore the condition.
        {
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;
    PROCEND condition_handler;

    PROCEDURE revert_to_old_catalog;

      VAR
        fs_path: fst$path,
        p_new_physical_fmd: ^pft$physical_fmd;

      replace_catalog (path, old_catalog_locator, p_new_parent_catalog_file, p_new_catalog_object,
            p_new_physical_fmd, local_status);
      IF local_status.normal THEN
        status.normal := TRUE;
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        STRINGREP (text.value, text.size, 'Unable to reorganize catalog ', fs_path (1, fs_path_size), '.');
        pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
              local_status);
        pfv$unreorganized_catalogs := pfv$unreorganized_catalogs + 1;
      ELSE
        pfp$log_ascii ('Previous error from replace_catalog.', ascii_logset, message_origin,
              critical_message, local_status);
        dmp$destroy_permanent_file (new_catalog_locator.global_file_name, p_old_physical_fmd^.fmd,
              local_status);
        out_of_space := out_of_space AND NOT local_status.normal;
        delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator, p_new_permit_list);
        IF p_new_physical_fmd <> NIL THEN
          osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
                #OFFSET(^p_new_parent_catalog_file^.catalog_heap) - 16),
                ^p_new_parent_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_new_physical_fmd IN p_new_parent_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                  'catalog', prevalidate_free_result, #OFFSET(p_new_physical_fmd));
            p_new_physical_fmd := NIL;
          IFEND;
        IFEND;
        log_deleted_catalog_object (path, critical_message, status);
        pfv$overhaul_errors := pfv$overhaul_errors + 1;
        moved_or_destroyed_catalog := TRUE;
      IFEND;
    PROCEND revert_to_old_catalog;

    status.normal := TRUE;
    verify_heap := FALSE;
    #SPOIL (verify_heap);
    osp$establish_condition_handler (^condition_handler, NOT block_exit);

    p_new_parent_catalog_file := new_parent_catalog_locator.p_catalog_file;
    pfp$build_fmd_pointer (p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator,
          p_old_parent_catalog_file, p_old_physical_fmd);
    IF p_old_physical_fmd <> NIL THEN
      internal_catalog_name := p_new_catalog_object^.object_entry.internal_object_name;
      global_file_name := p_new_catalog_object^.object_entry.catalog_object_locator.global_file_name;
      catalog_or_cycle.cycle_specified := FALSE;
      IF p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object THEN
        {
        { Purged catalogs are currently unrecoverable, if reconciliation is
        { chosen, because job recovery will be unable to attach the catalog
        { due to its use of the external catalog name.
        {
        overhaul_fmd (set_overhaul_choices, path, catalog_or_cycle, rmc$mass_storage_device,
              global_file_name, reconcile_locator, purge_catalog,
              ^p_new_parent_catalog_file^.catalog_heap, p_old_physical_fmd, p_new_physical_fmd,
              resides_on_system_device, mass_storage_classes, ignore_unreconciled_file, status);
      ELSE
        overhaul_fmd (set_overhaul_choices, path, catalog_or_cycle, rmc$mass_storage_device,
              global_file_name, reconcile_locator, NOT purge_catalog,
              ^p_new_parent_catalog_file^.catalog_heap, p_old_physical_fmd, p_new_physical_fmd,
              resides_on_system_device, mass_storage_classes, ignore_unreconciled_file, status);
      IFEND;

      IF status.normal THEN
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          pfp$attach_catalog (^p_old_physical_fmd^.fmd, path [pfc$set_path_index], internal_catalog_name,
                global_file_name, pfc$write_access, NOT catalog_remote, old_catalog_locator, status);
        ELSE
          pfp$attach_catalog (^p_old_physical_fmd^.fmd, path [pfc$set_path_index], internal_catalog_name,
                global_file_name, pfc$read_access, NOT catalog_remote, old_catalog_locator, status);
        IFEND;

        IF status.normal THEN
          IF (pfc$reconcile_fmds IN set_overhaul_choices) AND
                NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
            verify_heap := TRUE;
            #SPOIL (verify_heap);
            osp$verify_heap (^old_catalog_locator.p_catalog_file^.catalog_heap, status.normal);
            #SPOIL (verify_heap);
            verify_heap := FALSE;
            #SPOIL (verify_heap);
          IFEND;

          IF status.normal THEN
            IF (p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object) AND
                  (pfc$reconcile_fmds IN set_overhaul_choices) THEN
              temp_set_overhaul_choices := set_overhaul_choices -
                    $pft$set_overhaul_choices [pfc$recover_purged_files];
            ELSE
              temp_set_overhaul_choices := set_overhaul_choices;
            IFEND;

            overhaul_physical_catalog (temp_set_overhaul_choices, path, reconcile_locator, authority,
                  old_catalog_locator, new_catalog_locator, moved_or_destroyed_child, status);
            IF status.normal OR (status.condition = pfe$recovery_summary) OR
                  (status.condition = pfe$catalog_full) THEN
              IF p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object THEN
                IF pfc$reconcile_fmds IN set_overhaul_choices THEN
                  {
                  { Purged catalogs are currently unrecoverable, if
                  { reconciliation is chosen, because job recovery will be
                  { unable to attach the catalog due to its use of the
                  { external catalog name.
                  {
                  delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                        p_new_permit_list);
                  IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                    IF p_new_physical_fmd <> NIL THEN
                      osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
                            #OFFSET(^p_new_parent_catalog_file^.catalog_heap) - 16),
                            ^p_new_parent_catalog_file^.catalog_heap, prevalidate_free_result);
                      IF prevalidate_free_result = osc$heap_free_valid THEN
                        FREE p_new_physical_fmd IN p_new_parent_catalog_file^.catalog_heap;
                      ELSE
                        pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                              'catalog', prevalidate_free_result, #OFFSET(p_new_physical_fmd));
                        p_new_physical_fmd := NIL;
                      IFEND;
                    IFEND;
                  ELSE
                    {
                    { In this case the "new" and "old" parent catalogs are
                    { actually the same catalog since reorganization was not
                    { selected. We are deleting the catalog from the old parent.
                    {
                    osp$prevalidate_free ((#OFFSET(p_old_physical_fmd) -
                          #OFFSET(^p_new_parent_catalog_file^.catalog_heap) - 16),
                          ^p_new_parent_catalog_file^.catalog_heap, prevalidate_free_result);
                    IF prevalidate_free_result = osc$heap_free_valid THEN
                      FREE p_old_physical_fmd IN p_new_parent_catalog_file^.catalog_heap;
                    ELSE
                      pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                            'catalog', prevalidate_free_result, #OFFSET(p_old_physical_fmd));
                      p_old_physical_fmd := NIL;
                    IFEND;
                  IFEND;
                  IF NOT (pfc$delete_unreconciled_objects IN set_overhaul_choices) THEN
                    dmp$destroy_permanent_file (new_catalog_locator.global_file_name,
                          p_old_physical_fmd^.fmd, local_status);
                    out_of_space := out_of_space AND NOT local_status.normal;
                  IFEND;

                  IF pfc$recover_purged_files IN set_overhaul_choices THEN
                    PUSH p_fs_path;
                    pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                    STRINGREP (text.value, text.size, 'Purged catalog ', p_fs_path^ (1, fs_path_size),
                          ' deleted.');
                    pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin,
                          {critical_message} FALSE, status);
                    pfv$purged_catalogs_deleted := pfv$purged_catalogs_deleted + 1;
                  IFEND;

                  IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                    scratch_segment_pointer.kind := amc$cell_pointer;
                    scratch_segment_pointer.cell_pointer := new_catalog_locator.p_catalog_file;
                    mmp$delete_scratch_segment (scratch_segment_pointer, local_status);
                    pfp$process_unexpected_status (local_status);
                  IFEND;
                IFEND;
              ELSEIF pfc$reconcile_fmds IN set_overhaul_choices THEN
                IF (status.normal OR (status.condition = pfe$recovery_summary)) AND
                      (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                  mmp$get_segment_length (new_catalog_locator.p_catalog_file, validation_ring,
                        catalog_segment_length, getsl_allfs_status);
                  IF getsl_allfs_status.normal THEN
                    dmp$allocate_file_space_r1 (old_catalog_locator.system_file_id, byte_address,
                          catalog_segment_length, chapter, osc$nowait, sfc$no_limit, getsl_allfs_status);
                    IF (NOT getsl_allfs_status.normal) AND
                          ((getsl_allfs_status.condition = dme$unable_to_alloc_all_space) OR
                          (getsl_allfs_status.condition = dme$volume_unavailable) OR
                          (getsl_allfs_status.condition = dme$some_volumes_not_online)) AND
                          NOT out_of_space THEN
                      {
                      { The MAT may be out of space.  Allow it a chance to be
                      { refilled from the DAT and try again.
                      {
                      pmp$delay (1000 {1 second}, local_status);
                      dmp$allocate_file_space_r1 (old_catalog_locator.system_file_id, byte_address,
                            catalog_segment_length, chapter, osc$nowait, sfc$no_limit, getsl_allfs_status);
                      IF (NOT getsl_allfs_status.normal) AND
                            ((getsl_allfs_status.condition = dme$unable_to_alloc_all_space) OR
                            (getsl_allfs_status.condition = dme$volume_unavailable) OR
                            (getsl_allfs_status.condition = dme$some_volumes_not_online)) THEN
                        {
                        { Allow the logger a chance to run and try again.
                        {
                        pmp$delay (90000 {1.5 minutes}, local_status);
                        dmp$allocate_file_space_r1 (old_catalog_locator.system_file_id, byte_address,
                              catalog_segment_length, chapter, osc$nowait, sfc$no_limit, getsl_allfs_status);
                        out_of_space := (NOT getsl_allfs_status.normal) AND
                              ((getsl_allfs_status.condition = dme$unable_to_alloc_all_space) OR
                              (getsl_allfs_status.condition = dme$volume_unavailable) OR
                              (getsl_allfs_status.condition = dme$some_volumes_not_online));
                      IFEND;
                    IFEND;

                    IF getsl_allfs_status.normal THEN
                      {
                      { Rewrite the "old" catalog with the reorganized, scratch
                      { catalog.
                      {
                      mmp$set_segment_length (old_catalog_locator.p_catalog_file, validation_ring,
                             {segment_length} 0, local_status);
                      i#move (new_catalog_locator.p_catalog_file, old_catalog_locator.p_catalog_file,
                            catalog_segment_length);
                    ELSE
                      pfp$log_error (getsl_allfs_status, ascii_logset, message_origin, critical_message);
                      pfp$log_ascii ('Previous error from dmp$allocate_file_space_r1.', ascii_logset,
                            message_origin, critical_message, local_status);
                      revert_to_old_catalog;
                    IFEND;
                  ELSE
                    pfp$log_error (getsl_allfs_status, ascii_logset, message_origin, critical_message);
                    pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset,
                          message_origin, critical_message, local_status);
                    revert_to_old_catalog;
                  IFEND;
                ELSEIF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                  {
                  { Ran out of scratch segment space.
                  {
                  revert_to_old_catalog;
                  getsl_allfs_status.normal := FALSE;
                ELSE
                  mmp$get_segment_length (old_catalog_locator.p_catalog_file, validation_ring,
                        catalog_segment_length, getsl_allfs_status);
                  IF getsl_allfs_status.normal THEN
                    status.normal := status.normal OR (status.condition = pfe$catalog_full);
                  ELSEIF moved_or_destroyed_child THEN
                    {
                    { It is impossible to revert to using the old catalog.
                    {
                    pfp$log_error (getsl_allfs_status, ascii_logset, message_origin, critical_message);
                    pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset,
                          message_origin, critical_message, local_status);
                    dmp$destroy_permanent_file (new_catalog_locator.global_file_name,
                          p_old_physical_fmd^.fmd, local_status);
                    out_of_space := out_of_space AND NOT local_status.normal;
                    delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                          p_new_permit_list);
                    osp$prevalidate_free ((#OFFSET(p_old_physical_fmd) -
                          #OFFSET(^p_new_parent_catalog_file^.catalog_heap) - 16),
                          ^p_new_parent_catalog_file^.catalog_heap, prevalidate_free_result);
                    IF prevalidate_free_result = osc$heap_free_valid THEN
                      FREE p_old_physical_fmd IN p_new_parent_catalog_file^.catalog_heap;
                    ELSE
                      pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                            'catalog', prevalidate_free_result, #OFFSET(p_old_physical_fmd));
                      p_old_physical_fmd := NIL;
                    IFEND;
                    log_deleted_catalog_object (path, critical_message, status);
                    pfv$overhaul_errors := pfv$overhaul_errors + 1;
                    moved_or_destroyed_catalog := TRUE;
                  ELSE
                    pfp$log_error (getsl_allfs_status, ascii_logset, message_origin,
                          {critical_message} FALSE);
                    pfp$log_ascii ('Previous error from mmp$get_segment_length.', ascii_logset,
                          message_origin, {critical_message} FALSE, local_status);
                    PUSH p_fs_path;
                    pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                    STRINGREP (text.value, text.size, 'Reverting to unmodified version of catalog ',
                          p_fs_path^ (1, fs_path_size), '.');
                    pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin,
                          {critical_message} FALSE, local_status);
                  IFEND;
                IFEND;

                IF getsl_allfs_status.normal THEN
                  {
                  { Force the "new" catalog to be written to disk now.
                  {
                  write_modified_catalog (set_overhaul_choices, path, resides_on_system_device,
                        mass_storage_classes, catalog_segment_length, reconcile_locator,
                        ^p_old_physical_fmd^.fmd, authority, p_new_parent_catalog_file, p_new_catalog_object,
                        p_new_physical_fmd, old_catalog_locator, moved_or_destroyed_catalog, local_status);
                  IF NOT local_status.normal THEN
                    {
                    { It is impossible to revert to using the old catalog.
                    {
                    dmp$destroy_permanent_file (new_catalog_locator.global_file_name,
                          p_old_physical_fmd^.fmd, local_status);
                    out_of_space := out_of_space AND NOT local_status.normal;
                    delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                          p_new_permit_list);
                    IF p_new_physical_fmd <> NIL THEN
                      osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
                            #OFFSET(^p_new_parent_catalog_file^.catalog_heap) - 16),
                            ^p_new_parent_catalog_file^.catalog_heap, prevalidate_free_result);
                      IF prevalidate_free_result = osc$heap_free_valid THEN
                        FREE p_new_physical_fmd IN p_new_parent_catalog_file^.catalog_heap;
                      ELSE
                        pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR',
                              'catalog', prevalidate_free_result, #OFFSET(p_new_physical_fmd));
                        p_new_physical_fmd := NIL;
                      IFEND;
                    IFEND;
                    log_deleted_catalog_object (path, critical_message, status);
                    pfv$overhaul_errors := pfv$overhaul_errors + 1;
                    moved_or_destroyed_catalog := TRUE;
                  IFEND;
                IFEND;

                IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                  scratch_segment_pointer.kind := amc$cell_pointer;
                  scratch_segment_pointer.cell_pointer := new_catalog_locator.p_catalog_file;
                  mmp$delete_scratch_segment (scratch_segment_pointer, local_status);
                  pfp$process_unexpected_status (local_status);
                IFEND;
              IFEND;

            ELSE { Overhaul_physical_catalog failed.
              IF pfc$reconcile_fmds IN set_overhaul_choices THEN
                IF status.condition <> pfe$bad_catalog_heap THEN
                  delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                        p_new_permit_list);
                  log_deleted_catalog_object (path, critical_message, status);
                IFEND;
              ELSEIF status.condition = pfe$bad_root_catalog_header THEN
                osp$set_status_condition (pfe$recovery_summary, status);
              IFEND;
              pfv$overhaul_errors := pfv$overhaul_errors + 1;
            IFEND;

          ELSE { Osp$verify_heap failed.
            IF NOT previous_reorganization.operator_already_queried THEN
              dpp$put_next_line (dpv$system_core_display,
                    ' Has a deadstart WITH REORGANIZATION been tried since the system was last up?',
                    local_status);
              IF local_status.normal THEN
                dpp$put_next_line (dpv$system_core_display, ' Enter yes or no: ', local_status);
              IFEND;
              IF local_status.normal THEN
                REPEAT
                  dpp$get_next_line (dpv$system_core_display, osc$wait, reply, line_received);
                  IF line_received THEN
                    dpp$put_next_line (dpv$system_core_display, reply, local_status);
                    #TRANSLATE (osv$lower_to_upper, reply, uc_reply);
                    IF (uc_reply = 'Y') OR (uc_reply (1, 3) = 'YES') THEN
                      previous_reorganization.operator_already_queried := TRUE;
                      previous_reorganization.already_attempted := TRUE;
                    ELSEIF (uc_reply = 'N') OR (uc_reply (1, 2) = 'NO') THEN
                      previous_reorganization.operator_already_queried := TRUE;
                      previous_reorganization.already_attempted := FALSE;
                    ELSE
                      dpp$put_next_line (dpv$system_core_display, '--ERROR--  Please enter yes or no: ',
                            local_status);
                    IFEND;
                  ELSE
                    dpp$put_next_line (dpv$system_core_display, reply, local_status);
                    previous_reorganization.operator_already_queried := TRUE;
                    previous_reorganization.already_attempted := FALSE;
                  IFEND;
                UNTIL previous_reorganization.operator_already_queried;
              IFEND;
            IFEND;
            IF previous_reorganization.already_attempted THEN
              pfp$log_ascii ('Bad catalog heap encountered.', ascii_logset, message_origin, critical_message,
                    local_status);
              delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                    p_new_permit_list);
              log_deleted_catalog_object (path, critical_message, status);
              pfv$overhaul_errors := pfv$overhaul_errors + 1;
            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$bad_catalog_heap,
                    p_fs_path^ (1, fs_path_size), status);
              pfp$log_ascii ('* * * * * * * * * * * * * * * * * * * * *', ascii_logset, message_origin,
                    {critical_message} FALSE, local_status);
              pfp$log_ascii ('* REDEADSTART using System Core Command:', ascii_logset, message_origin,
                    critical_message, local_status);
              pfp$log_ascii ('* SETSA REORGANIZE_PERMANENT_FILES 1', ascii_logset, message_origin,
                    critical_message, local_status);
              pfp$log_ascii ('* * * * * * * * * * * * * * * * * * * * *', ascii_logset, message_origin,
                    {critical_message} FALSE, local_status);
            IFEND;
          IFEND;

          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);

        ELSE { Pfp$attach_catalog failed.
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
          IF pfc$reconcile_fmds IN set_overhaul_choices THEN
            delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                  p_new_permit_list);
            log_deleted_catalog_object (path, critical_message, status);
          IFEND;
          pfv$overhaul_errors := pfv$overhaul_errors + 1;
        IFEND;

      ELSE { Overhaul_fmd failed.
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          IF p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object THEN
            delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                  p_new_permit_list);
            log_deleted_catalog_object (path, {critical_message} FALSE, status);
            pfv$purged_catalogs_deleted := pfv$purged_catalogs_deleted + 1;

          ELSEIF status.condition = dme$some_volumes_not_online THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            STRINGREP (text.value, text.size, 'Catalog ', p_fs_path^ (1, fs_path_size),
                  ' resides on an off-line device.');
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                  local_status);
            IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
              delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                    p_new_permit_list);
              log_deleted_catalog_object (path, {critical_message} FALSE, status);
              pfv$unreconciled_cats_deleted := pfv$unreconciled_cats_deleted + 1;
            ELSE
              IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                pfp$build_fmd_locator (p_new_physical_fmd, p_new_parent_catalog_file,
                        p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
                pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
                        p_new_catalog_object^.checksum);
              IFEND;
              osp$set_status_condition (pfe$recovery_summary, status);
              pfv$catalogs_missing_media := pfv$catalogs_missing_media + 1;
            IFEND;

          ELSEIF (status.condition = dme$volume_unavailable) OR
                (status.condition = ste$master_not_active) THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            STRINGREP (text.value, text.size, 'Catalog ', p_fs_path^ (1, fs_path_size),
                  ' resides on an unavailable device.');
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                  local_status);
            osp$set_status_condition (pfe$recovery_summary, status);
            IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
              pfp$build_fmd_locator (p_new_physical_fmd, p_new_parent_catalog_file,
                      p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
              pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
                      p_new_catalog_object^.checksum);
            IFEND;

          ELSEIF status.condition = ste$vol_not_found THEN
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            STRINGREP (text.value, text.size, 'Catalog ', p_fs_path^ (1, fs_path_size),
                  ' resides on a volume which is not a member of any set.');
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                  local_status);
            IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
              delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                    p_new_permit_list);
              log_deleted_catalog_object (path, {critical_message} FALSE, status);
              pfv$unreconciled_cats_deleted := pfv$unreconciled_cats_deleted + 1;
            ELSE
              IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
                pfp$build_fmd_locator (p_new_physical_fmd, p_new_parent_catalog_file,
                        p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
                pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
                        p_new_catalog_object^.checksum);
              IFEND;
              osp$set_status_condition (pfe$recovery_summary, status);
              pfv$catalogs_not_in_set := pfv$catalogs_not_in_set + 1;
            IFEND;

          ELSEIF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
            delete_catalog_object (^path, p_new_catalog_object, new_parent_catalog_locator,
                  p_new_permit_list);
            log_deleted_catalog_object (path, {critical_message} FALSE, status);
            pfv$unreconciled_cats_deleted := pfv$unreconciled_cats_deleted + 1;

          ELSEIF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            pfp$build_fmd_locator (p_new_physical_fmd, p_new_parent_catalog_file,
                    p_new_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
            pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
                    p_new_catalog_object^.checksum);
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND overhaul_external_catalog;

?? TITLE := '  overhaul_file_cycle', EJECT ??

  PROCEDURE overhaul_file_cycle
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         purge_cycle: boolean;
         p_old_catalog_file: {input^} ^pft$catalog_file;
         p_new_catalog_file: {i^/o^} ^pft$catalog_file;
         p_cycle: {i^/o^} ^pft$physical_cycle;
     VAR cycle_destroyed: {i/o} boolean;
     VAR empty_cycle_list: {i/o} boolean;
     VAR normal_or_recovered_cycles: {i/o} boolean;
     VAR status: ost$status);

    VAR
      catalog_or_cycle: pft$catalog_or_cycle,
      device_class: rmt$device_class,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      initial_attach_status: [oss$job_paged_literal, READ] pft$attach_status :=
            [0, [REP 5 of 0], [REP 5 of 0]],
      local_status: ost$status,
      mass_storage_classes: dmt$class,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_new_archive_list: ^pft$archive_list,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_new_stored_file_label: ^pft$physical_file_label,
      p_old_archive_list: ^pft$archive_list,
      p_old_physical_fmd: ^pft$physical_fmd,
      p_old_stored_file_label: ^pft$physical_file_label,
      path_index: pft$catalog_path_index,
      prevalidate_free_result: ost$prevalidate_free_result,
      resides_on_system_device: boolean,
      text: pft$string,
      unreconciled_file: boolean,
      valid_archive_entry_exists: boolean;

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

    PROCEDURE delete_cycle_and_log_deletion;

      IF purge_cycle THEN
        STRINGREP (text.value, text.size, 'Purged cycle ', fs_path (1, fs_path_size),
              p_cycle^.cycle_entry.cycle_number, ' deleted.');
        text.value (14 + fs_path_size) := '.';
      ELSE
        STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
              p_cycle^.cycle_entry.cycle_number, ' deleted.');
        text.value (7 + fs_path_size) := '.';
        pfv$unreconciled_cycles_deleted := pfv$unreconciled_cycles_deleted + 1;
        osp$set_status_condition (pfe$recovery_summary, status);
      IFEND;
      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$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
            local_status);
    PROCEND delete_cycle_and_log_deletion;

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

    PROCEDURE delete_fmd_and_file_label;

      {
      { The fmd and file label still exist in the catalog. (They will not
      { have been allocated in the new catalog when reorganizing.)
      {
      IF p_new_physical_fmd = NIL THEN
        osp$prevalidate_free ((#OFFSET(p_old_physical_fmd) -
              #OFFSET(^p_old_catalog_file^.catalog_heap) - 16),
              ^p_old_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_old_physical_fmd IN p_old_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_physical_fmd));
          p_old_physical_fmd := NIL;
        IFEND;
      ELSE
        osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
              #OFFSET(^p_old_catalog_file^.catalog_heap) - 16),
              ^p_old_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_physical_fmd IN p_old_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_new_physical_fmd));
          p_new_physical_fmd := NIL;
        IFEND;
      IFEND;
      pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, p_old_catalog_file,
            p_old_stored_file_label);
      IF p_old_stored_file_label <> NIL THEN
        osp$prevalidate_free ((#OFFSET(p_old_stored_file_label) -
              #OFFSET(^p_old_catalog_file^.catalog_heap) - 16),
              ^p_old_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_old_stored_file_label IN p_old_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;
    PROCEND delete_fmd_and_file_label;

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

    PROCEDURE release_cycle;

      VAR
        archive_index: pft$archive_index,
        comparison_result: pmt$comparison_result,
        release_date_time: ost$date_time;

      p_cycle^.cycle_entry.data_residence := pfc$offline_data;
      p_cycle^.cycle_entry.attach_status := initial_attach_status;
      IF p_new_physical_fmd = NIL THEN
        IF p_old_physical_fmd <> NIL THEN
          osp$prevalidate_free ((#OFFSET(p_old_physical_fmd) -
                #OFFSET(^p_old_catalog_file^.catalog_heap) - 16),
                ^p_old_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_old_physical_fmd IN p_old_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_physical_fmd));
            p_old_physical_fmd := NIL;
          IFEND;
        IFEND;
      ELSE
        osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
              #OFFSET(^p_new_catalog_file^.catalog_heap) - 16),
              ^p_new_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_physical_fmd IN p_new_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_new_physical_fmd));
          p_new_physical_fmd := NIL;
        IFEND;
      IFEND;
      p_old_physical_fmd := NIL;

      pfp$build_fmd_locator (p_new_physical_fmd, p_new_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_new_archive_list <> NIL THEN

        pmp$get_compact_date_time (release_date_time, local_status);
      /set_release_date_time/
        FOR archive_index := 1 TO UPPERBOUND (p_new_archive_list^) DO
          pmp$date_time_compare (p_new_archive_list^ [archive_index].archive_entry.modification_date_time,
                p_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_new_archive_list^ [archive_index].archive_entry.last_release_date_time := release_date_time;
            pfp$compute_checksum (#LOC (p_new_archive_list^ [archive_index].archive_entry),
                  #SIZE (p_new_archive_list^ [archive_index].archive_entry),
                  p_new_archive_list^ [archive_index].checksum);
          IFEND;
        FOREND /set_release_date_time/;
      IFEND;

      STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
            p_cycle^.cycle_entry.cycle_number, ' released.');
      text.value (7 + fs_path_size) := '.';
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
            local_status);
      pfv$unreconciled_cycle_released := pfv$unreconciled_cycle_released + 1;

    PROCEND release_cycle;

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

    PROCEDURE retain_cycle;

      VAR
        p_parent_catalog_path: ^pft$complete_path;

      ALLOCATE p_new_physical_fmd: [[REP #SIZE (p_old_physical_fmd^.fmd) OF cell]]
            IN p_new_catalog_file^.catalog_heap;
      IF p_new_physical_fmd = NIL THEN
        PUSH p_parent_catalog_path: [1 .. UPPERBOUND (path) - 1];
        FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
          p_parent_catalog_path^ [path_index] := path [path_index];
        FOREND;
        pfp$convert_pf_path_to_fs_path (p_parent_catalog_path^, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      ELSE
        p_cycle^.cycle_entry.attach_status := initial_attach_status;
        p_new_physical_fmd^ := p_old_physical_fmd^;
        pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file, p_cycle^.cycle_entry.fmd_locator);
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
        STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
              p_cycle^.cycle_entry.cycle_number, ' with archive images for older version retained.');
        text.value (7 + fs_path_size) := '.';
        pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
              local_status);
        pfv$unreconciled_cycle_retained := pfv$unreconciled_cycle_retained + 1;
      IFEND;

    PROCEND retain_cycle;

?? OLDTITLE ??
?? EJECT ??

    {
    { Overhaul the archive list.
    {
    pfp$build_archive_list_pointer (p_cycle^.cycle_entry.archive_list_locator, p_old_catalog_file,
          p_old_archive_list);
    IF p_old_archive_list <> NIL THEN
      overhaul_archive_list (set_overhaul_choices, path, p_cycle^.cycle_entry.cycle_number,
            p_old_catalog_file, p_new_catalog_file, p_old_archive_list, p_new_archive_list, local_status);
      IF NOT local_status.normal THEN
        IF local_status.condition = pfe$catalog_full THEN
          status := local_status;
          RETURN;
        ELSEIF status.normal THEN
          status := local_status;
        IFEND;
      IFEND;
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        pfp$build_archive_list_locator (p_new_archive_list, p_new_catalog_file,
              p_cycle^.cycle_entry.archive_list_locator);
        pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
      IFEND;
    IFEND;

    {
    { Overhaul the File Media Descriptor (FMD).
    {
    pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_old_catalog_file, p_old_physical_fmd);
    IF p_old_physical_fmd = NIL THEN
      empty_cycle_list := FALSE;
      normal_or_recovered_cycles := TRUE;
      status.normal := TRUE;
    ELSE
      catalog_or_cycle.cycle_specified := TRUE;
      catalog_or_cycle.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;
      overhaul_fmd (set_overhaul_choices, path, catalog_or_cycle, device_class,
            p_cycle^.cycle_entry.internal_cycle_name, reconcile_locator, purge_cycle,
            ^p_new_catalog_file^.catalog_heap, p_old_physical_fmd, p_new_physical_fmd,
            resides_on_system_device, mass_storage_classes, unreconciled_file, status);

      IF status.normal THEN
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          IF purge_cycle THEN
            IF NOT (pfc$delete_unreconciled_objects IN set_overhaul_choices) THEN
              IF device_class = rmc$mass_storage_device THEN
                IF p_new_physical_fmd = NIL THEN
                  dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name,
                        p_old_physical_fmd^.fmd, local_status);
                ELSE
                  dmp$destroy_permanent_file (p_cycle^.cycle_entry.internal_cycle_name,
                        p_new_physical_fmd^.fmd, local_status);
                IFEND;
                IF local_status.normal THEN
                  cycle_destroyed := TRUE;
                  out_of_space := FALSE;
                IFEND;
              ELSEIF device_class = rmc$magnetic_tape_device THEN
                cycle_destroyed := TRUE;
              IFEND;
            IFEND;

            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              delete_fmd_and_file_label;
            IFEND;
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            delete_cycle_and_log_deletion;
            RETURN;
          ELSE
            IF p_new_physical_fmd <> NIL THEN
              pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file,
                    p_cycle^.cycle_entry.fmd_locator);
              IF (device_class = rmc$mass_storage_device) AND pfp$cycle_attached_for_write (p_cycle) THEN
                update_stale_eoi (^path, p_new_physical_fmd, p_cycle, p_new_catalog_file);
              IFEND;
            IFEND;
            p_cycle^.cycle_entry.attach_status := initial_attach_status;
          IFEND;
        IFEND;
      ELSE
        CASE status.condition OF
        = dme$some_volumes_not_online =
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                p_cycle^.cycle_entry.cycle_number, ' resides on one or more off-line devices.');
          text.value (7 + fs_path_size) := '.';
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                local_status);
          IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
            IF (p_old_archive_list <> NIL) AND (p_new_archive_list <> NIL) THEN
              pfp$check_archive_entries (p_new_catalog_file, p_cycle, valid_archive_entry_exists,
                    local_status);
              IF local_status.normal THEN
                IF valid_archive_entry_exists THEN
                  release_cycle;
                ELSE
                  retain_cycle;
                IFEND;
              IFEND;
            ELSE
              IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                delete_fmd_and_file_label;
              IFEND;
              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$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
              STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                    p_cycle^.cycle_entry.cycle_number, ' deleted.');
              text.value (7 + fs_path_size) := '.';
              pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin,
                    {critical_message} FALSE, local_status);
              pfv$unreconciled_cycles_deleted := pfv$unreconciled_cycles_deleted + 1;
              status.normal := TRUE;
              RETURN;
            IFEND;
          ELSE
            p_cycle^.cycle_entry.attach_status := initial_attach_status;
            pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file, p_cycle^.cycle_entry.fmd_locator);
            pfv$cycles_missing_media := pfv$cycles_missing_media + 1;
          IFEND;

        = pfe$recovery_summary =
          IF unreconciled_file THEN
            delete_fmd_and_file_label;
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            IF (pfc$delete_unreconciled_objects IN set_overhaul_choices) OR purge_cycle THEN
              delete_cycle_and_log_deletion;
              RETURN;
            ELSEIF pfc$reconcile_fmds IN set_overhaul_choices THEN
              p_cycle^.cycle_entry.attach_status := initial_attach_status;
              pfp$build_fmd_locator ({p_new_physical_fmd} NIL, p_new_catalog_file,
                    p_cycle^.cycle_entry.fmd_locator);
              STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                    p_cycle^.cycle_entry.cycle_number,
                    ' data deleted for unreconciled file - recovery without image or system error.');
              text.value (7 + fs_path_size) := '.';
              pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin,
                    {critical_message} FALSE, local_status);
              pfv$unreconciled_cycle_data_del := pfv$unreconciled_cycle_data_del + 1;
            IFEND;
          IFEND;

        = dme$volume_unavailable, ste$master_not_active =
          {
          { This can only occur if the volume went down after volume or set
          { activation, respectively, so the cycle must not be deleted.
          {
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                p_cycle^.cycle_entry.cycle_number, ' resides on one or more unavailable devices.');
          text.value (7 + fs_path_size) := '.';
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                local_status);
          p_cycle^.cycle_entry.attach_status := initial_attach_status;
          pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file, p_cycle^.cycle_entry.fmd_locator);

        = pfe$catalog_full =
          IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            RETURN;
          ELSE
            status.normal := TRUE;
          IFEND;

        = ste$vol_not_found =
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, 'Cycle ', fs_path (1, fs_path_size),
                p_cycle^.cycle_entry.cycle_number, ' resides on a volume which is not a member of any set.');
          text.value (7 + fs_path_size) := '.';
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                local_status);
          IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              delete_fmd_and_file_label;
            IFEND;
            delete_cycle_and_log_deletion;
            RETURN;
          ELSE
            p_cycle^.cycle_entry.attach_status := initial_attach_status;
            pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file, p_cycle^.cycle_entry.fmd_locator);
            pfv$cycles_not_in_set := pfv$cycles_not_in_set + 1;
          IFEND;

        ELSE
          IF (pfc$delete_unreconciled_objects IN set_overhaul_choices) OR purge_cycle THEN
            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              delete_fmd_and_file_label;
            IFEND;
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            delete_cycle_and_log_deletion;
            RETURN;
          ELSEIF pfc$reconcile_fmds IN set_overhaul_choices THEN
            p_cycle^.cycle_entry.attach_status := initial_attach_status;
            pfp$build_fmd_locator (p_new_physical_fmd, p_new_catalog_file, p_cycle^.cycle_entry.fmd_locator);
          IFEND;
        CASEND;

        status.normal := TRUE;
      IFEND;

      empty_cycle_list := FALSE;
      normal_or_recovered_cycles := TRUE;
    IFEND;

    {
    { Overhaul the file label.
    {
    pfp$build_file_label_pointer (p_cycle^.cycle_entry.file_label_locator, p_old_catalog_file,
          p_old_stored_file_label);
    IF p_old_stored_file_label <> NIL THEN
      overhaul_file_label (set_overhaul_choices, path, p_cycle^.cycle_entry.cycle_number,
            p_old_stored_file_label, ^p_new_catalog_file^.catalog_heap, p_new_stored_file_label, status);
      IF status.normal THEN
        IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
          pfp$build_file_label_locator (p_new_stored_file_label, p_new_catalog_file,
                p_cycle^.cycle_entry.file_label_locator);
        IFEND;
      ELSEIF status.condition = pfe$catalog_full THEN
        RETURN;
      ELSEIF pfc$reconcile_fmds IN set_overhaul_choices THEN
        pfp$build_file_label_locator (NIL, p_new_catalog_file, p_cycle^.cycle_entry.file_label_locator);
      IFEND;
    IFEND;

    IF pfc$reconcile_fmds IN set_overhaul_choices THEN
      {
      { Remove mainframe usage.
      {
      p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
      IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) AND
            (p_old_catalog_file^.physical_catalog_header.catalog_header.version = pfc$catalog_version) THEN
        {
        { For upward and downward compatibility, only do this if this is the
        { current level of the catalog.
        {
        pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator,
              p_old_catalog_file, p_mainframe_usage_list);
        IF p_mainframe_usage_list <> NIL THEN
          osp$prevalidate_free ((#OFFSET(p_mainframe_usage_list) -
                #OFFSET(^p_new_catalog_file^.catalog_heap) - 16),
                ^p_new_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_mainframe_usage_list IN p_new_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;
      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 (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
    IFEND;
  PROCEND overhaul_file_cycle;

?? TITLE := '  overhaul_file_label', EJECT ??

  PROCEDURE overhaul_file_label
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         cycle_number: fst$cycle_number;
         p_old_stored_file_label: {input^} ^pft$physical_file_label;
         p_new_catalog_heap: {output^} ^pft$catalog_heap;
     VAR p_new_stored_file_label: ^pft$physical_file_label;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      p_catalog_path: ^pft$complete_path,
      path_index: pft$catalog_path_index;

    IF pfc$validate_files IN set_overhaul_choices THEN
      validate_file_label (path, cycle_number, p_old_stored_file_label, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    ELSE
      status.normal := TRUE;
    IFEND;

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      ALLOCATE p_new_stored_file_label: [[REP (#SIZE (p_old_stored_file_label^.file_label)) OF cell]] IN
            p_new_catalog_heap^;
      IF p_new_stored_file_label <> NIL THEN
        p_new_stored_file_label^ := p_old_stored_file_label^;
      ELSE
        PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
        FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
          p_catalog_path^ [path_index] := path [path_index];
        FOREND;
        pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      IFEND;
    IFEND;
  PROCEND overhaul_file_label;

?? TITLE := '  overhaul_file_object', EJECT ??

  PROCEDURE overhaul_file_object
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_old_catalog_file: {input^} ^pft$catalog_file;
         p_new_file_object: {i^/o^} ^pft$physical_object;
     VAR new_catalog_locator: {i/o} pft$catalog_locator;
     VAR cycle_destroyed: {i/o} boolean;
     VAR status: ost$status);

    VAR
      empty_cycle_list: boolean,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      normal_or_recovered_cycles: boolean,
      p_cycle_list: ^pft$cycle_list,
      p_log_list: ^pft$log_list,
      p_new_catalog_file: ^pft$catalog_file,
      p_new_catalog_heap: ^pft$catalog_heap,
      p_new_cycle_list: ^pft$cycle_list,
      p_new_log_list: ^pft$log_list,
      p_new_permit_list: ^pft$permit_list,
      p_permit_list: ^pft$permit_list,
      prevalidate_free_result: ost$prevalidate_free_result,
      text: pft$string;


    PROCEDURE delete_file_object;

      IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
        pfp$build_log_list_pointer (p_new_file_object^.object_entry.log_list_locator, p_old_catalog_file,
              p_log_list);
      IFEND;

      pfp$update_obj_list_descriptor (p_new_file_object, new_catalog_locator.object_list_descriptor);
      p_new_file_object^.object_entry.object_type := pfc$free_object;
      pfp$compute_checksum (#LOC (p_new_file_object^.object_entry), #SIZE (pft$object_entry),
            p_new_file_object^.checksum);

      IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) AND (p_log_list <> NIL) THEN
        osp$prevalidate_free ((#OFFSET(p_log_list) - #OFFSET(^p_new_catalog_file^.catalog_heap) - 16),
              ^p_new_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_log_list IN p_new_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;

      IF p_new_permit_list <> NIL THEN
        osp$prevalidate_free ((#OFFSET(p_new_permit_list) - #OFFSET(p_new_catalog_heap) - 16),
              p_new_catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_permit_list IN p_new_catalog_heap^;
        ELSE
          pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'PERMIT_LIST', 'file',
                prevalidate_free_result, #OFFSET(p_new_permit_list));
          p_new_permit_list := NIL;
        IFEND;
      IFEND;
    PROCEND delete_file_object;


    PROCEDURE log_deleted_file_object;

      STRINGREP (text.value, text.size, 'File ', fs_path (1, fs_path_size), ' deleted.');
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
    PROCEND log_deleted_file_object;


    p_new_catalog_file := new_catalog_locator.p_catalog_file;
    p_new_catalog_heap := ^p_new_catalog_file^.catalog_heap;
    p_new_permit_list := NIL;

    pfp$build_permit_list_pointer (p_new_file_object^.object_entry.permit_list_locator, p_old_catalog_file,
          p_permit_list);
    IF p_permit_list <> NIL THEN
      overhaul_permit_list (set_overhaul_choices, path, p_new_file_object^.object_entry.object_type,
            p_permit_list, p_new_catalog_heap, p_new_permit_list, status);
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        IF status.normal THEN
          pfp$build_permit_list_locator (p_new_permit_list, p_new_catalog_file,
                p_new_file_object^.object_entry.permit_list_locator);
        ELSEIF status.condition = pfe$catalog_full THEN
          RETURN;
        ELSE
          {
          { A permit entry is defective. Remove the file so that unauthorized
          { users may not access the file. (Because permit groups have
          { precedence over catalog/file permit hierarchies, either all
          { permits in the subtree of the highest level, permit containing
          { catalog in the path must be deleted, or all cycles of the file
          { must be deleted. The latter option has been chosen.)
          {
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          delete_file_object;
          log_deleted_file_object;
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    pfp$build_cycle_list_pointer (p_new_file_object^.object_entry.cycle_list_locator, p_old_catalog_file,
          p_cycle_list);
    IF p_cycle_list = NIL THEN
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, 'File ', fs_path (1, fs_path_size), ' has no cycles.');
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        delete_file_object;
        log_deleted_file_object;
      ELSE
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      IFEND;
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
      RETURN;
    ELSE
      overhaul_cycle_list (set_overhaul_choices, path, reconcile_locator, p_cycle_list, p_old_catalog_file,
            p_new_catalog_file, p_new_catalog_heap, cycle_destroyed, p_new_cycle_list, empty_cycle_list,
            normal_or_recovered_cycles, status);
      IF (NOT status.normal) AND ((status.condition = pfe$catalog_full) OR
            (status.condition = pfe$pf_system_error)) THEN
        RETURN;
      IFEND;
      {
      { The new cycle list contains pointers to items in the old catalog file
      { at this point. The following routines use the cycle entries from the
      { new cycle list, because in the case of reorganization the new cycle
      { list entries are known to be valid.
      {
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        pfp$build_cycle_list_locator (p_new_cycle_list, p_new_catalog_file,
              p_new_file_object^.object_entry.cycle_list_locator);
        {
        { Deleted, unreconciled cycle entries; unrecovered, purged cycle
        { entries; and cycle entries with defective file media descriptors
        { have all become free cycle entries. If the cycle list contains only
        { free entries, free the cycle list and delete the file. Log the
        { deletion only if there was a normal cycle residing on an available
        { device or if there was a purged cycle and recovery was chosen.
        {
        IF empty_cycle_list THEN
          osp$prevalidate_free ((#OFFSET(p_new_cycle_list) - #OFFSET(p_new_catalog_heap) - 16),
                p_new_catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_new_cycle_list IN p_new_catalog_heap^;
          ELSE
            pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'CYCLE_LIST', 'file',
                  prevalidate_free_result, #OFFSET(p_new_cycle_list));
            p_new_cycle_list := NIL;
          IFEND;
          delete_file_object;
          IF normal_or_recovered_cycles THEN
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            STRINGREP (text.value, text.size, 'File ', fs_path (1, fs_path_size), ' has no cycles.');
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
            log_deleted_file_object;
            pfv$overhaul_errors := pfv$overhaul_errors + 1;
          IFEND;
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    pfp$build_log_list_pointer (p_new_file_object^.object_entry.log_list_locator, p_old_catalog_file,
          p_log_list);
    IF p_log_list <> NIL THEN
      overhaul_log_list (set_overhaul_choices, path, p_log_list, p_new_catalog_heap, p_new_log_list, status);
      {
      { Errors in log entries are not considered serious enough to delete a
      { file.
      {
      IF pfc$reconcile_fmds IN set_overhaul_choices THEN
        status.normal := status.normal OR (status.condition = pfe$catalog_full);
        pfp$build_log_list_locator (p_new_log_list, p_new_catalog_file,
              p_new_file_object^.object_entry.log_list_locator);
      ELSE
        RETURN;
      IFEND;
    IFEND;

    IF pfc$reconcile_fmds IN set_overhaul_choices THEN
      pfp$compute_checksum (#LOC (p_new_file_object^.object_entry), #SIZE (pft$object_entry),
            p_new_file_object^.checksum);
    IFEND;
  PROCEND overhaul_file_object;

?? TITLE := '  overhaul_fmd', EJECT ??

  PROCEDURE overhaul_fmd
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         catalog_or_cycle: pft$catalog_or_cycle;
         device_class: rmt$device_class;
         global_file_name: pft$internal_name;
         reconcile_locator: dmt$reconcile_locator;
         purge_object: boolean;
         p_parent_catalog_heap: {output^} ^pft$catalog_heap;
     VAR p_old_physical_fmd: {i^/o} ^pft$physical_fmd;
     VAR p_new_physical_fmd: ^pft$physical_fmd;
     VAR resides_on_system_device: boolean;
     VAR mass_storage_classes: dmt$class;
     VAR unreconciled_file: boolean;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      global_file_string: ost$name,
      local_status: ost$status,
      p_parent_catalog_path: pft$p_complete_path,
      path_index: pft$catalog_path_index,
      stored_fmd_size: dmt$stored_fmd_size;

    p_new_physical_fmd := NIL;
    unreconciled_file := FALSE;

    IF pfc$validate_files IN set_overhaul_choices THEN
      validate_fmd (path, catalog_or_cycle, p_old_physical_fmd, status);
      IF NOT status.normal THEN
        unreconciled_file := TRUE;
        RETURN;
      IFEND;
    IFEND;

    IF pfc$reconcile_fmds IN set_overhaul_choices THEN
      IF device_class = rmc$mass_storage_device THEN
        {
        { Reconciliation must always be done, even for purged objects.
        {
        dmp$reconcile_fmd (reconcile_locator, global_file_name, p_old_physical_fmd^.fmd, purge_object,
              mass_storage_classes, stored_fmd_size, resides_on_system_device, status);
        IF status.normal THEN
          IF (NOT catalog_or_cycle.cycle_specified) OR purge_object THEN
            RETURN;
          IFEND;
        ELSEIF purge_object AND catalog_or_cycle.cycle_specified AND (status.condition <> dme$update_fmd) THEN
          status.normal := TRUE;
          RETURN;
        ELSE
          CASE status.condition OF
          = dme$update_fmd =
            IF catalog_or_cycle.cycle_specified THEN
              PUSH p_parent_catalog_path: [1 .. UPPERBOUND (path) - 1];
              FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
                p_parent_catalog_path^ [path_index] := path [path_index];
              FOREND;
              update_fmd (set_overhaul_choices, p_parent_catalog_path^, ^catalog_or_cycle.cycle_number,
                    global_file_name, reconcile_locator, stored_fmd_size, purge_object, p_parent_catalog_heap,
                    p_old_physical_fmd, p_new_physical_fmd, status);
            IFEND;
            RETURN;

          = dme$some_volumes_not_online, ste$vol_not_found =
            pfp$log_error (status, ascii_logset, message_origin, {critical_message} FALSE);
            IF (pfc$delete_unreconciled_objects IN set_overhaul_choices) OR purge_object THEN
              RETURN;
            IFEND;

          = dme$volume_unavailable =
            pfp$log_error (status, ascii_logset, message_origin, {critical_message} FALSE);
            IF purge_object THEN
              RETURN;
            IFEND;

          = dme$unknown_file =
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            IF catalog_or_cycle.cycle_specified THEN
              unreconciled_file := TRUE;
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unreconciled_file,
                    fs_path (1, fs_path_size), status);
              pfv$unreconciled_files := pfv$unreconciled_files + 1;
            ELSE
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unreconciled_catalog,
                    fs_path (1, fs_path_size), status);
              pfv$unreconciled_catalogs := pfv$unreconciled_catalogs + 1;
            IFEND;
            pmp$convert_binary_unique_name (global_file_name, global_file_string, local_status);
            osp$append_status_parameter (osc$status_parameter_delimiter, global_file_string, status);
            pfp$log_error (status, ascii_logset, message_origin, {critical_message} FALSE);
            osp$set_status_condition (pfe$recovery_summary, status);
            IF (pfc$delete_unreconciled_objects IN set_overhaul_choices) OR purge_object OR
                  unreconciled_file THEN
              RETURN;
            IFEND;

          ELSE
            pfp$log_error (status, ascii_logset, message_origin, critical_message);
            pfp$log_ascii ('Previous error from dmp$reconcile_fmd.', ascii_logset, message_origin,
                  critical_message, local_status);
            osp$set_status_condition (pfe$recovery_summary, status);
            pfv$overhaul_errors := pfv$overhaul_errors + 1;
            IF (pfc$delete_unreconciled_objects IN set_overhaul_choices) OR purge_object THEN
              RETURN;
            IFEND;
          CASEND;
        IFEND;
      ELSE
        status.normal := TRUE;
      IFEND;

      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        stored_fmd_size := #SIZE (p_old_physical_fmd^.fmd);
        ALLOCATE p_new_physical_fmd: [[REP stored_fmd_size OF cell]] IN p_parent_catalog_heap^;
        IF p_new_physical_fmd = NIL THEN
          PUSH p_parent_catalog_path: [1 .. UPPERBOUND (path) - 1];
          FOR path_index := 1 TO UPPERBOUND (path) - 1 DO
            p_parent_catalog_path^ [path_index] := path [path_index];
          FOREND;
          pfp$convert_pf_path_to_fs_path (p_parent_catalog_path^, fs_path, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
                status);
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
        ELSE
          p_new_physical_fmd^ := p_old_physical_fmd^;
        IFEND;
      IFEND;
    ELSE
      status.normal := TRUE;
    IFEND;
  PROCEND overhaul_fmd;

?? TITLE := '  overhaul_internal_catalog', EJECT ??

  PROCEDURE overhaul_internal_catalog
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         p_old_parent_catalog_file: {input^} ^pft$catalog_file;
         authority: pft$authority;
         p_new_catalog_object: {i^/o^} ^pft$physical_object;
     VAR new_parent_catalog_locator: pft$catalog_locator;
     VAR moved_or_destroyed_child: {i/o} boolean;
     VAR status: ost$status);

    VAR
      catalog_status: ost$status,
      fs_path_size: fst$path_size,
      internal_catalog_locator: pft$catalog_locator,
      object_list_descriptor: pft$object_list_descriptor,
      p_fs_path: ^fst$path,
      p_new_object_list: ^pft$object_list,
      p_object_list: ^pft$object_list,
      temp_set_overhaul_choices: pft$set_overhaul_choices,
      text: pft$string;

    pfp$build_object_list_pointer (p_new_catalog_object^.object_entry.catalog_object_locator.
          object_list_locator, p_old_parent_catalog_file, p_object_list);
    IF p_object_list <> NIL THEN
      IF (p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object) AND
            (pfc$reconcile_fmds IN set_overhaul_choices) THEN
        temp_set_overhaul_choices := set_overhaul_choices -
              $pft$set_overhaul_choices [pfc$recover_purged_files];
      ELSE
        temp_set_overhaul_choices := set_overhaul_choices;
      IFEND;
      internal_catalog_locator := new_parent_catalog_locator;

      object_list_descriptor.p_object_list := p_object_list;
      object_list_descriptor.sorted_object_count := 0;
      object_list_descriptor.free_sorted_object_count := 0;
      object_list_descriptor.catalog_type := pfc$internal_catalog;
      object_list_descriptor.p_parent_catalog := p_new_catalog_object;

      overhaul_catalog_content (temp_set_overhaul_choices, path, reconcile_locator, p_old_parent_catalog_file,
            authority, object_list_descriptor, internal_catalog_locator, moved_or_destroyed_child,
            p_new_object_list, catalog_status);
      IF (p_new_catalog_object^.object_entry.object_type = pfc$purged_catalog_object) AND
            (pfc$reconcile_fmds IN set_overhaul_choices) THEN
        {
        { Purged catalogs are currently unrecoverable, if reconciliation is
        { chosen, because job recovery will be unable to attach the catalog
        { due to its use of the external catalog name.
        {
        pfp$update_obj_list_descriptor (p_new_catalog_object,
              new_parent_catalog_locator.object_list_descriptor);
        p_new_catalog_object^.object_entry.object_type := pfc$free_object;
        pfp$compute_checksum (#LOC (p_new_catalog_object^.object_entry), #SIZE (pft$object_entry),
              p_new_catalog_object^.checksum);
        IF pfc$recover_purged_files IN set_overhaul_choices THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          STRINGREP (text.value, text.size, 'Purged catalog ', p_fs_path^ (1, fs_path_size), ' deleted.');
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                status);
          pfv$purged_catalogs_deleted := pfv$purged_catalogs_deleted + 1;
        IFEND;
      IFEND;

      IF (catalog_status.normal OR (catalog_status.condition = pfe$recovery_summary)) AND
            (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
        internal_catalog_locator.object_list_descriptor.p_object_list := NIL;
        internal_catalog_locator.object_list_descriptor.catalog_type := pfc$internal_catalog;
        internal_catalog_locator.object_list_descriptor.p_parent_catalog := p_new_catalog_object;
        pfp$update_object_list_locator (^path, p_new_object_list, internal_catalog_locator.p_catalog_file,
              internal_catalog_locator.object_list_descriptor);
      IFEND;

      IF NOT catalog_status.normal THEN
        status := catalog_status;
      IFEND;
    IFEND;
  PROCEND overhaul_internal_catalog;

?? TITLE := '  overhaul_log_list', EJECT ??

  PROCEDURE overhaul_log_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         p_log_list: {i^/o^} ^pft$log_list;
         p_catalog_heap: {output^} ^pft$catalog_heap;
     VAR p_new_log_list: ^pft$log_list;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      high_log_index: pft$log_index,
      log_count: pft$log_count,
      log_index: pft$log_index,
      log_status: ost$status,
      new_log_index: pft$log_index,
      p_catalog_path: ^pft$complete_path,
      physical_log: pft$physical_log,
      path_index: pft$catalog_path_index,
      text: pft$string;

    high_log_index := UPPERBOUND (p_log_list^);

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      log_count := 0;

      FOR log_index := 1 TO high_log_index DO
        IF p_log_list^ [log_index].log_entry.entry_type = pfc$normal_log_entry THEN
          log_count := log_count + 1;
        IFEND;
      FOREND;

      ALLOCATE p_new_log_list: [1 .. log_count] IN p_catalog_heap^;
      IF p_new_log_list = NIL THEN
        PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
        FOR path_index := 1 TO UPPERBOUND (p_catalog_path^) DO
          p_catalog_path^ [path_index] := path [path_index];
        FOREND;
        pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, {critical_message} FALSE);
      ELSE
        status.normal := TRUE;
      IFEND;
    ELSE
      p_new_log_list := p_log_list;
      status.normal := TRUE;
    IFEND;

    IF status.normal THEN
      new_log_index := 1;

    /overhaul_logs/
      FOR log_index := 1 TO high_log_index DO
        CASE p_log_list^ [log_index].log_entry.entry_type OF
        = pfc$free_log_entry =
          {
          { Do nothing.
          {

        = pfc$normal_log_entry =
          IF pfc$validate_files IN set_overhaul_choices THEN
            validate_log_entry (path, ^p_log_list^ [log_index], log_status);
            IF NOT log_status.normal THEN
              status := log_status;
              IF (pfc$reconcile_fmds IN set_overhaul_choices) AND
                    NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                p_log_list^ [log_index].log_entry.entry_type := pfc$free_log_entry;
                pfp$compute_checksum (#LOC (p_log_list^ [log_index].log_entry), #SIZE (pft$log_entry),
                      p_log_list^ [log_index].checksum);
              IFEND;
              CYCLE /overhaul_logs/;
            IFEND;
          IFEND;
          IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            p_new_log_list^ [new_log_index] := p_log_list^ [log_index];
            new_log_index := new_log_index + 1;
          IFEND;

        ELSE
          IF (pfc$reconcile_fmds IN set_overhaul_choices) AND
                NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
            p_log_list^ [log_index].log_entry.entry_type := pfc$free_log_entry;
            pfp$compute_checksum (#LOC (p_log_list^ [log_index].log_entry), #SIZE (pft$log_entry),
                  p_log_list^ [log_index].checksum);
          IFEND;
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, 'Invalid log entry type for file ', fs_path (1, fs_path_size),
                '.');
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
          pfv$overhaul_errors := pfv$overhaul_errors + 1;
        CASEND;
      FOREND /overhaul_logs/;

      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        physical_log.log_entry.entry_type := pfc$free_log_entry;
        pfp$compute_checksum (#LOC (physical_log.log_entry), #SIZE (pft$log_entry), physical_log.checksum);
        FOR log_index := new_log_index TO UPPERBOUND (p_new_log_list^) DO
          p_new_log_list^ [log_index] := physical_log;
        FOREND;
      IFEND;
    IFEND;
  PROCEND overhaul_log_list;

?? TITLE := '  overhaul_object_list', EJECT ??

  PROCEDURE overhaul_object_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         old_object_list_descriptor: pft$object_list_descriptor;
         new_catalog_locator: pft$catalog_locator;
     VAR p_new_object_list: ^pft$object_list;
     VAR status: ost$status);

    CONST
      object_expansion_count = 2;

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      high_object_index: pft$object_index,
      new_object_index: pft$object_index,
      new_path_index: pft$file_path_index,
      object_count: pft$object_count,
      object_index: pft$object_index,
      object_status: ost$status,
      p_new_path: ^pft$complete_path,
      p_object_list: pft$p_object_list,
      path_index: pft$catalog_path_index,
      physical_object: pft$physical_object,
      text: pft$string;

    p_object_list := old_object_list_descriptor.p_object_list;
    high_object_index := UPPERBOUND (p_object_list^);

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      object_count := 0;
      {
      { Count the number of objects in the object list. To increase
      { performance the objects are not validated during the counting process.
      { If validation has been selected, the objects will be validated prior
      { to moving them to the new object list. If an object is invalid, the
      { object list may contain more free entries than computed during the
      { count process.
      {
      FOR object_index := 1 TO high_object_index DO
        CASE p_object_list^ [object_index].object_entry.object_type OF
        = pfc$free_object =
          {
          { Do nothing.
          {
        = pfc$file_object, pfc$purged_file_object, pfc$catalog_object, pfc$purged_catalog_object =
          object_count := object_count + 1;
        ELSE
          {
          { Do nothing. This error will be processed later.
          {
        CASEND;
      FOREND;

      IF object_count + object_expansion_count < high_object_index THEN
        ALLOCATE p_new_object_list: [1 .. object_count + object_expansion_count] IN
              new_catalog_locator.p_catalog_file^.catalog_heap;
      ELSE
        ALLOCATE p_new_object_list: [1 .. high_object_index] IN
              new_catalog_locator.p_catalog_file^.catalog_heap;
      IFEND;

      IF p_new_object_list = 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$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      ELSE
        status.normal := TRUE;
      IFEND;
    ELSE
      p_new_object_list := p_object_list;
      status.normal := TRUE;
    IFEND;

    IF status.normal THEN
      new_path_index := UPPERBOUND (path) + 1;
      PUSH p_new_path: [1 .. new_path_index];
      FOR path_index := 1 TO new_path_index - 1 DO
        p_new_path^ [path_index] := path [path_index];
      FOREND;
      new_object_index := 1;

    /overhaul_objects/
      FOR object_index := 1 TO high_object_index DO
        CASE p_object_list^ [object_index].object_entry.object_type OF
        = pfc$free_object =
          {
          { Do nothing.
          {

        = pfc$file_object, pfc$purged_file_object, pfc$catalog_object, pfc$purged_catalog_object =
          IF pfc$validate_files IN set_overhaul_choices THEN
            p_new_path^ [new_path_index] := p_object_list^ [object_index].object_entry.external_object_name;
            validate_object_entry (p_new_path^, ^p_object_list^ [object_index], object_status);
            IF NOT object_status.normal THEN
              status := object_status;
              IF pfc$reconcile_fmds IN set_overhaul_choices THEN
                CASE p_object_list^ [object_index].object_entry.object_type OF
                = pfc$file_object, pfc$purged_file_object =
                  STRINGREP (text.value, text.size, 'File ');
                = pfc$catalog_object, pfc$purged_catalog_object =
                  STRINGREP (text.value, text.size, 'Catalog ');
                ELSE
                  STRINGREP (text.value, text.size, 'Catalog/file ');
                CASEND;
                p_new_path^ [new_path_index] := p_object_list^ [object_index].object_entry.
                      external_object_name;
                IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
                  p_object_list^ [object_index].object_entry.object_type := pfc$free_object;
                  pfp$compute_checksum (#LOC (p_object_list^ [object_index].object_entry),
                        #SIZE (pft$object_entry), p_object_list^ [object_index].checksum);
                IFEND;
                pfp$convert_pf_path_to_fs_path (p_new_path^, fs_path, fs_path_size);
                STRINGREP (text.value, text.size, text.value (1, text.size), fs_path (1, fs_path_size),
                      ' deleted.');
                pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
                      status);
              IFEND;
              CYCLE /overhaul_objects/;
            IFEND;
          IFEND;
          IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            p_new_object_list^ [new_object_index] := p_object_list^ [object_index];
            new_object_index := new_object_index + 1;
          IFEND;

        ELSE
          p_new_path^ [new_path_index] := p_object_list^ [object_index].object_entry.external_object_name;
          pfp$convert_pf_path_to_fs_path (p_new_path^, fs_path, fs_path_size);
          IF pfc$reconcile_fmds IN set_overhaul_choices THEN
            IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
              p_object_list^ [object_index].object_entry.object_type := pfc$free_object;
              pfp$compute_checksum (#LOC (p_object_list^ [object_index].object_entry),
                    #SIZE (pft$object_entry), p_object_list^ [object_index].checksum);
            IFEND;
            STRINGREP (text.value, text.size, 'Invalid object type; catalog/file ', fs_path (1, fs_path_size),
                  ' deleted.');
          ELSE
            STRINGREP (text.value, text.size, 'Invalid object type for catalog/file ',
                  fs_path (1, fs_path_size), '.');
          IFEND;
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
          pfv$overhaul_errors := pfv$overhaul_errors + 1;
        CASEND;
      FOREND /overhaul_objects/;

      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        physical_object.object_entry.object_type := pfc$free_object;
        pfp$compute_checksum (#LOC (physical_object.object_entry), #SIZE (pft$object_entry),
              physical_object.checksum);
        FOR object_index := new_object_index TO UPPERBOUND (p_new_object_list^) DO
          p_new_object_list^ [object_index] := physical_object;
        FOREND;
      IFEND;
    IFEND;
  PROCEND overhaul_object_list;

?? TITLE := '  overhaul_permit_list', EJECT ??

  PROCEDURE overhaul_permit_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         object_type: pft$object_types;
         p_permit_list: {input^} ^pft$permit_list;
         p_catalog_heap: {output^} ^pft$catalog_heap;
     VAR p_new_permit_list: ^pft$permit_list;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      high_permit_index: pft$permit_index,
      new_permit_index: pft$permit_index,
      p_catalog_path: ^pft$complete_path,
      path_index: pft$catalog_path_index,
      permit_count: pft$permit_count,
      permit_index: pft$permit_index,
      physical_permit: pft$physical_permit,
      text: pft$string;

    high_permit_index := UPPERBOUND (p_permit_list^);

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      permit_count := 0;

      FOR permit_index := 1 TO high_permit_index DO
        IF p_permit_list^ [permit_index].permit_entry.entry_type = pfc$normal_permit_entry THEN
          permit_count := permit_count + 1;
        IFEND;
      FOREND;

      IF permit_count = 0 THEN
        p_new_permit_list := NIL;
        status.normal := TRUE;
        RETURN;
      IFEND;

      ALLOCATE p_new_permit_list: [1 .. permit_count] IN p_catalog_heap^;
      IF p_new_permit_list = NIL THEN
        IF object_type IN $pft$object_selections [pfc$catalog_object, pfc$purged_catalog_object] THEN
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        ELSE
          PUSH p_catalog_path: [1 .. UPPERBOUND (path) - 1];
          FOR path_index := 1 TO UPPERBOUND (p_catalog_path^) DO
            p_catalog_path^ [path_index] := path [path_index];
          FOREND;
          pfp$convert_pf_path_to_fs_path (p_catalog_path^, fs_path, fs_path_size);
        IFEND;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, fs_path (1, fs_path_size),
              status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      ELSE
        status.normal := TRUE;
      IFEND;
    ELSE
      p_new_permit_list := p_permit_list;
      status.normal := TRUE;
    IFEND;

    IF status.normal THEN
      new_permit_index := 1;

      FOR permit_index := 1 TO high_permit_index DO
        CASE p_permit_list^ [permit_index].permit_entry.entry_type OF
        = pfc$free_permit_entry =
          {
          { Do nothing.
          {

        = pfc$normal_permit_entry =
          IF pfc$validate_files IN set_overhaul_choices THEN
            validate_permit_entry (path, object_type, ^p_permit_list^ [permit_index], status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
          IFEND;
          IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            p_new_permit_list^ [new_permit_index] := p_permit_list^ [permit_index];
            new_permit_index := new_permit_index + 1;
          IFEND;

        ELSE
          CASE object_type OF
          = pfc$file_object, pfc$purged_file_object =
            STRINGREP (text.value, text.size, 'Invalid permit entry type for file ');
          = pfc$catalog_object, pfc$purged_catalog_object =
            STRINGREP (text.value, text.size, 'Invalid permit entry type for catalog ');
          ELSE
            STRINGREP (text.value, text.size, 'Invalid permit entry type for catalog/file ');
          CASEND;
          pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
          STRINGREP (text.value, text.size, text.value (1, text.size), fs_path (1, fs_path_size), '.');
          pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
          pfv$overhaul_errors := pfv$overhaul_errors + 1;
          IF pfc$reconcile_fmds IN set_overhaul_choices THEN
            RETURN;
          IFEND;
        CASEND;
      FOREND;

      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        physical_permit.permit_entry.entry_type := pfc$free_permit_entry;
        pfp$compute_checksum (#LOC (physical_permit.permit_entry), #SIZE (pft$permit_entry),
              physical_permit.checksum);
        FOR permit_index := new_permit_index TO UPPERBOUND (p_new_permit_list^) DO
          p_new_permit_list^ [permit_index] := physical_permit;
        FOREND;
      IFEND;
    IFEND;
  PROCEND overhaul_permit_list;

?? TITLE := '  overhaul_physical_catalog', EJECT ??

  PROCEDURE overhaul_physical_catalog
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         reconcile_locator: dmt$reconcile_locator;
         authority: pft$authority;
     VAR old_catalog_locator: {i/o} pft$catalog_locator;
     VAR new_catalog_locator: pft$catalog_locator;
     VAR moved_or_destroyed_child: boolean;
     VAR status: ost$status);

    CONST
      block_exit = TRUE,
      second = 1000000 {mics/sec};

    VAR
      conditions: pmt$condition,
      current_date_time: ost$date_time,
      current_time: ost$time,
      current_timestamp: integer,
      found: boolean,
      fs_path_size: fst$path_size,
      established_handler: pmt$established_handler,
      local_status: ost$status,
      minimum_timestamp_interval: integer,
      maximum_timestamp_interval: integer,
      p_fs_path: ^fst$path,
      p_new_object_list: ^pft$object_list,
      scratch_segment_pointer: amt$segment_pointer,
      space_index: 1 .. osc$max_name_size + 1,
      text: pft$string;


    PROCEDURE condition_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;

      IF (condition.selector = pmc$system_conditions) OR
            (condition.selector = mmc$segment_access_condition) THEN
        osp$set_status_from_condition (pfc$permanent_file_manager_id, condition, p_sfsa, status,
              local_status);
        IF local_status.normal THEN
          pfp$log_error (status, ascii_logset, message_origin,
                (critical_message OR syv$nosve_internal_operations));
        ELSE
          pfp$log_error (local_status, ascii_logset, message_origin,
                (critical_message OR syv$nosve_internal_operations));
          status := local_status;
        IFEND;

        IF syv$nosve_internal_operations THEN
          pfp$log_ascii (
                'Invoking system core debugger, from overhaul_physical_catalog, due to unexpected condition.',
                ascii_logset, message_origin, {critical_message} TRUE, local_status);
          pfp$log_ascii ('Contact PF project.', ascii_logset, message_origin, {critical_message} TRUE,
                local_status);
          syp$invoke_system_debugger ('', 0, local_status);
        IFEND;

        previous_timestamp := #free_running_clock (0);
        EXIT overhaul_physical_catalog;
      ELSE
        {
        { Ignore the condition.
        {
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;
    PROCEND condition_handler;


    current_timestamp := #free_running_clock (0);
    minimum_timestamp_interval := dmv$ds_msg_update_interval * second;
    maximum_timestamp_interval := 15 * dmv$ds_msg_update_interval * second DIV 10;
    IF ((UPPERBOUND (path) = pfc$master_catalog_path_index) AND
          (previous_timestamp + minimum_timestamp_interval <= current_timestamp)) OR
          (previous_timestamp + maximum_timestamp_interval <= current_timestamp) THEN
      STRINGREP (text.value, text.size, '    Recovering ');
      IF UPPERBOUND (path) = pfc$master_catalog_path_index THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        STRINGREP (text.value, text.size, text.value (1, text.size), p_fs_path^ (1, fs_path_size), '.');
        previous_master_catalog := path [pfc$master_catalog_path_index];
      ELSE
        #SCAN (pfv$space_character, path [pfc$family_path_index], space_index, found);
        STRINGREP (text.value, text.size, text.value (1, text.size), ':',
              path [pfc$family_path_index] (1, space_index - 1), '.');
        IF UPPERBOUND (path) = pfc$family_path_index THEN
          previous_master_catalog := osc$null_name;
        ELSE
          #SCAN (pfv$space_character, path [pfc$master_catalog_path_index], space_index, found);
          STRINGREP (text.value, text.size, text.value (1, text.size),
                path [pfc$master_catalog_path_index] (1, space_index - 1), '.');
          IF path [pfc$master_catalog_path_index] = previous_master_catalog THEN
            #SCAN (pfv$space_character, path [UPPERBOUND (path)], space_index, found);
            STRINGREP (text.value, text.size, text.value (1, text.size), '..',
                  path [UPPERBOUND (path)] (1, space_index - 1), '.');
          ELSE
            previous_master_catalog := path [pfc$master_catalog_path_index];
          IFEND;
        IFEND;
      IFEND;
      pmp$get_date_time_at_timestamp (current_timestamp, pmc$use_system_local_time, current_date_time,
            local_status);
      IF local_status.normal THEN
        pmp$format_compact_time (current_date_time, osc$hms_time, current_time, local_status);
        IF local_status.normal THEN
          STRINGREP (text.value, text.size, text.value (1, text.size - 1), ' at ', current_time.hms);
        IFEND;
      IFEND;
      dpp$put_next_line (dpv$system_core_display, text.value (1, text.size), local_status);
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
            local_status);
      previous_timestamp := current_timestamp;
    IFEND;

    moved_or_destroyed_child := FALSE;
    osp$establish_condition_handler (^condition_handler, NOT block_exit);

    IF pfc$validate_files IN set_overhaul_choices THEN
      validate_catalog_header (path, ^old_catalog_locator.p_catalog_file^.physical_catalog_header, status);
    ELSE
      status.normal := TRUE;
    IFEND;

    IF status.normal THEN
      IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        {
        { Create a scratch catalog in which the old catalog data will be
        { reorganized.
        {
        mmp$create_scratch_segment (amc$cell_pointer, mmc$as_random, scratch_segment_pointer, status);
        IF status.normal THEN
          initialize_catalog_locator (old_catalog_locator, scratch_segment_pointer.cell_pointer,
                new_catalog_locator);
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      ELSE
        new_catalog_locator := old_catalog_locator;
      IFEND;

      IF status.normal THEN
        IF old_catalog_locator.object_list_descriptor.p_object_list <> NIL THEN
          overhaul_catalog_content (set_overhaul_choices, path, reconcile_locator,
                old_catalog_locator.p_catalog_file, authority, old_catalog_locator.object_list_descriptor,
                new_catalog_locator, moved_or_destroyed_child, p_new_object_list, status);
        ELSE
          p_new_object_list := NIL;
        IFEND;
        IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
          IF status.normal OR (status.condition = pfe$recovery_summary) THEN
            new_catalog_locator.object_list_descriptor.p_object_list := NIL;
            pfp$update_object_list_locator (^path, p_new_object_list, new_catalog_locator.p_catalog_file,
                  new_catalog_locator.object_list_descriptor);
          ELSE
            scratch_segment_pointer.cell_pointer := new_catalog_locator.p_catalog_file;
            mmp$delete_scratch_segment (scratch_segment_pointer, local_status);
            pfp$process_unexpected_status (local_status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND overhaul_physical_catalog;

?? TITLE := '  overhaul_sorted_object_list', EJECT ??

  PROCEDURE overhaul_sorted_object_list
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
     VAR object_list_descriptor: {i/o} pft$object_list_descriptor;
     VAR new_catalog_locator: pft$catalog_locator;
     VAR p_new_object_list: ^pft$object_list;
     VAR status: ost$status);

    VAR
      fs_path_size: fst$path_size,
      new_path_index: pft$file_path_index,
      object_count: pft$object_count,
      object_index: pft$object_index,
      object_status: ost$status,
      p_fs_path: ^fst$path,
      p_new_path: ^pft$complete_path,
      p_object_list: ^pft$object_list,
      path_index: pft$catalog_path_index,
      sort_object_list: boolean,
      text: pft$string;

    status.normal := TRUE;
    p_object_list := object_list_descriptor.p_object_list;
    sort_object_list := pfv$sort_catalog_object_list;

    new_path_index := UPPERBOUND (path) + 1;
    PUSH p_new_path: [1 .. new_path_index];
    FOR path_index := 1 TO UPPERBOUND (path) DO
      p_new_path^ [path_index] := path [path_index];
    FOREND;
    {
    { Validate each object in the old object list.
    {
    FOR object_index := 1 TO UPPERBOUND (p_object_list^) DO
      CASE p_object_list^ [object_index].object_entry.object_type OF
      = pfc$free_object =
        {
        { Do nothing.
        {

      = pfc$file_object, pfc$purged_file_object, pfc$catalog_object, pfc$purged_catalog_object =
        IF pfc$validate_files IN set_overhaul_choices THEN
          p_new_path^ [new_path_index] := p_object_list^ [object_index].object_entry.external_object_name;
          validate_object_entry (p_new_path^, ^p_object_list^ [object_index], object_status);
          IF NOT object_status.normal THEN
            status := object_status;
            IF pfc$reconcile_fmds IN set_overhaul_choices THEN
              CASE p_object_list^ [object_index].object_entry.object_type OF
              = pfc$file_object, pfc$purged_file_object =
                STRINGREP (text.value, text.size, 'File ');
              = pfc$catalog_object, pfc$purged_catalog_object =
                STRINGREP (text.value, text.size, 'Catalog ');
              ELSE
                STRINGREP (text.value, text.size, 'Catalog/file ');
              CASEND;
              p_object_list^ [object_index].object_entry.object_type := pfc$free_object;
              pfp$compute_checksum (#LOC (p_object_list^ [object_index].object_entry),
                    #SIZE (pft$object_entry), p_object_list^ [object_index].checksum);
              IF object_index <= object_list_descriptor.sorted_object_count THEN
                object_list_descriptor.free_sorted_object_count :=
                      object_list_descriptor.free_sorted_object_count + 1;
              IFEND;
              PUSH p_fs_path;
              pfp$convert_pf_path_to_fs_path (p_new_path^, p_fs_path^, fs_path_size);
              STRINGREP (text.value, text.size, text.value (1, text.size), p_fs_path^ (1, fs_path_size),
                    ' deleted.');
              pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message,
                    status);
            IFEND;
          IFEND;
        IFEND;

      ELSE
        p_new_path^ [new_path_index] := p_object_list^ [object_index].object_entry.external_object_name;
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (p_new_path^, p_fs_path^, fs_path_size);
        IF pfc$reconcile_fmds IN set_overhaul_choices THEN
          p_object_list^ [object_index].object_entry.object_type := pfc$free_object;
          pfp$compute_checksum (#LOC (p_object_list^ [object_index].object_entry),
                #SIZE (pft$object_entry), p_object_list^ [object_index].checksum);
          IF object_index <= object_list_descriptor.sorted_object_count THEN
            object_list_descriptor.free_sorted_object_count :=
                  object_list_descriptor.free_sorted_object_count + 1;
          IFEND;
          STRINGREP (text.value, text.size, 'Invalid object type; catalog/file ',
                p_fs_path^ (1, fs_path_size), ' deleted.');
        ELSE
          STRINGREP (text.value, text.size, 'Invalid object type for catalog/file ',
                p_fs_path^ (1, fs_path_size), '.');
        IFEND;
        pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
        osp$set_status_condition (pfe$recovery_summary, status);
        pfv$overhaul_errors := pfv$overhaul_errors + 1;
      CASEND;
      {
      { Verify the sorted portion of the object is actually sorted. If it
      { isn't, force sorting to occur.
      {
      IF (object_index > 1) AND (object_index <= object_list_descriptor.sorted_object_count) AND
            (p_object_list^ [object_index].object_entry.external_object_name <
            p_object_list^ [object_index - 1].object_entry.external_object_name) THEN
        sort_object_list := TRUE;
      IFEND;
    FOREND;

    IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      {
      { Allocate space in the new catalog for the object list; sort the object
      { list, if necessary; and move the objects from the old object list to
      { the new object list.
      {
      ALLOCATE p_new_object_list: [1 .. UPPERBOUND (p_object_list^)] IN
            new_catalog_locator.p_catalog_file^.catalog_heap;
      IF p_new_object_list = 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$catalog_full,
              p_fs_path^ (1, fs_path_size), status);
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
      ELSE
        status.normal := TRUE;
      IFEND;

      IF sort_object_list OR (object_list_descriptor.sorted_object_count = 0) THEN
        pfp$sort_object_list (p_object_list, p_new_object_list, new_catalog_locator.object_list_descriptor);
      ELSE
        FOR object_index := 1 to UPPERBOUND (p_object_list^) DO
          p_new_object_list^ [object_index] := p_object_list^ [object_index];
        FOREND;

        new_catalog_locator.object_list_descriptor.p_object_list := p_new_object_list;
        new_catalog_locator.object_list_descriptor.sorted_object_count :=
              object_list_descriptor.sorted_object_count;
        new_catalog_locator.object_list_descriptor.free_sorted_object_count :=
              object_list_descriptor.free_sorted_object_count;
      IFEND;
    ELSE
      p_new_object_list := p_object_list;
    IFEND;
  PROCEND overhaul_sorted_object_list;

?? TITLE := '  replace_catalog', EJECT ??

  PROCEDURE replace_catalog
    (    path: pft$complete_path;
         new_catalog_locator: pft$catalog_locator;
         p_parent_catalog_file: {output^} ^pft$catalog_file;
         p_catalog_object: {output^} ^pft$physical_object;
     VAR p_new_physical_fmd: {output} ^pft$physical_fmd;
     VAR status: ost$status);

    VAR
      local_status: ost$status,
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_physical_fmd: ^pft$physical_fmd,
      p_root: ^pft$root,
      p_stored_fmd: ^dmt$stored_fmd,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      stored_fmd_size: dmt$stored_fmd_size;

    p_new_physical_fmd := NIL;
    IF UPPERBOUND (path) = pfc$set_path_index THEN
      dmp$get_stored_fmd_size (new_catalog_locator.system_file_id, stored_fmd_size, status);
      IF status.normal THEN
        {
        { Update the file media descriptor for the root catalog.
        {
        PUSH p_root: [[REP 1 OF pft$internal_catalog_name, REP 1 OF dmt$stored_fmd_size,
              REP stored_fmd_size OF cell]];
        RESET p_root;
        NEXT p_internal_catalog_name IN p_root;
        p_internal_catalog_name^ := new_catalog_locator.global_file_name;
        NEXT p_stored_fmd_size IN p_root;
        p_stored_fmd_size^ := stored_fmd_size;
        NEXT p_stored_fmd: [[REP stored_fmd_size OF cell]] IN p_root;
        dmp$get_stored_fmd (new_catalog_locator.system_file_id, p_stored_fmd^, status);
        IF status.normal THEN
          {
          { Update Device Management tables to make sure the new catalog
          { structure is permanently recorded before changing the root. This
          { update prevents the loss of any catalogs should the system crash
          { and require recovery without image before periodic update occurs.
          {
          dmp$dev_mgmt_table_update;
          stp$store_pf_root (path [pfc$set_path_index], p_root^, status);
          pfp$process_unexpected_status (status);
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    ELSE
      {
      { Update the file media descriptor for a subcatalog in a parent catalog.
      {
      pfp$record_dm_file_parameters (^path, {p_cycle_number} NIL, new_catalog_locator.system_file_id,
            {device_class} rmc$mass_storage_device, {p_removable_media_req_info} NIL,
            {p_volume_list} NIL, ^p_parent_catalog_file^.catalog_heap, p_new_physical_fmd, status);
      IF status.normal THEN
        p_catalog_object^.object_entry.catalog_object_locator.global_file_name :=
              new_catalog_locator.global_file_name;
        pfp$build_fmd_locator (p_new_physical_fmd, p_parent_catalog_file,
              p_catalog_object^.object_entry.catalog_object_locator.fmd_locator);
        pfp$compute_checksum (#LOC (p_catalog_object^.object_entry), #SIZE (pft$object_entry),
              p_catalog_object^.checksum);
      IFEND;
    IFEND;
  PROCEND replace_catalog;

?? TITLE := '  update_fmd', EJECT ??

  PROCEDURE update_fmd
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         p_cycle_number: ^fst$cycle_number;
         global_file_name: pft$internal_name;
         reconcile_locator: dmt$reconcile_locator;
         new_stored_fmd_size: dmt$stored_fmd_size;
         purge_object: boolean;
         p_catalog_heap: {output^} ^pft$catalog_heap;
     VAR p_old_physical_fmd: {i^/o} ^pft$physical_fmd;
     VAR p_new_physical_fmd: ^pft$physical_fmd;
     VAR status: ost$status);

    VAR
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      prevalidate_free_result: ost$prevalidate_free_result;

    ALLOCATE p_new_physical_fmd: [[REP new_stored_fmd_size OF cell]] IN p_catalog_heap^;
    IF p_new_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$catalog_full, fs_path (1, fs_path_size),
            status);
      pfp$log_error (status, ascii_logset, message_origin, critical_message);
    ELSE
      dmp$get_reconciled_fmd (reconcile_locator, global_file_name, p_old_physical_fmd^.fmd,
            p_new_physical_fmd^.fmd, status);
      IF status.normal THEN
        pfp$compute_checksum (#LOC (p_new_physical_fmd^.fmd), #SIZE (p_new_physical_fmd^.fmd),
              p_new_physical_fmd^.checksum);
        IF NOT (pfc$reorganize_catalogs IN set_overhaul_choices) THEN
          {
          { The fmd still exists in the "new" catalog. (It will not have been
          { allocated in the new catalog when reorganizing.)
          {
          osp$prevalidate_free ((#OFFSET(p_old_physical_fmd) - #OFFSET(p_catalog_heap) - 16),
                p_catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_old_physical_fmd IN p_catalog_heap^;
          ELSE
            pfp$report_invalid_free (^path, p_cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
                  prevalidate_free_result, #OFFSET(p_old_physical_fmd));
            p_old_physical_fmd := NIL;
          IFEND;
        IFEND;
      ELSEIF NOT purge_object THEN
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
        pfp$log_ascii ('Previous error from dmp$get_reconciled_fmd.', ascii_logset, message_origin,
              critical_message, status);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
        pfv$overhaul_errors := pfv$overhaul_errors + 1;
      IFEND;
    IFEND;
  PROCEND update_fmd;

?? TITLE := '  update_stale_eoi', EJECT ??

  PROCEDURE update_stale_eoi
    (    p_path: ^pft$complete_path;
         p_physical_fmd: ^pft$physical_fmd;
         p_cycle: ^pft$physical_cycle;
         p_catalog_file: ^pft$catalog_file);

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

    IF (p_physical_fmd = NIL) OR (p_cycle = NIL) OR (p_catalog_file = NIL) THEN
      RETURN;
    IFEND;

    dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file, p_physical_fmd^.fmd,
          $pft$usage_selections [pfc$read], $pft$share_selections [pfc$read], pfc$average_share_history,
          pfc$maximum_pf_length, {restricted_attach} FALSE, {exit_on_unknown_file} FALSE,
          {server_file} FALSE, mmc$null_shared_queue, file_damaged, system_file_id, existing_sft_entry,
          local_status);

    IF local_status.normal AND (existing_sft_entry = dmc$restricted_attach_entry) THEN
      dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
            p_physical_fmd^.fmd, $pft$usage_selections [pfc$read], $pft$share_selections [pfc$read],
            pfc$average_share_history, pfc$maximum_pf_length, {restricted_attach} TRUE,
            {exit_on_unknown_file} FALSE, {server_file} FALSE, mmc$null_shared_queue, file_damaged,
            system_file_id,  existing_sft_entry, local_status);
    IFEND;

    IF local_status.normal THEN
      p_cycle^.cycle_entry.attach_status.attach_count := 0;
      pfp$update_stale_cycle_entry (system_file_id, p_cycle, local_status);
      pfp$detach_permanent_file (p_path, system_file_id, $pft$usage_selections [pfc$read],
            {catalog_access_allowed} TRUE, p_cycle, p_catalog_file, dmc$df_ignore_file_info,
            fmd_modified, file_info, local_status);
    IFEND;
  PROCEND update_stale_eoi;

?? TITLE := '  validate_amd', EJECT ??

  PROCEDURE validate_amd
    (    path: pft$complete_path;
         cycle_number: fst$cycle_number;
         p_amd: pft$p_physical_amd;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    IF p_amd <> NIL THEN
      pfp$compute_checksum (#LOC (p_amd^.amd), #SIZE (p_amd^.amd), checksum);
      IF checksum = p_amd^.checksum THEN
        status.normal := TRUE;
        RETURN;
      IFEND;
    IFEND;

    pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
    STRINGREP (text.value, text.size, 'Invalid archive media descriptor for cycle ',
          fs_path (1, fs_path_size), cycle_number, '.');
    text.value (44 + fs_path_size) := '.';
    pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
    pfp$display_memory_to_log (#LOC (p_amd^.amd), #SIZE (p_amd^.amd));
    osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
    pfv$overhaul_errors := pfv$overhaul_errors + 1;
  PROCEND validate_amd;

?? TITLE := '  validate_archive_entry', EJECT ??

  PROCEDURE validate_archive_entry
    (    path: pft$complete_path;
         cycle_number: fst$cycle_number;
         p_archive: pft$p_archive;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_archive^.archive_entry), #SIZE (pft$archive_entry), checksum);
    IF checksum = p_archive^.checksum THEN
      status.normal := TRUE;
    ELSE
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, 'Invalid archive entry for cycle ', fs_path (1, fs_path_size),
            cycle_number, '.');
      text.value (33 + fs_path_size) := '.';
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_archive^.archive_entry), #SIZE (pft$archive_entry));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_archive_entry;

?? TITLE := '  validate_catalog_header', EJECT ??

  PROCEDURE validate_catalog_header
    (    path: pft$complete_path;
         p_physical_catalog_header: {input^} ^pft$physical_catalog_header;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      found: boolean,
      fs_path_size: fst$path_size,
      p_fs_path: ^fst$path,
      space_index: 1 .. osc$max_name_size + 1,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_physical_catalog_header^.catalog_header), #SIZE (pft$catalog_header),
          checksum);
    IF checksum = p_physical_catalog_header^.checksum THEN
      status.normal := TRUE;
    ELSE
      IF UPPERBOUND (path) = pfc$set_path_index THEN
        #SCAN (pfv$space_character, path [pfc$set_path_index], space_index, found);
      pfp$display_memory_to_log (#LOC (p_physical_catalog_header^.catalog_header),
            #SIZE (pft$catalog_header));
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$bad_root_catalog_header,
              path [pfc$set_path_index] (1, space_index - 1), status);
      ELSE
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        STRINGREP (text.value, text.size, 'Invalid catalog header for catalog ',
              p_fs_path^ (1, fs_path_size));
        pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
        pfp$display_memory_to_log (#LOC (p_physical_catalog_header^.catalog_header),
               #SIZE (pft$catalog_header));
        {
        { Temporarily set the status to pfe$bad_root_catalog_header;
        { overhaul_external_catalog will map it to pfe$recovery_summary.
        {
        osp$set_status_condition (pfe$bad_root_catalog_header, status);
      IFEND;
    IFEND;
  PROCEND validate_catalog_header;

?? TITLE := '  validate_cycle_entry', EJECT ??

  PROCEDURE validate_cycle_entry
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         p_cycle: {input^} ^pft$physical_cycle;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), checksum);
    IF checksum = p_cycle^.checksum THEN
      status.normal := TRUE;
    ELSE
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      IF (p_cycle^.cycle_entry.entry_type = pfc$normal_cycle_entry) OR
            ((p_cycle^.cycle_entry.entry_type = pfc$purged_cycle_entry) AND
            (pfc$recover_purged_files IN set_overhaul_choices)) THEN
        STRINGREP (text.value, text.size, 'Invalid cycle entry for cycle ', fs_path (1, fs_path_size),
              p_cycle^.cycle_entry.cycle_number);
        text.value (31 + fs_path_size) := '.';
      ELSE
        STRINGREP (text.value, text.size, 'Invalid cycle entry for cycle ', fs_path (1, fs_path_size), '.?');
      IFEND;
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_cycle_entry;

?? TITLE := '  validate_file_label', EJECT ??

  PROCEDURE validate_file_label
    (    path: pft$complete_path;
         cycle_number: fst$cycle_number;
         p_stored_file_label: {input^} ^pft$physical_file_label;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_stored_file_label^.file_label), #SIZE (p_stored_file_label^.file_label),
          checksum);
    IF checksum = p_stored_file_label^.checksum THEN
      status.normal := TRUE;
    ELSE
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, 'Invalid file label for cycle ', fs_path (1, fs_path_size),
            cycle_number, '.');
      text.value (30 + fs_path_size) := '.';
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_stored_file_label^.file_label),
             #SIZE (p_stored_file_label^.file_label));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_file_label;

?? TITLE := '  validate_fmd', EJECT ??

  PROCEDURE validate_fmd
    (    path: pft$complete_path;
         catalog_or_cycle: pft$catalog_or_cycle;
         p_physical_fmd: {input^} ^pft$physical_fmd;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_physical_fmd^.fmd), #SIZE (p_physical_fmd^.fmd), checksum);
    IF checksum = p_physical_fmd^.checksum THEN
      status.normal := TRUE;
    ELSE
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      IF catalog_or_cycle.cycle_specified THEN
        STRINGREP (text.value, text.size, 'Invalid FMD for cycle ', fs_path (1, fs_path_size),
              catalog_or_cycle.cycle_number, '.');
        text.value (23 + fs_path_size) := '.';
      ELSE
        STRINGREP (text.value, text.size, 'Invalid FMD for catalog ', fs_path (1, fs_path_size), '.');
      IFEND;
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_physical_fmd^.fmd), #SIZE (p_physical_fmd^.fmd));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_fmd;

?? TITLE := '  validate_log_entry', EJECT ??

  PROCEDURE validate_log_entry
    (    path: pft$complete_path;
         p_log: {input^} ^pft$physical_log;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      log_name: fst$path,
      log_path: array [1 .. 3] of pft$name,
      log_size: fst$path_size,
      set_name: stt$set_name,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_log^.log_entry), #SIZE (pft$log_entry), checksum);
    IF checksum = p_log^.checksum THEN
      status.normal := TRUE;
    ELSE
      IF p_log^.log_entry.entry_type = pfc$normal_log_entry THEN
        pfp$get_family_set (p_log^.log_entry.user_id.family, set_name, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        log_path [1] := set_name;
        log_path [2] := p_log^.log_entry.user_id.family;
        log_path [3] := p_log^.log_entry.user_id.user;
        pfp$convert_pf_path_to_fs_path (log_path, log_name, log_size);
      ELSE
        log_name := '?';
        log_size := 1;
      IFEND;
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, 'Invalid log entry for user ', log_name (1, log_size), ' for file ',
            fs_path (1, fs_path_size));
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_log^.log_entry), #SIZE (pft$log_entry));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_log_entry;

?? TITLE := '  validate_object_entry', EJECT ??

  PROCEDURE validate_object_entry
    (    path: pft$complete_path;
         p_object: {input^} ^pft$physical_object;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_object^.object_entry), #SIZE (pft$object_entry), checksum);
    IF checksum = p_object^.checksum THEN
      status.normal := TRUE;
    ELSE
      CASE p_object^.object_entry.object_type OF
      = pfc$file_object, pfc$purged_file_object =
        STRINGREP (text.value, text.size, 'Invalid object entry for file ');
      = pfc$catalog_object, pfc$purged_catalog_object =
        STRINGREP (text.value, text.size, 'Invalid object entry for catalog ');
      ELSE
        STRINGREP (text.value, text.size, 'Invalid object entry for catalog/file ');
      CASEND;
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, text.value (1, text.size), fs_path (1, fs_path_size), '.');
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_object^.object_entry), #SIZE (pft$object_entry));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_object_entry;

?? TITLE := '  validate_overhaul_choices', EJECT ??

  PROCEDURE validate_overhaul_choices
    (    set_overhaul_choices: pft$set_overhaul_choices;
         ownership: pft$ownership;
     VAR new_set_overhaul_choices: pft$set_overhaul_choices;
     VAR status: ost$status);

    IF NOT (pfc$reconcile_fmds IN set_overhaul_choices) THEN
      IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
        {
        { By definition, deletion of irreconcilable catalogs and cycles cannot
        { be done without reconciliation.
        {
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$delete_needs_reconcile, '', status);
      ELSEIF pfc$reorganize_catalogs IN set_overhaul_choices THEN
        {
        { Currently reorganization cannot be done without reconciliation,
        { because the file media descriptors cannot be updated without
        { reconciliation.
        {
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$reorganize_needs_reconcile, '', status);
      IFEND;
    ELSEIF pfc$system_owner IN ownership THEN
      new_set_overhaul_choices := set_overhaul_choices;
      status.normal := TRUE;
    ELSEIF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      {
      { If the caller chooses reorganization and is not the system
      { administrator, then recovery of purged files will be performed as well.
      {
      new_set_overhaul_choices := set_overhaul_choices + $pft$set_overhaul_choices [pfc$recover_purged_files];
      status.normal := TRUE;
    ELSEIF set_overhaul_choices <= $pft$set_overhaul_choices [pfc$all_catalogs, pfc$recover_purged_files] THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$no_operation, '', status);
    IFEND;
  PROCEND validate_overhaul_choices;

?? TITLE := '  validate_permit_entry', EJECT ??

  PROCEDURE validate_permit_entry
    (    path: pft$complete_path;
         object_type: pft$object_types;
         p_permit: {input^} ^pft$physical_permit;
     VAR status: ost$status);

    VAR
      checksum: pft$checksum,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      text: pft$string;

    pfp$compute_checksum (#LOC (p_permit^.permit_entry), #SIZE (pft$permit_entry), checksum);
    IF checksum = p_permit^.checksum THEN
      status.normal := TRUE;
    ELSE
      CASE object_type OF
      = pfc$file_object, pfc$purged_file_object =
        STRINGREP (text.value, text.size, 'Invalid permit for file ');
      = pfc$catalog_object, pfc$purged_catalog_object =
        STRINGREP (text.value, text.size, 'Invalid permit for catalog ');
      ELSE
        STRINGREP (text.value, text.size, 'Invalid permit for catalog/file ');
      CASEND;
      pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
      STRINGREP (text.value, text.size, text.value (1, text.size), fs_path (1, fs_path_size), '.');
      pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, critical_message, status);
      pfp$display_memory_to_log (#LOC (p_permit^.permit_entry), #SIZE (pft$permit_entry));
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$recovery_summary, '', status);
      pfv$overhaul_errors := pfv$overhaul_errors + 1;
    IFEND;
  PROCEND validate_permit_entry;

?? TITLE := '  write_modified_catalog', EJECT ??

  PROCEDURE write_modified_catalog
    (    set_overhaul_choices: pft$set_overhaul_choices;
         path: pft$complete_path;
         resides_on_system_device: boolean;
         mass_storage_classes: dmt$class;
         catalog_segment_length: ost$segment_length;
         reconcile_locator: dmt$reconcile_locator;
         p_catalog_fmd: {input^} ^pft$fmd;
         authority: pft$authority;
         p_parent_catalog_file: {output^} ^pft$catalog_file;
         p_catalog_object: {output^} ^pft$physical_object;
     VAR p_new_physical_fmd: {output} ^pft$physical_fmd;
     VAR old_catalog_locator: {i/o} pft$catalog_locator;
     VAR moved_or_destroyed_catalog: boolean;
     VAR status: ost$status);

    CONST
      byte_address = 0,
      chapter = 0,
      max_attempts = 3,
      purge_catalog = TRUE;

    VAR
      attempt_count: [STATIC] 1 .. max_attempts := 1,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      local_mass_storage_classes: dmt$class,
      local_resides_on_system_device: boolean,
      local_status: ost$status,
      master_info: stt$volume_info,
      member_count: stt$number_of_members,
      member_list: ^stt$volume_list,
      move_catalog: boolean,
      move_root_message: string(61),
      new_catalog_locator: pft$catalog_locator,
      p_mass_storage_request_info: ^fmt$mass_storage_request_info,
      stored_fmd_size: dmt$stored_fmd_size,
      system_catalog: boolean,
      text: pft$string;

    p_new_physical_fmd := NIL;

    IF UPPERBOUND (path) = pfc$set_path_index THEN
      {
      { Just need master vsn.
      {
      PUSH member_list: [1 .. 1];
      stp$get_volumes_in_set (path [pfc$set_path_index], master_info, member_list^, member_count, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      PUSH p_mass_storage_request_info;
      p_mass_storage_request_info^.allocation_size := rmc$unspecified_allocation_size;
      p_mass_storage_request_info^.estimated_file_size := rmc$unspecified_file_size;
      p_mass_storage_request_info^.mass_storage_class := rmc$msc_system_catalogs;
      p_mass_storage_request_info^.initial_volume := master_info.recorded_vsn;
      p_mass_storage_request_info^.maintenance_job := FALSE;
      p_mass_storage_request_info^.transfer_size := rmc$unspecified_transfer_size;
      p_mass_storage_request_info^.user_privilege := rmc$system_user;
      p_mass_storage_request_info^.volume_overflow_allowed := FALSE;

      move_catalog := NOT resides_on_system_device;
      IF move_catalog THEN
        move_root_message (1,54) := 'INFORMATIVE: Moving root catalog to set master volume ';
        move_root_message (55, 6) := master_info.recorded_vsn;
        move_root_message (61, 1) := '.';
        pfp$log_ascii (move_root_message (1,61), ascii_logset, message_origin, critical_message, status);
      IFEND;
      local_resides_on_system_device := TRUE;
      local_mass_storage_classes := mass_storage_classes + $dmt$class [rmc$msc_system_critical_files];
    ELSE
      p_mass_storage_request_info := NIL;
      system_catalog := pfp$system_path (path);
      move_catalog := (system_catalog AND NOT (rmc$msc_system_catalogs IN mass_storage_classes)) OR
            ((NOT system_catalog) AND NOT (rmc$msc_user_catalogs IN mass_storage_classes));
      local_resides_on_system_device := resides_on_system_device;
      local_mass_storage_classes := mass_storage_classes +
            $dmt$class [rmc$msc_system_catalogs, rmc$msc_user_catalogs];
    IFEND;

    IF NOT move_catalog THEN
      mmp$write_modified_pages (old_catalog_locator.p_catalog_file, catalog_segment_length, osc$wait,
            status);
    IFEND;

    IF move_catalog OR ((NOT status.normal) AND (attempt_count < max_attempts)) THEN
      {
      { Create a new catalog and allocate the necessary space.
      {
      pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} FALSE,
            new_catalog_locator, status);
      IF status.normal THEN
        dmp$allocate_file_space_r1 (new_catalog_locator.system_file_id, byte_address, catalog_segment_length,
              chapter, osc$nowait, sfc$no_limit, status);
        IF (NOT status.normal) AND ((status.condition = dme$unable_to_alloc_all_space) OR
              (status.condition = dme$volume_unavailable) OR (status.condition = dme$some_volumes_not_online))
              AND NOT out_of_space THEN
          {
          { The MAT may be out of space.  Allow it a chance to be refilled from
          { the DAT and try again.
          {
          pmp$delay (1000 {1 second}, status);
          dmp$allocate_file_space_r1 (new_catalog_locator.system_file_id, byte_address,
                catalog_segment_length, chapter, osc$nowait, sfc$no_limit, status);
          IF (NOT status.normal) AND ((status.condition = dme$unable_to_alloc_all_space) OR
                (status.condition = dme$volume_unavailable) OR
                (status.condition = dme$some_volumes_not_online)) THEN
            {
            { Allow the logger a chance to run and try again.
            {
            pmp$delay (90000 {1.5 minutes}, status);
            dmp$allocate_file_space_r1 (new_catalog_locator.system_file_id, byte_address,
                  catalog_segment_length, chapter, osc$nowait, sfc$no_limit, status);
            out_of_space := (NOT status.normal) AND ((status.condition = dme$unable_to_alloc_all_space) OR
                  (status.condition = dme$volume_unavailable) OR
                  (status.condition = dme$some_volumes_not_online));
          IFEND;
        IFEND;
      IFEND;
      {
      { Copy the reconciled/reorganized catalog to the new catalog and call
      { write_modified_catalog to try again.
      {
      IF status.normal THEN
        i#move (old_catalog_locator.p_catalog_file, new_catalog_locator.p_catalog_file,
              catalog_segment_length);
        IF NOT move_catalog THEN
          attempt_count := attempt_count + 1;
        IFEND;
        write_modified_catalog (set_overhaul_choices, path, local_resides_on_system_device,
              local_mass_storage_classes, catalog_segment_length, reconcile_locator, p_catalog_fmd,
              authority, p_parent_catalog_file, p_catalog_object, p_new_physical_fmd,
              new_catalog_locator, moved_or_destroyed_catalog, status);
        IF NOT move_catalog THEN
          attempt_count := attempt_count - 1;
        IFEND;

        IF status.normal AND (attempt_count = 1) THEN
          replace_catalog (path, new_catalog_locator, p_parent_catalog_file, p_catalog_object,
                p_new_physical_fmd, status);
          IF status.normal THEN
            IF pfc$delete_unreconciled_objects IN set_overhaul_choices THEN
              dmp$reconcile_fmd (reconcile_locator, old_catalog_locator.global_file_name, p_catalog_fmd^,
                    purge_catalog, local_mass_storage_classes, stored_fmd_size,
                    local_resides_on_system_device, local_status);
            ELSE
              dmp$destroy_permanent_file (old_catalog_locator.global_file_name, p_catalog_fmd^,
                    local_status);
            IFEND;

            catalog_moved := TRUE;
            moved_or_destroyed_catalog := TRUE;
            IF move_catalog THEN
              pfv$catalogs_moved := pfv$catalogs_moved + 1;
            IFEND;
          IFEND;
        IFEND;

        IF status.normal THEN
          pfp$return_catalog (old_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          old_catalog_locator := new_catalog_locator;
        ELSE
          pfp$destroy_catalog (new_catalog_locator, local_status);
        IFEND;
      ELSE
        IF move_catalog AND (p_mass_storage_request_info <> NIL) THEN
          pfp$log_ascii ('INFORMATIVE: Unable to move root catalog to set master volume.',
                ascii_logset, message_origin, critical_message, status);
          status.normal := TRUE;
        ELSE
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
        IFEND;
      IFEND;
    ELSEIF NOT status.normal THEN
        pfp$log_error (status, ascii_logset, message_origin, critical_message);
    ELSEIF pfc$reorganize_catalogs IN set_overhaul_choices THEN
      {
      { The file media descriptor (fmd) must be allocated in the new, parent
      { catalog. (The fmd still exists in the parent catalog when not
      { reorganizing.)
      {
      replace_catalog (path, old_catalog_locator, p_parent_catalog_file, p_catalog_object,
            p_new_physical_fmd, status);
    IFEND;

    IF (NOT status.normal) AND (attempt_count = 1) THEN
      pfp$log_ascii ('Previous error from write_modified_catalog.', ascii_logset, message_origin,
            critical_message, local_status);
      IF move_catalog THEN
        mmp$write_modified_pages (old_catalog_locator.p_catalog_file, catalog_segment_length, osc$wait,
              status);
        IF status.normal THEN
          IF pfc$reorganize_catalogs IN set_overhaul_choices THEN
            {
            { The file media descriptor (fmd) must be allocated in the new,
            { parent catalog. (The fmd still exists in the parent catalog when
            { not reorganizing.)
            {
            replace_catalog (path, old_catalog_locator, p_parent_catalog_file, p_catalog_object,
                  p_new_physical_fmd, status);
          IFEND;
          IF status.normal THEN
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            STRINGREP (text.value, text.size, 'Unable to move catalog ', fs_path (1, fs_path_size),
                  ' to a catalog device; it will continue to reside on a non catalog device.');
            pfp$log_ascii (text.value (1, text.size), ascii_logset, message_origin, {critical_message} FALSE,
                  local_status);
            pfv$immovable_catalogs := pfv$immovable_catalogs + 1;
          IFEND;
        ELSE
          pfp$log_error (status, ascii_logset, message_origin, critical_message);
          pfp$log_ascii ('Previous error from write_modified_catalog.', ascii_logset, message_origin,
                critical_message, local_status);
        IFEND;
      IFEND;
    IFEND;
  PROCEND write_modified_catalog;

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