PROCEDURE rap$install_file (
  from, f: file = $required
  to, t: file = $required
  save_previous_cycles, spc: boolean = $optional
  access_modes, access_mode, am: list of key
      none, read, execute, append, modify, shorten, write, all, cycle, control
    keyend = $optional
  share_modes, share_mode, sm: list of key
      none, read, execute, append, modify, shorten, write, all
    keyend = $optional
  application_information, ai: string 0..31 = $optional
  ring_attributes, ring_attribute, ra: (BY_NAME) list 1..3 of ..
    integer 1..15 = $optional
  storage_class, sc: any of
      key
        unspecified, product, service_critical_product, system_critical_file
        system_permanent_file, user_permanent_file
      keyend
      name 1..1
    anyend = $optional
  status)

  VAR
    command_file: file = $local//$name($unique)
    delete_extra_cycles: boolean = false
    destination_file_exists: boolean = false
    from_file_string: string
    high_cycle: integer
    hold_string_am: string 0..$max_string = ''
    hold_string_sm: string 0..$max_string = ''
    hold_string_ai: string 0..$max_string = ''
    ignore_status: status
    local_status: status
    loop: integer
    rav$installation_defaults: (XREF) rat$installation_defaults
    rav$installation_environment: (XREF) rat$installation_environment
    rav$subproduct_information: (XREF) rat$subproduct_information
    ring: array 1 .. 3 of integer
    task_ring: integer
    temp_file: file = $local//$name($unique)
  VAREND

*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
" This routine copies a file from a source ('FROM') to a destination ('TO')
" and appropriately manages file permits and attributes.
"
" A note regarding backing up and restoring a file:
" If a cycle is backed up and restored to a non-existent file, permits
" are lost; however, ring attributes are retained.  Permits apply to
" files; ring attributes apply to cycles of a file.
"
" If the 'TO' file already exists, the following statements are true:
"   *  The $high cycle of 'FROM' is restored to the $next cycle of 'TO'
"   *  Permits of 'TO' are inherited from the existing destination file,
"      unless specifically overridden by parameters or installation
"      default/environment variables.
"
" If the 'TO' file does not exist, the following statements are true:
"   *  All cycles of 'FROM' are restored to 'TO'
"   *  Permits of 'TO' are inherited from the cycles of 'FROM', unless
"      specifically overidden by parameters and/or values
"      contained in global variables.
"
*IFEND



  install_block: ..
    BLOCK


*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Get the ring attributes of the 'FROM' file for later processing
"  The R2 value of the 'FROM' file determines the ring level of the
"  task that will perform the installation.
"
*IFEND


  IF $specified(ring_attributes) THEN
    ring(1) = ring_attributes(1)
    ring(2) = ring_attributes(2)
    ring(3) = ring_attributes(3)
  ELSE
    rap$get_file_ring_attributes fn=from r=ring status=local_status
    EXIT install_block WHEN NOT local_status.normal
  IFEND


*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Establish requested storage class
"
"  Should 'TO' file inherit storage class from 'FROM' file????
"
*IFEND


  IF NOT rav$installation_defaults.ignore_storage_class THEN
    IF $specified(storage_class) THEN
      $system.include_command 'request_mass_storage to fc=storage_class' status=local_status
      EXIT install_block WHEN NOT local_status.normal
    IFEND
  IFEND



*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Backup and restore the source file ('FROM') to the destination file ('TO').
"  Use the ring established by R2 of 'FROM'.
"
*IFEND


  IF ring(2) < $ring THEN
    task_ring = ring(2)
  ELSE
    task_ring = $ring
  IFEND

  IF NOT $file(to permanent) THEN
COLLECT_TEXT command_file until='**'
    $system.osf$sou_library.system_operator_utility
        TASK r=task_ring
          $system.osf$builtin_library.backup_permanent_file bf=temp_file l=$null
            backup_file f=from
          quit
          $system.osf$builtin_library.restore_permanent_file l=$null
            restore_file f=from bf=temp_file nfn=to
          quit
        TASKEND
    quit
**
  ELSE    " Destination file ('TO') already exists
COLLECT_TEXT command_file until='**'
    destination_file_exists = true
    high_cycle = $file(from cycle_number)
    from_file_string = $string(from)//'.'//$string(high_cycle)
    $system.osf$sou_library.system_operator_utility
        TASK r=task_ring
          $system.osf$builtin_library.backup_permanent_file bf=temp_file l=$null
            backup_file f=$fname(from_file_string)
          quit
          $system.osf$builtin_library.restore_permanent_file l=$null
            restore_file f=$fname(from_file_string) bf=temp_file nfn=to.$next
          quit
      TASKEND
    quit
**
  IFEND

  $system.include_file f=command_file status=local_status
  $system.delete_file f=command_file status=ignore_status
  $system.delete_file f=temp_file status=ignore_status
  EXIT install_block WHEN NOT local_status.normal



*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Only delete previous cycles if requested, and only after a successful
"  file install has been performed, and only if the destination file existed
"  prior to the creation of the destination file ('TO').
"
"  The parameter SAVE_PREVIOUS_CYCLES takes precedence over the value of the
"  global variable SAVE_PREVIOUS_CYCLES
"
*IFEND


  IF destination_file_exists THEN
    delete_extra_cycles = NOT rav$installation_environment.save_previous_cycles
    IF $specified(save_previous_cycles) THEN
      delete_extra_cycles = NOT save_previous_cycles
    IFEND
    IF delete_extra_cycles THEN
      IF ring(1) < $ring THEN
        task_ring = ring(1)
      ELSE
        task_ring = $ring
      IFEND
COLLECT_TEXT command_file until='**'
    $system.osf$sou_library.system_operator_utility
        TASK r=task_ring
          $system.osf$builtin_library.backup_permanent_files bf=$null l=$list
            exclude_highest_cycle noc=1
            delete_file_contents f=to
          QUIT
        TASKEND
    quit
**
      $system.include_file f=command_file status=local_status
      $system.delete_file f=command_file status=ignore_status
      EXIT install_block WHEN NOT local_status.normal
    IFEND
  IFEND


*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Create a public file permit for the destination file if the destination
"  file did not previously exist and any of the parameters access_modes,
"  share_modes, or application_information were specified.
"
*IFEND

    IF (NOT destination_file_exists) AND ..
         ($specified(access_modes) OR $specified(share_modes) OR $specified(application_information)) THEN
      $system.create_file_permit f=to g=public am=access_modes sm=share_modes ai=application_information ..
            status=local_status
      EXIT install_block WHEN NOT local_status.normal
    IFEND


*IF $variable(wev$proc_doc,declared)<>'UNKNOWN'
"
"  Establish proper file ring attributes for destination file.  If the
"  installation default variable RELAX_RING_SETTINGS is false, set the
"  destination file's ring attributes based on the following:
"
"     1.  If the parameter ring_attributes is specified, use these values;
"     2.  if not, use the ring attributes from the source file ('FROM').
"
"  If the installation default variable RELAX_RING_SETTINGS is true, set the
"  destination file's ring attributes based on the following:
"
"     1.  If the parameter ring_attributes is specified, use these values;
"     2.  If not, do not set any specific ring attributes for the destination
"         file ('FROM')
"
"
*IFEND


  IF (NOT rav$installation_defaults.relax_ring_settings) OR ..
     ((rav$installation_defaults.relax_ring_settings) AND ($specified(ring_attributes))) THEN
    $system.change_file_attributes to ra=(ring(1) ring(2) ring(3)) status=local_status
    EXIT install_block WHEN NOT local_status.normal
  IFEND


    BLOCKEND install_block

  EXIT procedure with local_status WHEN NOT local_status.normal

PROCEND rap$install_file
