source: trunk/minix/lib/stdio/fopen.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 3.0 KB
Line 
1/*
2 * fopen.c - open a stream
3 */
4/* $Header: /cvsup/minix/src/lib/stdio/fopen.c,v 1.4 2006/02/02 16:59:07 beng Exp $ */
5
6#if defined(_POSIX_SOURCE)
7#include <sys/types.h>
8#endif
9#include <stdio.h>
10#include <stdlib.h>
11#include "loc_incl.h"
12#include <sys/stat.h>
13
14#define PMODE 0666
15
16/* The next 3 defines are true in all UNIX systems known to me.
17 */
18#define O_RDONLY 0
19#define O_WRONLY 1
20#define O_RDWR 2
21
22/* Since the O_CREAT flag is not available on all systems, we can't get it
23 * from the standard library. Furthermore, even if we know that <fcntl.h>
24 * contains such a flag, it's not sure whether it can be used, since we
25 * might be cross-compiling for another system, which may use an entirely
26 * different value for O_CREAT (or not support such a mode). The safest
27 * thing is to just use the Version 7 semantics for open, and use creat()
28 * whenever necessary.
29 *
30 * Another problem is O_APPEND, for which the same holds. When "a"
31 * open-mode is used, an lseek() to the end is done before every write()
32 * system-call.
33 *
34 * The O_CREAT, O_TRUNC and O_APPEND given here, are only for convenience.
35 * They are not passed to open(), so the values don't have to match a value
36 * from the real world. It is enough when they are unique.
37 */
38#define O_CREAT 0x010
39#define O_TRUNC 0x020
40#define O_APPEND 0x040
41
42int _open(const char *path, int flags);
43int _creat(const char *path, _mnx_Mode_t mode);
44int _close(int d);
45
46FILE *
47fopen(const char *name, const char *mode)
48{
49 register int i;
50 int rwmode = 0, rwflags = 0;
51 FILE *stream;
52 struct stat st;
53 int fd, flags = 0;
54
55 for (i = 0; __iotab[i] != 0 ; i++)
56 if ( i >= FOPEN_MAX-1 )
57 return (FILE *)NULL;
58
59 switch(*mode++) {
60 case 'r':
61 flags |= _IOREAD | _IOREADING;
62 rwmode = O_RDONLY;
63 break;
64 case 'w':
65 flags |= _IOWRITE | _IOWRITING;
66 rwmode = O_WRONLY;
67 rwflags = O_CREAT | O_TRUNC;
68 break;
69 case 'a':
70 flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
71 rwmode = O_WRONLY;
72 rwflags |= O_APPEND | O_CREAT;
73 break;
74 default:
75 return (FILE *)NULL;
76 }
77
78 while (*mode) {
79 switch(*mode++) {
80 case 'b':
81 continue;
82 case '+':
83 rwmode = O_RDWR;
84 flags |= _IOREAD | _IOWRITE;
85 continue;
86 /* The sequence may be followed by additional characters */
87 default:
88 break;
89 }
90 break;
91 }
92
93 /* Perform a creat() when the file should be truncated or when
94 * the file is opened for writing and the open() failed.
95 */
96 if ((rwflags & O_TRUNC)
97 || (((fd = _open(name, rwmode)) < 0)
98 && (rwflags & O_CREAT))) {
99 if (((fd = _creat(name, PMODE)) > 0) && flags | _IOREAD) {
100 (void) _close(fd);
101 fd = _open(name, rwmode);
102 }
103
104 }
105
106 if (fd < 0) return (FILE *)NULL;
107
108 if ( fstat( fd, &st ) < 0 ) {
109 _close(fd);
110 return (FILE *)NULL;
111 }
112
113 if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO;
114
115 if (( stream = (FILE *) malloc(sizeof(FILE))) == NULL ) {
116 _close(fd);
117 return (FILE *)NULL;
118 }
119
120 if ((flags & (_IOREAD | _IOWRITE)) == (_IOREAD | _IOWRITE))
121 flags &= ~(_IOREADING | _IOWRITING);
122
123 stream->_count = 0;
124 stream->_fd = fd;
125 stream->_flags = flags;
126 stream->_buf = NULL;
127 __iotab[i] = stream;
128 return stream;
129}
Note: See TracBrowser for help on using the repository browser.