[comp.os.vms] converting fixed record files

KROMME@HDETUD5.BITNET (J.G. KROMME IRI/DELFT 015-783543) (11/06/87)

Using the standard utilities under VMS it is impossible, as far as
I know, to convert a fixed record file to a file with shorter records,
without loosing the remainder, what I want is simple to redefine the
fixed record size of a file.
I know that it is possible to write a program to read and write in
the desired format, but is there a more sophisticated way to do this,
or did I not read the manuals well?

KROMME@HDETUD5

carl@CITHEX.CALTECH.EDU (Carl J Lydick) (11/09/87)

 > Using the standard utilities under VMS it is impossible, as far as
 > I know, to convert a fixed record file to a file with shorter records,
 > without loosing the remainder, what I want is simple to redefine the
 > fixed record size of a file.
 > I know that it is possible to write a program to read and write in
 > the desired format, but is there a more sophisticated way to do this,
 > or did I not read the manuals well?

The answer, to the best of my knowledge, is not in the manuals.  There is
a hint as to how to do it in the module $RMEDEF in SYS$LIBRARY:FORSYSDEF.TLB.
The following programs (one in FORTRAN, one in C) do this (note that the
checks on the value of the blocksize variable are VERY important: if you
set the blocksize to an illegal value, RMS will no longer be willing to
access the file; at that point, the only way to fix things is to edit the
disk's index file):

! Fortran program to change a file's record length field:
      INCLUDE '($FABDEF)'
      INCLUDE '($RMEDEF)'
      RECORD /FABDEF/ MYFAB
      INTEGER*4 LENGTH, STATUS, SYS$OPEN, SYS$CLOSE, SYS$MODIFY, BLKSIZ
      BYTE FILENAME(80)
      MYFAB.FAB$B_BID = FAB$C_BID
      MYFAB.FAB$B_BLN = FAB$C_BLN
      MYFAB.FAB$L_FNA = %LOC(FILENAME)
      MYFAB.FAB$B_FAC = FAB$M_PUT
      MYFAB.FAB$L_FOP = IOR(FAB$M_ESC,MYFAB.FAB$L_FOP)
      MYFAB.FAB$L_CTX = IOR(RME$C_SETRFM,MYFAB.FAB$L_CTX)
      MYFAB.FAB$W_IFI = 0
      TYPE 5, 'Blocksize: '
5     FORMAT(1X,A,$)
      ACCEPT *, BLKSIZ
      IF (BLKSIZ .LT. 1 .OR. BLKSIZ .GT. 32767) THEN
         TYPE *, ' BLKSIZ must be in the range [1,32767]'
         GOTO 999
      ENDIF
10    TYPE 5, 'Filename: '
      READ(5,20,END=999) LENGTH, (FILENAME(I), I = 1, LENGTH)
20    FORMAT(Q, 80A1)
      MYFAB.FAB$B_FNS = LENGTH
      STATUS = SYS$OPEN(MYFAB, %VAL(0),%VAL(0))
      IF (IAND(STATUS, 7) .NE. 1) TYPE *, ' OPEN ERROR. STATUS = ', status
      MYFAB.FAB$W_MRS = BLKSIZ
      STATUS = SYS$MODIFY(MYFAB, %VAL(0), %VAL(0))
      IF (IAND(STATUS, 7) .NE. 1) TYPE *, ' MODIFY ERROR. STATUS = ', status
      STATUS = SYS$CLOSE(MYFAB, %VAL(0), %VAL(0))
      IF (IAND(STATUS, 7) .NE. 1) TYPE *, ' CLOSE ERROR. STATUS = ', status
      GOTO 10
999   END


/* C program to change a file's record length field: */
#include <fab.h>
#define RME$C_SETRFM	0X00000001
main(nargs, args)	int nargs;	char **args;
{ struct FAB myfab = cc$rms_fab;
  long blksiz, atol(), status;
  if (--nargs < 2 || sscanf(*++args, "%d%c", &blksiz, &status) != 1)
  { puts("USAGE: MODRFM blocksize file [file...]");
    exit(1);
  }
  if (blksiz < 1 || blksiz > 32767) {
  { puts("blocksize must be in the range [1,32767]");
    exit(1);
  }
  myfab.fab$b_fac = FAB$M_PUT;
  myfab.fab$l_fop |= FAB$M_ESC;
  myfab.fab$l_ctx |= RME$C_SETRFM;
  myfab.fab$w_ifi = 0;
  while (--nargs > 0) {
    myfab.fab$l_fna = *++args;
    myfab.fab$b_fns = strlen(*args);
    if (((status = SYS$OPEN(&myfab, 0, 0)) & 7) != 1)
      exit((printf("Couldn't open %s\n", *args), status));
    myfab.fab$w_mrs = blksiz;
    if (((status = SYS$MODIFY(&myfab, 0, 0)) & 7) != 1)
      exit((printf("Couldn't modify %s\n", *args), status));
    if (((status = SYS$CLOSE(&myfab, 0, 0)) & 7) != 1)
      exit((printf("Couldn't close %s\n", *args), status));
  }
}

rrk@byuvax.bitnet (11/10/87)

There is one way I know of (Refer to the ACP section of your I/O reference
guide).  Open a file from RMS using the UFO bit.  Then use a FIB block to
do a write attributes.  This should allow you to change record size without
affecting the data.