2 * fopen.c - open a stream
4 /* $Id: fopen.c,v 1.9 1994/06/24 11:49:28 ceriel Exp $ */
12 /* The next 3 defines are true in all UNIX systems known to me.
18 /* Since the O_CREAT flag is not available on all systems, we can't get it
19 * from the standard library. Furthermore, even if we know that <fcntl.h>
20 * contains such a flag, it's not sure whether it can be used, since we
21 * might be cross-compiling for another system, which may use an entirely
22 * different value for O_CREAT (or not support such a mode). The safest
23 * thing is to just use the Version 7 semantics for open, and use creat()
26 * Another problem is O_APPEND, for which the same holds. When "a"
27 * open-mode is used, an lseek() to the end is done before every write()
30 * The O_CREAT, O_TRUNC and O_APPEND given here, are only for convenience.
31 * They are not passed to open(), so the values don't have to match a value
32 * from the real world. It is enough when they are unique.
36 #define O_APPEND 0x040
38 int _open(const char *path, int flags);
39 int _creat(const char *path, int mode);
43 fopen(const char *name, const char *mode)
46 int rwmode = 0, rwflags = 0;
50 for (i = 0; __iotab[i] != 0 ; i++)
51 if ( i >= FOPEN_MAX-1 )
56 flags |= _IOREAD | _IOREADING;
60 flags |= _IOWRITE | _IOWRITING;
62 rwflags = O_CREAT | O_TRUNC;
65 flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
67 rwflags |= O_APPEND | O_CREAT;
79 flags |= _IOREAD | _IOWRITE;
81 /* The sequence may be followed by additional characters */
88 /* Perform a creat() when the file should be truncated or when
89 * the file is opened for writing and the open() failed.
91 if ((rwflags & O_TRUNC)
92 || (((fd = _open(name, rwmode)) < 0)
93 && (rwflags & O_CREAT))) {
94 if (((fd = _creat(name, PMODE)) > 0) && flags | _IOREAD) {
96 fd = _open(name, rwmode);
101 if (fd < 0) return (FILE *)NULL;
103 if (( stream = (FILE *) malloc(sizeof(FILE))) == NULL ) {
108 if ((flags & (_IOREAD | _IOWRITE)) == (_IOREAD | _IOWRITE))
109 flags &= ~(_IOREADING | _IOWRITING);
113 stream->_flags = flags;