?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : File System : Detach File' ??
MODULE fsm$detach_file;
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??

?? PUSH (LISTEXT := ON) ??
*copyc ame$lfn_program_actions
*copyc ame$attribute_validation_errors
*copyc fst$detachment_options
*copyc fst$file_reference
*copyc oss$job_paged_literal
?? POP ??
*copyc bap$delete_art_entry
*copyc bap$return
*copyc bap$set_evaluated_file_abnormal
*copyc clp$evaluate_file_reference
*copyc clp$validate_local_file_name
*copyc fsv$evaluated_file_reference
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$enforce_exception_policies
*copyc osp$file_access_condition
*copyc osv$initial_exception_context

  VAR
    detachment_option_names: [STATIC, READ, oss$job_paged_literal] array
          [fsc$do_unload_volume .. fsc$do_unload_volume] of ost$name := [
          {fsc$do_unload_volume ........... = 002} 'UNLOAD_VOLUME                '];

?? TITLE := 'PROCEDURE validate_detachment_options', EJECT ??

    PROCEDURE validate_detachment_options
      (    evaluated_file_reference: fst$evaluated_file_reference;
           detachment_options: ^fst$detachment_options;
       VAR status: ost$status);

      CONST
        detach_file_request = 'FSP$DETACH_FILE',
        detachment_options_parameter = 'DETACHMENT_OPTIONS';

      VAR
        detachment_option_index: integer,
        detachment_option_name: ost$name;

      status.normal := TRUE;

      FOR detachment_option_index := 1 TO UPPERBOUND (detachment_options^) DO
        detachment_option_name := osc$null_name;
        CASE detachment_options^ [detachment_option_index].selector OF
        = fsc$do_unload_volume =
          IF (detachment_options^ [detachment_option_index].unload_volume < LOWERVALUE (boolean)) OR
                (detachment_options^ [detachment_option_index].unload_volume > UPPERVALUE (boolean)) THEN
            detachment_option_name := detachment_option_names [fsc$do_unload_volume];
          IFEND;
        = fsc$do_null_detachment_option =
          ;
        ELSE
          bap$set_evaluated_file_abnormal (evaluated_file_reference, ame$improper_file_attrib_key,
                detach_file_request, detachment_options_parameter, status);
          osp$append_status_integer (osc$status_parameter_delimiter, detachment_option_index, {radix} 10,
                {include_radix} FALSE, status);
        CASEND;

        IF status.normal AND (detachment_option_name <> osc$null_name) THEN
          bap$set_evaluated_file_abnormal (evaluated_file_reference, ame$improper_file_attrib_value,
                detach_file_request, detachment_options_parameter, status);
          osp$append_status_parameter (osc$status_parameter_delimiter, detachment_option_name, status);
        IFEND;
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      FOREND;

    PROCEND validate_detachment_options;

?? TITLE := 'PROCEDURE [XDCL, #GATE] fsp$detach_file', EJECT ??

  PROCEDURE [XDCL, #GATE] fsp$detach_file
    (    file: fst$file_reference;
         detachment_options: ^fst$detachment_options;
     VAR status: ost$status);

    VAR
      context: ^ost$ecp_exception_context,
      evaluated_file_reference: fst$evaluated_file_reference,
      ignore_status: ost$status,
      local_detachment_options: ^fst$detachment_options,
      local_file_name: amt$local_file_name,
      local_status: ost$status,
      name_is_path_handle: boolean,
      name_is_valid: boolean,
      path_handle: fmt$path_handle;

    local_status.normal := TRUE;
    context := NIL;
    status.normal := TRUE;

  /detach_file/
    BEGIN
      clp$validate_local_file_name (file, local_file_name, path_handle, name_is_path_handle, name_is_valid);
      IF name_is_path_handle THEN

{       The call to clp$validate_local_file_name and this path_handle check is
{       here because clp$evaluate_file_reference returns the full path for an
{       alias path handle.

        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 := path_handle;
      ELSE
        clp$evaluate_file_reference (file, $clt$file_ref_parsing_options [clc$use_$local_as_working_cat],
              {resolve_cycle_number} FALSE, evaluated_file_reference, status);
        IF NOT status.normal THEN
          EXIT /detach_file/;
        IFEND;
      IFEND;

      IF detachment_options <> NIL THEN
        PUSH local_detachment_options: [1 .. UPPERBOUND (detachment_options^)];
        local_detachment_options^ := detachment_options^;
        validate_detachment_options (evaluated_file_reference, local_detachment_options, status);
        IF NOT status.normal THEN
          EXIT /detach_file/;
        IFEND;
      ELSE
        local_detachment_options := NIL;
      IFEND;

     REPEAT
        bap$return (evaluated_file_reference, local_detachment_options, status);
        IF osp$file_access_condition (status) THEN
          IF context = NIL THEN
            PUSH context;
            context^ := osv$initial_exception_context;
            context^.file.selector := osc$ecp_evaluated_file_ref;
            context^.file.evaluated_file_reference := evaluated_file_reference;
          IFEND;
          context^.condition_status := status;
          osp$enforce_exception_policies (context^);
          status := context^.condition_status;
        IFEND;
      UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);
      IF (status.normal OR (status.condition = ame$file_not_known)) AND name_is_valid THEN
        bap$delete_art_entry (local_file_name, ignore_status);
      IFEND;

    END /detach_file/;

    IF NOT local_status.normal THEN
      status := local_status;
    IFEND;

  PROCEND fsp$detach_file;

MODEND fsm$detach_file;
