?? TITLE := 'NOS/VE Permanent Files : File System Interface Management' ??
MODULE pfm$file_system_interfaces;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains those routines that interface to memory manager,
{   device manager, and file manager.
{
{ NOTES:
{   For those routines dealing with catalogs, the catalog described by the
{   catalog locator refers to the PHYSICAL catalog.  Thus care must be taken by
{   the caller to make sure that a call to pfp$destroy_catalog, for example, is
{   not made when really only an internal catalog is to be removed.
{
{   Access to the queued catalog table, must be referenced from the task
{   private pointers.  These task private pointers allow a task to run as if it
{   was running on behalf of a different job.

?? NEWTITLE := '  Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc i#current_sequence_position
*copyc oss$job_paged_literal
*copyc oss$task_shared
*copyc jmc$system_family
*copyc pfc$average_share_history
*copyc pfc$catalog_allocation_size
*copyc pfc$catalog_ring
*copyc pfc$maximum_catalog_length
*copyc pfc$maximum_pf_length
*copyc pfc$null_shared_queue
*copyc dfd$file_server_info
*copyc osd$integer_limits
*copyc ame$put_validation_errors
*copyc dme$tape_errors
*copyc fse$attach_validation_errors
*copyc pfe$error_condition_codes
*copyc pfe$internal_error_conditions
*copyc rme$request_command_exceptions
*copyc rme$request_mass_storage
*copyc amt$file_byte_address
*copyc dft$command_buffer
*copyc dmt$error_condition_codes
*copyc dmt$stored_tape_fmd_header
*copyc dmt$stored_tape_volume_list
*copyc dmt$tape_job_lun_table
*copyc fmt$mass_storage_request_info
*copyc fmt$pf_attachment_info
*copyc fmt$removable_media_req_info
*copyc gft$file_kind
*copyc gft$system_file_identifier
*copyc ost$processor_model_number
*copyc pft$access_kind
*copyc pft$catalog_locator
*copyc pft$df_define
*copyc pft$internal_path
*copyc pft$p_catalog_heap
*copyc pft$p_cycle
*copyc pft$p_fmd
*copyc pft$p_physical_fmd
*copyc pft$p_queued_internal_catalog
*copyc pft$p_table_info
*copyc pft$physical_cycle
*copyc sft$file_space_limit_kind
?? POP ??
*copyc fmf$ring_attributes_valid
*copyc bap$fetch_tape_validation
*copyc clp$get_variable_value
*copyc cmp$deadstart_phase
*copyc cmp$get_ms_class_on_volume
*copyc cmp$post_deadstart
*copyc dmp$attach_file
*copyc dmp$close_tape_volume
*copyc dmp$create_file_entry
*copyc dmp$create_tape_file_sfid
*copyc dmp$delete_file_descriptor
*copyc dmp$destroy_file
*copyc dmp$destroy_permanent_file
*copyc dmp$detach_file
*copyc dmp$enable_damage_detection
*copyc dmp$fetch_segment_file_info
*copyc dmp$fetch_server_sft_info
*copyc dmp$get_file_info
*copyc dmp$get_reconciled_fmd
*copyc dmp$get_stored_fmd
*copyc dmp$get_stored_fmd_header_info
*copyc dmp$get_stored_fmd_size
*copyc dmp$get_stored_fmd_volume_list
*copyc dmp$reconcile_fmd
*copyc dmp$store_valid_class_in_fmd
*copyc dsp$system_committed
*copyc fmp$attach_file
*copyc fmp$lock_path_table
*copyc fmp$unlock_path_table
*copyc iop$tape_file_attached
*copyc jmp$system_job
*copyc mmp$close_segment
*copyc mmp$lock_catalog_segment
*copyc mmp$open_file_segment
*copyc mmp$unlock_segment
*copyc osp$append_status_file
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$clear_job_signature_lock
*copyc osp$file_access_condition
*copyc osp$generate_log_message
*copyc osp$generate_unique_binary_name
*copyc osp$get_set_name
*copyc osp$initialize_signature_lock
*copyc osp$log_job_recovery_message
*copyc osp$log_job_recovery_status
*copyc osp$log_unformatted_status
*copyc osp$prevalidate_free
*copyc osp$reset_heap
*copyc osp$set_job_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$test_signature_lock
*copyc osp$verify_heap
*copyc pfp$attach_for_write
*copyc pfp$build_fmd_locator
*copyc pfp$build_fmd_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$check_catalog_alarm
*copyc pfp$check_cycle_busy
*copyc pfp$clear_catalog_alarm
*copyc pfp$compute_checksum
*copyc pfp$convert_cycle_path_to_strng
*copyc pfp$convert_density_to_dm
*copyc pfp$convert_device_class_to_rm
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$convert_pf_to_fs_structure
*copyc pfp$get_rem_media_req_info
*copyc pfp$get_rem_media_volume_list
*copyc pfp$map_usage_selections
*copyc pfp$process_unexpected_status
*copyc pfp$report_invalid_free
*copyc pfp$report_unexpected_status
*copyc pfp$set_catalog_alarm
*copyc pfp$system_path
*copyc pmp$date_time_compare
*copyc pmp$get_job_names
*copyc pmp$get_pseudo_mainframe_id
*copyc pmp$get_user_identification
*copyc pmp$log_ascii
*copyc pmp$wait
*copyc rmp$build_mass_storage_info
*copyc rmp$validate_mass_storage_info
*copyc sfp$get_job_limit
*copyc stp$get_pf_root
*copyc stp$store_pf_root
*copyc dfv$file_server_info_enabled
*copyc dmv$active_volume_table
*copyc dmv$reconcile_locator
*copyc fmv$default_detachment_options
*copyc gfv$null_sfid
*copyc iov$number_of_tape_units
*copyc osv$job_pageable_heap
*copyc osv$system_family_name
*copyc pfv$allow_catalog_write
*copyc pfv$debug_catalog_access
*copyc pfv$flush_catalogs
*copyc pfv$locked_catalog_list
*copyc pfv$null_unique_name
*copyc pfv$p_p_job_heap
*copyc pfv$p_p_newest_queued_catalog
*copyc pfv$p_p_queued_catalog_table
*copyc pfv$p_queued_catalog_table_lock
*copyc pfv$task_account
*copyc pfv$task_family
*copyc pfv$task_project
*copyc pfv$task_user
*copyc pfv$unattached_status
*copyc pfv$verify_catalog_heaps
*copyc pfv$write_usage
*copyc sfv$dynamic_file_space_limits
*copyc fmi$get_ring_attributes
*copyc i#move

  VAR
    pfv$assign_volume_retry_wait: [XREF] integer,
    pfv$honor_scl_var_create_file: [XREF] boolean;

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

  CONST
    pfc$file_class_index = 1,
    pfc$volume_overflow_index = 7,
    pfc$owner_index = 8,
    pfc$allocation_size_index = 10,
    pfc$initial_volume_index = 11,
    pfc$transfer_size_index = 12,
    pfc$dm_file_attribute_count = 12;

  CONST
    pfc$queued_catalog_table_size = 32;

  CONST
    assign_volume = TRUE,
    byte_address = 0,
    file_share_history = dmc$minimum_file_share_his,
    include_radix = TRUE,
    radix = 10;

  TYPE
    pft$dm_file_attributes = array [1 .. pfc$dm_file_attribute_count] of dmt$new_file_attribute;

  VAR
    pfv$null_tape_fmd_header_space: [XDCL, #GATE, oss$job_paged_literal, READ] array [1 .. 48] of
          boolean := [REP 48 of FALSE];

  VAR
    { These variables reside in task shared to allow update from task private
    { pointers.
    pfv$p_newest_queued_catalog: [XDCL, #GATE, oss$task_shared] pft$p_queued_catalog := NIL,
    pfv$p_queued_catalog_table: [XDCL, #GATE, oss$task_shared] pft$p_queued_catalog_table := NIL,
    pfv$queued_catalog_table_lock: [XDCL, #GATE, oss$task_shared] ost$signature_lock := [0];

?? FMT (FORMAT := OFF) ??
  VAR
    initial_dm_file_attributes: [oss$job_paged_literal, READ] pft$dm_file_attributes := [
          [dmc$class, rmc$unspecified_file_class],
          [dmc$class_ordinal, dmc$default_class_ordinal],
          [dmc$clear_space, FALSE],
          [dmc$file_limit, amc$file_byte_limit],
          [dmc$locked_file, [FALSE]],
          [dmc$master_volume_required, FALSE],
          [dmc$overflow, TRUE],
          [dmc$owner, sfc$no_limit],
          [dmc$preset_value, 0],
          [dmc$requested_allocation_size, dmc$unspecified_allocation_size],
          [dmc$requested_volume, [rmc$unspecified_vsn, * ]],
          [dmc$requested_transfer_size, dmc$unspecified_transfer_size]],
?? FMT (FORMAT := ON) ??
  null_catalog_header_space: [oss$job_paged_literal, READ] array [1 .. 48] OF boolean := [REP 48 OF FALSE];

?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$mainframe_attachment', EJECT ??

  FUNCTION [INLINE] f$mainframe_attachment
    (    mainframe_id: pmt$binary_mainframe_id;
         p_catalog_file: {input^} ^pft$catalog_file;
         p_mainframe_usage_list: {input^} ^pft$mainframe_usage_list;
         cycle_entry: pft$cycle_entry): boolean;

    VAR
      entry_p: ^pft$mainframe_usage_entry,
      mainframe: pft$mainframe_count;

    f$mainframe_attachment := FALSE;

    IF (cycle_entry.first_mainframe_usage_entry.entry_type = pfc$normal_mainframe_entry) AND
          (cycle_entry.first_mainframe_usage_entry.mainframe_id = mainframe_id) AND
          (cycle_entry.first_mainframe_usage_entry.attach_count > 0) THEN

      f$mainframe_attachment := TRUE;

    ELSEIF p_mainframe_usage_list <> NIL THEN

      FOR mainframe := 1 TO UPPERBOUND (p_mainframe_usage_list^) DO
        entry_p := ^p_mainframe_usage_list^ [mainframe].mainframe_usage;
        IF (entry_p^.entry_type = pfc$normal_mainframe_entry) AND (mainframe_id = entry_p^.mainframe_id) AND
              (entry_p^.attach_count > 0) THEN
          f$mainframe_attachment := TRUE;
          RETURN; {----->
        IFEND;
      FOREND;
    IFEND;

  FUNCEND f$mainframe_attachment;
?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$first_queued_catalog', EJECT ??

  FUNCTION [INLINE] f$first_queued_catalog: pft$p_queued_catalog;

    IF (pfv$p_p_newest_queued_catalog^ <> NIL) AND NOT pfv$p_p_newest_queued_catalog^^.valid_catalog THEN
      f$first_queued_catalog := NIL;
    ELSE
      f$first_queued_catalog := pfv$p_p_newest_queued_catalog^;
    IFEND;

  FUNCEND f$first_queued_catalog;
?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$next_queued_catalog', EJECT ??

  FUNCTION [INLINE] f$next_queued_catalog
    (    p_queued_catalog: {input^} pft$p_queued_catalog): pft$p_queued_catalog;

    VAR
      p_next_queued_catalog: pft$p_queued_catalog;

    p_next_queued_catalog := p_queued_catalog^.p_next_newest;
    IF NOT p_next_queued_catalog^.valid_catalog OR (p_next_queued_catalog = pfv$p_p_newest_queued_catalog^)
          THEN
      p_next_queued_catalog := NIL;
    IFEND;

    f$next_queued_catalog := p_next_queued_catalog;

  FUNCEND f$next_queued_catalog;
?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$queued_cat_by_external', EJECT ??

  FUNCTION [INLINE] f$queued_cat_by_external
    (    external_catalog_name: pft$name;
         parent_catalog_internal_name: pft$internal_catalog_name): pft$p_queued_catalog;

    VAR
      p_queued_catalog: pft$p_queued_catalog;

    p_queued_catalog := f$first_queued_catalog ();
    WHILE (p_queued_catalog <> NIL) AND NOT ((p_queued_catalog^.external_catalog_name =
          external_catalog_name) AND (p_queued_catalog^.parent_catalog_internal_name =
          parent_catalog_internal_name)) DO
      p_queued_catalog := f$next_queued_catalog (p_queued_catalog);
    WHILEND;

    f$queued_cat_by_external := p_queued_catalog;

  FUNCEND f$queued_cat_by_external;
?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$queued_cat_by_internal', EJECT ??

  FUNCTION [INLINE] f$queued_cat_by_internal
    (    internal_catalog_name: pft$internal_catalog_name): pft$p_queued_catalog;

    VAR
      p_queued_catalog: pft$p_queued_catalog;

    p_queued_catalog := f$first_queued_catalog ();
    WHILE (p_queued_catalog <> NIL) AND (p_queued_catalog^.internal_catalog_name <> internal_catalog_name) DO
      p_queued_catalog := f$next_queued_catalog (p_queued_catalog);
    WHILEND;

    f$queued_cat_by_internal := p_queued_catalog;

  FUNCEND f$queued_cat_by_internal;
?? OLDTITLE ??
?? NEWTITLE := '  [INLINE] f$stale_cycle_entry', EJECT ??

  FUNCTION [INLINE] f$stale_cycle_entry
    (    cycle_entry: pft$cycle_entry): boolean;

    f$stale_cycle_entry := cycle_entry.data_modification_date_time.year <= 0;

  FUNCEND f$stale_cycle_entry;
?? OLDTITLE ??
?? NEWTITLE := '  f$volume_available_for_assign', EJECT ??

{ PURPOSE:
{   The purpose of this function is to determine whether or not there is
{   a volume to which a file or catalog can be assigned.  It is called
{   only when a DME$UNABLE_TO_ALLOC_ALL_SPACE condition is returned
{   by DMP$CREATE_FILE_ENTRY since in some situations, a
{   DME$UNABLE_TO_ALLOC_ALL_SPACE is returned when a volume can be
{   assigned to the file or catalog.

  FUNCTION [INLINE] f$volume_available_for_assign
    (    set_name: stt$set_name;
         mass_storage_class: dmt$class_member;
         initial_volume: rmt$recorded_vsn): boolean;

    VAR
      avt_index: ost$positive_integers,
      entry_p: ^dmt$active_volume_table_entry;

    FOR avt_index := LOWERBOUND (dmv$active_volume_table.table_p^)
          TO UPPERBOUND (dmv$active_volume_table.table_p^) DO
      entry_p := ^dmv$active_volume_table.table_p^ [avt_index];
      IF (NOT entry_p^.entry_available)
{      } AND (set_name = entry_p^.mass_storage.set_name)
{      } AND (mass_storage_class IN entry_p^.mass_storage.class)
{      } AND (NOT entry_p^.mass_storage.volume_unavailable)
{      } AND (NOT entry_p^.mass_storage.space_gone)
{      } AND ((initial_volume = rmc$unspecified_vsn) OR ((initial_volume <> rmc$unspecified_vsn) AND
            (initial_volume = entry_p^.mass_storage.recorded_vsn))) THEN
        f$volume_available_for_assign := TRUE;
        RETURN; {----->
      IFEND;
    FOREND;

    f$volume_available_for_assign := FALSE;

  FUNCEND f$volume_available_for_assign;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] pfp$attach_catalog', EJECT ??

{ DESIGN:
{   If the catalog is found to be queued, it will be removed from the queue.
{   This procedure opens the catalog.
{
{ NOTE:
{   This procedure should only be used by those procedures that cannot obtain
{   the information required for queuing.

  PROCEDURE [XDCL] pfp$attach_catalog
    (    p_fmd: {input^} pft$p_fmd;
         set_name: stt$set_name;
         internal_catalog_name: pft$internal_name;
         global_file_name: ost$binary_unique_name;
         access_kind: pft$access_kind;
         catalog_remote: boolean;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    VAR
      catalog_found_queued: boolean,
      local_status: ost$status,
      p_queued_catalog: pft$p_queued_catalog;

    status.normal := TRUE;
    osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);

    p_queued_catalog := f$queued_cat_by_internal (internal_catalog_name);
    catalog_found_queued := (p_queued_catalog <> NIL);
    IF catalog_found_queued THEN
      build_catalog_locator (p_queued_catalog, catalog_locator, status);
      IF status.normal THEN
        free_queued_catalog (p_queued_catalog);
      IFEND;
    IFEND;

    osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);

    IF status.normal AND (NOT catalog_found_queued) THEN
      pfp$physically_attach_catalog (set_name, internal_catalog_name, global_file_name, p_fmd, catalog_remote,
            catalog_locator, status);
    IFEND;

    IF status.normal THEN
      pfp$open_attached_catalog (access_kind, catalog_locator, status);
    IFEND;

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

  PROCEND pfp$attach_catalog;

?? TITLE := '  [XDCL] pfp$attach_last_queued_catalog', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to attempt attaching the last catalog in
{   the path of internal catalogs.
{
{ DESIGN:
{   If the last catalog is not found, then an attempt will be made to attach
{   the next to last catalog, and so on up through the master catalog level.
{   This procedure opens the found catalog.  If no catalog is found in the
{   queued catalog table, then pfe$no_queued_catalog_found is returned.  If a
{   queued catalog is found, the found_catalog_index parameter returns the
{   index into the internal_path of the catalog that was found.  If the last
{   catalog was found, the catalog will be locked for the specified access, otherwise
{   the catalog will be locked for read access.

  PROCEDURE [XDCL] pfp$attach_last_queued_catalog
    (    set_name: stt$set_name;
         internal_path: pft$internal_path;
         last_catalog_index: pft$array_index;
         access_kind: pft$access_kind;
     VAR found_catalog_index: pft$array_index;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    VAR
      access: pft$access_kind,
      any_queued_catalog_found: boolean,
      local_status: ost$status,
      p_queued_catalog: pft$p_queued_catalog;

    status.normal := TRUE;
    any_queued_catalog_found := FALSE;
    osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);

  /search_queued_catalog_table/
    FOR found_catalog_index := last_catalog_index DOWNTO pfc$master_catalog_path_index DO
      p_queued_catalog := f$queued_cat_by_internal (internal_path [found_catalog_index]);
      IF p_queued_catalog <> NIL THEN
        build_catalog_locator (p_queued_catalog, catalog_locator, status);
        IF NOT status.normal THEN
          EXIT /search_queued_catalog_table/; {----->
        IFEND;
        any_queued_catalog_found := TRUE;
        free_queued_catalog (p_queued_catalog);
        EXIT /search_queued_catalog_table/; {----->
      IFEND;
    FOREND /search_queued_catalog_table/;

    osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);

    IF NOT status.normal AND (status.condition = pfe$catalog_access_retry) THEN
      pfp$return_catalog (catalog_locator, local_status);
      pfp$process_unexpected_status (local_status);
      RETURN; {----->
    IFEND;

    IF any_queued_catalog_found THEN
      IF found_catalog_index = last_catalog_index THEN
        access := access_kind;
      ELSE
        access := pfc$read_access;
      IFEND;
      pfp$open_attached_catalog (access, catalog_locator, status);
      IF NOT status.normal THEN
        pfp$return_catalog (catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    ELSE
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$no_queued_catalog_found, '', status);
    IFEND;

  PROCEND pfp$attach_last_queued_catalog;

?? TITLE := '  [XDCL] pfp$attach_permanent_file', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to interface with the device manager to
{   attach a permanent file, and then to interface with the local file manager
{   to associate the attached permanent file with a local file name for the job.

  PROCEDURE [XDCL] pfp$attach_permanent_file
    (    family_location: pft$family_location;
         mainframe_id: pmt$binary_mainframe_id;
         local_file_name: amt$local_file_name;
         path: pft$complete_path;
         attached_pf_table_index: pft$attached_pf_table_index;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         application_info: pft$application_info;
         validation_ring: ost$valid_ring;
         password_protected: boolean;
         allowed_cycle_damage_symptoms: fst$cycle_damage_symptoms;
         enable_media_damage_detection: boolean;
         implicit_attach: boolean;
         update_catalog: boolean;
         authority: pft$authority;
         p_file_label: {input} ^fmt$file_label;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_physical_cycle: {i^/o^} ^pft$physical_cycle;
     VAR system_file_id: gft$system_file_identifier;
     VAR file_damaged: boolean;
     VAR flush_catalog_pages: {i/o} boolean;
     VAR path_handle: {client only} fmt$path_handle;
     VAR p_file_server_buffers: {file server only: i/o^} ^pft$file_server_buffers;
     VAR status: ost$status);

    CONST
      allow_other_mainframe_writer = TRUE,
      critical_message = TRUE,
      cycle_created = TRUE,
      flush_pages = TRUE,
      message_origin = pmc$msg_origin_system;

    VAR
      apfid: pft$attached_permanent_file_id,
      bytes_allocated: amt$file_byte_address,
      cycle_path_string: ost$string,
      detachment_options: fmt$detachment_options,
      device_class: rmt$device_class,
      evaluated_file_reference: fst$evaluated_file_reference,
      exclusive_attach_client_mf: boolean,
      exclusive_attach_executing_mf: boolean,
      executing_mainframe_id: pmt$binary_mainframe_id,
      existing_sft_entry: dmt$existing_sft_entry,
      exit_on_unknown_file: boolean,
      file_info: dmt$file_information,
      file_modified: boolean,
      file_space_limit_kind: sft$file_space_limit_kind,
      fmd_modified: boolean,
      fs_path_size: fst$path_size,
      local_status: ost$status,
      locked_file: dmt$locked_file,
      p_fs_path: ^fst$path,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_physical_fmd: ^pft$physical_fmd,
      p_volume_list: ^rmt$volume_list,
      pf_attachment_info: fmt$pf_attachment_info,
      pfs_limit: sft$limit,
      recorded_vsn: rmt$recorded_vsn,
      removable_media_req_info: fmt$removable_media_req_info,
      restricted_attach: boolean,
      server_file: boolean,
      shared_queue: mmt$shared_queue,
      tape_file_attached: boolean,
      tape_validation: boolean,
      update_fmd: boolean,
      usage_intentions: pft$permit_selections,
      volume_count: 0 .. amc$max_vol_number;

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

    IF device_class = rmc$mass_storage_device THEN
      pfp$build_fmd_pointer (p_physical_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);

      IF p_physical_fmd = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_physical_cycle^.cycle_entry.cycle_number,
              radix, NOT include_radix, status);
        RETURN; {----->
      IFEND;

      restricted_attach := NOT update_catalog;
      locked_file.required := FALSE;
      exit_on_unknown_file := (p_physical_cycle^.cycle_entry.attach_status.attach_count > 0) AND
            ((p_physical_cycle^.cycle_entry.attach_status.usage_counts [pfc$shorten] > 0) OR
            (p_physical_cycle^.cycle_entry.attach_status.usage_counts [pfc$append] > 0) OR
            (p_physical_cycle^.cycle_entry.attach_status.usage_counts [pfc$modify] > 0));
      server_file := family_location = pfc$server_mainframe;

      IF (share_selections <> $pft$share_selections []) AND
            p_physical_cycle^.cycle_entry.shared_queue_info.defined THEN
        shared_queue := p_physical_cycle^.cycle_entry.shared_queue_info.shared_queue;
      ELSE
        shared_queue := mmc$null_shared_queue;
      IFEND;

      dmp$attach_file (p_physical_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
            p_physical_fmd^.fmd, usage_selections, share_selections, pfc$average_share_history,
            pfc$maximum_pf_length, restricted_attach, exit_on_unknown_file, server_file, shared_queue,
            file_damaged, system_file_id, existing_sft_entry, status);

      IF status.normal AND (existing_sft_entry <> dmc$normal_entry) THEN
        IF p_physical_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
          flush_catalog_pages := pfv$flush_catalogs;
          pfp$reconcile_fmd (^path, p_physical_cycle^.cycle_entry.internal_cycle_name, existing_sft_entry,
                update_catalog, p_catalog_file, p_physical_cycle, p_physical_fmd, status);
        IFEND;

        IF status.normal AND ((existing_sft_entry = dmc$restricted_attach_entry) OR
              (exit_on_unknown_file AND (existing_sft_entry = dmc$entry_not_found))) THEN
          dmp$attach_file (p_physical_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
                p_physical_fmd^.fmd, usage_selections, share_selections, pfc$average_share_history,
                pfc$maximum_pf_length, restricted_attach, {exit_on_unknown_file} FALSE, server_file,
                shared_queue, file_damaged, system_file_id, existing_sft_entry, status);
          IF status.normal THEN
            pfp$update_stale_cycle_entry (system_file_id, p_physical_cycle, status);
          IFEND;
        IFEND;
      IFEND;

      IF status.normal THEN
        IF update_catalog THEN
          pfp$map_usage_selections (usage_selections, usage_intentions);
          IF p_physical_cycle^.cycle_entry.attach_status.attach_count > 0 THEN {Otherwise, no check is needed
            pfp$check_cycle_busy (path, usage_intentions, share_selections, mainframe_id, p_catalog_file,
                  p_physical_cycle^.cycle_entry, status);
          IFEND;
        IFEND;

        IF file_damaged AND NOT (fsc$media_image_inconsistent IN allowed_cycle_damage_symptoms) 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$media_image_inconsistent,
                p_fs_path^ (1, fs_path_size), status);
        IFEND;

        IF enable_media_damage_detection AND (NOT file_damaged) AND
              pfp$attach_for_write (usage_selections) THEN
          dmp$enable_damage_detection (system_file_id, p_physical_cycle^.cycle_entry.internal_cycle_name,
                local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF status.normal THEN
          IF family_location = pfc$server_mainframe THEN
            set_server_output (NOT cycle_created, application_info,
                  p_physical_cycle^.cycle_entry.cycle_number, NOT allow_other_mainframe_writer,
                  p_physical_cycle^.cycle_entry.internal_cycle_name, usage_selections, share_selections,
                  password_protected, attached_pf_table_index, system_file_id, p_file_label, {p_fmd} NIL,
                  device_class, bytes_allocated, p_file_server_buffers, status);
          ELSE
            apfid.family_location := pfc$local_mainframe;
            apfid.attached_pf_table_index := attached_pf_table_index;
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
            evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
            evaluated_file_reference.cycle_reference.cycle_number :=
                  p_physical_cycle^.cycle_entry.cycle_number;

            IF (pfc$master_catalog_owner IN authority.ownership) AND
                  (usage_selections * pfv$write_usage <> $pft$usage_selections []) THEN
              file_space_limit_kind := sfc$perm_file_space_limit;
              IF sfv$dynamic_file_space_limits AND (pfc$append IN usage_selections) THEN
                sfp$get_job_limit (avc$pfs_limit_name, pfs_limit, status);
                IF status.normal THEN
                  IF pfs_limit.accumulator >= pfs_limit.job_abort_limit THEN
                    osp$set_status_condition (ame$file_space_limit_exceeded, status);
                  IFEND;
                ELSE
                  status.normal := TRUE;
                IFEND;
              IFEND;
            ELSE
              file_space_limit_kind := sfc$no_limit;
            IFEND;

            IF status.normal THEN
              pf_attachment_info.apfid := apfid;
              pf_attachment_info.application_info := application_info;
              pf_attachment_info.implicit_attach := implicit_attach;
              pf_attachment_info.password_protected := password_protected;
              fmp$attach_file (local_file_name, p_physical_cycle^.cycle_entry.global_file_name,
                    p_physical_cycle^.cycle_entry.internal_cycle_name, system_file_id, usage_selections,
                    share_selections, validation_ring, file_space_limit_kind, p_file_label,
                    ^pf_attachment_info, rmc$mass_storage_device, {p_removable_media_req_info} NIL,
                    {p_volume_list} NIL, evaluated_file_reference, status);
              path_handle := evaluated_file_reference.path_handle_info.path_handle;
            IFEND;

            IF NOT status.normal THEN
              IF status.condition = ame$file_space_limit_exceeded THEN
                PUSH p_fs_path;
                pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                osp$append_status_file (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
                osp$append_status_parameter (osc$status_parameter_delimiter, 'Permanent', status);
              ELSEIF status.condition = ame$ring_validation_error 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$invalid_ring_access,
                      p_fs_path^ (1, fs_path_size), status);
              ELSEIF status.condition = pfe$lfn_in_use THEN
                ;
              ELSEIF (status.condition = rme$redundant_device_assignment) OR
                    (status.condition = rme$device_assignment_conflict) THEN
                osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$lfn_in_use, local_file_name,
                      status);
              ELSE
                pfp$report_unexpected_status (status);
                PUSH p_fs_path;
                pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size),
                      status);
                osp$log_unformatted_status (^status, -$pmt$ascii_logset [], message_origin,
                      NOT critical_message);
              IFEND;
            IFEND;
          IFEND;
        IFEND;

        IF NOT status.normal THEN
          pfp$detach_permanent_file (^path, system_file_id, $pft$usage_selections [],
                {catalog_access_allowed} TRUE, p_physical_cycle, p_catalog_file, dmc$df_ignore_file_info,
                fmd_modified, file_info, local_status);
          pfp$process_unexpected_status (local_status);

          IF (status.condition <> pfe$cycle_busy) AND (status.condition <> pfe$lfn_in_use) AND
                (status.condition <> pfe$invalid_ring_access) AND
                (status.condition <> ame$file_space_limit_exceeded) AND
                (status.condition <> pfe$media_image_inconsistent) AND
                (status.condition <> pfe$pf_system_error) THEN
            pfp$report_unexpected_status (status);
          IFEND;
        IFEND;
      ELSE { Dmp$attach_file or pfp$reconcile_fmd failed.
        pfp$convert_cycle_path_to_strng (path, p_physical_cycle^.cycle_entry.cycle_number, cycle_path_string);
        IF status.condition = dme$volume_unavailable THEN
          recorded_vsn := status.text.value (2, 6);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_unavailable,
                cycle_path_string.value (1, cycle_path_string.size), status);
          osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
        ELSEIF status.condition = dme$some_volumes_not_online THEN
          recorded_vsn := status.text.value (2, 6);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_not_online,
                cycle_path_string.value (1, cycle_path_string.size), status);
          osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
        ELSEIF status.condition = dme$allocation_mismatch THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$allocation_mismatch,
                cycle_path_string.value (1, cycle_path_string.size), status);
        ELSE
          IF status.condition <> pfe$pf_system_error THEN
            pfp$report_unexpected_status (status);
          IFEND;
          osp$append_status_parameter (osc$status_parameter_delimiter, cycle_path_string.
                value (1, cycle_path_string.size), status);
          osp$log_unformatted_status (^status, -$pmt$ascii_logset [], message_origin, NOT critical_message);
        IFEND;
      IFEND;

      IF status.normal AND update_catalog THEN
        IF f$stale_cycle_entry (p_physical_cycle^.cycle_entry) THEN
          pfp$update_stale_cycle_entry (system_file_id, p_physical_cycle, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      IFEND;
    ELSEIF device_class = rmc$magnetic_tape_device THEN
      file_damaged := FALSE;

      pfp$build_mainfram_list_pointer (p_physical_cycle^.cycle_entry.mainframe_usage_list_locator,
            p_catalog_file, p_mainframe_usage_list);
      IF (family_location = pfc$server_mainframe) AND f$mainframe_attachment
            (mainframe_id, p_catalog_file, p_mainframe_usage_list, p_physical_cycle^.cycle_entry) THEN
        osp$set_status_condition (pfe$tape_attached_on_client, status);
      IFEND;

      IF status.normal THEN
        pmp$get_pseudo_mainframe_id (executing_mainframe_id);
        IF update_catalog AND f$mainframe_attachment (executing_mainframe_id, p_catalog_file,
              p_mainframe_usage_list, p_physical_cycle^.cycle_entry) THEN
          iop$tape_file_attached (p_physical_cycle^.cycle_entry.global_file_name, tape_file_attached,
                local_status);
          IF local_status.normal AND (NOT tape_file_attached) THEN
            pfp$clear_cycle_attachments (^path, p_catalog_file, p_physical_cycle);
          IFEND;
        IFEND;
      IFEND;

      IF status.normal AND update_catalog THEN
        pfp$map_usage_selections (usage_selections, usage_intentions);
        IF p_physical_cycle^.cycle_entry.attach_status.attach_count > 0 THEN {Otherwise, no check is needed
          pfp$check_cycle_busy (path, usage_intentions, share_selections, mainframe_id, p_catalog_file,
                p_physical_cycle^.cycle_entry, status);
        IFEND;
      IFEND;

      IF status.normal THEN
        pfp$build_fmd_pointer (p_physical_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);

        IF p_physical_fmd = NIL THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
                p_fs_path^ (1, fs_path_size), status);
          osp$append_status_integer (osc$status_parameter_delimiter,
                p_physical_cycle^.cycle_entry.cycle_number, radix, NOT include_radix, status);
        IFEND;

        IF status.normal THEN
          IF family_location = pfc$local_mainframe THEN
            apfid.family_location := pfc$local_mainframe;
            apfid.attached_pf_table_index := attached_pf_table_index;
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
            evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
            evaluated_file_reference.cycle_reference.cycle_number :=
                  p_physical_cycle^.cycle_entry.cycle_number;
            pfp$get_rem_media_req_info (^p_physical_fmd^.fmd, ^removable_media_req_info, volume_count,
                  status);

            IF status.normal THEN
              IF usage_selections * pfv$write_usage = $pft$usage_selections [] THEN
                removable_media_req_info.write_ring := rmc$no_write_ring;
              ELSE
                removable_media_req_info.write_ring := rmc$write_ring;
              IFEND;

              PUSH p_volume_list: [1 .. volume_count];
              pfp$get_rem_media_volume_list (^p_physical_fmd^.fmd, p_volume_list, status);

              IF status.normal THEN
                dmp$create_tape_file_sfid (^removable_media_req_info, p_volume_list, system_file_id, status);

                IF status.normal THEN
                  pf_attachment_info.apfid := apfid;
                  pf_attachment_info.application_info := application_info;
                  pf_attachment_info.implicit_attach := implicit_attach;
                  pf_attachment_info.password_protected := password_protected;
                  fmp$attach_file (local_file_name, p_physical_cycle^.cycle_entry.global_file_name,
                        p_physical_cycle^.cycle_entry.internal_cycle_name, system_file_id, usage_selections,
                        share_selections, validation_ring, sfc$no_limit, p_file_label, ^pf_attachment_info,
                        device_class, ^removable_media_req_info, p_volume_list, evaluated_file_reference,
                        status);
                  path_handle := evaluated_file_reference.path_handle_info.path_handle;

                  IF NOT status.normal THEN
                    detachment_options := fmv$default_detachment_options;
                    detachment_options.device_class := rmc$magnetic_tape_device;
                    detachment_options.physical_unload := TRUE;
                    dmp$close_tape_volume (system_file_id, detachment_options, local_status);

                    IF status.condition = ame$ring_validation_error 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$invalid_ring_access,
                            p_fs_path^ (1, fs_path_size), status);
                    ELSEIF (status.condition = pfe$lfn_in_use) OR
                          (status.condition = rme$redundant_device_assignment) OR
                          (status.condition = rme$device_assignment_conflict) THEN
                      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$lfn_in_use, local_file_name,
                            status);
                    ELSE
                      pfp$report_unexpected_status (status);
                      PUSH p_fs_path;
                      pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                      osp$append_status_parameter (osc$status_parameter_delimiter,
                            p_fs_path^ (1, fs_path_size), status);
                      osp$log_unformatted_status (^status, -$pmt$ascii_logset [], message_origin,
                            NOT critical_message);
                    IFEND;
                  IFEND;
                ELSEIF status.condition = dme$tape_attach_limit_exceeded THEN
                  PUSH p_fs_path;
                  pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
                  osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$tape_attach_limit_exceeded,
                        p_fs_path^ (1, fs_path_size), status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        iov$number_of_tape_units + dmc$extra_lun_table_entries, radix, NOT include_radix,
                        status);
                IFEND;
              IFEND;
            IFEND;
          ELSE {server mainframe}
            set_server_output (NOT cycle_created, application_info,
                  p_physical_cycle^.cycle_entry.cycle_number, NOT allow_other_mainframe_writer,
                  p_physical_cycle^.cycle_entry.internal_cycle_name, usage_selections, share_selections,
                  password_protected, attached_pf_table_index, system_file_id, p_file_label,
                  ^p_physical_fmd^.fmd, device_class, bytes_allocated, p_file_server_buffers, status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND pfp$attach_permanent_file;

?? TITLE := '  [XDCL] pfp$attach_root_catalog', EJECT ??
{ PURPOSE:
{   This procedure attaches and opens the root catalog.

  PROCEDURE [XDCL] pfp$attach_root_catalog
    (    set_name: stt$set_name;
         access_kind: pft$access_kind;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    pfp$get_root_attached (set_name, catalog_locator, status);
    IF status.normal THEN
      pfp$open_attached_catalog (access_kind, catalog_locator, status);
    IFEND;

  PROCEND pfp$attach_root_catalog;

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

{ PURPOSE:
{   The purpose of this procedure is to determine whether new items which were
{   added to the cycle entry in R1.4.1 are stale.  These items will be stale if
{   the cycle was created or modified by an R1.3.1 or older version of the
{   system.
{
{ NOTE:
{   This procedure should be deleted two releases after R1.4.1 when it is no
{   longer necessary to support an upgrade from an R1.3.1 or earlier system.

  PROCEDURE [XDCL] pfp$check_for_stale_cycle_entry
    (    cycle_entry: pft$cycle_entry;
     VAR stale_cycle_entry: boolean);

    stale_cycle_entry := f$stale_cycle_entry (cycle_entry);

  PROCEND pfp$check_for_stale_cycle_entry;
?? TITLE := '  [XDCL] pfp$clear_cycle_attachments', EJECT ??

  PROCEDURE [XDCL] pfp$clear_cycle_attachments
    (    p_path: ^pft$complete_path;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
         p_cycle: {i^/o^} ^pft$physical_cycle);

    VAR
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      prevalidate_free_result: ost$prevalidate_free_result;

    p_cycle^.cycle_entry.attach_status := pfv$unattached_status;
    p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
    pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator, p_catalog_file,
          p_mainframe_usage_list);
    IF p_mainframe_usage_list <> NIL THEN
      osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
            ^p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_mainframe_usage_list IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (p_path, ^p_cycle^.cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST', 'file',
              prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
        p_mainframe_usage_list := NIL;
      IFEND;
    IFEND;
    pfp$build_mainfram_list_locator ({p_mainframe_usage_list} NIL, {p_catalog_file} NIL,
          p_cycle^.cycle_entry.mainframe_usage_list_locator);
    pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);

  PROCEND pfp$clear_cycle_attachments;

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

  PROCEDURE [XDCL] pfp$create_catalog
    (    catalog_path: pft$complete_path;
         p_mass_storage_request_info: ^fmt$mass_storage_request_info;
         authority: pft$authority;
         lock_catalog: boolean;
     VAR new_catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    CONST
      file_type = gfc$fk_catalog;

    CONST
      catalog_algorithm = 0;

    VAR
      dm_file_attributes: pft$dm_file_attributes,
      file_returned: boolean,
      file_share_selections: pft$share_selections,
      file_usage: pft$usage_selections,
      i: integer,
      local_status: ost$status,
      segment_pointer: mmt$segment_pointer;

    status.normal := TRUE;

    new_catalog_locator.set_name := catalog_path [pfc$set_path_index];
    new_catalog_locator.new_catalog := TRUE;
    new_catalog_locator.queuing_info.set_catalog_alarm := FALSE;
    {
    { New catalogs are NOT queued.
    {
    new_catalog_locator.queuing_info.attach_queued := FALSE;

    file_usage := -$pft$usage_selections [];
    file_share_selections := $pft$share_selections [];

    IF p_mass_storage_request_info <> NIL THEN
      p_mass_storage_request_info^.allocation_size := pfc$catalog_allocation_size;
    IFEND;

    generate_dm_file_attributes (catalog_path, pfc$catalog_object, {validation_ring} osc$tsrv_ring,
          {use_scl_variable_defaults} FALSE, p_mass_storage_request_info, authority, dm_file_attributes,
          status);

    IF status.normal THEN

    /assign_catalog_to_volume/
      WHILE TRUE DO
        dmp$create_file_entry (file_type, file_usage, file_share_selections, file_share_history,
              ^dm_file_attributes, byte_address, assign_volume, new_catalog_locator.global_file_name,
              new_catalog_locator.system_file_id, status);
        IF (NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space) AND
              f$volume_available_for_assign (catalog_path [pfc$set_path_index],
              dm_file_attributes [pfc$file_class_index].class,
              dm_file_attributes [pfc$initial_volume_index].requested_volume.recorded_vsn) THEN
          pmp$wait (pfv$assign_volume_retry_wait, pfv$assign_volume_retry_wait);
          CYCLE /assign_catalog_to_volume/; {----->
        ELSE
          EXIT /assign_catalog_to_volume/; {----->
        IFEND;
      WHILEND /assign_catalog_to_volume/;
      new_catalog_locator.attached := status.normal;
      new_catalog_locator.internal_catalog_name := new_catalog_locator.global_file_name;
    IFEND;

    IF status.normal THEN
      mmp$open_file_segment (new_catalog_locator.system_file_id, NIL, mmc$cell_pointer, pfc$catalog_ring,
            sfc$no_limit, segment_pointer, status);
      new_catalog_locator.open := status.normal;

      IF status.normal THEN
        IF lock_catalog THEN
          mmp$lock_catalog_segment (segment_pointer.cell_pointer, mmc$lus_lock_for_write, osc$wait, status);
          new_catalog_locator.locked := status.normal;
        ELSE
          new_catalog_locator.locked := FALSE;
        IFEND;

        IF status.normal THEN
          new_catalog_locator.access_kind := pfc$write_access;
          new_catalog_locator.p_catalog_file := segment_pointer.cell_pointer;
          osp$reset_heap (^new_catalog_locator.p_catalog_file^.catalog_heap,
                #SIZE (new_catalog_locator.p_catalog_file^.catalog_heap), FALSE, catalog_algorithm);
          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);
          new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.valid := TRUE;
          new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.version :=
                pfc$catalog_version;
          new_catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.
                reserved_catalog_header_space := null_catalog_header_space;
          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.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 := pfv$flush_catalogs;
          new_catalog_locator.abort_catalog_operation := FALSE;

        /initialize_locked_catalog_list/
          FOR i := 1 TO UPPERBOUND (pfv$locked_catalog_list) DO
            IF pfv$locked_catalog_list [i] = NIL THEN
              pfv$locked_catalog_list [i] := segment_pointer.cell_pointer;
              EXIT /initialize_locked_catalog_list/; {----->
            IFEND;
          FOREND /initialize_locked_catalog_list/;
        ELSE
          {
          { The lock failed - back out.
          {
          mmp$close_segment (segment_pointer, pfc$catalog_ring, local_status);
          new_catalog_locator.open := FALSE;
          pfp$process_unexpected_status (local_status);
          dmp$destroy_file (new_catalog_locator.system_file_id, sfc$no_limit, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;
      ELSE
        {
        { The open failed - back out.
        {
        dmp$destroy_file (new_catalog_locator.system_file_id, sfc$no_limit, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;
  PROCEND pfp$create_catalog;

?? TITLE := '  [XDCL] pfp$create_permanent_file', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to interface with the file system to
{   create a permanent file.

  PROCEDURE [XDCL] pfp$create_permanent_file
    (    family_location: pft$family_location;
         local_file_name: amt$local_file_name;
         path: pft$complete_path;
         cycle_number: fst$cycle_number;
         attached_pf_table_index: pft$attached_pf_table_index;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         application_info: pft$application_info;
         validation_ring: ost$valid_ring;
         password_protected: boolean;
         enable_media_damage_detection: boolean;
         implicit_attach: boolean;
         recreate_attached_cycle_data: boolean;
         p_file_label: {input} fmt$p_file_label;
         device_class: rmt$device_class;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         p_removable_media_req_info: {input} ^fmt$removable_media_req_info;
         p_volume_list: {input} ^rmt$volume_list;
         authority: pft$authority;
     VAR path_handle: {client only} fmt$path_handle;
     VAR system_file_id: gft$system_file_identifier;
     VAR internal_cycle_name: pft$internal_name;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {server only: i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

    VAR
      apfid: pft$attached_permanent_file_id,
      cycle_path_string: ost$string,
      detachment_options: fmt$detachment_options,
      dm_file_attributes: pft$dm_file_attributes,
      evaluated_file_reference: fst$evaluated_file_reference,
      file_class: string (1),
      file_info: dmt$file_information,
      file_modified: boolean,
      file_space_limit_kind: sft$file_space_limit_kind,
      fmd_modified: boolean,
      fs_path: fst$path,
      fs_path_size: fst$path_size,
      get_stored_fmd_status: ost$status,
      global_file_name: ost$binary_unique_name,
      initial_volume: ost$name,
      local_status: ost$status,
      p_fmd: pft$p_fmd,
      p_physical_fmd: pft$p_physical_fmd,
      path_string: ost$string,
      pf_attachment_info: fmt$pf_attachment_info,
      pfs_limit: sft$limit,
      recorded_vsn: rmt$recorded_vsn,
      stored_fmd_size: dmt$stored_fmd_size;

    IF device_class = rmc$mass_storage_device THEN
      IF sfv$dynamic_file_space_limits THEN
        sfp$get_job_limit (avc$pfs_limit_name, pfs_limit, status);
        IF status.normal THEN
          IF pfs_limit.accumulator >= pfs_limit.job_abort_limit THEN
            osp$set_status_condition (ame$file_space_limit_exceeded, status);
            pfp$convert_cycle_path_to_strng (path, cycle_number, path_string);
            osp$append_status_file (osc$status_parameter_delimiter, path_string.value (1, path_string.size),
                  status);
            osp$append_status_parameter (osc$status_parameter_delimiter, 'Permanent', status);
            RETURN; {----->
          IFEND;
        ELSE
          status.normal := TRUE;
        IFEND;
      IFEND;

      generate_dm_file_attributes (path, pfc$file_object, validation_ring, pfv$honor_scl_var_create_file,
            p_mass_storage_request_info, authority, dm_file_attributes, status);

      IF status.normal THEN

      /assign_file_to_volume/
        WHILE TRUE DO
          dmp$create_file_entry ({file_type} gfc$fk_job_permanent_file, usage_selections, share_selections,
                file_share_history, ^dm_file_attributes, byte_address, assign_volume, internal_cycle_name,
                system_file_id, status);
          IF (NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space) AND
                f$volume_available_for_assign (path [pfc$set_path_index],
                dm_file_attributes [pfc$file_class_index].class,
                dm_file_attributes [pfc$initial_volume_index].requested_volume.recorded_vsn) THEN
            pmp$wait (pfv$assign_volume_retry_wait, pfv$assign_volume_retry_wait);
            CYCLE /assign_file_to_volume/; {----->
          ELSE
            EXIT /assign_file_to_volume/; {----->
          IFEND;
        WHILEND /assign_file_to_volume/;
      IFEND;

      IF status.normal THEN
        IF enable_media_damage_detection AND pfp$attach_for_write (usage_selections) THEN
          dmp$enable_damage_detection (system_file_id, internal_cycle_name, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF dm_file_attributes [pfc$file_class_index].class = rmc$unspecified_file_class THEN
          store_valid_file_class_in_fmd (path, pfc$file_object, system_file_id, local_status);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF family_location = pfc$local_mainframe THEN
          dmp$get_file_info (system_file_id, file_info, status);
          IF status.normal THEN
            bytes_allocated := file_info.total_allocated_length;
            apfid.family_location := pfc$local_mainframe;
            apfid.attached_pf_table_index := attached_pf_table_index;
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
            evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
            evaluated_file_reference.cycle_reference.cycle_number := cycle_number;
            IF (pfc$master_catalog_owner IN authority.ownership) AND
                  ((usage_selections * pfv$write_usage) <> $pft$usage_selections []) THEN
              file_space_limit_kind := sfc$perm_file_space_limit;
            ELSE
              file_space_limit_kind := sfc$no_limit;
            IFEND;
            IF NOT recreate_attached_cycle_data THEN
              pf_attachment_info.apfid := apfid;
              pf_attachment_info.application_info := application_info;
              pf_attachment_info.implicit_attach := implicit_attach;
              pf_attachment_info.password_protected := password_protected;
              fmp$attach_file (local_file_name, internal_cycle_name, internal_cycle_name, system_file_id,
                    usage_selections, share_selections, validation_ring, file_space_limit_kind,
                    p_file_label, ^pf_attachment_info, rmc$mass_storage_device,
                    {p_removable_media_req_info} NIL, {p_volume_list} NIL, evaluated_file_reference, status);
              path_handle := evaluated_file_reference.path_handle_info.path_handle;
            IFEND;
          IFEND;
        ELSE
          set_server_output ({cycle_created} TRUE, application_info, cycle_number,
                {allow_other_mainframe_writer} FALSE, internal_cycle_name, usage_selections, share_selections,
                password_protected, attached_pf_table_index, system_file_id, p_file_label, {p_fmd} NIL,
                device_class, bytes_allocated, p_file_server_buffers, status);
        IFEND;

        IF NOT status.normal THEN
          {
          { Remove the device manager's knowledge of the file.
          {
          dmp$detach_file (system_file_id, {access_allowed} TRUE, {flush_pages} TRUE, dmc$df_ignore_file_info
                {ignore file_info - not used from the detach} , file_modified, fmd_modified, file_info,
                local_status);
          pfp$process_unexpected_status (local_status);

          dmp$get_stored_fmd_size (system_file_id, stored_fmd_size, get_stored_fmd_status);
          IF get_stored_fmd_status.normal THEN
            PUSH p_fmd: [[REP stored_fmd_size OF cell]];
            RESET p_fmd;
            dmp$get_stored_fmd (system_file_id, p_fmd^, get_stored_fmd_status);
            pfp$process_unexpected_status (get_stored_fmd_status);
            dmp$delete_file_descriptor (system_file_id, local_status);
            pfp$process_unexpected_status (local_status);

            IF get_stored_fmd_status.normal THEN
              dmp$destroy_permanent_file (internal_cycle_name, p_fmd^, local_status);
              pfp$process_unexpected_status (local_status);
            IFEND;
          ELSE
            pfp$report_unexpected_status (get_stored_fmd_status);
          IFEND;
        IFEND;
      ELSE { Dmp$create_file_entry failed.
        {
        { Initialize initial_volume.
        {
        IF p_mass_storage_request_info <> NIL THEN
          IF p_mass_storage_request_info^.initial_volume = rmc$unspecified_vsn THEN
            initial_volume := 'Unspecified Volume.';
          ELSE
            initial_volume := p_mass_storage_request_info^.initial_volume;
          IFEND;
        ELSE
          initial_volume := 'Permanent File Device';
        IFEND;
      IFEND;

      IF status.normal THEN
        ;
      ELSEIF status.condition = ame$ring_validation_error THEN
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$invalid_ring_access,
              fs_path (1, fs_path_size), status);
      ELSEIF (status.condition = pfe$lfn_in_use) OR (status.condition = pfe$pf_system_error) OR
            (status.condition = rme$file_class_not_valid) OR (status.condition = rme$job_not_valid) OR
            (status.condition = rme$volume_overflow_required) OR
            (status.condition = rme$vsn_not_part_of_set) OR (status.condition = dme$unable_to_alloc_all_space)
            THEN
        ;
      ELSEIF status.condition = rme$device_assignment_conflict THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$lfn_in_use, local_file_name, status);
      ELSEIF status.condition = rme$redundant_device_assignment THEN
        pfp$convert_cycle_path_to_strng (path, cycle_number, cycle_path_string);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_purged_cycle,
              cycle_path_string.value (1, cycle_path_string.size), status);
      ELSEIF status.condition = dme$file_class_not_valid THEN
        file_class := dm_file_attributes [pfc$file_class_index].class;
        osp$set_status_abnormal (rmc$resource_management_id, rme$file_class_not_valid, initial_volume,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, file_class, status);
      ELSEIF status.condition = dme$volume_unavailable THEN
        recorded_vsn := status.text.value (2, 6);
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_unavailable,
              fs_path (1, fs_path_size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSEIF status.condition = dme$some_volumes_not_online THEN
        recorded_vsn := status.text.value (2, 6);
        pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_not_online,
              fs_path (1, fs_path_size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;

    ELSEIF device_class = rmc$magnetic_tape_device THEN
      osp$generate_unique_binary_name (internal_cycle_name, status);
      IF status.normal THEN
        IF family_location = pfc$local_mainframe THEN
          dmp$create_tape_file_sfid (p_removable_media_req_info, p_volume_list, system_file_id, status);
          IF status.normal THEN
            bytes_allocated := 0;
            apfid.family_location := pfc$local_mainframe;
            apfid.attached_pf_table_index := attached_pf_table_index;
            pfp$convert_pf_to_fs_structure (path, evaluated_file_reference);
            evaluated_file_reference.cycle_reference.specification := fsc$cycle_number;
            evaluated_file_reference.cycle_reference.cycle_number := cycle_number;
            file_space_limit_kind := sfc$no_limit;
            pf_attachment_info.apfid := apfid;
            pf_attachment_info.application_info := application_info;
            pf_attachment_info.implicit_attach := implicit_attach;
            pf_attachment_info.password_protected := password_protected;
            fmp$attach_file (local_file_name, internal_cycle_name, internal_cycle_name, system_file_id,
                  usage_selections, share_selections, validation_ring, file_space_limit_kind, p_file_label,
                  ^pf_attachment_info, device_class, p_removable_media_req_info, p_volume_list,
                  evaluated_file_reference, status);
            path_handle := evaluated_file_reference.path_handle_info.path_handle;
            IF NOT status.normal THEN
              detachment_options := fmv$default_detachment_options;
              detachment_options.device_class := rmc$magnetic_tape_device;
              detachment_options.physical_unload := TRUE;
              dmp$close_tape_volume (system_file_id, detachment_options, local_status);
            IFEND;
          ELSEIF status.condition = dme$tape_attach_limit_exceeded THEN
            pfp$convert_pf_path_to_fs_path (path, fs_path, fs_path_size);
            osp$set_status_abnormal (pfc$permanent_file_manager_id, fse$tape_attach_limit_exceeded,
                  fs_path (1, fs_path_size), status);
            osp$append_status_integer (osc$status_parameter_delimiter,
                  iov$number_of_tape_units + dmc$extra_lun_table_entries, radix, NOT include_radix, status);
          IFEND;
        ELSE {server mainframe}
          set_server_output ({cycle_created} TRUE, application_info, cycle_number,
                {allow_other_mainframe_writer} FALSE, internal_cycle_name, usage_selections, share_selections,
                password_protected, attached_pf_table_index, system_file_id, p_file_label, {p_fmd} NIL,
                device_class, bytes_allocated, p_file_server_buffers, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND pfp$create_permanent_file;

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

  PROCEDURE [XDCL] pfp$destroy_catalog
    (VAR catalog_locator: {i/o} pft$catalog_locator;
     VAR status: ost$status);

    VAR
      close_status: ost$status,
      delete_status: ost$status,
      destroy_catalog: boolean,
      destroy_status: ost$status,
      detach_status: ost$status,
      external_name: pft$name,
      file_info: dmt$file_information,
      file_modified: boolean,
      fmd_modified: boolean,
      get_stored_fmd_status: ost$status,
      p_fmd: pft$p_fmd,
      segment_pointer: mmt$segment_pointer,
      stored_fmd_size: dmt$stored_fmd_size;

    close_status.normal := TRUE;
    detach_status.normal := TRUE;
    get_stored_fmd_status.normal := TRUE;
    delete_status.normal := TRUE;
    destroy_status.normal := TRUE;

    IF catalog_locator.queuing_info.set_catalog_alarm THEN
      IF catalog_locator.queuing_info.attach_queued THEN
        external_name := catalog_locator.queuing_info.external_catalog_name;
      ELSE
        external_name := 'unknown';
      IFEND;
      pfp$set_catalog_alarm (catalog_locator.global_file_name, catalog_locator.internal_catalog_name,
            external_name, {destroy_on_last_detach} TRUE);
    IFEND;

    {
    { Attempt to return as many of the job and system resources as possible.
    {

    IF catalog_locator.attached THEN
      IF catalog_locator.open THEN
        segment_pointer.kind := mmc$cell_pointer;
        segment_pointer.cell_pointer := catalog_locator.p_catalog_file;
        mmp$close_segment (segment_pointer, pfc$catalog_ring, close_status);
        catalog_locator.open := FALSE;
        pfp$process_unexpected_status (close_status);
      IFEND;

      dmp$detach_file (catalog_locator.system_file_id, {access_allowed} TRUE, {flush_pages} TRUE,
            dmc$df_ignore_file_info, file_modified, fmd_modified, file_info, detach_status);
      catalog_locator.attached := FALSE;
      pfp$process_unexpected_status (detach_status);

      dmp$get_stored_fmd_size (catalog_locator.system_file_id, stored_fmd_size, get_stored_fmd_status);
      IF get_stored_fmd_status.normal THEN
        PUSH p_fmd: [[REP stored_fmd_size OF cell]];
        RESET p_fmd;
        dmp$get_stored_fmd (catalog_locator.system_file_id, p_fmd^, get_stored_fmd_status);
        pfp$process_unexpected_status (get_stored_fmd_status);

        dmp$delete_file_descriptor (catalog_locator.system_file_id, delete_status);
        destroy_catalog := delete_status.normal;
        IF NOT delete_status.normal THEN
          IF delete_status.condition = dme$file_descriptor_not_deleted THEN
            {
            { There are other users of this deleted catalog.
            {
            IF NOT catalog_locator.queuing_info.set_catalog_alarm THEN
              IF catalog_locator.queuing_info.attach_queued THEN
                external_name := catalog_locator.queuing_info.external_catalog_name;
              ELSE
                external_name := 'unknown';
              IFEND;
              pfp$set_catalog_alarm (catalog_locator.global_file_name, catalog_locator.internal_catalog_name,
                    external_name, {destroy_on_last_detach} TRUE);
            IFEND;
            delete_status.normal := TRUE;
          ELSE
            pfp$report_unexpected_status (delete_status);
          IFEND;
        ELSEIF catalog_locator.queuing_info.set_catalog_alarm THEN
          pfp$clear_catalog_alarm (catalog_locator.global_file_name);
        IFEND;

        IF catalog_locator.queuing_info.attach_queued AND catalog_locator.queuing_info.access_queued THEN
          free_internal_catalog_list (catalog_locator.queuing_info.p_internal_catalog_list);
        IFEND;

        IF get_stored_fmd_status.normal AND destroy_catalog THEN
          dmp$destroy_permanent_file (catalog_locator.global_file_name, p_fmd^, destroy_status);
          pfp$process_unexpected_status (destroy_status);
        IFEND;
      ELSE { dmp$get_stored_fmd_size failed.
        pfp$report_unexpected_status (status);
      IFEND;
    IFEND;

    IF NOT close_status.normal THEN
      status := close_status;
    ELSEIF NOT detach_status.normal THEN
      status := detach_status;
    ELSEIF NOT get_stored_fmd_status.normal THEN
      status := get_stored_fmd_status;
    ELSEIF NOT delete_status.normal THEN
      status := delete_status;
    ELSEIF NOT destroy_status.normal THEN
      status := destroy_status;
    ELSE
      status.normal := TRUE;
    IFEND;
  PROCEND pfp$destroy_catalog;

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

  PROCEDURE [XDCL, #GATE] pfp$detach_all_catalogs;

    VAR
      catalog_alarm_set: boolean,
      destroy_on_last_detach: boolean,
      ignore_catalog_deleted: boolean,
      p_queued_catalog: pft$p_queued_catalog,
      status: ost$status;

    osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);

    p_queued_catalog := f$first_queued_catalog ();
    WHILE p_queued_catalog <> NIL DO
      pfp$check_catalog_alarm (p_queued_catalog^.global_file_name, catalog_alarm_set, destroy_on_last_detach);
      physically_detach_catalog (p_queued_catalog^.system_file_id, p_queued_catalog^.global_file_name,
            catalog_alarm_set, destroy_on_last_detach, {flush_catalog} TRUE, ignore_catalog_deleted, status);
      pfp$process_unexpected_status (status);
      IF p_queued_catalog^.access_queued THEN
        free_internal_catalog_list (p_queued_catalog^.p_internal_catalog_list);
      IFEND;
      free_queued_catalog (p_queued_catalog);
      p_queued_catalog := f$first_queued_catalog ();
    WHILEND;

    osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);
  PROCEND pfp$detach_all_catalogs;

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

  PROCEDURE [XDCL] pfp$detach_permanent_file
    (    p_path: ^pft$complete_path;
         system_file_id: gft$system_file_identifier;
         usage_selections: pft$usage_selections;
         catalog_access_allowed: boolean;
         p_cycle: {i^/o^} pft$p_cycle;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
         return_file_info_option: dmt$df_return_file_info_option;
     VAR fmd_modified: boolean;
     VAR file_info: dmt$file_information;
     VAR status: ost$status);

    VAR
      access_allowed: boolean,
      file_modified: boolean,
      flush_pages: boolean,
      p_new_fmd: pft$p_physical_fmd,
      p_old_fmd: pft$p_physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      usage_option: pft$usage_options;

    status.normal := TRUE;

    {
    { Flush pages whenever the cycle is attached with any form of write access.
    {

    access_allowed := usage_selections <> $pft$usage_selections [];
    flush_pages := ((usage_selections * $pft$usage_selections [pfc$shorten, pfc$append,
          pfc$modify]) <> $pft$usage_selections []);
    IF flush_pages THEN

    /locate_last_attach_for_write/
      FOR usage_option := pfc$shorten TO pfc$modify DO
        IF usage_option IN usage_selections THEN
          IF p_cycle^.cycle_entry.attach_status.usage_counts [usage_option] > 1 THEN
            flush_pages := FALSE;
            EXIT /locate_last_attach_for_write/; {----->
          IFEND;
        ELSE
          IF p_cycle^.cycle_entry.attach_status.usage_counts [usage_option] > 0 THEN
            flush_pages := FALSE;
            EXIT /locate_last_attach_for_write/; {----->
          IFEND;
        IFEND;
      FOREND /locate_last_attach_for_write/;
    IFEND;

    dmp$detach_file (system_file_id, access_allowed, flush_pages, return_file_info_option, file_modified,
          fmd_modified, file_info, status);
    IF status.normal THEN
      IF fmd_modified THEN
        IF catalog_access_allowed OR dsp$system_committed () THEN
          IF p_cycle^.cycle_entry.entry_type = pfc$normal_cycle_entry THEN
            pfp$record_dm_file_parameters (p_path, ^p_cycle^.cycle_entry.cycle_number, system_file_id,
                  rmc$mass_storage_device, {p_removable_media_req_info} NIL, {p_volume_list} NIL,
                  ^p_catalog_file^.catalog_heap, p_new_fmd, status);
            IF status.normal THEN
              pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_old_fmd);
              pfp$build_fmd_locator (p_new_fmd, p_catalog_file, p_cycle^.cycle_entry.fmd_locator);
              pfp$compute_checksum (#LOC (p_cycle^.cycle_entry), #SIZE (pft$cycle_entry), p_cycle^.checksum);
              IF p_old_fmd <> NIL THEN
                osp$prevalidate_free ((#OFFSET (p_old_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) - 16),
                      ^p_catalog_file^.catalog_heap, prevalidate_free_result);
                IF prevalidate_free_result = osc$heap_free_valid THEN
                  FREE p_old_fmd IN p_catalog_file^.catalog_heap;
                ELSE
                  pfp$report_invalid_free (p_path, ^p_cycle^.cycle_entry.cycle_number,
                        'FILE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result, #OFFSET (p_old_fmd));
                  p_old_fmd := NIL;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      IF status.normal THEN
        dmp$delete_file_descriptor (system_file_id, status);
        IF NOT (status.normal) AND (status.condition = dme$file_descriptor_not_deleted) THEN
          status.normal := TRUE;
        IFEND;
      IFEND;
    IFEND;

  PROCEND pfp$detach_permanent_file;

?? TITLE := '  [XDCL] pfp$detach_queued_catalog', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to remove a queued catalog from the queued
{   catalog table and to detach the catalog.
{
{ NOTES:
{   The catalog detachment may be deferred; see detach_catalog for details.
{   This procedure is called by pfp$detach_unavail_queued_cat, which may need
{   to be called following an unsuccessful attempt to access a catalog due to
{   an unavailable volume.

  PROCEDURE [XDCL] pfp$detach_queued_catalog
    (    internal_catalog_name: pft$internal_catalog_name;
     VAR catalog_locator: {i/o} pft$catalog_locator);

    VAR
      local_status: ost$status,
      p_queued_catalog: ^pft$queued_catalog;

    osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);
    p_queued_catalog := f$queued_cat_by_internal (internal_catalog_name);

    IF p_queued_catalog = NIL THEN
      osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);
    ELSE
      free_queued_catalog (p_queued_catalog);
      osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);
      catalog_locator.queuing_info.set_catalog_alarm := TRUE;
      detach_catalog (catalog_locator, local_status);
    IFEND;
  PROCEND pfp$detach_queued_catalog;

?? TITLE := '  [XDCL] pfp$dm_create_file_entry', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to interface with the file system to
{   create a permanent file without modifying and BAM or PF tables.

  PROCEDURE [XDCL] pfp$dm_create_file_entry
    (    path: pft$complete_path;
         cycle_number: fst$cycle_number;
         authority: pft$authority;
         usage_selections: pft$usage_selections;
         share_selections: pft$share_selections;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
     VAR system_file_id: gft$system_file_identifier;
     VAR global_file_name: ost$binary_unique_name;
     VAR status: ost$status);

    VAR
      cycle_path_string: ost$string,
      dm_file_attributes: pft$dm_file_attributes,
      file_class: string (1),
      fs_path_size: fst$path_size,
      initial_volume: ost$name,
      p_fs_path: ^fst$path,
      recorded_vsn: rmt$recorded_vsn;

    generate_dm_file_attributes (path, pfc$file_object, {validation_ring} osc$tsrv_ring,
          {use_scl_variable_defaults} FALSE, p_mass_storage_request_info, authority, dm_file_attributes,
          status);

    IF status.normal THEN

    /assign_file_to_volume/
      WHILE TRUE DO
        dmp$create_file_entry ({file_type} gfc$fk_job_permanent_file, usage_selections, share_selections,
              file_share_history, ^dm_file_attributes, byte_address, assign_volume, global_file_name,
              system_file_id, status);
        IF (NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space) AND
              f$volume_available_for_assign (path [pfc$set_path_index],
              dm_file_attributes [pfc$file_class_index].class,
              dm_file_attributes [pfc$initial_volume_index].requested_volume.recorded_vsn) THEN
          pmp$wait (pfv$assign_volume_retry_wait, pfv$assign_volume_retry_wait);
          CYCLE /assign_file_to_volume/; {----->
        ELSE
          EXIT /assign_file_to_volume/; {----->
        IFEND;
      WHILEND /assign_file_to_volume/;
    IFEND;

    IF NOT status.normal THEN
      {
      { Initialize initial_volume.
      {
      IF p_mass_storage_request_info <> NIL THEN
        IF p_mass_storage_request_info^.initial_volume = rmc$unspecified_vsn THEN
          initial_volume := 'Unspecified Volume.';
        ELSE
          initial_volume := p_mass_storage_request_info^.initial_volume;
        IFEND;
      ELSE
        initial_volume := 'Permanent File Device';
      IFEND;

      IF (status.condition = pfe$lfn_in_use) OR (status.condition = pfe$pf_system_error) OR
            (status.condition = rme$file_class_not_valid) OR (status.condition = rme$job_not_valid) OR
            (status.condition = rme$volume_overflow_required) OR
            (status.condition = rme$vsn_not_part_of_set) OR (status.condition = dme$unable_to_alloc_all_space)
            THEN
        ;
      ELSEIF status.condition = rme$redundant_device_assignment THEN
        pfp$convert_cycle_path_to_strng (path, cycle_number, cycle_path_string);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$duplicate_purged_cycle,
              cycle_path_string.value (1, cycle_path_string.size), status);
      ELSEIF status.condition = dme$file_class_not_valid THEN
        file_class := dm_file_attributes [pfc$file_class_index].class;
        osp$set_status_abnormal (rmc$resource_management_id, rme$file_class_not_valid, initial_volume,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, file_class, status);
      ELSEIF status.condition = dme$volume_unavailable THEN
        recorded_vsn := status.text.value (2, 6);
        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$volume_unavailable,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSEIF status.condition = dme$some_volumes_not_online THEN
        recorded_vsn := status.text.value (2, 6);
        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$volume_not_online,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    IFEND;

  PROCEND pfp$dm_create_file_entry;

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

  PROCEDURE [XDCL] pfp$get_queued_catalog
    (    external_catalog_name: pft$name;
         parent_internal_name: pft$internal_catalog_name;
     VAR catalog_attach_queued: boolean;
     VAR catalog_access_queued: boolean;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    VAR
      local_status: ost$status,
      p_queued_catalog: pft$p_queued_catalog;

    status.normal := TRUE;

    osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);

    p_queued_catalog := f$queued_cat_by_external (external_catalog_name, parent_internal_name);
    catalog_attach_queued := (p_queued_catalog <> NIL);
    catalog_access_queued := FALSE;
    IF catalog_attach_queued THEN
      build_catalog_locator (p_queued_catalog, catalog_locator, status);
      IF status.normal THEN
        catalog_access_queued := catalog_locator.queuing_info.access_queued;
        free_queued_catalog (p_queued_catalog);
      IFEND;
    IFEND;

    osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);

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

  PROCEND pfp$get_queued_catalog;

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

  PROCEDURE [XDCL] pfp$get_root_attached
    (    set_name: stt$set_name;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

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

    pfp$get_queued_catalog (set_name, pfv$null_unique_name, root_attach_queued, root_access_queued,
          catalog_locator, status);

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

      IF status.normal THEN
        RESET p_root;
        NEXT p_internal_catalog_name IN p_root;
        NEXT p_stored_fmd_size IN p_root;
        NEXT p_stored_fmd: [[REP p_stored_fmd_size^ OF cell]] IN p_root;
        pfp$physically_attach_catalog (set_name, p_internal_catalog_name^, p_internal_catalog_name^,
              p_stored_fmd, {catalog_remote} FALSE, catalog_locator, status);
        IF status.normal THEN
          catalog_locator.queuing_info.attach_queued := TRUE;
          catalog_locator.queuing_info.parent_catalog_internal_name := pfv$null_unique_name;
          catalog_locator.queuing_info.external_catalog_name := set_name;
          catalog_locator.queuing_info.charge_id.account := osc$null_name;
          catalog_locator.queuing_info.charge_id.project := osc$null_name;
          catalog_locator.queuing_info.access_queued := TRUE;
          catalog_locator.queuing_info.p_internal_catalog_list := NIL;
          catalog_locator.queuing_info.permit.entry_type := pfc$free_permit_entry;
        IFEND;
      IFEND;
    IFEND;

  PROCEND pfp$get_root_attached;

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

  PROCEDURE [XDCL] pfp$open_attached_catalog
    (    access_kind: pft$access_kind;
     VAR catalog_locator: {i/o} pft$catalog_locator;
     VAR status: ost$status);

    VAR
      catalog_alarm_set: boolean,
      destroy_on_last_detach: boolean,
      heap_ok: boolean,
      i: integer,
      ignore_status: ost$status,
      length: integer,
      line: string (256),
      local_status: ost$status,
      segment_pointer: mmt$segment_pointer;

    catalog_locator.open := FALSE;
    IF NOT cmp$post_deadstart () AND (access_kind = pfc$write_access) AND
          (cmp$deadstart_phase () <> osc$installation_deadstart) AND NOT pfv$allow_catalog_write THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$no_access_before_commit, '', status);
      RETURN; {----->
    IFEND;

    mmp$open_file_segment (catalog_locator.system_file_id, NIL, mmc$cell_pointer, pfc$catalog_ring,
          sfc$no_limit, segment_pointer, status);
    catalog_locator.open := status.normal;
    IF status.normal THEN
      pfp$check_catalog_alarm (catalog_locator.global_file_name, catalog_alarm_set, destroy_on_last_detach);
      IF catalog_alarm_set AND destroy_on_last_detach THEN
        IF pfv$debug_catalog_access THEN
          STRINGREP (line, length, 'PFP$OPEN_ATTACHED_CATALOG',
                ' catalog alarm detected before attempting to lock catalog segment.');
          pmp$log_ascii (line (1, length), $pmt$ascii_logset [pmc$job_log, pmc$system_log],
                pmc$msg_origin_system, ignore_status);
        IFEND;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_access_retry, '', status);
      ELSE
        IF access_kind = pfc$read_access THEN
          mmp$lock_catalog_segment (segment_pointer.cell_pointer, mmc$lus_lock_for_read, osc$nowait, status);
        ELSE
          mmp$lock_catalog_segment (segment_pointer.cell_pointer, mmc$lus_lock_for_write, osc$nowait, status);
        IFEND;
        catalog_locator.locked := status.normal;
        IF status.normal THEN
          pfp$check_catalog_alarm (catalog_locator.global_file_name, catalog_alarm_set,
                destroy_on_last_detach);
          IF catalog_alarm_set AND destroy_on_last_detach THEN
            IF pfv$debug_catalog_access THEN
              STRINGREP (line, length, 'PFP$OPEN_ATTACHED_CATALOG',
                    ' catalog alarm detected after locking catalog segment.');
              pmp$log_ascii (line (1, length), $pmt$ascii_logset [pmc$job_log, pmc$system_log],
                    pmc$msg_origin_system, ignore_status);
            IFEND;
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_access_retry, '', status);
            mmp$unlock_segment (segment_pointer.cell_pointer, mmc$lus_free, osc$nowait, local_status);
            pfp$process_unexpected_status (local_status);
          IFEND;
        ELSEIF status.condition = mme$segment_locked_another_task THEN
          IF pfv$debug_catalog_access THEN
            STRINGREP (line, length, 'PFP$OPEN_ATTACHED_CATALOG', ' unable to lock catalog segment.');
            pmp$log_ascii (line (1, length), $pmt$ascii_logset [pmc$job_log, pmc$system_log],
                  pmc$msg_origin_system, ignore_status);
          IFEND;
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_access_retry, '', status);
        IFEND;
      IFEND;

      IF status.normal THEN
        catalog_locator.access_kind := access_kind;
        catalog_locator.p_catalog_file := segment_pointer.cell_pointer;
        pfp$build_object_list_pointer (catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.
              object_list_locator, catalog_locator.p_catalog_file,
              catalog_locator.object_list_descriptor.p_object_list);
        catalog_locator.object_list_descriptor.sorted_object_count :=
              catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.object_list_locator.
              sorted_object_count;
        catalog_locator.object_list_descriptor.free_sorted_object_count :=
              catalog_locator.p_catalog_file^.physical_catalog_header.catalog_header.object_list_locator.
              free_sorted_object_count;
        catalog_locator.object_list_descriptor.catalog_type := pfc$external_catalog;
        catalog_locator.object_list_descriptor.p_physical_catalog_header :=
              ^catalog_locator.p_catalog_file^.physical_catalog_header;
        catalog_locator.flush_catalog_pages := (access_kind = pfc$write_access) AND pfv$flush_catalogs;
        catalog_locator.abort_catalog_operation := FALSE;

      /initialize_locked_catalog_list/
        FOR i := 1 TO UPPERBOUND (pfv$locked_catalog_list) DO
          IF pfv$locked_catalog_list [i] = NIL THEN
            pfv$locked_catalog_list [i] := segment_pointer.cell_pointer;
            EXIT /initialize_locked_catalog_list/; {----->
          IFEND;
        FOREND /initialize_locked_catalog_list/;

        IF pfv$verify_catalog_heaps THEN
          osp$verify_heap (^catalog_locator.p_catalog_file^.catalog_heap, heap_ok);
          IF NOT heap_ok THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$corrupted_catalog_heap,
                  'PFP$OPEN_ATTACHED_CATALOG', local_status);
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], local_status,
                  ignore_status);
            pfp$report_unexpected_status (local_status);
          IFEND;
        IFEND;
      ELSE
        IF osp$file_access_condition (status) THEN
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_volume_unavailable,
                catalog_locator.recorded_vsn, status);
        ELSEIF status.condition <> pfe$catalog_access_retry THEN
          pfp$report_unexpected_status (status);
        IFEND;
        mmp$close_segment (segment_pointer, pfc$catalog_ring, local_status);
        catalog_locator.open := FALSE;
        pfp$process_unexpected_status (local_status);
      IFEND;
    ELSE
      IF osp$file_access_condition (status) THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_volume_unavailable,
              catalog_locator.recorded_vsn, status);
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    IFEND;
  PROCEND pfp$open_attached_catalog;

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

  PROCEDURE [XDCL] pfp$physically_attach_catalog
    (    set_name: stt$set_name;
         internal_catalog_name: pft$internal_catalog_name;
         global_file_name: ost$binary_unique_name;
         p_fmd: {input^} pft$p_fmd;
         catalog_remote: boolean;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    CONST
      flush_pages = TRUE;

    VAR
      catalog_alarm_set: boolean,
      destroy_on_last_detach: boolean,
      existing_sft_entry: dmt$existing_sft_entry,
      file_damaged: boolean,
      fmd_header: pft$fmd_header,
      ignore_status: ost$status,
      length: integer,
      line: string (256),
      locked_file: dmt$locked_file,
      p_volume_list: ^pft$volume_list,
      recorded_vsn: rmt$recorded_vsn;

    catalog_locator.set_name := set_name;
    catalog_locator.internal_catalog_name := internal_catalog_name;
    catalog_locator.global_file_name := global_file_name;
    catalog_locator.recorded_vsn := rmc$unspecified_vsn;
    catalog_locator.new_catalog := FALSE;
    catalog_locator.queuing_info.set_catalog_alarm := FALSE;
    catalog_locator.queuing_info.attach_queued := FALSE;
    catalog_locator.attached := FALSE;

    pfp$check_catalog_alarm (global_file_name, catalog_alarm_set, destroy_on_last_detach);
    IF catalog_alarm_set AND destroy_on_last_detach THEN
      IF pfv$debug_catalog_access THEN
        STRINGREP (line, length, 'PFP$PHYSICALLY_ATTACH_CATALOG',
              ' catalog alarm detected before attempting to attach catalog.');
        pmp$log_ascii (line (1, length), $pmt$ascii_logset [pmc$job_log, pmc$system_log],
              pmc$msg_origin_system, ignore_status);
      IFEND;
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_access_retry, '', status);
      RETURN; {----->
    IFEND;

    locked_file.required := TRUE;
    dmp$attach_file (global_file_name, gfc$fk_catalog, p_fmd^, -$pft$usage_selections [],
          -$pft$share_selections [], pfc$average_share_history, pfc$maximum_catalog_length,
          {restricted_attach} FALSE, {exit_on_unknown_file} FALSE, {server_file} FALSE, mmc$null_shared_queue,
          file_damaged, catalog_locator.system_file_id, existing_sft_entry, status);
    IF status.normal THEN
      catalog_locator.attached := TRUE;
      catalog_locator.open := FALSE;

      dmp$get_stored_fmd_header_info (p_fmd, fmd_header, status);
      IF status.normal AND (fmd_header.number_of_subfiles > 0) THEN
        PUSH p_volume_list: [1 .. fmd_header.number_of_subfiles];
        dmp$get_stored_fmd_volume_list (p_fmd, p_volume_list, status);
        IF status.normal THEN
          catalog_locator.recorded_vsn := p_volume_list^ [1];
        IFEND;
      IFEND;
    ELSEIF status.condition = dme$volume_unavailable THEN
      recorded_vsn := status.text.value (2, 6);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_volume_unavailable, recorded_vsn,
            status);
      catalog_locator.recorded_vsn := recorded_vsn;
    ELSEIF status.condition = dme$some_volumes_not_online THEN
      recorded_vsn := status.text.value (2, 6);
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_volume_not_online, recorded_vsn,
            status);
      catalog_locator.recorded_vsn := recorded_vsn;
    ELSE
      pfp$report_unexpected_status (status);
    IFEND;

  PROCEND pfp$physically_attach_catalog;

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

  PROCEDURE [XDCL, #GATE] pfp$r2_get_queued_catalog_table
    (VAR p_info: {i^/o} pft$p_table_info;
     VAR status: ost$status);

    VAR
      p_external_name: ^pft$name,
      p_info_internal_catalog: pft$p_queued_internal_catalog,
      p_newest_catalog: pft$p_queued_catalog,
      p_next_internal_catalog: pft$p_queued_internal_catalog,
      p_record_id: ^pft$record_id,
      p_table: pft$p_queued_catalog_table,
      p_table_lock: ^ost$signature_lock,
      p_table_name: ^pft$table_name,
      p_table_size: ^integer,
      pp_newest_queued_catalog: ^pft$p_queued_catalog,
      pp_table: ^pft$p_queued_catalog_table,
      qct_entry: integer;

    status.normal := TRUE;

    NEXT p_table_name IN p_info;
    IF p_table_name = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table name', status);
      RETURN; {----->
    IFEND;
    p_table_name^ := 'QUEUED_CATALOG_TABLE';
    {
    { Put the table out in the queued order, i.e. from newest to oldest.
    {
    NEXT p_record_id IN p_info;
    IF p_record_id = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
      RETURN; {----->
    IFEND;
    p_record_id^ := 'AGEINFOT';

    NEXT p_table_size IN p_info;
    IF p_table_size = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table size', status);
      RETURN; {----->
    IFEND;
    p_table_size^ := 0;

    p_newest_catalog := f$first_queued_catalog ();
    WHILE p_newest_catalog <> NIL DO
      NEXT p_external_name IN p_info;
      IF p_external_name = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'external name', status);
        RETURN; {----->
      IFEND;
      p_external_name^ := p_newest_catalog^.external_catalog_name;
      p_table_size^ := p_table_size^ +1;
      p_newest_catalog := f$next_queued_catalog (p_newest_catalog);
    WHILEND;

    NEXT p_record_id IN p_info;
    IF p_record_id = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
      RETURN; {----->
    IFEND;
    p_record_id^ := 'TABLLOCK';

    NEXT p_table_lock IN p_info;
    IF p_table_lock = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table lock', status);
      RETURN; {----->
    IFEND;
    p_table_lock^ := pfv$p_queued_catalog_table_lock^;

    NEXT p_record_id IN p_info;
    IF p_record_id = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
      RETURN; {----->
    IFEND;
    p_record_id^ := 'PNEWQCAT';

    NEXT pp_newest_queued_catalog IN p_info;
    IF pp_newest_queued_catalog = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'p newest queued', status);
      RETURN; {----->
    IFEND;
    pp_newest_queued_catalog^ := pfv$p_p_newest_queued_catalog^;

    NEXT p_record_id IN p_info;
    IF p_record_id = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
      RETURN; {----->
    IFEND;
    p_record_id^ := 'QCTSTART';

    NEXT pp_table IN p_info;
    IF pp_table = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'p qct', status);
      RETURN; {----->
    IFEND;
    pp_table^ := pfv$p_p_queued_catalog_table^;

    NEXT p_record_id IN p_info;
    IF p_record_id = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
      RETURN; {----->
    IFEND;
    p_record_id^ := 'TABLSIZE';

    NEXT p_table_size IN p_info;
    IF p_table_size = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table size', status);
      RETURN; {----->
    ELSEIF pfv$p_p_queued_catalog_table^ = NIL THEN
      p_table_size^ := 0;
    ELSE
      p_table_size^ := UPPERBOUND (pfv$p_p_queued_catalog_table^^);

      NEXT p_record_id IN p_info;
      IF p_record_id = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
        RETURN; {----->
      IFEND;
      p_record_id^ := 'QCATABLE';

      NEXT p_table: [1 .. p_table_size^] IN p_info;
      IF p_table = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table', status);
        RETURN; {----->
      IFEND;
      p_table^ := pfv$p_p_queued_catalog_table^^;
      {
      { Now go through and append any internally queued catalogs.
      {
      NEXT p_record_id IN p_info;
      IF p_record_id = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'record id', status);
        RETURN; {----->
      IFEND;
      p_record_id^ := 'NOINTCAT';

      NEXT p_table_size IN p_info;
      IF p_table_size = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'table size', status);
        RETURN; {----->
      IFEND;
      p_table_size^ := 0;

      FOR qct_entry := 1 TO UPPERBOUND (pfv$p_p_queued_catalog_table^^) DO
        IF pfv$p_p_queued_catalog_table^^ [qct_entry].valid_catalog AND
              pfv$p_p_queued_catalog_table^^ [qct_entry].access_queued THEN
          p_next_internal_catalog := pfv$p_p_queued_catalog_table^^ [qct_entry].p_internal_catalog_list;
          WHILE p_next_internal_catalog <> NIL DO
            NEXT p_info_internal_catalog IN p_info;
            IF p_info_internal_catalog = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$info_full, 'internal catalog',
                    status);
              RETURN; {----->
            IFEND;
            p_table_size^ := p_table_size^ +1;
            p_info_internal_catalog^ := p_next_internal_catalog^;
            p_next_internal_catalog := p_next_internal_catalog^.p_next_internal_catalog;
          WHILEND;
        IFEND;
      FOREND;
    IFEND;
  PROCEND pfp$r2_get_queued_catalog_table;

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

  PROCEDURE [XDCL] pfp$reconcile_fmd
    (    p_path: ^pft$complete_path;
         internal_cycle_name: pft$internal_name;
         existing_sft_entry: dmt$existing_sft_entry;
         update_catalog: boolean;
         p_catalog_file: {i^/o^} pft$p_catalog_file;
         p_cycle: {i^/o^} pft$p_cycle;
     VAR p_physical_fmd: {i^/o^} pft$p_physical_fmd;
     VAR status: ost$status);

    VAR
      fmd_size: dmt$stored_fmd_size,
      mass_storage_class: dmt$class,
      p_mainframe_usage_list: ^pft$mainframe_usage_list,
      p_new_physical_fmd: ^pft$physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      resides_on_system_device: boolean,
      share_option: pft$share_options,
      usage_option: pft$usage_options;

    status.normal := TRUE;

    IF (existing_sft_entry <> dmc$normal_entry) AND (p_cycle^.cycle_entry.attach_status.attach_count > 0) THEN
      IF ((p_cycle^.cycle_entry.attach_status.usage_counts [pfc$shorten] > 0) OR
            (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$append] > 0) OR
            (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$modify] > 0)) AND
            (existing_sft_entry <> dmc$restricted_attach_entry) THEN
        dmp$reconcile_fmd (dmv$reconcile_locator, internal_cycle_name, p_physical_fmd^.fmd,
              {purge_file} FALSE, mass_storage_class, fmd_size, resides_on_system_device, status);

        IF status.normal OR (status.condition = dme$update_fmd) THEN
          IF NOT status.normal THEN
            IF update_catalog THEN
              ALLOCATE p_new_physical_fmd: [[REP fmd_size OF cell]] IN p_catalog_file^.catalog_heap;
            ELSE
              ALLOCATE p_new_physical_fmd: [[REP fmd_size OF cell]] IN osv$job_pageable_heap^;
            IFEND;

            IF p_new_physical_fmd = NIL THEN
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle fmd', status);
            ELSE
              dmp$get_reconciled_fmd (dmv$reconcile_locator, internal_cycle_name, p_physical_fmd^.fmd,
                    p_new_physical_fmd^.fmd, status);
              IF status.normal THEN
                pfp$compute_checksum (^p_new_physical_fmd^.fmd, #SIZE (p_new_physical_fmd^.fmd),
                      p_new_physical_fmd^.checksum);

                IF update_catalog THEN
                  pfp$build_fmd_locator (p_new_physical_fmd, p_catalog_file,
                        p_cycle^.cycle_entry.fmd_locator);
                  osp$prevalidate_free ((#OFFSET (p_physical_fmd) - #OFFSET (^p_catalog_file^.catalog_heap) -
                        16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
                  IF prevalidate_free_result = osc$heap_free_valid THEN
                    FREE p_physical_fmd IN p_catalog_file^.catalog_heap;
                  ELSE
                    pfp$report_invalid_free (p_path, ^p_cycle^.cycle_entry.cycle_number,
                          'FILE_MEDIA_DESCRIPTOR', 'file', prevalidate_free_result, #OFFSET (p_physical_fmd));
                    p_physical_fmd := NIL;
                  IFEND;
                IFEND;
                p_physical_fmd := p_new_physical_fmd;
              ELSE
                pfp$report_unexpected_status (status);
              IFEND;
            IFEND;
          IFEND;
        ELSEIF NOT osp$file_access_condition (status) THEN
          IF (dmv$reconcile_locator = NIL) AND NOT dsp$system_committed () THEN
            {
            { When attaching prior to building the reconcile list, overflow
            { must not be allowed.
            {
            status.normal := TRUE;
          ELSE
            pfp$report_unexpected_status (status);
          IFEND;
        IFEND;
      IFEND;
      {
      { Clear all attach, usage, prevent usage and mainframe usage counts.
      {
      IF update_catalog AND status.normal THEN
        p_cycle^.cycle_entry.attach_status := pfv$unattached_status;

        p_cycle^.cycle_entry.first_mainframe_usage_entry.entry_type := pfc$free_mainframe_entry;
        pfp$build_mainfram_list_pointer (p_cycle^.cycle_entry.mainframe_usage_list_locator, p_catalog_file,
              p_mainframe_usage_list);
        IF p_mainframe_usage_list <> NIL THEN
          osp$prevalidate_free ((#OFFSET (p_mainframe_usage_list) - #OFFSET (^p_catalog_file^.catalog_heap) -
                16), ^p_catalog_file^.catalog_heap, prevalidate_free_result);
          IF prevalidate_free_result = osc$heap_free_valid THEN
            FREE p_mainframe_usage_list IN p_catalog_file^.catalog_heap;
          ELSE
            pfp$report_invalid_free (p_path, ^p_cycle^.cycle_entry.cycle_number, 'MAINFRAME_USAGE_LIST',
                  'file', prevalidate_free_result, #OFFSET (p_mainframe_usage_list));
            p_mainframe_usage_list := NIL;
          IFEND;
        IFEND;
        pfp$build_mainfram_list_locator ({p_mainframe_usage_list} NIL, {p_catalog_file} NIL,
              p_cycle^.cycle_entry.mainframe_usage_list_locator);

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

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

  PROCEDURE [XDCL] pfp$record_dm_file_parameters
    (    p_path: ^pft$complete_path;
         p_cycle_number: ^fst$cycle_number;
         system_file_id: gft$system_file_identifier;
         device_class: rmt$device_class;
         p_removable_media_req_info: {input^} ^fmt$removable_media_req_info;
         p_volume_list: {input^} ^rmt$volume_list;
         p_catalog_heap: {output^} pft$p_catalog_heap;
     VAR p_new_stored_fmd: {output} pft$p_physical_fmd;
     VAR status: ost$status);

    VAR
      p_fmd: ^pft$fmd,
      p_stored_tape_fmd_header: ^dmt$stored_tape_fmd_header,
      p_stored_tape_volume_list: ^dmt$stored_tape_volume_list,
      prevalidate_free_result: ost$prevalidate_free_result,
      stored_fmd_size: dmt$stored_fmd_size,
      volume_list_index: integer;

    status.normal := TRUE;

    IF device_class = rmc$mass_storage_device THEN
      REPEAT
        dmp$get_stored_fmd_size (system_file_id, stored_fmd_size, status);
        IF status.normal THEN
          ALLOCATE p_new_stored_fmd: [[REP stored_fmd_size OF cell]] IN p_catalog_heap^;
          IF p_new_stored_fmd = NIL THEN
            osp$set_status_condition (pfe$catalog_full, status);
          ELSE
            dmp$get_stored_fmd (system_file_id, p_new_stored_fmd^.fmd, status);
            IF NOT status.normal THEN
              osp$prevalidate_free ((#OFFSET (p_new_stored_fmd) - #OFFSET (p_catalog_heap) - 16),
                    p_catalog_heap, prevalidate_free_result);
              IF prevalidate_free_result = osc$heap_free_valid THEN
                FREE p_new_stored_fmd IN p_catalog_heap^;
              ELSE
                IF p_cycle_number <> NIL THEN
                  pfp$report_invalid_free (p_path, p_cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
                        prevalidate_free_result, #OFFSET (p_new_stored_fmd));
                ELSE
                  pfp$report_invalid_free (p_path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR', 'catalog',
                        prevalidate_free_result, #OFFSET (p_new_stored_fmd));
                IFEND;
                p_new_stored_fmd := NIL;
              IFEND;
              IF status.condition <> dme$fmd_too_small THEN
                pfp$report_unexpected_status (status);
              IFEND;
            IFEND;
          IFEND;
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      UNTIL status.normal OR (status.condition <> dme$fmd_too_small);

    ELSEIF device_class = rmc$magnetic_tape_device THEN
      PUSH p_stored_tape_volume_list: [1 .. UPPERBOUND (p_volume_list^)];
      stored_fmd_size := #SIZE (dmt$stored_tape_fmd_header) + #SIZE (p_stored_tape_volume_list^);

      ALLOCATE p_new_stored_fmd: [[REP stored_fmd_size OF cell]] IN p_catalog_heap^;
      IF p_new_stored_fmd = NIL THEN
        osp$set_status_condition (pfe$catalog_full, status);
      IFEND;

      IF status.normal THEN
        p_fmd := ^p_new_stored_fmd^.fmd;
        NEXT p_stored_tape_fmd_header IN p_fmd;
        p_stored_tape_fmd_header^.version := dmc$stored_tape_fmd_version_1;
        pfp$convert_density_to_dm (p_removable_media_req_info^.density, p_stored_tape_fmd_header^.density);
        p_stored_tape_fmd_header^.removable_media_group := p_removable_media_req_info^.removable_media_group;
        p_stored_tape_fmd_header^.volume_count := UPPERBOUND (p_volume_list^);
        p_stored_tape_fmd_header^.volume_overflow_allowed :=
              p_removable_media_req_info^.volume_overflow_allowed;
        p_stored_tape_fmd_header^.reserved_tape_fmd_header_space := pfv$null_tape_fmd_header_space;

        NEXT p_stored_tape_volume_list: [1 .. UPPERBOUND (p_volume_list^)] IN p_fmd;

        FOR volume_list_index := 1 TO UPPERBOUND (p_volume_list^) DO
          p_stored_tape_volume_list^ [volume_list_index].external_vsn :=
                p_volume_list^ [volume_list_index].external_vsn;
          p_stored_tape_volume_list^ [volume_list_index].recorded_vsn :=
                p_volume_list^ [volume_list_index].recorded_vsn;
        FOREND;
      IFEND;
    IFEND;

    IF status.normal THEN
      pfp$compute_checksum (#LOC (p_new_stored_fmd^.fmd), #SIZE (p_new_stored_fmd^.fmd),
            p_new_stored_fmd^.checksum);
    IFEND;

  PROCEND pfp$record_dm_file_parameters;

?? TITLE := '  [XDCL] pfp$remove_queued_catalogs', EJECT ??
{ PURPOSE:
{   This procedure deletes the queued catalog table.
{
{ DESIGN:
{   The job file manager is called to remove catalog entries from the job file
{   table.
{
{ NOTES:
{   This procedure is intended to be used only by active job recovery!  This
{   procedures does NOT assume that rollback has occurred!

  PROCEDURE [XDCL] pfp$remove_queued_catalogs;

    VAR
      display_status: ost$status,
      lock_status: ost$signature_lock_status,
      p_queued_catalog: pft$p_queued_catalog,
      status: ost$status;

    osp$test_signature_lock (pfv$p_queued_catalog_table_lock^, lock_status);
    IF lock_status <> osc$sls_not_locked THEN
      osp$log_job_recovery_message ('PF queued catalog table locked.', display_status);
      osp$initialize_signature_lock (pfv$p_queued_catalog_table_lock^, status);
      pfp$process_unexpected_status (status);
      pfv$p_p_queued_catalog_table^ := NIL;
      pfv$p_p_newest_queued_catalog^ := NIL;
    IFEND;

    p_queued_catalog := f$first_queued_catalog ();

  /free_all_internal_catalogs/
    WHILE p_queued_catalog <> NIL DO
      IF p_queued_catalog^.access_queued THEN
        free_internal_catalog_list (p_queued_catalog^.p_internal_catalog_list);
      IFEND;
      free_queued_catalog (p_queued_catalog);
      p_queued_catalog := f$first_queued_catalog ();
    WHILEND /free_all_internal_catalogs/;

    pfv$p_p_newest_queued_catalog^ := NIL;

    IF pfv$p_queued_catalog_table <> NIL THEN
      FREE pfv$p_p_queued_catalog_table^ IN pfv$p_p_job_heap^^;
    IFEND;

  PROCEND pfp$remove_queued_catalogs;

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

  PROCEDURE [XDCL] pfp$return_catalog
    (VAR catalog_locator: {i/o} pft$catalog_locator;
     VAR status: ost$status);

    VAR
      close_status: ost$status,
      detach_status: ost$status,
      external_name: pft$name,
      file_returned: boolean,
      heap_ok: boolean,
      i: integer,
      ignore_status: ost$status,
      local_status: ost$status,
      segment_pointer: mmt$segment_pointer,
      unlock_status: ost$status;

    unlock_status.normal := TRUE;
    close_status.normal := TRUE;
    detach_status.normal := TRUE;

    IF catalog_locator.queuing_info.set_catalog_alarm THEN
      IF catalog_locator.queuing_info.attach_queued THEN
        external_name := catalog_locator.queuing_info.external_catalog_name;
      ELSE
        external_name := 'unknown';
      IFEND;
      pfp$set_catalog_alarm (catalog_locator.global_file_name, catalog_locator.internal_catalog_name,
            external_name, {destroy_on_last_detach} FALSE);
    IFEND;

    IF catalog_locator.attached THEN
      IF catalog_locator.open THEN
        IF pfv$verify_catalog_heaps THEN
          osp$verify_heap (^catalog_locator.p_catalog_file^.catalog_heap, heap_ok);
          IF NOT heap_ok THEN
            osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$corrupted_catalog_heap,
                  'PFP$RETURN_CATALOG', local_status);
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], local_status,
                  ignore_status);
            pfp$report_unexpected_status (local_status);
          IFEND;
        IFEND;
        IF catalog_locator.locked THEN
          IF catalog_locator.abort_catalog_operation THEN
            mmp$unlock_segment (catalog_locator.p_catalog_file, mmc$lus_free, osc$nowait, unlock_status);
          ELSEIF catalog_locator.flush_catalog_pages THEN
            mmp$unlock_segment (catalog_locator.p_catalog_file, mmc$lus_protected_write, osc$nowait,
                  unlock_status);
          ELSE
            mmp$unlock_segment (catalog_locator.p_catalog_file, mmc$lus_none, osc$nowait, unlock_status);
          IFEND;
          catalog_locator.locked := FALSE;

        /initialize_locked_catalog_list/
          FOR i := 1 TO UPPERBOUND (pfv$locked_catalog_list) DO
            IF pfv$locked_catalog_list [i] <> NIL THEN
              IF #SEGMENT (pfv$locked_catalog_list [i]) = #SEGMENT (catalog_locator.p_catalog_file) THEN
                pfv$locked_catalog_list [i] := NIL;
                EXIT /initialize_locked_catalog_list/; {----->
              IFEND;
            IFEND;
          FOREND /initialize_locked_catalog_list/;
          pfp$process_unexpected_status (unlock_status);
        IFEND;

        segment_pointer.kind := mmc$cell_pointer;
        segment_pointer.cell_pointer := catalog_locator.p_catalog_file;
        mmp$close_segment (segment_pointer, pfc$catalog_ring, close_status);
        catalog_locator.open := FALSE;
        pfp$process_unexpected_status (close_status);
      IFEND;

      detach_catalog (catalog_locator, detach_status);
      catalog_locator.attached := FALSE;
      pfp$process_unexpected_status (detach_status);
    IFEND;

    IF NOT unlock_status.normal THEN
      status := unlock_status;
    ELSEIF NOT close_status.normal THEN
      status := close_status;
    ELSEIF NOT detach_status.normal THEN
      status := detach_status;
    ELSE
      status.normal := TRUE;
    IFEND;
  PROCEND pfp$return_catalog;

?? TITLE := '  [XDCL] pfp$update_stale_cycle_entry', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to update new items which were added to
{   the cycle entry in R1.4.1.  These items will be stale if the file cycle was
{   created or modified by an R1.3.1 or older version of the system.
{
{ DESIGN:
{   The items in the cycle entry which are updated are eoi, bytes_allocated,
{   and data_modification_date_time.
{
{ NOTE:
{   This procedure should be deleted two releases after R1.4.1, when it is no
{   longer necessary to support an upgrade from an R1.3.1 or earlier system.

  PROCEDURE [XDCL] pfp$update_stale_cycle_entry
    (    system_file_id: gft$system_file_identifier;
         p_physical_cycle: {i^/o^} ^pft$physical_cycle;
     VAR status: ost$status);

    VAR
      dm_file_information: dmt$file_information;

    IF p_physical_cycle^.cycle_entry.attach_status.attach_count = 0 THEN
      dmp$get_file_info (system_file_id, dm_file_information, status);

      IF status.normal THEN
        p_physical_cycle^.cycle_entry.data_modification_date_time :=
              p_physical_cycle^.cycle_entry.cycle_statistics.modification_date_time;
        p_physical_cycle^.cycle_entry.device_information.eoi := dm_file_information.eoi_byte_address;
        p_physical_cycle^.cycle_entry.device_information.bytes_allocated :=
              dm_file_information.total_allocated_length;
        pfp$compute_checksum (#LOC (p_physical_cycle^.cycle_entry), #SIZE (pft$cycle_entry),
              p_physical_cycle^.checksum);
      IFEND;
    IFEND;
  PROCEND pfp$update_stale_cycle_entry;

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

  PROCEDURE [XDCL] pfp$validate_ring_access
    (    path: pft$complete_path;
         p_file_label: {input} fmt$p_file_label;
         usage_selections: pft$usage_selections;
         validation_ring: ost$valid_ring;
     VAR status: ost$status);

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

    fmi$get_ring_attributes (p_file_label, cycle_formerly_opened_info, status);
    IF status.normal THEN
      IF NOT fmf$ring_attributes_valid (cycle_formerly_opened_info, usage_selections, validation_ring) 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$invalid_ring_access,
              p_fs_path^ (1, fs_path_size), status);
      IFEND;
    ELSE
      PUSH p_fs_path;
      pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
      osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
    IFEND;
  PROCEND pfp$validate_ring_access;

?? TITLE := '  build_catalog_locator', EJECT ??

  PROCEDURE build_catalog_locator
    (    p_queued_catalog: {i^/o^} ^pft$queued_catalog;
     VAR catalog_locator: pft$catalog_locator;
     VAR status: ost$status);

    VAR
      catalog_alarm_set: boolean,
      ignore_destroy_on_last_detach: boolean;

    status.normal := TRUE;

    catalog_locator.set_name := p_queued_catalog^.set_name;
    catalog_locator.internal_catalog_name := p_queued_catalog^.internal_catalog_name;
    catalog_locator.global_file_name := p_queued_catalog^.global_file_name;
    catalog_locator.recorded_vsn := p_queued_catalog^.recorded_vsn;
    catalog_locator.new_catalog := FALSE;
    catalog_locator.attached := TRUE;
    catalog_locator.system_file_id := p_queued_catalog^.system_file_id;
    catalog_locator.open := FALSE;

    catalog_locator.queuing_info.set_catalog_alarm := FALSE;
    catalog_locator.queuing_info.attach_queued := TRUE;
    catalog_locator.queuing_info.parent_catalog_internal_name :=
          p_queued_catalog^.parent_catalog_internal_name;
    catalog_locator.queuing_info.external_catalog_name := p_queued_catalog^.external_catalog_name;
    catalog_locator.queuing_info.charge_id := p_queued_catalog^.charge_id;
    catalog_locator.queuing_info.access_queued := p_queued_catalog^.access_queued;

    IF catalog_locator.queuing_info.access_queued THEN
      catalog_locator.queuing_info.p_internal_catalog_list := p_queued_catalog^.p_internal_catalog_list;
      catalog_locator.queuing_info.permit.entry_type := p_queued_catalog^.permit.entry_type;

      IF catalog_locator.queuing_info.permit.entry_type = pfc$normal_permit_entry THEN
        catalog_locator.queuing_info.permit.group.group_type := p_queued_catalog^.permit.group_type;
        CASE p_queued_catalog^.permit.group_type OF
        = pfc$public =
          ;
        = pfc$family =
          catalog_locator.queuing_info.permit.group.family_description.family := pfv$task_family;
        = pfc$account =
          catalog_locator.queuing_info.permit.group.account_description.family := pfv$task_family;
          catalog_locator.queuing_info.permit.group.account_description.account := pfv$task_account;
        = pfc$project =
          catalog_locator.queuing_info.permit.group.project_description.family := pfv$task_family;
          catalog_locator.queuing_info.permit.group.project_description.account := pfv$task_account;
          catalog_locator.queuing_info.permit.group.project_description.project := pfv$task_project;
        = pfc$user =
          catalog_locator.queuing_info.permit.group.user_description.family := pfv$task_family;
          catalog_locator.queuing_info.permit.group.user_description.user := pfv$task_user;
        = pfc$user_account =
          catalog_locator.queuing_info.permit.group.user_account_description.family := pfv$task_family;
          catalog_locator.queuing_info.permit.group.user_account_description.account := pfv$task_account;
          catalog_locator.queuing_info.permit.group.user_account_description.user := pfv$task_user;
        = pfc$member =
          catalog_locator.queuing_info.permit.group.member_description.family := pfv$task_family;
          catalog_locator.queuing_info.permit.group.member_description.account := pfv$task_account;
          catalog_locator.queuing_info.permit.group.member_description.project := pfv$task_project;
          catalog_locator.queuing_info.permit.group.member_description.user := pfv$task_user;
        ELSE
          ;
        CASEND;
        catalog_locator.queuing_info.permit.usage_permissions := p_queued_catalog^.permit.usage_permissions;
        catalog_locator.queuing_info.permit.share_requirements := p_queued_catalog^.permit.share_requirements;
        catalog_locator.queuing_info.permit.application_info := p_queued_catalog^.permit.application_info;
      IFEND;
    IFEND;

    pfp$check_catalog_alarm (p_queued_catalog^.global_file_name, catalog_alarm_set,
          ignore_destroy_on_last_detach);
    IF catalog_alarm_set THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_access_retry, '', status);
    IFEND;

  PROCEND build_catalog_locator;

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

  PROCEDURE [INLINE] create_queued_catalog_table;

    VAR
      index: integer,
      p_current: pft$p_queued_catalog;


    IF (pfv$p_p_queued_catalog_table^ = NIL) AND (pfc$queued_catalog_table_size > 0) THEN
      ALLOCATE pfv$p_p_queued_catalog_table^: [1 .. pfc$queued_catalog_table_size] IN pfv$p_p_job_heap^^;
    IFEND;

    IF pfv$p_p_queued_catalog_table^ <> NIL THEN
      pfv$p_p_newest_queued_catalog^ := ^pfv$p_p_queued_catalog_table^^ [1];
      FOR index := UPPERBOUND (pfv$p_p_queued_catalog_table^^) DOWNTO 1 DO
        p_current := ^pfv$p_p_queued_catalog_table^^ [index];
        p_current^.valid_catalog := FALSE;
        p_current^.p_next_newest := pfv$p_p_newest_queued_catalog^;
        pfv$p_p_newest_queued_catalog^^.p_next_oldest := p_current;
        pfv$p_p_newest_queued_catalog^ := p_current;
      FOREND;
    IFEND;
  PROCEND create_queued_catalog_table;

?? TITLE := '  detach_catalog', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to do one or more of the following:
{     o detach the catalog (the catalog will be destroyed if it has a
{       destroy_on_last_detach catalog alarm and this is the last detach)
{     o dequeue all subcatalogs internal to the catalog
{     o queue the catalog
{
{ NOTE:
{   If this procedure is changed, then pfp$detach_unavail_queued_cat may also
{   need to be changed.

  PROCEDURE detach_catalog
    (VAR catalog_locator: {i/o} pft$catalog_locator;
     VAR status: ost$status);

    VAR
      catalog_alarm_set: boolean,
      catalog_deleted: boolean,
      catalog_detached: boolean,
      destroy_on_last_detach: boolean,
      external_name: pft$name,
      old_queued_catalog: pft$queued_catalog,
      p_newest_queued_catalog: ^pft$queued_catalog,
      p_queued_catalog: pft$p_queued_catalog;

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

    {
    { Determine whether the catalog should be detached now or queued for later use.
    {

    pfp$check_catalog_alarm (catalog_locator.global_file_name, catalog_alarm_set, destroy_on_last_detach);

    IF catalog_locator.new_catalog OR (NOT catalog_locator.queuing_info.attach_queued) OR
          catalog_alarm_set THEN
      physically_detach_catalog (catalog_locator.system_file_id, catalog_locator.global_file_name,
            catalog_alarm_set, destroy_on_last_detach, {flush_catalog} TRUE, catalog_deleted, status);
      catalog_detached := TRUE;
    IFEND;

    IF status.normal THEN
      IF catalog_detached THEN
        IF catalog_alarm_set THEN
          osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);
          p_queued_catalog := f$queued_cat_by_internal (catalog_locator.internal_catalog_name);
          IF p_queued_catalog <> NIL THEN
            free_internal_catalog_list (catalog_locator.queuing_info.p_internal_catalog_list);
            free_queued_catalog (p_queued_catalog);
          IFEND;
          osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);
        IFEND;
      ELSE
        {
        { The catalog was not detached; queue the catalog for later use.
        {
        osp$set_job_signature_lock (pfv$p_queued_catalog_table_lock^);
        rotate_catalog_queue (p_newest_queued_catalog);
        IF p_newest_queued_catalog <> NIL THEN
          old_queued_catalog := p_newest_queued_catalog^;
          {
          { Build queued catalog table entry from catalog_locator.
          {
          p_newest_queued_catalog^.valid_catalog := TRUE;
          p_newest_queued_catalog^.set_name := catalog_locator.set_name;
          p_newest_queued_catalog^.parent_catalog_internal_name :=
                catalog_locator.queuing_info.parent_catalog_internal_name;
          p_newest_queued_catalog^.external_catalog_name := catalog_locator.queuing_info.
                external_catalog_name;
          p_newest_queued_catalog^.internal_catalog_name := catalog_locator.internal_catalog_name;
          p_newest_queued_catalog^.global_file_name := catalog_locator.global_file_name;
          p_newest_queued_catalog^.recorded_vsn := catalog_locator.recorded_vsn;
          p_newest_queued_catalog^.charge_id := catalog_locator.queuing_info.charge_id;
          p_newest_queued_catalog^.system_file_id := catalog_locator.system_file_id;
          p_newest_queued_catalog^.access_queued := catalog_locator.queuing_info.access_queued;
          IF p_newest_queued_catalog^.access_queued THEN
            p_newest_queued_catalog^.p_internal_catalog_list :=
                  catalog_locator.queuing_info.p_internal_catalog_list;
            p_newest_queued_catalog^.permit.entry_type := catalog_locator.queuing_info.permit.entry_type;
            IF p_newest_queued_catalog^.permit.entry_type = pfc$normal_permit_entry THEN
              p_newest_queued_catalog^.permit.usage_permissions :=
                    catalog_locator.queuing_info.permit.usage_permissions;
              p_newest_queued_catalog^.permit.share_requirements :=
                    catalog_locator.queuing_info.permit.share_requirements;
              p_newest_queued_catalog^.permit.application_info :=
                    catalog_locator.queuing_info.permit.application_info;
              p_newest_queued_catalog^.permit.group_type := catalog_locator.queuing_info.permit.group.
                    group_type;
            IFEND;
          IFEND;
        IFEND;
        osp$clear_job_signature_lock (pfv$p_queued_catalog_table_lock^);
        IF p_newest_queued_catalog = NIL THEN
          {
          { Unable to get queue entry or queueing not selected.
          {
          physically_detach_catalog (catalog_locator.system_file_id, catalog_locator.global_file_name,
                catalog_alarm_set, destroy_on_last_detach, {flush_catalog} TRUE, catalog_deleted, status);
          IF catalog_locator.queuing_info.access_queued THEN
            free_internal_catalog_list (catalog_locator.queuing_info.p_internal_catalog_list);
          IFEND;
        ELSEIF old_queued_catalog.valid_catalog THEN { Old catalog aged out.
          pfp$check_catalog_alarm (old_queued_catalog.global_file_name, catalog_alarm_set,
                destroy_on_last_detach);
          physically_detach_catalog (old_queued_catalog.system_file_id, old_queued_catalog.global_file_name,
                catalog_alarm_set, destroy_on_last_detach, {flush_catalog} TRUE, catalog_deleted, status);
          IF old_queued_catalog.access_queued THEN
            free_internal_catalog_list (old_queued_catalog.p_internal_catalog_list);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND detach_catalog;

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

  PROCEDURE [INLINE] fetch_file_usage
    (    system_file_id: gft$system_file_identifier;
     VAR file_usage: dmt$usage_count);

    VAR
      file_info: dmt$segment_file_info,
      status: ost$status;

    dmp$fetch_segment_file_info (system_file_id, 0, file_info, status);
    IF status.normal THEN
      file_usage := file_info.usage_count;
    ELSE
      file_usage := 0;
      pfp$report_unexpected_status (status);
    IFEND;
  PROCEND fetch_file_usage;

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

  PROCEDURE [INLINE] free_internal_catalog_list
    (VAR p_internal_catalog: {i/o} pft$p_queued_internal_catalog);

    { p_internal_catalog is the start of a linked list of internal catalogs.

    VAR
      next_internal_catalog: pft$p_queued_internal_catalog;

    WHILE p_internal_catalog <> NIL DO
      next_internal_catalog := p_internal_catalog^.p_next_internal_catalog;
      FREE p_internal_catalog IN pfv$p_p_job_heap^^;
      p_internal_catalog := next_internal_catalog;
    WHILEND;
  PROCEND free_internal_catalog_list;

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

  PROCEDURE [INLINE] free_queued_catalog
    (    p_queued_catalog: {i/o^} pft$p_queued_catalog);

    VAR
      p_next_newest: pft$p_queued_catalog,
      p_next_oldest: pft$p_queued_catalog;

    p_queued_catalog^.valid_catalog := FALSE;
    IF p_queued_catalog = pfv$p_p_newest_queued_catalog^ THEN
      pfv$p_p_newest_queued_catalog^ := p_queued_catalog^.p_next_newest;
    ELSE
      p_next_oldest := p_queued_catalog^.p_next_oldest;
      p_next_newest := p_queued_catalog^.p_next_newest;
      p_next_oldest^.p_next_newest := p_next_newest;
      p_next_newest^.p_next_oldest := p_next_oldest;
      p_next_newest := pfv$p_p_newest_queued_catalog^;
      p_next_oldest := p_next_newest^.p_next_oldest;
      p_queued_catalog^.p_next_oldest := p_next_oldest;
      p_queued_catalog^.p_next_newest := p_next_newest;
      p_next_oldest^.p_next_newest := p_queued_catalog;
      p_next_newest^.p_next_oldest := p_queued_catalog;
    IFEND;
  PROCEND free_queued_catalog;

?? TITLE := '  generate_dm_file_attributes', EJECT ??

  PROCEDURE generate_dm_file_attributes
    (    path: pft$complete_path;
         object_type: pft$object_types;
         validation_ring: ost$valid_ring;
         use_scl_variable_defaults: boolean;
         p_mass_storage_request_info: {input} ^fmt$mass_storage_request_info;
         authority: pft$authority;
     VAR dm_file_attributes: pft$dm_file_attributes;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      local_status: ost$status,
      ms_class_info: cmt$ms_class_info,
      p_data_value: ^clt$data_value,
      p_local_ms_request_info: ^fmt$mass_storage_request_info,
      scl_variable_default_used: boolean,
      system_file: boolean,
      user_id: ost$user_identification,
      volume_found: boolean;

    status.normal := TRUE;

    {
    { Validate mass storage request info.
    {

    p_local_ms_request_info := NIL;
    system_file := pfp$system_path (path);

    IF p_mass_storage_request_info <> NIL THEN
      PUSH p_local_ms_request_info;
      p_local_ms_request_info^ := p_mass_storage_request_info^;
      scl_variable_default_used := FALSE;
      IF use_scl_variable_defaults THEN
        IF p_local_ms_request_info^.mass_storage_class = rmc$unspecified_file_class THEN
          clp$get_variable_value ('RMV$MASS_STORAGE_CLASS', p_data_value, local_status);
          IF local_status.normal AND (p_data_value <> NIL) THEN
            IF p_data_value^.kind = clc$name THEN
              IF p_data_value^.name_value (2) = ' ' THEN
                CASE p_data_value^.name_value (1) OF
                = 'A' .. 'Z' =
                  p_local_ms_request_info^.mass_storage_class := p_data_value^.name_value (1);
                  scl_variable_default_used := TRUE;
                ELSE
                  pmp$log_ascii ('Invalid value for variable RMV$MASS_STORAGE_CLASS ignored.',
                        $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
                CASEND;
              ELSE
                pmp$log_ascii ('Invalid value for variable RMV$MASS_STORAGE_CLASS ignored.',
                      $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
              IFEND;
            ELSE
              pmp$log_ascii ('Invalid type for variable RMV$MASS_STORAGE_CLASS ignored.',
                    $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
            IFEND;
          IFEND;
        IFEND;
        IF p_local_ms_request_info^.initial_volume = rmc$unspecified_vsn THEN
          clp$get_variable_value ('RMV$INITIAL_VOLUME', p_data_value, local_status);
          IF local_status.normal AND (p_data_value <> NIL) THEN
            IF p_data_value^.kind = clc$name THEN
              p_local_ms_request_info^.initial_volume := p_data_value^.name_value;
              scl_variable_default_used := TRUE;
              IF p_local_ms_request_info^.mass_storage_class = rmc$unspecified_file_class THEN
                IF system_file THEN
                  p_local_ms_request_info^.mass_storage_class := rmc$msc_system_permanent_files;
                ELSE
                  p_local_ms_request_info^.mass_storage_class := rmc$msc_user_permanent_files;
                IFEND;
              IFEND;
            ELSE
              pmp$log_ascii ('Invalid type for variable RMV$INITIAL_VOLUME ignored.',
                    $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
            IFEND;
          IFEND;
        IFEND;
      IFEND;
      rmp$validate_mass_storage_info (path [pfc$set_path_index], {object_permanent} TRUE, object_type,
            p_local_ms_request_info, status);
      IF NOT status.normal THEN
        IF scl_variable_default_used THEN
          p_local_ms_request_info^ := p_mass_storage_request_info^;
          rmp$validate_mass_storage_info (path [pfc$set_path_index], {object_permanent} TRUE, object_type,
                p_local_ms_request_info, local_status);
          IF local_status.normal THEN
            pmp$log_ascii ('The following error caused by an invalid value for variable ' CAT
                  'RMV$INITIAL_VOLUME or RMV$MASS_STORAGE_CLASS was ignored.', $pmt$ascii_logset
                  [pmc$job_log], pmc$msg_origin_system, ignore_status);
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], status, ignore_status);
            status.normal := TRUE;
          ELSE
            status := local_status;
            RETURN; {----->
          IFEND;
        ELSE
          RETURN; {----->
        IFEND;
      IFEND;
    ELSEIF use_scl_variable_defaults THEN
      clp$get_variable_value ('RMV$MASS_STORAGE_CLASS', p_data_value, local_status);
      IF local_status.normal AND (p_data_value <> NIL) THEN
        IF p_data_value^.kind = clc$name THEN
          IF p_data_value^.name_value (2) = ' ' THEN
            IF p_local_ms_request_info = NIL THEN
              PUSH p_local_ms_request_info;
              rmp$build_mass_storage_info ({allocation_size} rmc$unspecified_allocation_size,
                    {estimated_file_size} rmc$unspecified_file_size, {initial_volume} rmc$unspecified_vsn,
                    {mass_storage_class} rmc$unspecified_file_class, {shared_queue} pfc$null_shared_queue,
                    {transfer_size} rmc$unspecified_transfer_size, {volume_overflow_allowed} TRUE,
                    validation_ring, p_local_ms_request_info, local_status);
              IF NOT local_status.normal THEN
                p_local_ms_request_info := NIL;
              IFEND;
            IFEND;
            IF p_local_ms_request_info <> NIL THEN
              CASE p_data_value^.name_value (1) OF
              = 'A' .. 'Z' =
                p_local_ms_request_info^.mass_storage_class := p_data_value^.name_value (1);
                scl_variable_default_used := TRUE;
              ELSE
                pmp$log_ascii ('Invalid value for variable RMV$MASS_STORAGE_CLASS ignored.',
                      $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
              CASEND;
            IFEND;
          ELSE
            pmp$log_ascii ('Invalid value for variable RMV$MASS_STORAGE_CLASS ignored.',
                  $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
          IFEND;
        ELSE
          pmp$log_ascii ('Invalid type for variable RMV$MASS_STORAGE_CLASS ignored.',
                $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
        IFEND;
      IFEND;
      clp$get_variable_value ('RMV$INITIAL_VOLUME', p_data_value, local_status);
      IF local_status.normal AND (p_data_value <> NIL) THEN
        IF p_data_value^.kind = clc$name THEN
          IF p_local_ms_request_info = NIL THEN
            PUSH p_local_ms_request_info;
            rmp$build_mass_storage_info ({allocation_size} rmc$unspecified_allocation_size,
                  {estimated_file_size} rmc$unspecified_file_size, {initial_volume} rmc$unspecified_vsn,
                  {mass_storage_class} rmc$unspecified_file_class, {shared_queue} pfc$null_shared_queue,
                  {transfer_size} rmc$unspecified_transfer_size, {volume_overflow_allowed} TRUE,
                  validation_ring, p_local_ms_request_info, local_status);
            IF local_status.normal THEN
              p_local_ms_request_info^.initial_volume := p_data_value^.name_value;
              IF system_file THEN
                p_local_ms_request_info^.mass_storage_class := rmc$msc_system_permanent_files;
              ELSE
                p_local_ms_request_info^.mass_storage_class := rmc$msc_user_permanent_files;
              IFEND;
            ELSE
              p_local_ms_request_info := NIL;
            IFEND;
          ELSE
            p_local_ms_request_info^.initial_volume := p_data_value^.name_value;
          IFEND;
        ELSE
          pmp$log_ascii ('Invalid type for variable RMV$INITIAL_VOLUME ignored.',
                $pmt$ascii_logset [pmc$job_log], pmc$msg_origin_system, ignore_status);
        IFEND;
      IFEND;
      IF p_local_ms_request_info <> NIL THEN
        rmp$validate_mass_storage_info (path [pfc$set_path_index], {object_permanent} TRUE, object_type,
              p_local_ms_request_info, local_status);
        IF NOT local_status.normal THEN
          pmp$log_ascii ('The following error caused by an invalid value for variable ' CAT
                'RMV$INITIAL_VOLUME or RMV$MASS_STORAGE_CLASS was ignored.', $pmt$ascii_logset [pmc$job_log],
                pmc$msg_origin_system, ignore_status);
          osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], local_status, ignore_status);
          p_local_ms_request_info := NIL;
        IFEND;
      IFEND;
    IFEND;

    dm_file_attributes := initial_dm_file_attributes;
    dm_file_attributes [pfc$initial_volume_index].requested_volume.setname := path [pfc$set_path_index];

    CASE object_type OF
    = pfc$file_object =
      IF system_file THEN
        dm_file_attributes [pfc$file_class_index].class := rmc$msc_system_permanent_files;
      ELSE
        dm_file_attributes [pfc$file_class_index].class := rmc$msc_user_permanent_files;
        IF pfc$master_catalog_owner IN authority.ownership THEN
          dm_file_attributes [pfc$owner_index].file_space_limit := sfc$perm_file_space_limit;
        IFEND;
      IFEND;

    = pfc$catalog_object =
      IF system_file THEN
        dm_file_attributes [pfc$file_class_index].class := rmc$msc_system_catalogs;
      ELSE
        dm_file_attributes [pfc$file_class_index].class := rmc$msc_user_catalogs;
      IFEND;
      dm_file_attributes [pfc$volume_overflow_index].overflow_allowed := FALSE;
      dm_file_attributes [pfc$allocation_size_index].requested_allocation_size := pfc$catalog_allocation_size;

    ELSE
      ;
    CASEND;

    {
    { Assign attributes from a request_mass_storage command.
    {
    IF p_local_ms_request_info <> NIL THEN
      IF p_local_ms_request_info^.mass_storage_class <> rmc$unspecified_file_class THEN
        dm_file_attributes [pfc$file_class_index].class := p_local_ms_request_info^.mass_storage_class;
      ELSEIF p_local_ms_request_info^.initial_volume <> rmc$unspecified_vsn THEN
        pmp$get_user_identification (user_id, status);
        IF status.normal AND (jmp$system_job () OR (user_id.user = jmc$system_user)) THEN
          cmp$get_ms_class_on_volume (p_local_ms_request_info^.initial_volume, volume_found, ms_class_info);
          IF volume_found AND NOT ms_class_info.classes [dm_file_attributes [pfc$file_class_index].class] THEN
            dm_file_attributes [pfc$file_class_index].class := rmc$unspecified_file_class;
          IFEND;
        IFEND;
      IFEND;

      dm_file_attributes [pfc$volume_overflow_index].overflow_allowed :=
            p_local_ms_request_info^.volume_overflow_allowed;
      dm_file_attributes [pfc$allocation_size_index].requested_allocation_size :=
            p_local_ms_request_info^.allocation_size;
      dm_file_attributes [pfc$initial_volume_index].requested_volume.recorded_vsn :=
            p_local_ms_request_info^.initial_volume;
      dm_file_attributes [pfc$transfer_size_index].requested_transfer_size :=
            p_local_ms_request_info^.transfer_size;
    IFEND;
  PROCEND generate_dm_file_attributes;

?? TITLE := '  physically_detach_catalog', EJECT ??

  PROCEDURE physically_detach_catalog
    (    system_file_id: gft$system_file_identifier;
         global_file_name: ost$binary_unique_name;
         catalog_alarm_set: boolean;
         destroy_on_last_detach: boolean;
         flush_catalog: boolean;
     VAR catalog_deleted: boolean;
     VAR status: ost$status);

    VAR
      catalog_usage: dmt$usage_count,
      file_info: dmt$file_information,
      file_modified: boolean,
      fmd_modified: boolean,
      p_fmd: pft$p_fmd,
      stored_fmd_size: dmt$stored_fmd_size;

    {
    { Flush catalog pages only when detaching the last instance of attach.
    {
    fetch_file_usage (system_file_id, catalog_usage);
    dmp$detach_file (system_file_id, {access_allowed} TRUE, ((catalog_usage = 1) AND flush_catalog),
          dmc$df_ignore_file_info, file_modified, fmd_modified, file_info, status);
    IF status.normal THEN
      dmp$delete_file_descriptor (system_file_id, status);
      IF status.normal THEN
        catalog_deleted := TRUE;
      ELSE
        catalog_deleted := FALSE;
        IF status.condition = dme$file_descriptor_not_deleted THEN
          status.normal := TRUE;
        ELSE
          pfp$report_unexpected_status (status);
        IFEND;
      IFEND;
    ELSE
      catalog_deleted := FALSE;
      pfp$report_unexpected_status (status);
    IFEND;

    IF catalog_alarm_set AND catalog_deleted AND (catalog_usage = 1) THEN
      pfp$clear_catalog_alarm (global_file_name);
      IF destroy_on_last_detach THEN
        dmp$get_stored_fmd_size (system_file_id, stored_fmd_size, status);
        IF status.normal THEN
          PUSH p_fmd: [[REP stored_fmd_size OF cell]];
          RESET p_fmd;
          dmp$get_stored_fmd (system_file_id, p_fmd^, status);
          IF status.normal THEN
            dmp$destroy_permanent_file (global_file_name, p_fmd^, status);
          IFEND;
        IFEND;
        pfp$process_unexpected_status (status);
      IFEND;
    IFEND;

  PROCEND physically_detach_catalog;

?? TITLE := '  store_valid_file_class_in_fmd', EJECT ??

  PROCEDURE [INLINE] store_valid_file_class_in_fmd
    (    path: pft$complete_path;
         object_type: pft$object_types;
         system_file_id: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      system_file: boolean,
      valid_file_class: dmt$class_member;

    status.normal := TRUE;

    system_file := pfp$system_path (path);

    CASE object_type OF
    = pfc$file_object =
      IF system_file THEN
        valid_file_class := rmc$msc_system_permanent_files;
      ELSE
        valid_file_class := rmc$msc_user_permanent_files;
      IFEND;

    = pfc$catalog_object =
      IF system_file THEN
        valid_file_class := rmc$msc_system_catalogs;
      ELSE
        valid_file_class := rmc$msc_user_catalogs;
      IFEND;
    ELSE
      ;
    CASEND;

    dmp$store_valid_class_in_fmd (system_file_id, valid_file_class, status);

  PROCEND store_valid_file_class_in_fmd;

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

  PROCEDURE [INLINE] rotate_catalog_queue
    (VAR p_newest_queued_catalog: {output} pft$p_queued_catalog);

    IF pfv$p_p_newest_queued_catalog^ = NIL THEN
      create_queued_catalog_table;
    ELSE
      pfv$p_p_newest_queued_catalog^ := pfv$p_p_newest_queued_catalog^^.p_next_oldest;
    IFEND;

    p_newest_queued_catalog := pfv$p_p_newest_queued_catalog^;
  PROCEND rotate_catalog_queue;

?? TITLE := '  set_server_output', EJECT ??

  PROCEDURE set_server_output
    (    cycle_created: boolean;
         application_info: pft$application_info;
         cycle_number: fst$cycle_number;
         allow_other_mainframe_writer: boolean;
         internal_cycle_name: pft$internal_name;
         usage_intentions: pft$usage_selections;
         share_selections: pft$share_selections;
         password_protected: boolean;
         attached_pf_table_index: pft$attached_pf_table_index;
         system_file_id: gft$system_file_identifier;
         p_file_label: {input} fmt$p_file_label;
         p_fmd: {input} pft$p_fmd,
         device_class: rmt$device_class;
     VAR bytes_allocated: amt$file_byte_address;
     VAR p_file_server_buffers: {i^/o^} pft$p_file_server_buffers;
     VAR status: ost$status);

    VAR
      p_server_file_output: ^pft$server_file_output,
      p_nexted_fmd: pft$p_fmd,
      p_nexted_label: fmt$p_file_label;

    NEXT p_server_file_output IN p_file_server_buffers^.p_send_parameters;
    p_server_file_output^.allow_other_mainframe_writer := allow_other_mainframe_writer;
    p_server_file_output^.application_info := application_info;
    p_server_file_output^.attached_pf_table_index := attached_pf_table_index;
    p_server_file_output^.cycle_created := cycle_created;
    p_server_file_output^.cycle_number := cycle_number;
    p_server_file_output^.global_file_name := internal_cycle_name;
    p_server_file_output^.password_protected := password_protected;
    p_server_file_output^.share_selections := share_selections;
    p_server_file_output^.usage_selections := usage_intentions;

    bytes_allocated := 0;
    IF device_class = rmc$mass_storage_device THEN
      dmp$fetch_server_sft_info (system_file_id, p_server_file_output^.dm_parameters, p_file_server_buffers,
            status);
      IF status.normal THEN
        bytes_allocated := p_server_file_output^.dm_parameters.total_allocated_length;
      ELSE
        status.normal := TRUE;
      IFEND;
    IFEND;

    IF p_file_label = NIL THEN
      p_server_file_output^.label_length := 0;
    ELSE
      p_server_file_output^.label_length := #SIZE (p_file_label^);
      IF p_fmd = NIL THEN
        NEXT p_nexted_label: [[REP p_server_file_output^.label_length OF cell]] IN
              p_file_server_buffers^.p_send_parameters;
        IF p_nexted_label = NIL THEN
          NEXT p_nexted_label: [[REP p_server_file_output^.label_length OF cell]] IN
                p_file_server_buffers^.p_send_data;
        IFEND;
      ELSE
        NEXT p_nexted_label: [[REP p_server_file_output^.label_length OF cell]] IN
              p_file_server_buffers^.p_send_data;
      IFEND;
      IF p_nexted_label = NIL THEN
        osp$system_error (' File server data area overflow in SET_SERVER_OUTPUT.', NIL);
      IFEND;
      p_nexted_label^ := p_file_label^;
    IFEND;

    IF p_fmd = NIL THEN
      p_server_file_output^.rem_media_fmd_length := 0;
    ELSE
      p_server_file_output^.rem_media_fmd_length := #SIZE (p_fmd^);
      NEXT p_nexted_fmd: [[REP p_server_file_output^.rem_media_fmd_length OF cell]] IN
            p_file_server_buffers^.p_send_data;
      IF p_nexted_fmd = NIL THEN
        osp$system_error (' File server data area overflow in SET_SERVER_OUTPUT.', NIL);
      IFEND;
      p_nexted_fmd^ := p_fmd^;
    IFEND;

  PROCEND set_server_output;

MODEND pfm$file_system_interfaces;
