|
1615
|
1
|
|
|
2 /*
|
|
2054
|
3 * fopen.c
|
|
1615
|
4 *
|
|
2054
|
5 * Copyright (c) 1991 Symantec Corporation. All rights reserved.
|
|
1615
|
6 *
|
|
|
7 */
|
|
|
8
|
|
2054
|
9 #include <MacHeaders>
|
|
|
10
|
|
1615
|
11 #include "stdio.h"
|
|
|
12 #include "errno.h"
|
|
|
13 #include "string.h"
|
|
|
14 #include "ansi_private.h"
|
|
|
15
|
|
2054
|
16 extern long _ftype, _fcreator;
|
|
1615
|
17
|
|
|
18 #define fcbVPtr(fcb) (* (VCB **) (fcb + 20))
|
|
|
19 #define fcbDirID(fcb) (* (long *) (fcb + 58))
|
|
|
20 #define fcbCName(fcb) (fcb + 62)
|
|
|
21
|
|
|
22 static void setfiletype(StringPtr, int);
|
|
|
23 static void stdio_exit(void);
|
|
|
24 static int fileio(FILE *, int);
|
|
|
25 static int close(FILE *);
|
|
|
26 static void replace(unsigned char *, size_t, int, int);
|
|
|
27
|
|
2054
|
28 FILE *freopenRF();
|
|
|
29 FILE *__openRF();
|
|
1615
|
30
|
|
|
31 FILE *
|
|
2054
|
32 fopenRF(const char *filename, const char *mode)
|
|
1615
|
33 {
|
|
|
34 return(freopenRF(filename, mode, __getfile()));
|
|
|
35 }
|
|
|
36
|
|
|
37
|
|
|
38 FILE *
|
|
2054
|
39 freopenRF(const char *filename, const char *mode, FILE *fp)
|
|
1615
|
40 {
|
|
|
41 int omode, oflag;
|
|
|
42
|
|
|
43 /* interpret "rwa" */
|
|
|
44
|
|
|
45 if (mode[0] == 'r') {
|
|
|
46 omode = fsRdPerm;
|
|
|
47 oflag = 0;
|
|
|
48 }
|
|
|
49 else if (mode[0] == 'w') {
|
|
|
50 omode = fsWrPerm;
|
|
|
51 oflag = F_CREAT+F_TRUNC;
|
|
|
52 }
|
|
|
53 else if (mode[0] == 'a') {
|
|
|
54 omode = fsWrPerm;
|
|
|
55 oflag = F_CREAT+F_APPEND;
|
|
|
56 }
|
|
|
57 else {
|
|
|
58 errno = EINVAL;
|
|
|
59 return(NULL);
|
|
|
60 }
|
|
|
61
|
|
|
62 /* interpret "b+" */
|
|
|
63
|
|
|
64 if (mode[1] == 'b') {
|
|
|
65 oflag |= F_BINARY;
|
|
|
66 if (mode[2] == '+')
|
|
|
67 omode = fsRdWrPerm;
|
|
|
68 }
|
|
|
69 else if (mode[1] == '+') {
|
|
|
70 omode = fsRdWrPerm;
|
|
|
71 if (mode[2] == 'b')
|
|
|
72 oflag |= F_BINARY;
|
|
|
73 }
|
|
|
74
|
|
|
75 /* open the file */
|
|
|
76
|
|
|
77 return(__openRF(filename, omode, oflag, fp));
|
|
|
78 }
|
|
|
79
|
|
|
80
|
|
|
81 FILE *
|
|
2054
|
82 __openRF(const char *filename, int omode, int oflag, FILE *fp)
|
|
1615
|
83 {
|
|
2054
|
84 IOParam pb;
|
|
1615
|
85 char pname[FILENAME_MAX];
|
|
|
86
|
|
|
87 if (fp == NULL)
|
|
|
88 return(NULL);
|
|
|
89 fclose(fp);
|
|
|
90
|
|
|
91 /* set up pb */
|
|
|
92
|
|
|
93 pb.ioNamePtr = __c2p(filename, pname);
|
|
|
94 pb.ioVRefNum = 0;
|
|
|
95 pb.ioVersNum = 0;
|
|
|
96 pb.ioPermssn = omode;
|
|
|
97 pb.ioMisc = 0;
|
|
|
98
|
|
|
99 /* create file */
|
|
|
100
|
|
|
101 if (oflag & F_CREAT) {
|
|
2054
|
102 PBCreateSync((ParmBlkPtr)&pb);
|
|
1615
|
103 if (pb.ioResult == noErr)
|
|
|
104 oflag &= ~F_TRUNC;
|
|
|
105 else if (pb.ioResult == dupFNErr && !(oflag & F_EXCL))
|
|
|
106 oflag &= ~F_CREAT;
|
|
|
107 else {
|
|
|
108 errno = pb.ioResult;
|
|
|
109 return(NULL);
|
|
|
110 }
|
|
|
111 }
|
|
|
112
|
|
2054
|
113 /* open file */
|
|
1615
|
114
|
|
2054
|
115 PBOpenRFSync((ParmBlkPtr)&pb);
|
|
1615
|
116 if (pb.ioResult) {
|
|
|
117 errno = pb.ioResult;
|
|
2054
|
118 if (oflag & F_CREAT)
|
|
|
119 PBDeleteSync((ParmBlkPtr)&pb);
|
|
1615
|
120 return(NULL);
|
|
|
121 }
|
|
|
122 fp->refnum = pb.ioRefNum;
|
|
|
123
|
|
|
124 /* get/set file length */
|
|
|
125
|
|
2054
|
126 if (oflag & F_TRUNC)
|
|
|
127 PBSetEOFSync((ParmBlkPtr)&pb);
|
|
|
128 else if (!(oflag & F_CREAT))
|
|
|
129 PBGetEOFSync((ParmBlkPtr)&pb);
|
|
1615
|
130 fp->len = (fpos_t) pb.ioMisc;
|
|
|
131
|
|
|
132 /* initialize rest of FILE structure */
|
|
|
133
|
|
|
134 if (oflag & F_APPEND) {
|
|
|
135 fp->append = 1;
|
|
|
136 fp->pos = fp->len;
|
|
|
137 }
|
|
|
138 if (oflag & F_BINARY)
|
|
|
139 fp->binary = 1;
|
|
|
140 setvbuf(fp, NULL, _IOFBF, BUFSIZ);
|
|
|
141 fp->proc = fileio;
|
|
|
142
|
|
|
143 /* set file type */
|
|
|
144
|
|
|
145 if (oflag & (F_CREAT|F_TRUNC))
|
|
|
146 setfiletype(pb.ioNamePtr, oflag);
|
|
|
147
|
|
|
148 /* done */
|
|
|
149
|
|
|
150 __atexit_stdio(stdio_exit);
|
|
|
151 return(fp);
|
|
|
152 }
|
|
|
153
|
|
|
154
|
|
|
155 /*
|
|
|
156 * setfiletype - set type/creator of new file
|
|
|
157 *
|
|
|
158 */
|
|
|
159
|
|
|
160 static void
|
|
2054
|
161 setfiletype(StringPtr name, int oflag)
|
|
1615
|
162 {
|
|
2054
|
163 FileParam pb;
|
|
1615
|
164
|
|
|
165 pb.ioNamePtr = name;
|
|
|
166 pb.ioVRefNum = 0;
|
|
|
167 pb.ioFVersNum = 0;
|
|
|
168 pb.ioFDirIndex = 0;
|
|
2054
|
169 if (PBGetFInfoSync((ParmBlkPtr)&pb) == noErr) {
|
|
|
170 if (oflag & F_BINARY)
|
|
|
171 pb.ioFlFndrInfo.fdType = _ftype;
|
|
|
172 else
|
|
|
173 pb.ioFlFndrInfo.fdType = 'TEXT';
|
|
|
174 pb.ioFlFndrInfo.fdCreator = _fcreator;
|
|
|
175 PBSetFInfoSync((ParmBlkPtr)&pb);
|
|
1615
|
176 }
|
|
|
177 }
|
|
|
178
|
|
|
179
|
|
|
180 /*
|
|
|
181 * stdio_exit - stdio shutdown routine
|
|
|
182 *
|
|
|
183 */
|
|
|
184
|
|
|
185 static void
|
|
2054
|
186 stdio_exit(void)
|
|
1615
|
187 {
|
|
|
188 register FILE *fp;
|
|
|
189 int n;
|
|
|
190
|
|
|
191 for (fp = &__file[0], n = FOPEN_MAX; n--; fp++)
|
|
|
192 fclose(fp);
|
|
|
193 }
|
|
|
194
|
|
|
195
|
|
|
196 /*
|
|
|
197 * fileio - I/O handler proc for files and devices
|
|
|
198 *
|
|
|
199 */
|
|
|
200
|
|
|
201 static int
|
|
2054
|
202 fileio(FILE *fp, int i)
|
|
1615
|
203 {
|
|
2054
|
204 IOParam pb;
|
|
1615
|
205
|
|
|
206 pb.ioRefNum = fp->refnum;
|
|
|
207 switch (i) {
|
|
|
208
|
|
|
209 /* read */
|
|
|
210
|
|
|
211 case 0:
|
|
|
212 pb.ioBuffer = (Ptr) fp->ptr;
|
|
|
213 pb.ioReqCount = fp->cnt;
|
|
|
214 pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
|
|
|
215 pb.ioPosOffset = fp->pos - fp->cnt;
|
|
2054
|
216 PBReadSync((ParmBlkPtr)&pb);
|
|
1615
|
217 if (pb.ioResult == eofErr) {
|
|
|
218 fp->pos = pb.ioPosOffset;
|
|
|
219 if (fp->cnt = pb.ioActCount)
|
|
|
220 pb.ioResult = 0;
|
|
|
221 else {
|
|
|
222 fp->eof = 1;
|
|
|
223 return(EOF);
|
|
|
224 }
|
|
|
225 }
|
|
2054
|
226 if (!pb.ioResult && !fp->binary)
|
|
1615
|
227 replace(fp->ptr, fp->cnt, '\r', '\n');
|
|
|
228 break;
|
|
|
229
|
|
|
230 /* write */
|
|
|
231
|
|
|
232 case 1:
|
|
|
233 pb.ioBuffer = (Ptr) fp->ptr;
|
|
|
234 pb.ioReqCount = fp->cnt;
|
|
|
235 pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
|
|
|
236 if ((pb.ioPosOffset = fp->pos - fp->cnt) > fp->len) {
|
|
|
237 pb.ioMisc = (Ptr) pb.ioPosOffset;
|
|
2054
|
238 if (PBSetEOFSync((ParmBlkPtr)&pb) != noErr)
|
|
|
239 break;
|
|
1615
|
240 }
|
|
|
241 if (!fp->binary)
|
|
|
242 replace(fp->ptr, fp->cnt, '\n', '\r');
|
|
2054
|
243 PBWriteSync((ParmBlkPtr)&pb);
|
|
|
244 if (!pb.ioResult && pb.ioPosOffset > fp->len)
|
|
1615
|
245 fp->len = pb.ioPosOffset;
|
|
|
246 break;
|
|
|
247
|
|
|
248 /* close */
|
|
|
249
|
|
|
250 case 2:
|
|
|
251 pb.ioResult = close(fp);
|
|
|
252 break;
|
|
|
253 }
|
|
|
254
|
|
|
255 /* done */
|
|
|
256
|
|
|
257 if (pb.ioResult) {
|
|
2054
|
258 if (i < 2) {
|
|
|
259 fp->pos -= fp->cnt;
|
|
|
260 fp->cnt = 0;
|
|
|
261 }
|
|
1615
|
262 fp->err = 1;
|
|
|
263 errno = pb.ioResult;
|
|
|
264 return(EOF);
|
|
|
265 }
|
|
|
266 return(0);
|
|
|
267 }
|
|
|
268
|
|
|
269
|
|
|
270 static int
|
|
2054
|
271 close(FILE *fp)
|
|
1615
|
272 {
|
|
|
273 HFileParam pb;
|
|
|
274 Str255 buf;
|
|
|
275 register char *fcb = FCBSPtr + fp->refnum;
|
|
|
276 VCB *vcb = fcbVPtr(fcb);
|
|
|
277 register char *s;
|
|
2054
|
278 enum { none, MFS, HFS } del = none;
|
|
1615
|
279
|
|
|
280 pb.ioVRefNum = vcb->vcbVRefNum;
|
|
2054
|
281 if (fp->remove) {
|
|
|
282 pb.ioNamePtr = buf;
|
|
|
283 pb.ioFVersNum = 0;
|
|
1615
|
284
|
|
2054
|
285 /* close temporary file - HFS */
|
|
|
286
|
|
|
287 if (vcb->vcbSigWord == 0x4244) {
|
|
|
288 pb.ioDirID = fcbDirID(fcb);
|
|
|
289 s = fcbCName(fcb);
|
|
|
290 memcpy(buf, s, Length(s) + 1);
|
|
|
291 del = HFS;
|
|
|
292 }
|
|
1615
|
293
|
|
2054
|
294 /* close temporary file - MFS */
|
|
|
295
|
|
|
296 else if (vcb->vcbSigWord == 0xD2D7) {
|
|
|
297 for (pb.ioFDirIndex = 1; PBGetFInfoSync((ParmBlkPtr)&pb) == noErr; pb.ioFDirIndex++) {
|
|
|
298 if (pb.ioFRefNum == fp->refnum) {
|
|
|
299 del = MFS;
|
|
|
300 break;
|
|
|
301 }
|
|
|
302 }
|
|
1615
|
303 }
|
|
|
304 }
|
|
|
305
|
|
2054
|
306 /* close file and flush volume buffer */
|
|
1615
|
307
|
|
2054
|
308 pb.ioFRefNum = fp->refnum;
|
|
|
309 if (PBCloseSync((ParmBlkPtr)&pb) == noErr) {
|
|
|
310 if (del == MFS)
|
|
|
311 PBDeleteSync((ParmBlkPtr)&pb);
|
|
|
312 else if (del == HFS)
|
|
|
313 PBHDeleteSync((HParmBlkPtr)&pb);
|
|
|
314 pb.ioNamePtr = 0;
|
|
|
315 PBFlushVolSync((ParmBlkPtr)&pb);
|
|
1615
|
316 }
|
|
|
317 return(pb.ioResult);
|
|
|
318 }
|
|
|
319
|
|
|
320
|
|
|
321 /*
|
|
|
322 * replace - routine for doing CR/LF conversion
|
|
|
323 *
|
|
|
324 */
|
|
|
325
|
|
|
326 static void
|
|
2054
|
327 replace(register unsigned char *s, register size_t n, register int c1, register int c2)
|
|
1615
|
328 {
|
|
2054
|
329 #pragma options(honor_register)
|
|
1615
|
330 register unsigned char *t;
|
|
|
331
|
|
|
332 for (; n && (t = memchr(s, c1, n)); s = t) {
|
|
|
333 *t++ = c2;
|
|
|
334 n -= t - s;
|
|
|
335 }
|
|
|
336 }
|