[comp.lang.c] VMS C file type and stdio - help!

marc@rna.UUCP (Marc Johnson) (08/11/88)

Posting this for a friend in Israel.
Any responses would be appreciated and should be e-mailed to:
rna!marc@ROCKVAX  or  marc%rna@rockefeller.edu.

------------------------------------------------------------------------------
I am trying to write a VMS C program that takes some data files on the
microVax and then converts them into my private binary format.  So far this
seemingly trivial task has taken a week. I won't go into all of the details,
but the problem is creating a binary file.  VMS doesn't just have files,
it has file types.  One must choose a file type, and then put data in the
file according to the rules and limits of that type.  What I want to do is
the following:

        1. Use the C standard I/O calls (fopen, fwrite, fclose) to
	   write a stream of binary bytes into a file.
        2. Use ftell to find out where I am in the file.
        3. Use fseek to move to a new position in the file.
        4. Create a file which kermit can access and transmit literally,
	   meaning that the byte sequence on the VMS system then appears
	   on the remote system.

I have tried most of the VMS file types, and I have not yet found one that
does what I want (STDIO binary files):

a. Using the default STDIO file type, stmlf (stream lf), the file is created
   perfectly, but kermit can't send it, because even when I tell kermit that
   the file is binary, it expands LF to CR-LF.  Also with some files, their
   internal data is such that kermit fails, because the VAX record management
   software (rms) doesn't encounter a LF character during a read of reclen
   characters.
b. Using the file type fixed, fwrite fails to put anything into the file.
c. Using the file type stm (stream), every four bytes are followed by CR-LF.
d. Using the file type udf (undefined), the file is written correctly, but
   ftell works incorrectly, and fwrites following an fseek fail to work.
e. I haven't tried var and vfc file types, because I understand from talking
   to DEC support engineers that they put extra stuff in the file to delimit
   my "records."

By the way, I am creating these various file types using the extra rms
parameters of fopen: fopen("test.dat", "w+", "rfm=udf").

We have been asking DEC about this problem, and in three days, I have yet to
speak to anyone who has ever programmed in VMS C. They keep asking me what
type of records I want to write, and I keep saying I want to use STDIO (which
they have never heard of) to write a file containing binary bytes.
------------------------------------------------------------------------------

Thanks in advance, netters!

Marc Johnson for Kaare Christian

dhesi@bsu-cs.UUCP (Rahul Dhesi) (08/18/88)

In response to the request for a solution to the problem of how to
create a binary file under VAX/VMS that allows arbitrary seeks:  There
is no ideal solution (other than switching to UNIX, of course), but you
can get by if you use stream-LF files.

Kermit will not let you transfer a stream-LF file without risking
corrupting it with newline conversions.  The standard VMS "Kermit-32"
won't treat a stream-LF file as a binary file and sends it line by line
instead.

Kermit transfer can still be done, however.  My bilf.c utility (that is
included with source code for zoo 2.0) will convert between stream-LF
and fixed-length-record (FLR) files.  So to do a Kermit transfer, use
bilf.c to convert to FLR format, then transfer with Kermit as a binary
file.  Or the other way around.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

scjones@sdrc.UUCP (Larry Jones) (08/19/88)

In article <3689@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> In response to the request for a solution to the problem of how to
> create a binary file under VAX/VMS that allows arbitrary seeks:  There
> is no ideal solution (other than switching to UNIX, of course), but you
> can get by if you use stream-LF files.
> 
> Kermit will not let you transfer a stream-LF file without risking
> corrupting it with newline conversions.  The standard VMS "Kermit-32"
> won't treat a stream-LF file as a binary file and sends it line by line
> instead.
> 
> Kermit transfer can still be done, however.  My bilf.c utility (that is
> included with source code for zoo 2.0) will convert between stream-LF
> and fixed-length-record (FLR) files.  So to do a Kermit transfer, use
> bilf.c to convert to FLR format, then transfer with Kermit as a binary
> file.  Or the other way around.

If you're using Digital's Vax-11 C, it's much easier to just tell it you
want fixed length records in the first place.  All you need do is add three
additional arguments on to the fopen call: "recfm=f", "mrs=512", "ctx=stm"
(that's from memory, so I hope I got them right).  The first says you want
fixed-length records, the seconds says to make them 512 bytes long, and the
last tells the C library to ignore the fact that the file is record structured
and pretend it's a stream file instead (which works just grand as long as the
records are fixed rather than variable-length).

It is worthwhile to note that the Vax-11 C documentation contains a typo
listing the last argument as "ctx=str".  It is still more interesting that
the library itself contains a bug which causes it to report some bizzare
VMS-specific error if you actually try that rather than reporting "invalid
argument value" as it should.  In any event, "ctx=stm" is correct.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
Nancy Reagan on superconductivity: "Just say mho."

egisin@watmath.waterloo.edu (Eric Gisin) (08/19/88)

In article <3689@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> 
> In response to the request for a solution to the problem of how to
> create a binary file under VAX/VMS that allows arbitrary seeks:  There
> is no ideal solution (other than switching to UNIX, of course), but you
> can get by if you use stream-LF files.
> 
You can create the file in C as a stream-LF file,
then change the file type to binary stream (UDF, no record attribute).
Kermit will be able to handle UDF files unless it goes
out of its way to disallow them.
I haven't programmed VMS in a long time, but I think
changing file types is done with an undocumented RMS function,
or with a disk ACP QIO function. (I don't have access to manuals)

leo@philmds.UUCP (Leo de Wit) (08/23/88)

In article <351@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>In article <3689@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
   [Rahul's reply omitted]...
>If you're using Digital's Vax-11 C, it's much easier to just tell it you
>want fixed length records in the first place.  All you need do is add three
>additional arguments on to the fopen call: "recfm=f", "mrs=512", "ctx=stm"
>(that's from memory, so I hope I got them right).  The first says you want
>fixed-length records, the seconds says to make them 512 bytes long, and the
>last tells the C library to ignore the fact that the file is record structured
>and pretend it's a stream file instead (which works just grand as long as the
>records are fixed rather than variable-length).

Unless you're *VERY SURE* never having to port this code (and who can
nowadays), you should not use this non-portable form of fopen. If you
port to a system with ANSI style C compiler (supporting prototypes) you
have a problem with the third argument of fopen(); it has only got two
parameters on Unix.
Besides, it is not really needed, as the default file type for VAX VMS C is
stream LF, which amounts to 512 byte records. This will just read 512 byte
blocks each time (except for the last one); I checked it.

                           Leo.

P.S. Why in the first place couldn't they leave the library functions
alone, instead of 'adding all those nice features' (see also extra
format types in printf, etc.)? The least they (DEC) should have done is
warn inadvertent users of possible portability problems. Lucky me to
come from a Unix womb (and as such somewhat better aware of the problems) 8-).

leo@philmds.UUCP (Leo de Wit) (08/24/88)

In article <20448@watmath.waterloo.edu> egisin@watmath.waterloo.edu (Eric Gisin) writes:
|You can create the file in C as a stream-LF file,
|then change the file type to binary stream (UDF, no record attribute).
|Kermit will be able to handle UDF files unless it goes
|out of its way to disallow them.
|I haven't programmed VMS in a long time, but I think
|changing file types is done with an undocumented RMS function,
|or with a disk ACP QIO function. (I don't have access to manuals)

To convert file types in VMS, use convert ( 8-).
From a program the convert utility is a three-stage rocket:
	conv$pass_files(),
	conv$pass_options(),
	conv$convert().
Consult your manuals for the correct parameters.

                   Leo.

mkhaw@teknowledge-vaxc.ARPA (Mike Khaw) (08/25/88)

> P.S. Why in the first place couldn't they leave the library functions
> alone, instead of 'adding all those nice features' (see also extra
> format types in printf, etc.)? The least they (DEC) should have done is
> warn inadvertent users of possible portability problems. Lucky me to

The VMS C compiler does have a "/standard=portable" switch that makes
the compiler check for non-portable constructs.  However, the VMS
implementation of stdio.h DOES NOT PASS the portability check, so the
signal/noise ratio of the portability warning messages is pretty low
for a large class of C programs (is it significant that the default for
the compiler is /standard=noportable?).  You'd think they would write
the "standard" .h files in such a way that they'd pass the portability
checks; e.g., via #ifdefs.

I'm a lot happier since I stopped programming on VMS!

Mike Khaw
-- 
internet: mkhaw@teknowledge.arpa
uucp:	  {uunet|sun|ucbvax|decwrl|uw-beaver}!mkhaw%teknowledge.arpa
hardcopy: Teknowledge Inc, 1850 Embarcadero Rd, POB 10119, Palo Alto, CA 94303

scjones@sdrc.UUCP (Larry Jones) (08/25/88)

In article <613@philmds.UUCP>, leo@philmds.UUCP (Leo de Wit) writes:
> In article <351@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
> [stuff about using DEC extensions to fopen to get the correct record
> structure]
> 
> Unless you're *VERY SURE* never having to port this code (and who can
> nowadays), you should not use this non-portable form of fopen. If you
> port to a system with ANSI style C compiler (supporting prototypes) you
> have a problem with the third argument of fopen(); it has only got two
> parameters on Unix.

Well, I wouldn't say you shouldn't use it, but I will say you should put an
"#ifdef vax11c" around it!

> Besides, it is not really needed, as the default file type for VAX VMS C is
> stream LF, which amounts to 512 byte records. This will just read 512 byte
> blocks each time (except for the last one); I checked it.

This is wrong - if it wasn't needed, why would people be asking how to do it?
The problem is not reading the file with C, the problem is with programs which
are written in other languages which read RECORDS - something C has no (or at
least very little) concept of.  If you try to read a record from a stream-LF
file, RMS gives you everything up to the next linefeed.  If your buffer isn't
big enought to hold it, you get an error and loose data.  Record format IS
significant.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
Nancy Reagan on superconductivity: "Just say mho."

egisin@watmath.waterloo.edu (Eric Gisin) (08/26/88)

In article <618@philmds.UUCP>, leo@philmds.UUCP (Leo de Wit) writes:
> In article <20448@watmath.waterloo.edu> egisin@watmath.waterloo.edu (Eric Gisin) writes:
> |You can create the file in C as a stream-LF file,
> |then change the file type to binary stream (UDF, no record attribute).
> To convert file types in VMS, use convert ( 8-).

The convert utility does not do what they wanted.
It will expect the input file to have a valid record
structure, which is generally not the case when binary
data is written by C programs. Convert will also "drop" '\n's,
and start a new record. 

What I meant is change the file type in the "file header"
(I forget the correct term, I'm refering to the on-disk
equivalent of the FAB) without changing the file data.

christiansen@CHEWI.CHE.WISC.EDU ("REED CHRISTIANSEN") (08/30/88)

In article <613@philmds.UUCP>, mcvax!hp4nl!philmds!leo@uunet.uunet (Leo
de Wit) writes:
>In article <351@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>>In article <3689@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>   [Rahul's reply omitted]...
>>  [Larry's text omitted]...
>
> [Some of Leo's stuff omitted]...
>P.S. Why in the first place couldn't they [DEC] leave the library functions
>alone, instead of 'adding all those nice features' (see also extra
     The problem (if there is one) is that the vanilla-C file types
     aren't adequate to deal with files created outside of the C
     environment, as these were.  DEC could have put a crippled C
     on VAX/VMS, one that would not have the capabilities of their
     other languages, but they decided to supplement (NOT SUPPLANT) the
     Unix-style I/O.  You can still do Unix-style I/O...
>format types in printf, etc.)? The least they (DEC) should have done is
>warn inadvertent users of possible portability problems.
     They do.  Doesn't anybody read the user documentation?  Chapter 1 of
     the VAC C Run-Time Library Information manual dicusses portability
     issues in painful detail:  Section 1 of Chapter 1 discusses Unix I/O
     (and how to be compatible, if you wish); Section 4 of Chapter 1
     discusses many other portability concerns.  And, too, they devote an
     entire chapter (4) to Unix I/O.
>Lucky me to come from a Unix womb (and as such somewhat better aware of the
> problems) 8-).
     This isn't the first VMS question that could have been answered by
     people opening up the manuals and spending a few minutes to spin through
     them.