[an error occurred while processing this directive]

HP OpenVMS Systems

ask the wizard
Content starts here

Accessing RMS (compressed) records?

» close window

The Question is:

 
I have a third party file that has compressed data starting
at byte 114 of a 485 byte record. Byte 1 thru 113 is ascii.
Is there a VMS command to unparse the data and convert/write
it to a sequential file?
 
 


The Answer is :

 
  Without knowing what sort of data compression scheme is used, this
  question is difficult to answer.
 
  Opening and reading an RMS file is trivial, the code to perform the
  decompression depends on the algorithm used.
 
  Attached is C code that opens an RMS file, and displays the records
  of the file to the terminal.  Several changes -- support for a longer
  record length, and the decompression scheme, obviously -- would need
  to be made to this example for your particular application.
 
 
/*
** COPYRIGHT (c) 1992 BY
** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.
** ALL RIGHTS RESERVED.
**
** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
** ONLY  IN  ACCORDANCE  OF  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER
** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
** OTHER PERSON.  NO TITLE TO AND  OWNERSHIP OF THE  SOFTWARE IS  HEREBY
** TRANSFERRED.
**
** THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE
** AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
** CORPORATION.
**
** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS
** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
*/
 
/*
**++
**  Facility:
**
**	Examples
**
**  Version: V1.1
**
**  Abstract:
**
**	Example of working with RMS calls from C
**
**  Author:
**	Steve Hoffman (XDELTA::HOFFMAN)
**
**  Creation Date:  1-Jan-1990
**
**  Modification History:
**	    Hoffman	15-Oct-1994	Updates for DEC C
**--
*/
 
/*
//  RMS_EXAMPLES.C
//
//  Program displays some RMS calls made from the c language.  Types out
//  the calling process's SYS$LOGIN:LOGIN.COM file to SYS$OUTPUT.
//
//  Included is a main and three subroutines.  The subroutines open,
//  read a record, and close the file.  Several hooks, such as the
//  use of the NAM block to obtain the specification of the file that
//  was actually opened, are included but are not currently used.
//
//  To build:
//
//    $ CC [/DECC] [/DEBUG/NOOPTIM] RMS_EXAMPLES
//    $ LINK [/DEBUG] RMS_EXAMPLES
//    $ RUN [/[NO]DEBUG] RMS_EXAMPLES
*/
 
#include <lib$routines.h>
#include <rms.h>
#include <starlet.h>
#include <string.h>
#include <ssdef.h>
#include <stdio.h>
#include <stsdef.h>
 
/*
// RMS_MRS is the maximum record size that can be read (and thus
// displayed) by this program.
*/
#define RMS_MRS	255
 
/*
// The following is the core data structure for the program.
// The various RMS subroutines all communicate via a pointer
// referencing this struct.
*/
struct RmsFileContext
    {
    struct FAB fab;
    struct RAB rab;
    struct NAM nam;
    char rss[NAM$C_MAXRSS];
    short max_rec_siz;
    char *data_buffer;
    };
 
RmsFileOpen( void **CtxArg,
char *FileName, char *DefFileName, int flags, int rss )
    {
    int RetStat;
    struct RmsFileContext *Ctx;
    int howbig = sizeof( struct RmsFileContext );
 
    /*
    // acquire some space for a Context block.
    */
    RetStat = lib$get_vm( &howbig, &Ctx, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    *CtxArg = (void *) Ctx;
 
    /*
    // Fill in the various fields of the Context block.
    // -- Builds the File Access Block (FAB), the Record Access
    // Block (RAB) and the Name (NAM) Block.  Along with some
    // other miscellaneous housekeeping stuff.
    */
    Ctx->fab = cc$rms_fab;
    Ctx->rab = cc$rms_rab;
    Ctx->nam = cc$rms_nam;
 
    Ctx->fab.fab$l_nam = &Ctx->nam;
    Ctx->fab.fab$l_fop = FAB$M_NAM;
    Ctx->fab.fab$b_fac = FAB$M_GET;
 
    Ctx->fab.fab$l_fna = FileName;
    Ctx->fab.fab$b_fns = strlen( FileName );
    Ctx->fab.fab$l_dna = DefFileName;
    Ctx->fab.fab$b_dns = strlen( DefFileName );
 
    Ctx->rab.rab$l_fab = &Ctx->fab;
 
    Ctx->nam.nam$b_rss = NAM$C_MAXRSS;
    Ctx->nam.nam$l_rsa = Ctx->rss;
 
    Ctx->rab.rab$b_rac = RAB$C_SEQ;
 
    /*
    // Attempt to open the file...
    */
    RetStat = sys$open( &Ctx->fab, 0, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    /*
    // Allocate a buffer large enough for the biggest record.
    */
    RetStat = lib$get_vm( &RMS_MRS, &Ctx->data_buffer, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    /*
    // Attempt to connect the record stream to the file...
    */
    RetStat = sys$connect( &Ctx->rab, 0, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    return RetStat;
    }
 
RmsFileRead( void **CtxArg, char **BufAdr, int *BufLen )
    {
    int RetStat;
    struct RmsFileContext *Ctx = *CtxArg;
 
    Ctx->rab.rab$l_ubf = Ctx->data_buffer;
    Ctx->rab.rab$w_usz = RMS_MRS;
 
    RetStat = sys$get( &Ctx->rab, 0, 0 );
 
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	{
        *BufLen = (char) 0;
	*BufAdr = (char) 0;
	return RetStat;
	}
 
    *BufAdr = Ctx->rab.rab$l_rbf;
    *BufLen = Ctx->rab.rab$w_rsz;
 
    return RetStat;
    }
 
RmsFileClose( void **CtxArg )
    {
    int RetStat;
    struct RmsFileContext *Ctx = *CtxArg;
 
    /*
    // Free up the record buffer...
    */
    RetStat = lib$free_vm( &RMS_MRS, &Ctx->data_buffer, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    /*
    // Be nice and clean up the record stream...
    */
    RetStat = sys$disconnect( &Ctx->rab, 0, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    /*
    // And close the file...
    */
    RetStat = sys$close( &Ctx->fab, 0, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    /*
    // And free up the allocated memory...
    */
    RetStat = lib$free_vm( &sizeof( struct RmsFileContext ), CtxArg, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;
 
    return RetStat;
 
    }
main()
    {
    int RetStat;
    void *Context;
    char *BufAdr;
    int BufLen;
 
    /*
    // Open the file.  Minimal checking is performed.  Read access only.
    */
    RetStat = RmsFileOpen( &Context, "LOGIN", "SYS$LOGIN:.COM", 0, 0 );
 
    /*
    // Read the file.  Minimal checking is performed.
    */
    for (;;)
	{
	RetStat = RmsFileRead( &Context, &BufAdr, &BufLen );
	if ( $VMS_STATUS_SUCCESS( RetStat ) )
	    printf("%*.*s\n", BufLen, BufLen, BufAdr );
	else
	    break;
	}
 
    /*
    // Close up shop.
    */
    RetStat = RmsFileClose( &Context );
 
    return RetStat;
    }
 

answer written or last revised on ( 6-JUL-1998 )

» close window