?? NEWTITLE := 'NOS/VE Device Management' ??
MODULE dmm$destroy_permanent_file;
?? RIGHT := 110 ??

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rmd$volume_declarations
*copyc amt$file_byte_address
*copyc dmt$device_file_list_index
*copyc dmt$device_file_stored_fmd
*copyc dmt$disk_file_descriptor
*copyc dmt$error_condition_codes
*copyc dmt$global_file_name
*copyc dmt$stored_fmd
*copyc dmt$stored_ms_fmd_header
*copyc gft$locked_file_desc_entry_p
*copyc gft$system_file_identifier
*copyc ost$status
?? POP ??
*copyc dmp$clear_master_attach_lock
*copyc dmp$close_file
*copyc dmp$decrement_class_activity
*copyc dmp$generate_gfn_hash
*copyc dmp$get_active_vol_attributes
*copyc dmp$get_disk_file_descriptor_p
*copyc dmp$open_directory
*copyc dmp$process_device_log_entry
*copyc dmp$search_avt_by_rvsn
*copyc dmp$search_avt_by_vsn
*copyc dmp$search_fdt_by_gfn
*copyc dmp$search_vol_directory_name
*copyc dmp$set_master_attach_lock
*copyc gfp$get_locked_fde_p
*copyc gfp$unlock_fde_p
*copyc mmp$write_modified_pages
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
?? TITLE := '  dmp$destroy_permanent_file', EJECT ??
*copyc dmh$destroy_permanent_file

  PROCEDURE [XDCL, #GATE] dmp$destroy_permanent_file
    (    global_file_name: dmt$global_file_name;
         stored_fmd: dmt$stored_fmd;
     VAR status: ost$status);

    VAR
      p_stored_fmd_version: ^dmt$stored_ms_version_number,
      p_stored_fmd_header: ^dmt$stored_ms_fmd_header,
      p_stored_fmd_subfile: ^dmt$stored_ms_fmd_subfile,
      log_entry: dmt$dl_entry,
      i: integer,
      avt_index: dmt$active_volume_table_index,
      file_tables_in_mainframe: boolean,
      active_volume_entry_found: boolean,
      volume_offline_count: integer,
      recorded_vsn: rmt$recorded_vsn,
      p_fmd_seq: ^dmt$stored_fmd;

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

  /process_request/
    BEGIN
      inhibit_recovery (global_file_name, file_tables_in_mainframe, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      IF file_tables_in_mainframe THEN
        EXIT /process_request/; {----->
      IFEND;

      p_fmd_seq := ^stored_fmd;
      RESET p_fmd_seq;

      NEXT p_stored_fmd_version IN p_fmd_seq;

      NEXT p_stored_fmd_header: [p_stored_fmd_version^] IN p_fmd_seq;
      IF p_stored_fmd_header = NIL THEN
        osp$set_status_abnormal (dmc$device_manager_ident, dme$invalid_fmd,
              'No fmd header - dmp$destroy_permanent_file.', status);
        EXIT /process_request/; {----->
      IFEND;

      CASE p_stored_fmd_version^ OF
      = 0 =
        IF p_stored_fmd_header^.version_0_0.number_fmds = 0 THEN
          RETURN; {----->
        IFEND;
        log_entry.kind := dmc$dl_purge_file;
        log_entry.purge_file_block.global_file_name := global_file_name;

        FOR i := 1 TO p_stored_fmd_header^.version_0_0.number_fmds DO
          NEXT p_stored_fmd_subfile: [p_stored_fmd_version^] IN p_fmd_seq;
          IF p_stored_fmd_subfile = NIL THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$invalid_fmd,
                  'FMD too small to hold subfiles - dmp$destroy_permanent_file.', status);
            EXIT /process_request/; {----->
          IFEND;
          dmp$search_avt_by_vsn (p_stored_fmd_subfile^.version_0_0.internal_vsn, avt_index,
                active_volume_entry_found);
          IF NOT active_volume_entry_found THEN
            volume_offline_count := volume_offline_count + 1;
            recorded_vsn := p_stored_fmd_subfile^.version_0_0.recorded_vsn;
          ELSE
            log_entry.purge_file_block.file_byte_address := p_stored_fmd_subfile^.version_0_0.
                  stored_byte_address * dmc$byte_address_converter;
            log_entry.purge_file_block.dfl_index := p_stored_fmd_subfile^.version_0_0.device_file_list_index;
            dmp$process_device_log_entry (avt_index, log_entry, status);
            IF NOT status.normal THEN
              EXIT /process_request/; {----->
            IFEND;
          IFEND;
        FOREND;
      ELSE
        osp$set_status_abnormal (dmc$device_manager_ident, dme$unsupported_fmd_version,
              'Unsupported FMD version number - dmp$destroy_permanent_file.', status);
      CASEND;

    END /process_request/;

    IF (status.normal) AND (volume_offline_count <> 0) THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$some_volumes_not_online, recorded_vsn, status);
    IFEND;

  PROCEND dmp$destroy_permanent_file;
?? TITLE := '  dmp$destroy_device_file', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$destroy_device_file
    (    recorded_vsn: rmt$recorded_vsn;
         user_supplied_name: ost$name;
     VAR status: ost$status);

    VAR
      close_status: ost$status,
      active_vol_attributes: array [1 .. 1] of dmt$assigned_ms_vol_attribute,
      volume_active: boolean,
      directory_sfid: gft$system_file_identifier,
      directory_index: dmt$directory_index,
      p_directory: ^dmt$ms_volume_directory,
      entry_found: boolean,
      stored_df_fmd: dmt$device_file_stored_fmd,
      global_file_name: dmt$global_file_name;

    status.normal := TRUE;

  /process_request/
    BEGIN
      active_vol_attributes [1].keyword := dmc$ms_volume_directory;

      dmp$get_active_vol_attributes (recorded_vsn, 0, active_vol_attributes, volume_active);
      IF NOT volume_active THEN
        {
        { issue mount request
        {
        osp$set_status_abnormal (dmc$device_manager_ident, dme$avt_entry_not_found,
              'Volume not in AVT - dmp$destroy_device_file.', status);
        osp$append_status_parameter (' ', recorded_vsn, status);
        EXIT /process_request/; {----->
      IFEND;

      directory_sfid := active_vol_attributes [1].directory_sfid;

      directory_index := 0;
      dmp$search_vol_directory_name (user_supplied_name, directory_sfid, directory_index, entry_found,
            status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      IF NOT entry_found THEN
        osp$set_status_abnormal (dmc$device_manager_ident, dme$unknown_device_file,
              'Unknown device file name - dmp$destroy_device_file.', status);
        osp$append_status_parameter (' ', user_supplied_name, status);
        EXIT /process_request/; {----->
      IFEND;

      dmp$open_directory (directory_sfid, osc$os_ring_1, osc$tsrv_ring, mmc$sar_write_extend,
            mmc$as_sequential, p_directory, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      stored_df_fmd := p_directory^.entries [directory_index].stored_df_fmd;
      global_file_name := p_directory^.entries [directory_index].global_file_name;

      dmp$destroy_permanent_file (global_file_name, stored_df_fmd, status);
      IF status.normal THEN
        p_directory^.entries [directory_index].entry_available := TRUE;
        mmp$write_modified_pages (p_directory, #SIZE (p_directory^), osc$wait, status);
      IFEND;

      dmp$close_file (p_directory, close_status);
      IF NOT close_status.normal THEN
        IF status.normal THEN
          status := close_status;
        IFEND;
      IFEND;

    END /process_request/;

  PROCEND dmp$destroy_device_file;
?? TITLE := '  dmp$destroy_sub_file', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$destroy_sub_file
    (    global_file_name: dmt$global_file_name;
         recorded_vsn: rmt$recorded_vsn;
         dfl_index: dmt$device_file_list_index;
         byte_address: amt$file_byte_address;
     VAR status: ost$status);

    VAR
      log_entry: dmt$dl_entry,
      avt_index: dmt$active_volume_table_index,
      file_tables_in_mainframe: boolean,
      avt_entry_found: boolean;

    status.normal := TRUE;

    log_entry.kind := dmc$dl_purge_file;
    log_entry.purge_file_block.global_file_name := global_file_name;
    log_entry.purge_file_block.dfl_index := dfl_index;
    log_entry.purge_file_block.file_byte_address := byte_address;

    dmp$search_avt_by_rvsn (recorded_vsn, avt_index, avt_entry_found);
    IF NOT avt_entry_found THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$avt_entry_not_found,
            'Volume not mounted - dmp$destroy_sub_file.', status);
      osp$append_status_parameter (' ', recorded_vsn, status);
      RETURN; {----->
    IFEND;

    inhibit_recovery (global_file_name, file_tables_in_mainframe, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF NOT file_tables_in_mainframe THEN
      dmp$process_device_log_entry (avt_index, log_entry, status);
    IFEND;

  PROCEND dmp$destroy_sub_file;
?? TITLE := '  inhibit_recovery', EJECT ??

  PROCEDURE inhibit_recovery
    (    global_file_name: dmt$global_file_name;
     VAR existing_entry_found: boolean;
     VAR status: ost$status);

    VAR
      sfid: gft$system_file_identifier,
      file_hash: dmt$file_hash,
      p_fde: gft$locked_file_desc_entry_p,
      p_dfd: ^dmt$disk_file_descriptor;

    status.normal := TRUE;

{ Build SFID.
    dmp$generate_gfn_hash (global_file_name, file_hash);
    sfid.file_hash := file_hash;
    sfid.residence := gfc$tr_system;

{ Set master attach lock.
    dmp$set_master_attach_lock (sfid);

{ Find, lock and set the purge flag for any existing SFT entry.
    dmp$search_fdt_by_gfn (sfid.residence, global_file_name, sfid.file_entry_index, existing_entry_found);
    IF existing_entry_found THEN
      gfp$get_locked_fde_p (sfid, p_fde);
      existing_entry_found := (p_fde^.global_file_name = global_file_name);
      IF existing_entry_found THEN
        dmp$get_disk_file_descriptor_p (p_fde, p_dfd);
        p_dfd^.purged := TRUE;

        dmp$decrement_class_activity (p_dfd);
      IFEND;
      gfp$unlock_fde_p (p_fde);
    IFEND;

{ Clear master attach lock.
    dmp$clear_master_attach_lock (sfid);

  PROCEND inhibit_recovery;
?? OLDTITLE ??
MODEND dmm$destroy_permanent_file;
