?? RIGHT := 110 ??
?? NEWTITLE := 'INSTALL_SOFTWARE Utility: RAP$ACCESS_DIRECTORY_FOR_WRITE Interface.' ??
MODULE ram$access_directory_for_write;

{ PURPOSE:
{   This module contains the interface that access the IDB Directory for
{   write.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rac$idb_directory_level
*copyc rac$idb_directory_name
*copyc rac$inss_processor_version
*copyc rae$install_software_cc
*copyc rat$idb_directory_pointers
*copyc rat$path
*copyc rat$sequence_descriptor_types
?? POP ??
*copyc amp$get_file_attributes
*copyc amp$get_segment_pointer
*copyc amp$set_segment_eoi
*copyc clp$include_line
*copyc fsp$close_file
*copyc fsp$open_file
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$set_status_abnormal
*copyc pmp$get_compact_date_time

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] rap$access_directory_for_write', EJECT ??

{ PURPOSE:
{   This interface access the IDB Directory for write mode.  If the
{   directory file does not already exist it will be created and
{   initialized.  A segment pointer and the file identifier are returned,
{   along with a boolean that specifies file open.
{
{ DESIGN:
{   The initializing of the directory involves creating the sequence
{   descriptor and directory header.
{
{
{ NOTES:
{

  PROCEDURE [XDCL] rap$access_directory_for_write
    (    installation_database: rat$path;
     VAR directory_segment_pointer: amt$segment_pointer;
     VAR directory_fid: amt$file_identifier;
     VAR directory_file_opened: boolean;
     VAR status: ost$status);


    VAR
      attachment_options: array [1 .. 3] of fst$attachment_option,
      command_line: string (800),
      command_length: integer,
      directory: rat$path,
      directory_pointers: rat$idb_directory_pointers,
      existing_file: boolean,
      ignore_attributes: array [1 .. 1] of amt$get_item,
      ignore_contains_data: boolean,
      ignore_status: ost$status,
      initialize_directory: boolean,
      length: integer,
      local_file: boolean,
      local_status: ost$status;


?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure cleans up when an abort situation occurs within the
{   block structure.
{
{ DESIGN:
{   The function of this condition handler is to close the IDB directory
{   when an abort condition arises.
{
{ NOTES:
{

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        ignore_status: ost$status;

      fsp$close_file (directory_fid, ignore_status);

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??


    status.normal := TRUE;

    attachment_options [1].selector := fsc$access_and_share_modes;
    attachment_options [1].access_modes.selector := fsc$specific_access_modes;
    attachment_options [1].access_modes.value := $fst$file_access_options
          [fsc$read, fsc$shorten, fsc$append, fsc$modify];
    attachment_options [1].share_modes.selector := fsc$determine_from_access_modes;
    attachment_options [2].selector := fsc$create_file;
    attachment_options [2].create_file := TRUE;
    attachment_options [3].selector := fsc$wait_for_attachment;
    attachment_options [3].wait_for_attachment.wait := osc$wait;
    attachment_options [3].wait_for_attachment.wait_time := fsc$longest_wait_time;

    { Assemble the path to the IDB Directory using the installation database path and the directory name.

    STRINGREP (directory.path, directory.size, installation_database.path (1, installation_database.size),
          '.', rac$idb_directory_name);

    { If the IDB directory does not exist it will be created and initialized.

    ignore_attributes [1].key := amc$file_length;

    amp$get_file_attributes (directory.path (1, directory.size), ignore_attributes, local_file, existing_file,
          ignore_contains_data, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    initialize_directory := NOT (local_file OR existing_file);

    osp$establish_block_exit_hndlr (^abort_handler);

  /main/
    BEGIN

      directory_file_opened := TRUE;
      fsp$open_file (directory.path (1, directory.size), amc$segment, ^attachment_options, NIL, NIL, NIL, NIL,
            directory_fid, status);
      IF NOT status.normal THEN
        directory_file_opened := FALSE;
        EXIT /main/;
      IFEND;

      amp$get_segment_pointer (directory_fid, amc$sequence_pointer, directory_segment_pointer, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      IF initialize_directory THEN
        directory_pointers.sequence_p := directory_segment_pointer.sequence_pointer;

        RESET directory_pointers.sequence_p;
        NEXT directory_pointers.sequence_descriptor_p IN directory_pointers.sequence_p;
        IF directory_pointers.sequence_descriptor_p = NIL THEN
          osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'IDB DIRECTORY', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'SEQUENCE DESCRIPTOR', status);
          EXIT /main/;
        IFEND;

        pmp$get_compact_date_time (directory_pointers.sequence_descriptor_p^.sequence_creation_date_time,
              status);
        IF NOT status.normal THEN
          EXIT /main/;
        IFEND;

        directory_pointers.sequence_descriptor_p^.processor_version := rac$inss_processor_version;
        directory_pointers.sequence_descriptor_p^.sequence_type := rac$idb_directory_sequence;
        directory_pointers.sequence_descriptor_p^.sequence_level := rac$idb_directory_level;

        NEXT directory_pointers.header_p IN directory_pointers.sequence_p;
        IF directory_pointers.header_p = NIL THEN
          osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'IDB DIRECTORY', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'HEADER', status);
          EXIT /main/;
        IFEND;

        directory_pointers.header_p^.deferred_count := 0;
        directory_pointers.header_p^.directory_size := 0;

        NEXT directory_pointers.directory_p: [1 .. 1] IN directory_pointers.sequence_p;
        IF directory_pointers.directory_p = NIL THEN
          osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'IDB directory', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'DIRECTORY', status);
          EXIT /main/;
        IFEND;

        directory_pointers.header_p^.directory_rel_p := #REL (directory_pointers.directory_p,
              directory_pointers.sequence_p^);

        directory_segment_pointer.sequence_pointer := directory_pointers.sequence_p;
        amp$set_segment_eoi (directory_fid, directory_segment_pointer, status);

      IFEND;

    END /main/;

    IF directory_file_opened AND (NOT status.normal) THEN
      fsp$close_file (directory_fid, ignore_status);
    IFEND;

    IF (NOT status.normal) AND initialize_directory THEN

      { Delete the IDB Directory file with ignore status.

      STRINGREP (command_line, command_length, '$system.delete_file f=', directory.path (1, directory.size));
      clp$include_line (command_line (1, command_length), TRUE, osc$null_name, ignore_status);

    IFEND;

    osp$disestablish_cond_handler;

  PROCEND rap$access_directory_for_write;
MODEND ram$access_directory_for_write;
