|
|
1.1 root 1: /*
2: * libc/stdio/_fopen.c
3: * ANSI-compliant C standard i/o library internals.
4: * _fopen()
5: * Open a file.
6: */
7:
8: /*
9: * The recognized mode strings are as follows:
10: * mode a.k.a. notfound found mode truncate append
11: * r error read RMODE 0 0
12: * w create trunc. WMODE 1 0
13: * a create append WMODE 0 1
14: * r+ rw r+w error rd.&wr. RWMODE 0 0
15: * w+ wr w+r create trunc. RWMODE 1 0
16: * a+ ar a+r create app.&rd RWMODE 0 1
17: * In all cases, a trailing 'b' means ascii==1, otherwise ascii==0.
18: * ANSI 4.9.5.3 requires only the first mode forms above (e.g. "r+")
19: * but tolerates the alternate forms (e.g. "r+w" or "rw",
20: * see code involving local 'cn' below).
21: * Use the given FILE if fp is not NULL, otherwise allocate a new FILE.
22: * Use the given fd if nonnegative.
23: * The get and put function pointers in the FILE are initialized
24: * later, possibly after a setvbuf() call specifying desired buffering.
25: */
26:
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include "stdio.int.h"
30:
31: #define RMODE 0
32: #define WMODE 1
33: #define RWMODE 2
34: #define CRMODE 0666 /* default access permissions on create */
35:
36: FILE *
37: _fopen(name, type, fp, fd) char *name, *type; register FILE *fp; register int fd;
38: {
39: register _FILE2 *f2p;
40: register int mode;
41: int truncate, append, ascii;
42: char c, cn;
43:
44: /* Parse the type string and set flags accordingly. */
45: mode = WMODE;
46: ascii = 1;
47: truncate = append = 0;
48: cn = 'r';
49: if ((c = *type++) == 'r') {
50: mode = RMODE;
51: cn = 'w';
52: } else if (c=='w')
53: truncate++;
54: else if (c=='a')
55: append++;
56: else
57: return NULL;
58: if ((c = *type) != '\0') {
59: if (c == 'b') {
60: ascii = 0;
61: c = *++type;
62: }
63: if (c == '+') {
64: mode = RWMODE;
65: c = *++type;
66: }
67: if (c == cn) {
68: mode = RWMODE;
69: c = *++type;
70: }
71: if (c == 'b') {
72: ascii = 0;
73: c = *++type;
74: }
75: if (c != '\0')
76: return NULL;
77: }
78:
79: #if _ASCII
80: /*
81: * Beware of ASCII files ending with ASCII EOF character in append mode.
82: * Open for r+w, to allow checking last character.
83: */
84: if (append
85: && ascii
86: && (fd >= 0 || (fd = open(name, RWMODE)) >=0)) {
87: if (lseek(fd, -1L, SEEK_END) != -1L) { /* seek to end-1 */
88: if (read(fd, &c, 1) == 1 /* read last char */
89: && c == _EOFCHAR) /* last char is EOF */
90: lseek(fd, -1L, SEEK_CUR); /* so unread it */
91: } else /* might be empty */
92: lseek(fd, 0L, SEEK_END);
93: }
94: #endif
95:
96: /* Try opening existing file, unless truncation is specified. */
97: if (fd < 0 && !truncate)
98: fd = open(name, mode);
99:
100: /*
101: * If "r" or "r+" and the open above failed, return an error.
102: * If "w" or "w+", create the file.
103: * If "a" or "a+" and the open above, create the file.
104: * If "w+" or "a+", close it and reopen with the desired mode.
105: */
106: if (fd < 0
107: && (truncate || append)
108: && (fd = creat(name, CRMODE)) >= 0
109: && mode != WMODE) {
110: close(fd);
111: fd = open(name, mode);
112: }
113: if (fd < 0)
114: return NULL; /* Open failed */
115:
116: #if _ASCII
117: if (append && !ascii) /* ASCII append seek above */
118: #else
119: if (append)
120: #endif
121: lseek(fd, 0L, SEEK_END); /* Seek to end */
122:
123: /* Allocate a FILE if necessary, die on failure. */
124: if (fp == NULL) {
125: if ((fp = (FILE *)malloc(sizeof(FILE)+sizeof(_FILE2))) == NULL) {
126: close(fd);
127: return NULL;
128: }
129: fp->_f2p = (char *)fp + sizeof(FILE);
130: }
131:
132: /* Initialize the FILE. */
133: fp->_cc = 0;
134: fp->_cp = NULL;
135: fp->_ff1 = 0;
136: fp->_fd = fd;
137: fp->_ff2 = _FINUSE;
138: fp->_mode = _MODE_UNINIT;
139: f2p = fp->_f2p;
140: f2p->_gt = &_fginit;
141: f2p->_pt = &_fpinit;
142: f2p->_bp = f2p->_dp = f2p->_ep = f2p->_nm = NULL;
143: f2p->_uc = 0;
144: if (append)
145: fp->_ff2 |= _FAPPND;
146: #if _ASCII
147: if (ascii)
148: fp->_ff2 |= _FASCII;
149: #if MSDOS
150: else
151: _setraw(fd);
152: #endif
153: #endif
154: if (mode == RMODE) {
155: fp->_ff1 |= _FRONLY;
156: f2p->_pt = &_fpute;
157: } else if (mode == WMODE) {
158: fp->_ff1 |= _FWONLY;
159: f2p->_gt = &_fgete;
160: } else if (mode == RWMODE)
161: fp->_ff1 |= _FRW;
162: return fp;
163: }
164:
165: /* end of libc/stdio/_fopen.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.