|
|
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: n * 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:
30: #define RMODE 0
31: #define WMODE 1
32: #define RWMODE 2
33: #define CRMODE 0666 /* default access permissions on create */
34:
35: FILE *
36: _fopen(name, type, fp, fd) char *name, *type; register FILE *fp; register int fd;
37: {
38: register _FILE2 *f2p;
39: register int mode;
40: int truncate, append, ascii;
41: char c, cn;
42:
43: /* Parse the type string and set flags accordingly. */
44: mode = WMODE;
45: ascii = 1;
46: truncate = append = 0;
47: cn = 'r';
48: if ((c = *type++) == 'r') {
49: mode = RMODE;
50: cn = 'w';
51: } else if (c=='w')
52: truncate++;
53: else if (c=='a')
54: append++;
55: else
56: return NULL;
57: if ((c = *type) != '\0') {
58: if (c == 'b') {
59: ascii = 0;
60: c = *++type;
61: }
62: if (c == '+') {
63: mode = RWMODE;
64: c = *++type;
65: }
66: if (c == cn) {
67: mode = RWMODE;
68: c = *++type;
69: }
70: if (c == 'b') {
71: ascii = 0;
72: c = *++type;
73: }
74: if (c != '\0')
75: return NULL;
76: }
77:
78: #if _ASCII
79: /*
80: * Beware of ASCII files ending with ASCII EOF character in append mode.
81: * Open for r+w, to allow checking last character.
82: */
83: if (append
84: && ascii
85: && (fd >= 0 || (fd = open(name, RWMODE)) >=0)) {
86: if (lseek(fd, -1L, SEEK_END) != -1L) { /* seek to end-1 */
87: if (read(fd, &c, 1) == 1 /* read last char */
88: && c == _EOFCHAR) /* last char is EOF */
89: lseek(fd, -1L, SEEK_CUR); /* so unread it */
90: } else /* might be empty */
91: lseek(fd, 0L, SEEK_END);
92: }
93: #endif
94:
95: /* Try opening existing file, unless truncation is specified. */
96: if (fd < 0 && !truncate)
97: fd = open(name, mode);
98:
99: /*
100: * If "r" or "r+" and the open above failed, return an error.
101: * If "w" or "w+", create the file.
102: * If "a" or "a+" and the open above, create the file.
103: * If "w+" or "a+", close it and reopen with the desired mode.
104: */
105: if (fd < 0
106: && (truncate || append)
107: && (fd = creat(name, CRMODE)) >= 0
108: && mode != WMODE) {
109: close(fd);
110: fd = open(name, mode);
111: }
112: if (fd < 0)
113: return NULL; /* Open failed */
114:
115: #if _ASCII
116: if (append && !ascii) /* ASCII append seek above */
117: #else
118: if (append)
119: #endif
120: lseek(fd, 0L, SEEK_END); /* Seek to end */
121:
122: /* Allocate a FILE if necessary, die on failure. */
123: if (fp == NULL) {
124: if ((fp = (FILE *)malloc(sizeof(FILE)+sizeof(_FILE2))) == NULL) {
125: close(fd);
126: return NULL;
127: }
128: fp->_f2p = (char *)fp + sizeof(FILE);
129: }
130:
131: /* Initialize the FILE. */
132: fp->_cc = 0;
133: fp->_cp = NULL;
134: fp->_ff1 = 0;
135: fp->_fd = fd;
136: fp->_ff2 = _FINUSE;
137: fp->_mode = _MODE_UNINIT;
138: f2p = fp->_f2p;
139: f2p->_gt = &_fginit;
140: f2p->_pt = &_fpinit;
141: f2p->_bp = f2p->_dp = f2p->_ep = f2p->_nm = NULL;
142: f2p->_uc = 0;
143: if (append)
144: fp->_ff2 |= _FAPPND;
145: #if _ASCII
146: if (ascii)
147: fp->_ff2 |= _FASCII;
148: #if MSDOS
149: else
150: _setraw(fd);
151: #endif
152: #endif
153: if (mode == RMODE) {
154: fp->_ff1 |= _FRONLY;
155: f2p->_pt = &_fpute;
156: } else if (mode == WMODE) {
157: fp->_ff1 |= _FWONLY;
158: f2p->_gt = &_fgete;
159: } else if (mode == RWMODE)
160: fp->_ff1 |= _FRW;
161: return fp;
162: }
163:
164: /* 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.