*copyc osd$default_pragmats
?? RIGHT := 110 ??
??
NEWTITLE := ' NOS/VE Backup/Restore Utilities:  data_file ', EJECT ??
MODULE pum$data_file;
{
{
{   This module provides procedures to process the "data file".
{ The data file is a binary form output of a backup listing.
{ To select a data file, the user should issue the select_data_file
{ request prior to a backup subcommand.
{   The data file currently really only provides a mapping being global_file_name
{ and full path name.  Thus one may run this and save the data file, and later
{ query the data file looking for a specific global_file_name either by
{ the pup$find_stored_file_gfn cybil interface, or the search_data_file
{ subcommand of restore.  Please note:  the search_data_file subcommand
{ is not very robust about improper input, so be carefull.
{
?? NEWTITLE := '   Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc pud$backup_file
*copyc pue$error_condition_codes
*copyc amt$local_file_name
?? POP ??
*copyc amp$close
*copyc amp$get_file_attributes
*copyc amp$get_segment_pointer
*copyc amp$open
*copyc clp$convert_string_to_integer
*copyc clp$get_value
*copyc clp$scan_parameter_list
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc pfp$get_family_set
*copyc pmp$convert_unique_to_binary
*copyc pup$convert_gfn_to_string
*copyc pup$crack_file_reference
*copyc pup$write_cycle_selector
*copyc pup$write_path
*copyc osv$lower_to_upper
?? TITLE := '    Global Variables', EJECT ??

  VAR
    puv$data_file_selected: [XDCL, STATIC] boolean := FALSE,
    gfn_file: [STATIC] amt$local_file_name := 'GFNFILE                        ',
    p_sequence: [STATIC] ^SEQ ( * ) := NIL,
    p_number_of_cycles: [STATIC] ^integer := NIL;

  CONST
    puc$current_data_file_version = 'BACKUP_DATA_FILE_VERSION_001   ';

?? TITLE := '    pup$find_stored_file_gfn ', EJECT ??

  PROCEDURE pup$find_stored_file_gfn (gfn_file: amt$local_file_name;
        gfn: ost$binary_unique_name;
    VAR path_container: SEQ (REP 2000 OF cell);
    VAR cycle_selector: pft$cycle_selector;
    VAR status: ost$status);

    VAR
      file_id: amt$file_identifier,
      gfn_found: boolean,
      gfn_string: string (60),
      i: integer,
      local_status: ost$status,
      p_container: ^SEQ (REP 2000 of cell),
      p_gfn: ^ost$binary_unique_name,
      p_item_descriptor: ^put$backup_item_descriptor,
      p_number_of_cycles: ^integer,
      p_path: ^pft$path,
      p_path_length: ^integer,
      p_record_header: ^put$backup_file_record_header,
      p_version: ^ost$name,
      segment: amt$segment_pointer;

    gfn_found := FALSE;
    amp$open (gfn_file, amc$segment, NIL, file_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_segment_pointer (file_id, amc$sequence_pointer, segment, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    RESET segment.sequence_pointer;
    NEXT p_version IN segment.sequence_pointer;
    IF p_version = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, 'NIl version', status);
      RETURN;
    ELSEIF (p_version^ <> puc$current_data_file_version) THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$incompatible_backup_version, p_version^, status);
      RETURN;
    IFEND;
    NEXT p_number_of_cycles IN segment.sequence_pointer;
    IF p_number_of_cycles = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, 'NIL cycles', status);
    ELSE

    /search_file/
      FOR i := 1 TO p_number_of_cycles^ DO
        NEXT p_gfn IN segment.sequence_pointer;
        IF p_gfn = NIL THEN
          osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' NIL GFN', status);
          EXIT /search_file/;
        IFEND;
        NEXT p_record_header IN segment.sequence_pointer;
        IF p_record_header = NIL THEN
          osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' NIL record_header',
                status);
          EXIT /search_file/;
        IFEND;
        NEXT p_item_descriptor: [1 .. p_record_header^.size] IN segment.sequence_pointer;
        IF p_item_descriptor = NIL THEN
          osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' NIL item_descriptor',
                status);
          EXIT /search_file/;
        IFEND;
        IF p_gfn^ = gfn THEN
          gfn_found := TRUE;
          p_container := ^path_container;
          RESET p_container;
          NEXT p_path_length IN p_container;
          p_path_length^ := p_record_header^.size;
          NEXT p_path: [1 .. p_path_length^] IN p_container;
          IF p_path = NIL THEN
            osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' NIL path', status);
            EXIT /search_file/;
          IFEND;
          p_path^ := p_item_descriptor^.catalog_header.path;
          cycle_selector := p_item_descriptor^.pf_utility_entry.pf_selector.cycle_selector;
          status.normal := TRUE;
          EXIT /search_file/;
        IFEND;
      FOREND /search_file/;
    IFEND;
    IF status.normal AND NOT gfn_found THEN
      pup$convert_gfn_to_string (gfn, gfn_string);
      osp$set_status_abnormal (puc$pf_utility_id, pue$unknown_gfn, gfn_string, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, gfn_file, status);
    IFEND;
    amp$close (file_id, local_status);
  PROCEND pup$find_stored_file_gfn;

?? TITLE := '    [XDCL] pup$search_data_file ', EJECT ??

  PROCEDURE [XDCL] pup$search_data_file (parameter_list: clt$parameter_list;
    VAR status: ost$status);

?? RIGHT := 110 ??
{ pdt search_data_file (global_file_name, gfn:name = $required
{  data_file, df: file = $local.gfnfile
{  status)

?? PUSH (LISTEXT := ON) ??

    VAR
      search_data_file: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^search_data_file_names,
        ^search_data_file_params];

    VAR
      search_data_file_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 5] of
        clt$parameter_name_descriptor := [['GLOBAL_FILE_NAME', 1], ['GFN', 1], ['DATA_FILE', 2], ['DF', 2],
        ['STATUS', 3]];

    VAR
      search_data_file_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 3] of clt$parameter_descriptor
        := [

{ GLOBAL_FILE_NAME GFN }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, 1, osc$max_name_size]],

{ DATA_FILE DF }
      [[clc$optional_with_default, ^search_data_file_dv2], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
        clc$file_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
        clc$array_not_allowed, clc$status_value]]];

    VAR
      search_data_file_dv2: [STATIC, READ, cls$pdt_names_and_defaults] string (14) := '$local.gfnfile';

?? POP ??

    VAR
      cycle_selector: pft$cycle_selector,
      gfn_file: amt$local_file_name,
      global_file_name: ost$binary_unique_name,
      p_container: ^SEQ (REP 2000 of cell),
      p_path: ^pft$path,
      p_path_length: ^integer,
      path_container: SEQ (REP 2000 of cell),
      value: clt$value;

    clp$scan_parameter_list (parameter_list, search_data_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('GLOBAL_FILE_NAME', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    pmp$convert_unique_to_binary (value.name.value, global_file_name, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pup$crack_file_reference ('DATA_FILE', gfn_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pup$find_stored_file_gfn (gfn_file, global_file_name, path_container, cycle_selector, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    p_container := ^path_container;
    RESET p_container;
    NEXT p_path_length IN p_container;
    NEXT p_path: [1 .. p_path_length^] IN p_container;

    pup$write_path (p_path^, status);
    pup$write_cycle_selector (cycle_selector, status);
  PROCEND pup$search_data_file;

?? TITLE := '    [XDCL] pup$select_data_file ', EJECT ??

  PROCEDURE [XDCL] pup$select_data_file (parameter_list: clt$parameter_list;
    VAR status: ost$status);

?? RIGHT := 110 ??
{ PDT select_data_file_pdt (data_file, df: file = $local.gfnfile
{  status)

?? PUSH (LISTEXT := ON) ??

    VAR
      select_data_file_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
        [^select_data_file_pdt_names, ^select_data_file_pdt_params];

    VAR
      select_data_file_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
        clt$parameter_name_descriptor := [['DATA_FILE', 1], ['DF', 1], ['STATUS', 2]];

    VAR
      select_data_file_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of
        clt$parameter_descriptor := [

{ DATA_FILE DF }
      [[clc$optional_with_default, ^select_data_file_pdt_dv1], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
        clc$file_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
        clc$array_not_allowed, clc$status_value]]];

    VAR
      select_data_file_pdt_dv1: [STATIC, READ, cls$pdt_names_and_defaults] string (14) := '$local.gfnfile';

?? POP ??

    VAR
      gfn_file_id: amt$file_identifier,
      segment: amt$segment_pointer,
      p_version: ^ost$name;

    clp$scan_parameter_list (parameter_list, select_data_file_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF puv$data_file_selected THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$data_file_already_selected, gfn_file, status);
      RETURN;
    IFEND;

    pup$crack_file_reference ('DATA_FILE', gfn_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$open (gfn_file, amc$segment, NIL, gfn_file_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_segment_pointer (gfn_file_id, amc$sequence_pointer, segment, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    puv$data_file_selected := TRUE;
    RESET segment.sequence_pointer;
    p_sequence := segment.sequence_pointer;
    NEXT p_version IN p_sequence;
    IF p_version = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' NIL version', status);
      RETURN;
    IFEND;
    p_version^ := puc$current_data_file_version;
    NEXT p_number_of_cycles IN p_sequence;
    IF p_number_of_cycles = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, 'NIL cycles', status);
    ELSE
      p_number_of_cycles^ := 0;
    IFEND;
  PROCEND pup$select_data_file;


?? TITLE := '    [XDCL] pup$store_file_gfn ', EJECT ??

  PROCEDURE [XDCL] pup$store_file_gfn (gfn: ost$binary_unique_name;
        path: pft$path;
        cycle_selector: pft$cycle_selector;
    VAR status: ost$status);

    VAR
      p_gfn: ^ost$binary_unique_name,
      p_item_descriptor: ^put$backup_item_descriptor,
      p_record_header: ^put$backup_file_record_header,
      set_name: stt$set_name;

    status.normal := TRUE;

    pfp$get_family_set (path [pfc$family_name_index], set_name, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF p_number_of_cycles = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer,
        ' p_number_of_cycles NIL in pup$store_file_gfn', status);
      RETURN;
    IFEND;
    p_number_of_cycles^ := p_number_of_cycles^ + 1;

    NEXT p_gfn IN p_sequence;
    IF p_gfn = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' p_gfn ', status);
      RETURN;
    IFEND;
    p_gfn^ := gfn;

    NEXT p_record_header IN p_sequence;
    IF p_record_header = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' p_record_header ', status);
      RETURN;
    IFEND;
    p_record_header^.size := UPPERBOUND (path);
    p_record_header^.kind := puc$backup_item_identifier;

    NEXT p_item_descriptor: [1 .. UPPERBOUND (path)] IN p_sequence;
    IF p_item_descriptor = NIL THEN
      osp$set_status_abnormal (puc$pf_utility_id, pue$nil_data_file_pointer, ' p_item_descriptor ', status);
      RETURN;
    IFEND;
    p_item_descriptor^.pf_utility_entry.entry_type := puc$valid_cycle_entry;
    p_item_descriptor^.pf_utility_entry.pf_selector.pfn := path [UPPERBOUND (path)];
    p_item_descriptor^.pf_utility_entry.pf_selector.cycle_selector := cycle_selector;

    p_item_descriptor^.catalog_header.set_name := set_name;
    p_item_descriptor^.catalog_header.logical_path_length := UPPERBOUND (path);
    p_item_descriptor^.catalog_header.path := path;
  PROCEND pup$store_file_gfn;

MODEND pum$data_file;
