blob: f18f7d9a6672376fd4b744a323406123d2ab849c [file] [log] [blame]
Guido van Rossumdc0493a1994-05-06 14:16:55 +00001
2/*
3 * fopenRF.c -- Clone of fopen.c to open Mac resource forks.
4 *
5 * Copyright (c) 1989 Symantec Corporation. All rights reserved.
6 *
7 */
8
9#include "stdio.h"
10#include "errno.h"
11#include "string.h"
12#include "ansi_private.h"
13
14FILE *fopenRF(char *, char *);
15FILE *freopenRF(char *, char *, FILE *);
16FILE *__openRF(char *, int, int, FILE *);
17
18#include <Files.h>
19
20#define fcbVPtr(fcb) (* (VCB **) (fcb + 20))
21#define fcbDirID(fcb) (* (long *) (fcb + 58))
22#define fcbCName(fcb) (fcb + 62)
23
24static void setfiletype(StringPtr, int);
25static void stdio_exit(void);
26static int fileio(FILE *, int);
27static int close(FILE *);
28static void replace(unsigned char *, size_t, int, int);
29
30
31FILE *
32fopenRF(filename, mode)
33char *filename, *mode;
34{
35 return(freopenRF(filename, mode, __getfile()));
36}
37
38
39FILE *
40freopenRF(filename, mode, fp)
41char *filename;
42register char *mode;
43register FILE *fp;
44{
45 int omode, oflag;
46
47 /* interpret "rwa" */
48
49 if (mode[0] == 'r') {
50 omode = fsRdPerm;
51 oflag = 0;
52 }
53 else if (mode[0] == 'w') {
54 omode = fsWrPerm;
55 oflag = F_CREAT+F_TRUNC;
56 }
57 else if (mode[0] == 'a') {
58 omode = fsWrPerm;
59 oflag = F_CREAT+F_APPEND;
60 }
61 else {
62 errno = EINVAL;
63 return(NULL);
64 }
65
66 /* interpret "b+" */
67
68 if (mode[1] == 'b') {
69 oflag |= F_BINARY;
70 if (mode[2] == '+')
71 omode = fsRdWrPerm;
72 }
73 else if (mode[1] == '+') {
74 omode = fsRdWrPerm;
75 if (mode[2] == 'b')
76 oflag |= F_BINARY;
77 }
78
79 /* open the file */
80
81 return(__openRF(filename, omode, oflag, fp));
82}
83
84
85FILE *
86__openRF(filename, omode, oflag, fp)
87char *filename;
88int omode, oflag;
89register FILE *fp;
90{
91 ioParam pb;
92 char pname[FILENAME_MAX];
93
94 if (fp == NULL)
95 return(NULL);
96 fclose(fp);
97
98 /* set up pb */
99
100 pb.ioNamePtr = __c2p(filename, pname);
101 pb.ioVRefNum = 0;
102 pb.ioVersNum = 0;
103 pb.ioPermssn = omode;
104 pb.ioMisc = 0;
105
106 /* create file */
107
108 if (oflag & F_CREAT) {
109 asm {
110 lea pb,a0
111 _PBCreate
112 }
113 if (pb.ioResult == noErr)
114 oflag &= ~F_TRUNC;
115 else if (pb.ioResult == dupFNErr && !(oflag & F_EXCL))
116 oflag &= ~F_CREAT;
117 else {
118 errno = pb.ioResult;
119 return(NULL);
120 }
121 }
122
123 /* open resource file */
124
125 asm {
126 lea pb,a0
127 _PBOpenRF
128 }
129 if (pb.ioResult) {
130 errno = pb.ioResult;
131 if (oflag & F_CREAT) asm {
132 lea pb,a0
133 _PBDelete
134 }
135 return(NULL);
136 }
137 fp->refnum = pb.ioRefNum;
138
139 /* get/set file length */
140
141 if (oflag & F_TRUNC) asm {
142 lea pb,a0
143 _PBSetEOF
144 }
145 else if (!(oflag & F_CREAT)) asm {
146 lea pb,a0
147 _PBGetEOF
148 }
149 fp->len = (fpos_t) pb.ioMisc;
150
151 /* initialize rest of FILE structure */
152
153 if (oflag & F_APPEND) {
154 fp->append = 1;
155 fp->pos = fp->len;
156 }
157 if (oflag & F_BINARY)
158 fp->binary = 1;
159 setvbuf(fp, NULL, _IOFBF, BUFSIZ);
160 fp->proc = fileio;
161
162 /* set file type */
163
164 if (oflag & (F_CREAT|F_TRUNC))
165 setfiletype(pb.ioNamePtr, oflag);
166
167 /* done */
168
169 __atexit_stdio(stdio_exit);
170 return(fp);
171}
172
173
174/*
175 * setfiletype - set type/creator of new file
176 *
177 */
178
179static void
180setfiletype(name, oflag)
181StringPtr name;
182int oflag;
183{
184 fileParam pb;
185
186 pb.ioNamePtr = name;
187 pb.ioVRefNum = 0;
188 pb.ioFVersNum = 0;
189 pb.ioFDirIndex = 0;
190 asm {
191 lea pb,a0
192 _PBGetFInfo
193 bmi.s @1
194 }
195 pb.ioFlFndrInfo.fdType = pb.ioFlFndrInfo.fdCreator = '????';
196 if (!(oflag & F_BINARY))
197 pb.ioFlFndrInfo.fdType = 'TEXT';
198 asm {
199 lea pb,a0
200 _PBSetFInfo
201@1 }
202}
203
204
205/*
206 * stdio_exit - stdio shutdown routine
207 *
208 */
209
210static void
211stdio_exit()
212{
213 register FILE *fp;
214 int n;
215
216 for (fp = &__file[0], n = FOPEN_MAX; n--; fp++)
217 fclose(fp);
218}
219
220
221/*
222 * fileio - I/O handler proc for files and devices
223 *
224 */
225
226static int
227fileio(fp, i)
228register FILE *fp;
229int i;
230{
231 ioParam pb;
232
233 pb.ioRefNum = fp->refnum;
234 switch (i) {
235
236 /* read */
237
238 case 0:
239 pb.ioBuffer = (Ptr) fp->ptr;
240 pb.ioReqCount = fp->cnt;
241 pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
242 pb.ioPosOffset = fp->pos - fp->cnt;
243 asm {
244 lea pb,a0
245 _PBRead
246 }
247 if (pb.ioResult == eofErr) {
248 fp->pos = pb.ioPosOffset;
249 if (fp->cnt = pb.ioActCount)
250 pb.ioResult = 0;
251 else {
252 fp->eof = 1;
253 return(EOF);
254 }
255 }
256 if (pb.ioResult) {
257 fp->pos -= fp->cnt;
258 fp->cnt = 0;
259 }
260 else if (!fp->binary)
261 replace(fp->ptr, fp->cnt, '\r', '\n');
262 break;
263
264 /* write */
265
266 case 1:
267 pb.ioBuffer = (Ptr) fp->ptr;
268 pb.ioReqCount = fp->cnt;
269 pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
270 if ((pb.ioPosOffset = fp->pos - fp->cnt) > fp->len) {
271 pb.ioMisc = (Ptr) pb.ioPosOffset;
272 asm {
273 lea pb,a0
274 _PBSetEOF
275 bmi.s @1
276 }
277 }
278 if (!fp->binary)
279 replace(fp->ptr, fp->cnt, '\n', '\r');
280 asm {
281 lea pb,a0
282 _PBWrite
283@1 }
284 if (pb.ioResult) {
285 fp->pos -= fp->cnt;
286 fp->cnt = 0;
287 }
288 else if (pb.ioPosOffset > fp->len)
289 fp->len = pb.ioPosOffset;
290 break;
291
292 /* close */
293
294 case 2:
295 pb.ioResult = close(fp);
296 break;
297 }
298
299 /* done */
300
301 if (pb.ioResult) {
302 fp->err = 1;
303 errno = pb.ioResult;
304 return(EOF);
305 }
306 return(0);
307}
308
309
310static int
311close(fp)
312register FILE *fp;
313{
314 HFileParam pb;
315 Str255 buf;
316 register char *fcb = FCBSPtr + fp->refnum;
317 VCB *vcb = fcbVPtr(fcb);
318 register char *s;
319
320 pb.ioNamePtr = buf;
321 pb.ioFRefNum = fp->refnum;
322 pb.ioVRefNum = vcb->vcbVRefNum;
323 pb.ioFVersNum = 0;
324
325 /* close temporary file - HFS */
326
327 if (fp->delete && vcb->vcbSigWord == 0x4244) {
328 pb.ioDirID = fcbDirID(fcb);
329 s = fcbCName(fcb);
330 asm {
331 lea buf,a0
332 moveq #0,d0
333 move.b (s),d0
334@1 move.b (s)+,(a0)+
335 dbra d0,@1
336 lea pb,a0
337 _PBClose
338 bmi.s @9
339 _PBHDelete
340 }
341 }
342
343 /* close temporary file - MFS */
344
345 else if (fp->delete && vcb->vcbSigWord == 0xD2D7) {
346 pb.ioFDirIndex = 1;
347 do asm {
348 lea pb,a0
349 _PBGetFInfo
350 bmi.s @2
351 addq.w #1,pb.ioFDirIndex
352 } while (pb.ioFRefNum != fp->refnum);
353 asm {
354 lea pb,a0
355 _PBClose
356 bmi.s @9
357 _PBDelete
358 }
359 }
360
361 /* normal case - just close file */
362
363 else {
364 asm {
365@2 lea pb,a0
366 _PBClose
367 bmi.s @9
368 }
369 }
370
371 /* flush volume buffer */
372
373 pb.ioNamePtr = 0;
374 asm {
375 lea pb,a0
376 _PBFlshVol
377@9 }
378 return(pb.ioResult);
379}
380
381
382/*
383 * replace - routine for doing CR/LF conversion
384 *
385 */
386
387static void
388replace(s, n, c1, c2)
389register unsigned char *s;
390register size_t n;
391register int c1, c2;
392{
393 register unsigned char *t;
394
395 for (; n && (t = memchr(s, c1, n)); s = t) {
396 *t++ = c2;
397 n -= t - s;
398 }
399}