|
Thanks for the problem report.
The bug has been fixed in our development stream. The fix should be available
in the next ECO kits.
The problem is that the DEC C RTL does not initialize internal I/O buffer
with zeros while allocating the buffer for a file, so that, generally
speaking, the buffer may contain any garbage. The assumption is, that the
contents of the whole buffer is not important because only specified number
of bytes is written. It turned out, that this is not always true.
While accessing a file in stream mode, the DEC C RTL uses the $WRITE RMS
service to write the data.
If an odd number of bytes is specified in the $WRITE request for a device
which requires that only an even number of bytes can be transferred, an
extra byte is written.
The RMS Reference Manual has the following footnote in the description of
the $WRITE service:
�Certain devices require that an even number of bytes be transferred.
The DUMP utility, when invoked to dump the file in block mode, prints zeros
for the last block for all the bytes between the last word belonging to the
file and the end of the block. It prints second byte of the last word
regardless of whether this byte belongs to the file or not. One may consider
this as a bug in the DUMP utility.
In your case the buffer was containing the data from already closed file:
the buffer was deallocated on close() and allocated on open() at exactly the
same memory address. This is why you saw in the dump an extra byte from the
previous file.
I was able to reproduce the problem with the program which does not perform
any DEC C RTL I/O - see below.
Boris
TEST_RMS.COM
============
$ create test_rms.c
$ DECK
#include <stdio.h>
#include <stdlib.h>
#include <starlet.h>
#include <lib$routines.h>
#include <rms.h>
main( )
{
int status ;
static char buff[256] ;
struct FAB fab ;
struct RAB rab ;
fab = cc$rms_fab ;
rab = cc$rms_rab ;
fab.fab$l_fna = "TEST.DAT" ;
fab.fab$b_fns = 8 ;
fab.fab$b_rfm = FAB$C_STMLF ;
status = sys$open( &fab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
rab.rab$l_fab = &fab ;
rab.rab$l_ubf = &buff[0] ;
rab.rab$w_usz = 256 ;
status = sys$connect( &rab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
status = sys$get( &rab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
status = sys$close( &fab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
fab = cc$rms_fab ;
rab = cc$rms_rab ;
fab.fab$l_fna = "TEST2.DAT" ;
fab.fab$b_fns = 9 ;
fab.fab$b_rfm = FAB$C_STMLF ;
fab.fab$b_fac = FAB$M_BIO ;
status = sys$create( &fab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
rab.rab$l_fab = &fab ;
status = sys$connect( &rab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
buff[0] = 'A';
buff[1] = 'B';
buff[2] = '\n';
rab.rab$l_rbf = buff;
rab.rab$w_rsz = 3;
status = sys$write( &rab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
status = sys$close( &fab ) ;
if( (status&1)!=1 ) lib$stop( status ) ;
}
$ EOD
$!
$ if f$search("TEST.DAT") .nes. "" then Delete/nolog/noconf TEST.DAT;*
$ if f$search("TEST2.DAT") .nes. "" then Delete/nolog/noconf TEST2.DAT;*
$!
$ Create/FDL=SYS$INPUT TEST.DAT
RECORD
FORMAT STREAM_LF
$ Append SYS$INPUT TEST.DAT
0000000000
$!
$ cc test_rms
$ link test_rms
$ run test_rms
$!
$ Dump/byte/page TEST2.DAT
$ Dump/record TEST2.DAT
$ @TEST_RMS
Virtual block number 1 (00000001), 512 (0200) bytes
00 00 00 00 00 00 00 00 00 00 00 00 30 0A 42 41 AB.0............ 000000
^^
extra byte
|