[mod.computers.vax] copying VMS BACKUP save sets using FTP from Unix system

gmt@ARIZONA.EDU ("Gregg Townsend") (11/26/86)

I'm trying to prepare a VMS software package, in the form of a BACKUP save set,
for distribution via anonymous FTP.  The distributing machine will be a Vax
running 4.3 BSD Unix.  The save set copies to the Unix machine with no problems.
When I go to the VMS machine and copy the data back using binary FTP, the data
itself comes across fine but the block size gets set to 512 instead of the
correct (in this case) 8192.  To be precise, DIR/FULL shows
	Record format:  Fixed length 512 byte records
and everything else is correct.

There is a local utility here which resets the record format without altering
the file contents;  after running this, BACKUP can read the file.  What I need
now is a method that can be used by anyone who receives the file.  Is there a
way in a standard VMS system to do this?  The best anyone here could come up
with have involved kludges such as "copy to tape, then copy back" (which
assumes a tape drive) or "run this short little program" (which assumes an
appropriate compiler).  EXCHANGE and CONVERT appear almost-but-not-quite
capable of providing a fix.

If I have defined the problem too narrowly, and there's a better approach to
distributing a BACKUP file by FTP, by all means please let me know.

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325     gmt@Arizona.EDU (ARPAnet or CSnet)    ihnp4!arizona!gmt

carl@CitHex.Caltech.Edu.UUCP (11/27/86)

From:	ST%"gmt@arizona.edu" 25-Nov-86 22:28:10 MST
To:	ST%"INFO-VAX"
Subj:	copying VMS BACKUP save sets using FTP from Unix system
Message-Id: <8611260528.AA29122@megaron.arizona.edu>
Topic: infovax, Entry # 4073
In-Reply-To: <8611260520.AA25875@arizona.arizona.edu>

  >  I'm trying to prepare a VMS software package, in the form of a BACKUP save
  >  set, for distribution via anonymous FTP.  The distributing machine will be
  >  a Vax running 4.3 BSD Unix.  The save set copies to the Unix machine with
  >  no problems. When I go to the VMS machine and copy the data back using
  >  binary FTP, the data itself comes across fine but the block size gets set
  >  to 512 instead of the correct (in this case) 8192.  To be precise,
  >  DIR/FULL shows Record format:  Fixed length 512 byte records and
  >  everything else is correct. 

Below is the source (in both FORTRAN and C) for a proram to modify the record
format of a file.  It sets the record format of the selected files to FIXED,
with your choice of recordlength.  The FORTRAN program prompts for the record
length then for each file until it reaches an EOF on the input stream. 
The C program as the syntax "MCR MODRFM recordsize file1 [file2 [file3 ...]]"
They use an undocumented RMS routine (SYS$MODIFY) and a misdocumented FAB
field (FAB$L_CTX).
! Fortran program to change a file's record format 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
1     TYPE 5, 'Blocksize: '
5     FORMAT(1X,A,$)
      ACCEPT *, BLKSIZ
      IF(BLKSIZ .LT. 1 .OR.BLKSIZ .GT. 32767) THEN
        TYPE *,' Blocksize must be between 1 and 32767 inclusive.'
        GOTO 1
      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 format 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)
    exit((puts("USAGE: MODRFM blocksize file [file...]"),1));
  if (blksiz < 1 || blksiz > 32767)
    exit((puts("blocksize must be between 1 and 32767 inclusive."),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));
} }