[comp.os.vms] Creating files from C

SLOANE@UKANVAX.BITNET (Bob Sloane) (08/07/87)

Consider the following (very simple) C program.

#include stdio

main() {
    FILE *fd;

    fd = fopen("test.file","w");
    fprintf(fd,"This is a test.");
    fclose(fd);
}

If I compile, link and run this program, it works just fine, and
TEST.FILE is created under my current directory with my current
default protections.  Just as expected so far.

Now suppose I change protections on the file TEST.FILE.  I would
expect that, when I run the program again, the new version of the
file would have the same protections as the first version.  Wrong.
It has my default protections.  I always thought that the default
protections on a file came from:

    1. a previous of the same file, if one exists
    2. From the DEFAULT_PROTECTION ACL on the directory, of one exists
    3. from the PROCESS default protection.

At least that is what it says in the DCL Concepts manual on page 7-6.
Apparently C always uses the PROCESS default protection.  Can anyone
tell me why, or should I SPR this?

                      Bob Sloane
                      University of Kansas
                      Computer Center
                      (913) 864-0444
                      SLOANE@UKANVAX on BITNET

LEICHTER-JERRY@YALE.ARPA (08/10/87)

    Consider the following (very simple) C program [which opens a TEST.FILE
    for write and writes one line to it]....
    
    If I compile, link and run this program, it works just fine, and
    TEST.FILE is created under my current directory with my current
    default protections....
    
    Now suppose I change protections on the file TEST.FILE.  I would
    expect that, when I run the program again, the new version of the
    file would have the same protections as the first version.  Wrong.
    It has my default protections.  I always thought that the default
    protections on a file came from:
    
        1. a previous of the same file, if one exists
        2. From the DEFAULT_PROTECTION ACL on the directory, of one exists
        3. from the PROCESS default protection.

This is a common trap in VAX C.  It comes from an incompatibility between the
Unix and VMS file protection schemes.  Unix provides the umask() call to set
the default file protection ("mode").  In Unix, this "default" is absolute -
previous versions of the file - while there are no version numbers in Unix, at
the time a file is created it may be replacing a file of the same name -
directory protections, and so on have no effect.  VAX C emulates the umask()
call by saving away the argument and providing the implied VMS protections on
all subsequent file creations through the C I/O system.  Since the protections
are provided explicitly, they override any VMS defaults.

When a VAX C program starts up, its umask value is set from the process
defaults.  This provides an exact emulation of Unix semantics - but, as you've
discovered, it is incompatible with VMS semantics:  What was the VMS DEFAULT
becomes an explicitly-specified protection, which is then forced on the file.

I suppose one could come up with a better approximation of VMS semantics by
adding a bit of state that indicates whether the user has ever called umask.
If set, the C I/O system would provide an explicit protection; otherwise, it
would leave the protections off so that VMS defaults would apply.  If you work
through the details of this, especially with regard to subprocesses, you find
that it's not quite so simple, unfortunately - the difference between VMS and
Unix sematics here is fundamental.

It's interesting that VAX C, which in most cases resolves "unresolvable" con-
flicts between VMS and Unix semantics in favor of VMS, resolves this particu-
lar conflict in favor of Unix - probably by accident rather than design.  My
own inclination would be to go with the alternative I suggested above:  VMS
semantics until a umask call is made, then Unix semantics for the process and
all subsequently-created children.  Note that this would mean that a C program
might behave differently depending on whether it was just RUN or was started
up via vfork/exec.

If this is important to you, by all means file an SPR - perhaps suggesting
this solution, if you think it appropriate, or come up with a better one.

							-- Jerry
-------

adelman@LBL-CSA2.ARPA (Kenneth Adelman) (08/10/87)

    The problem with umask() was well put by Jerry. I ran into this
a few weeks ago and discovered an interesting workaround --

    (void) umask(-1);

    This tells the Unix emulator to deney all files access bits,
causing it to set the XAB$W_PROT field to zero.  However, setting
XAB$W_PRO to zero doesn't have the affect of creating a file with all
access denied, but rather creating a file with the VMS semantics for
default protection.

					    Kenneth Adelman
					    LBL