*copyc OSD$DEFAULT_PRAGMATS
?? NEWTITLE := 'NOS/VE File_Management : Close File' ??
MODULE fmm$close_file;
?? RIGHT := 110 ??
{
{ PURPOSE:
{   This module contains the interface that performs the necessary ring 2
{ operations for closing a file.
{
?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc bat$task_file_table
*copyc fst$file_access_options
?? POP ??
*copyc clp$check_name_for_path_handle
*copyc fmp$lock_path_table
*copyc fmp$return_file
*copyc fmp$unlock_path_table
*copyc mmp$close_segment
*copyc osp$decrement_locked_variable
*copyc osp$generate_log_message
*copyc fsv$evaluated_file_reference
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] fmp$close_file', EJECT ??

  PROCEDURE [XDCL, #GATE] fmp$close_file
    (    file_instance: ^bat$task_file_entry;
     VAR status: ost$status);

    VAR
      access_mode: fst$file_access_option,
      cl_path_handle: clt$path_handle,
      error: boolean,
      evaluated_file_reference: fst$evaluated_file_reference,
      file_pva: mmt$segment_pointer,
      global_file_information_p: ^bat$global_file_information,
      ignore_status: ost$status,
      instance_access_modes: fst$file_access_options,
      open_count: integer,
      record_positioning_info_p: ^bat$record_info;

{ The path table is locked to serialize access to the global file information.
    fmp$lock_path_table (status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    open_count := 0;
    global_file_information_p := file_instance^.global_file_information;
    IF global_file_information_p <> NIL THEN
      osp$decrement_locked_variable (global_file_information_p^.open_count, 1, open_count, error);

      #UNCHECKED_CONVERSION (file_instance^.instance_attributes.dynamic_label.access_mode,
            instance_access_modes);
      {Avoid decrementing multiple times should we retry due to file access condition
      file_instance^.instance_attributes.dynamic_label.access_mode := $pft$usage_selections [];

      FOR access_mode := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
        IF (access_mode IN instance_access_modes) AND (global_file_information_p^.
              opened_access_modes [access_mode] > 0) THEN
          global_file_information_p^.opened_access_modes [access_mode] :=
                global_file_information_p^.opened_access_modes [access_mode] - 1;
        IFEND;
        IF NOT (access_mode IN file_instance^.instance_attributes.dynamic_label.open_share_modes) AND
              (global_file_information_p^.prevented_open_access_modes [access_mode] > 0) THEN
          global_file_information_p^.prevented_open_access_modes [access_mode] :=
                global_file_information_p^.prevented_open_access_modes [access_mode] - 1;
        IFEND;
      FOREND;

      { Remember the current address for use by next private_read open for $ASIS
      { or new global open asis with no other instances of open.

      IF file_instance^.private_read_information <> NIL THEN
        record_positioning_info_p := ^file_instance^.private_read_information^.positioning_info.record_info;
      ELSE
        record_positioning_info_p := ^global_file_information_p^.positioning_info.record_info;
      IFEND;

      global_file_information_p^.asis_open_address := record_positioning_info_p^.current_byte_address;
      global_file_information_p^.asis_open_address := record_positioning_info_p^.bor_address;
      global_file_information_p^.asis_file_position:= record_positioning_info_p^.file_position;
    IFEND;

    IF (file_instance^.device_class = rmc$mass_storage_device) AND (file_instance^.file_pva <> NIL) THEN
      file_pva.kind := mmc$cell_pointer;
      file_pva.cell_pointer := file_instance^.file_pva;
      mmp$close_segment (file_pva, 1, status);
      file_instance^.file_pva := NIL;
      IF NOT status.normal THEN
        osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
        fmp$unlock_path_table;
        RETURN; {----->
      IFEND;
    IFEND;

    fmp$unlock_path_table;

    IF open_count <= 0 THEN
      IF file_instance^.system_file_label = NIL THEN

{ What the heck should I do here????
{   We do not know, if it's a permanent file or not, if we have to return it or not
{   We probably ended up here due to a task termination&cleanup in bap$open_file between
{   fmp$get_cd_info & store_attributes_in_tft.
{
{   The Cycle_Description must be right, have the label and the GFI. But how do we get to it?
{ Man, who thought this up? I see only one way: go through the path-table. But I'd like to see this
{ in a dump! I mean, if I'm right, then we have to do PT work for closing, when GFI or the label is NIL.
{ But stay away from it, if the FileId/TFT is properly setup.
{ And, anyway, can we figure out from the TFT if we passed creation????
{
{  Ff

      ELSEIF file_instance^.system_file_label^.descriptive_label.permanent_file THEN
        clp$check_name_for_path_handle (file_instance^.local_file_name, cl_path_handle);
        {change to call fmp$get_path_elements if status is nolonger ignored}
        evaluated_file_reference := fsv$evaluated_file_reference;
        evaluated_file_reference.path_handle_info.path_handle_present := TRUE;
        evaluated_file_reference.path_handle_info.path_handle := cl_path_handle.regular_handle;
        fmp$return_file (evaluated_file_reference, {implicit_detach} TRUE, {detachment_options} NIL, status);
      ELSEIF file_instance^.instance_attributes.dynamic_label.return_option = amc$return_at_close THEN
        clp$check_name_for_path_handle (file_instance^.local_file_name, cl_path_handle);
        {change to call fmp$get_path_elements if status is nolonger ignored}
        evaluated_file_reference := fsv$evaluated_file_reference;
        evaluated_file_reference.path_handle_info.path_handle_present := TRUE;
        evaluated_file_reference.path_handle_info.path_handle := cl_path_handle.regular_handle;
        fmp$return_file (evaluated_file_reference, {implicit_detach} FALSE, {detachment_options} NIL, status);
      IFEND;
    IFEND;

  PROCEND fmp$close_file;
?? OLDTITLE ??
MODEND fmm$close_file;

