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.