[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2116.0. "End of File Byte/Fixed length 512 byte records" by OSEC::LUNN ([email protected]) Tue Mar 11 1997 09:18

Crossposted in LASSIE::UCX

One of the applications which we support for our customer is an FTP
implementation (IFTP) written in C. I'm testing a new version on
a VAX running OpenVMS v6.1

They are experiencing some difficulty when copying certain files from
unix to VMS in binary mode. When using Multinet FTP the output file is
created with fixed 512-byte records and the End of File Byte (from
$DUMP/HEAD) is immediately after the end of the incoming data (short
of 512 bytes.) Experimentation shows that UCX does the same thing when
copying binaries from unix to VMS.

IFTP uses:

#define WRITE_BINARY "wb", "rfm=fix", "mrs=512"
    file = fopen (temp_path, WRITE_BINARY);

which creates identical output files to the standard FTP *except* for
the End of File Byte which IFTP locates (correctly?) at the beginning
of the next block. When used as input to the application for which this
file is intended, it only works with the EOF marker at the earlier
point.

I need to know what changes to make to the code to get the EOF marker
positioned immediately after the data. Can anyone help?

Thanks,

Dave Lunn.
T.RTitleUserPersonal
Name
DateLines
2116.1SPECXN::DERAMODan D'EramoTue Mar 11 1997 13:2328
        If the file header says that your file has fixed length record
        format with 512 byte records, then every record--including the
        last--had better have 512 bytes.  If the file header also says
        that the end of file position is in the middle of a [the last]
        record, then that file is "broken" and you should not expect
        any tool that you didn't write to be able to work with it.
        
        If the file header must store the exact end of file position,
        then I would use a different RMS record format, either the
        stream_lf or the undefined record formats, via
        
		fopen(pathname, "w", "rfm=stmlf", "rat=cr", "ctx=stm")
        
        or
        
        	fopen(pathname, "w", "rfm=udf", "rat=none", ...)

        [For the undefined record formats, what is the best way to
        specify the rest of the options?  Maybe "mrs=512", "ctx=stm"?
        Would "ctx=bin" also be needed?]
        
        If you must have both fixed length record format and the exact
        end of file position, you can always change the end of file
        position in the file header using the SET FILE/ATTRIBUTE=(...)
        command after creating the file.  You can also probably adjust
        it via RMS calls or by using ACP QIO's.
        
        Dan
2116.2try to force stream access modeTAVENG::BORISBoris Gubenko, ISETue Mar 11 1997 14:1587
  You should instruct the CRTL to process the file in stream access mode
  to avoid record access mode which is the default for "rfm=fix", "mrs=512".
  In record access mode the full 512-byte records are written/read.

  To force stream access mode specify:

	#define WRITE_BINARY "wb", "rfm=fix", "mrs=512", "ctx=stm", "rat=none"

  Note, that application reading this file should also specify "ctx=stm" if
  it uses the CRTL I/O, otherwise, by default, the record mode will be applied.
  In record mode application will get 512-byte records and EOF will be seen
  after the last record rather than immediately after the written data.

  If you're not sure how the application process the file, try undefined
  record format:

	#define WRITE_BINARY "wb", "rat=none", "rfm=udf", "ctx=stm"

  The program below illustrates the difference between record and stream
  access mode.

  Boris

$ say f$getsy("hw_name")
VAXstation 4000-VLC
$ say f$getsy("version")
V6.1
$ run x
record mode: bytes read: 1024
stream mode: bytes read: 520
$ anal/rms/fdl/out=tt x.x
....
RECORD
        BLOCK_SPAN              yes
        CARRIAGE_CONTROL        none
        FORMAT                  fixed
        SIZE                    512

X.C
===
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define WRITE_BINARY "w", "rfm=fix", "mrs=512", "ctx=stm", "rat=none"

main()
{
    FILE *file;
    char buf[510];
    int i;

    if ( !(file = fopen ("x.x", WRITE_BINARY )) )
	perror("fopen for write");

    memset(buf,'x',sizeof(buf));
    if ( fwrite(buf, sizeof(buf), 1, file) != 1 )
	perror("fwrite");

    memset(buf,'y',sizeof(buf));
    if ( fwrite(buf, 10, 1, file) != 1 )
	perror("fwrite");

    if ( fclose(file) )
	perror("fclose");

    if ( !(file = fopen ("x.x", "r")) )
	perror("fopen for read");

    for ( i = 0; fgetc(file) != EOF; i++ )
	;
    printf("record mode: bytes read: %d\n", i);

    if ( fclose(file) )
	perror("fclose");

    if ( !(file = fopen ("x.x", "r", "ctx=stm" )) )
	perror("fopen for read");

    for ( i = 0; fgetc(file) != EOF; i++ )
	;
    printf("stream mode: bytes read: %d\n", i);

    if ( fclose(file) )
	perror("fclose");
}
2116.3CSC64::BLAYLOCKIf at first you doubt,doubt again.Tue Mar 11 1997 19:3711

Fixed length 512 byte files with non-zero first free bytes
are actually pretty normal for .EXE files on a OpenVMS system.
The linker manages to do this by writting out any traceback and/or
debug information at the end of the file as variable length
records inside the framework of a FL512byte file.

In order to accomplish that on the OpenVMS side, you would need
to use an ACP $QIO function to reset the FFB value. This
is documented in the I/O Users Guide Part I.
2116.4fixed length records/ctx=stmOSEC::LUNN[email protected]Wed Mar 12 1997 05:0911
Thanks for the replies.

.2's suggestion for using stream mode does the trick nicely. I had
tried rfm=udf which also works but obviously leaves the file structure
looking different to 'standard' FTP output. Fixed 512 byte with ctx=stm
leaves the output files identical.

Cheers,

Dave.