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