ack/lang/cem/libcc.ansi/sys/stdio/fopen.c

119 lines
2.6 KiB
C
Raw Normal View History

1989-05-30 13:34:25 +00:00
/*
* fopen.c - open a stream
*/
1994-06-24 14:02:31 +00:00
/* $Id$ */
1989-05-30 13:34:25 +00:00
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include "loc_incl.h"
1989-05-30 13:34:25 +00:00
2018-06-23 16:54:40 +00:00
#if ACKCONF_WANT_STDIO
2018-06-21 20:33:47 +00:00
#define PMODE 0666
1989-05-30 13:34:25 +00:00
1989-12-18 15:04:14 +00:00
/* Since the O_CREAT flag is not available on all systems, we can't get it
* from the standard library. Furthermore, even if we know that <fcntl.h>
* contains such a flag, it's not sure whether it can be used, since we
* might be cross-compiling for another system, which may use an entirely
* different value for O_CREAT (or not support such a mode). The safest
* thing is to just use the Version 7 semantics for open, and use creat()
* whenever necessary.
*
* Another problem is O_APPEND, for which the same holds. When "a"
* open-mode is used, an lseek() to the end is done before every write()
* system-call.
*
* FIXME dtrg: I'm not sure this is relevant any more. Implementing O_CREAT
* and O_APPEND ought to be the job of the syscall library, no? Besides, the
* code requires valid definitions.
*
* Remember to fix freopen.c if changing this.
1989-12-18 15:04:14 +00:00
*/
1989-05-30 13:34:25 +00:00
2018-06-21 20:33:47 +00:00
FILE* fopen(const char* name, const char* mode)
1989-05-30 13:34:25 +00:00
{
register int i;
int rwmode = 0, rwflags = 0;
2018-06-21 20:33:47 +00:00
FILE* stream;
1989-05-30 13:34:25 +00:00
int fd, flags = 0;
2018-06-21 20:33:47 +00:00
for (i = 0; __iotab[i] != 0; i++)
if (i >= FOPEN_MAX - 1)
return (FILE*)NULL;
1989-05-30 13:34:25 +00:00
2018-06-21 20:33:47 +00:00
switch (*mode++)
{
case 'r':
flags |= _IOREAD | _IOREADING;
rwmode = O_RDONLY;
break;
case 'w':
flags |= _IOWRITE | _IOWRITING;
rwmode = O_WRONLY;
rwflags = O_CREAT | O_TRUNC;
break;
case 'a':
flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
rwmode = O_WRONLY;
rwflags |= O_APPEND | O_CREAT;
break;
default:
return (FILE*)NULL;
1989-05-30 13:34:25 +00:00
}
2018-06-21 20:33:47 +00:00
while (*mode)
{
switch (*mode++)
{
case 'b':
continue;
case '+':
rwmode = O_RDWR;
flags |= _IOREAD | _IOWRITE;
continue;
/* The sequence may be followed by additional characters */
default:
break;
1989-05-30 13:34:25 +00:00
}
break;
1989-05-30 13:34:25 +00:00
}
1989-12-18 15:04:14 +00:00
/* Perform a creat() when the file should be truncated or when
* the file is opened for writing and the open() failed.
*/
if ((rwflags & O_TRUNC)
|| (((fd = open(name, rwmode)) < 0)
2018-06-21 20:33:47 +00:00
&& (rwflags & O_CREAT)))
{
if (((fd = creat(name, PMODE)) > 0) && flags | _IOREAD)
{
(void)close(fd);
fd = open(name, rwmode);
1990-04-09 15:21:43 +00:00
}
}
1989-05-30 13:34:25 +00:00
2018-06-21 20:33:47 +00:00
if (fd < 0)
return (FILE*)NULL;
1989-05-30 13:34:25 +00:00
2018-06-21 20:33:47 +00:00
if ((stream = (FILE*)malloc(sizeof(FILE))) == NULL)
{
close(fd);
2018-06-21 20:33:47 +00:00
return (FILE*)NULL;
1989-05-30 13:34:25 +00:00
}
2018-06-21 20:33:47 +00:00
if ((flags & (_IOREAD | _IOWRITE)) == (_IOREAD | _IOWRITE))
1989-06-26 10:37:05 +00:00
flags &= ~(_IOREADING | _IOWRITING);
1989-05-30 13:34:25 +00:00
stream->_count = 0;
stream->_fd = fd;
stream->_flags = flags;
1989-06-26 10:37:05 +00:00
stream->_buf = NULL;
1989-12-18 15:04:14 +00:00
__iotab[i] = stream;
1989-05-30 13:34:25 +00:00
return stream;
}
2018-06-23 16:54:40 +00:00
#endif