blob: 04f192e434593fd099fb35f6a8a2ab4073a01bca [file] [log] [blame]
Guido van Rossumdc0493a1994-05-06 14:16:55 +00001
2/*
Guido van Rossum437a0e61995-01-02 19:13:30 +00003 * fopen.c
Guido van Rossumdc0493a1994-05-06 14:16:55 +00004 *
Guido van Rossum437a0e61995-01-02 19:13:30 +00005 * Copyright (c) 1991 Symantec Corporation. All rights reserved.
Guido van Rossumdc0493a1994-05-06 14:16:55 +00006 *
7 */
8
Guido van Rossum437a0e61995-01-02 19:13:30 +00009#include <MacHeaders>
10
Guido van Rossumdc0493a1994-05-06 14:16:55 +000011#include "stdio.h"
12#include "errno.h"
13#include "string.h"
14#include "ansi_private.h"
15
Guido van Rossum437a0e61995-01-02 19:13:30 +000016extern long _ftype, _fcreator;
Guido van Rossumdc0493a1994-05-06 14:16:55 +000017
18#define fcbVPtr(fcb) (* (VCB **) (fcb + 20))
19#define fcbDirID(fcb) (* (long *) (fcb + 58))
20#define fcbCName(fcb) (fcb + 62)
21
22static void setfiletype(StringPtr, int);
23static void stdio_exit(void);
24static int fileio(FILE *, int);
25static int close(FILE *);
26static void replace(unsigned char *, size_t, int, int);
27
Guido van Rossum437a0e61995-01-02 19:13:30 +000028FILE *freopenRF();
29FILE *__openRF();
Guido van Rossumdc0493a1994-05-06 14:16:55 +000030
31FILE *
Guido van Rossum437a0e61995-01-02 19:13:30 +000032fopenRF(const char *filename, const char *mode)
Guido van Rossumdc0493a1994-05-06 14:16:55 +000033{
34 return(freopenRF(filename, mode, __getfile()));
35}
36
37
38FILE *
Guido van Rossum437a0e61995-01-02 19:13:30 +000039freopenRF(const char *filename, const char *mode, FILE *fp)
Guido van Rossumdc0493a1994-05-06 14:16:55 +000040{
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
81FILE *
Guido van Rossum437a0e61995-01-02 19:13:30 +000082__openRF(const char *filename, int omode, int oflag, FILE *fp)
Guido van Rossumdc0493a1994-05-06 14:16:55 +000083{
Guido van Rossum437a0e61995-01-02 19:13:30 +000084 IOParam pb;
Guido van Rossumdc0493a1994-05-06 14:16:55 +000085 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) {
Guido van Rossum437a0e61995-01-02 19:13:30 +0000102 PBCreateSync((ParmBlkPtr)&pb);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000103 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
Guido van Rossum437a0e61995-01-02 19:13:30 +0000113 /* open file */
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000114
Guido van Rossum437a0e61995-01-02 19:13:30 +0000115 PBOpenRFSync((ParmBlkPtr)&pb);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000116 if (pb.ioResult) {
117 errno = pb.ioResult;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000118 if (oflag & F_CREAT)
119 PBDeleteSync((ParmBlkPtr)&pb);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000120 return(NULL);
121 }
122 fp->refnum = pb.ioRefNum;
123
124 /* get/set file length */
125
Guido van Rossum437a0e61995-01-02 19:13:30 +0000126 if (oflag & F_TRUNC)
127 PBSetEOFSync((ParmBlkPtr)&pb);
128 else if (!(oflag & F_CREAT))
129 PBGetEOFSync((ParmBlkPtr)&pb);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000130 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
160static void
Guido van Rossum437a0e61995-01-02 19:13:30 +0000161setfiletype(StringPtr name, int oflag)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000162{
Guido van Rossum437a0e61995-01-02 19:13:30 +0000163 FileParam pb;
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000164
165 pb.ioNamePtr = name;
166 pb.ioVRefNum = 0;
167 pb.ioFVersNum = 0;
168 pb.ioFDirIndex = 0;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000169 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);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000176 }
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000177}
178
179
180/*
181 * stdio_exit - stdio shutdown routine
182 *
183 */
184
185static void
Guido van Rossum437a0e61995-01-02 19:13:30 +0000186stdio_exit(void)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000187{
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
201static int
Guido van Rossum437a0e61995-01-02 19:13:30 +0000202fileio(FILE *fp, int i)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000203{
Guido van Rossum437a0e61995-01-02 19:13:30 +0000204 IOParam pb;
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000205
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;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000216 PBReadSync((ParmBlkPtr)&pb);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000217 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 }
Guido van Rossum437a0e61995-01-02 19:13:30 +0000226 if (!pb.ioResult && !fp->binary)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000227 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;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000238 if (PBSetEOFSync((ParmBlkPtr)&pb) != noErr)
239 break;
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000240 }
241 if (!fp->binary)
242 replace(fp->ptr, fp->cnt, '\n', '\r');
Guido van Rossum437a0e61995-01-02 19:13:30 +0000243 PBWriteSync((ParmBlkPtr)&pb);
244 if (!pb.ioResult && pb.ioPosOffset > fp->len)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000245 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) {
Guido van Rossum437a0e61995-01-02 19:13:30 +0000258 if (i < 2) {
259 fp->pos -= fp->cnt;
260 fp->cnt = 0;
261 }
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000262 fp->err = 1;
263 errno = pb.ioResult;
264 return(EOF);
265 }
266 return(0);
267}
268
269
270static int
Guido van Rossum437a0e61995-01-02 19:13:30 +0000271close(FILE *fp)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000272{
273 HFileParam pb;
274 Str255 buf;
275 register char *fcb = FCBSPtr + fp->refnum;
276 VCB *vcb = fcbVPtr(fcb);
277 register char *s;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000278 enum { none, MFS, HFS } del = none;
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000279
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000280 pb.ioVRefNum = vcb->vcbVRefNum;
Guido van Rossum437a0e61995-01-02 19:13:30 +0000281 if (fp->remove) {
282 pb.ioNamePtr = buf;
283 pb.ioFVersNum = 0;
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000284
Guido van Rossum437a0e61995-01-02 19:13:30 +0000285 /* 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 }
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000293
Guido van Rossum437a0e61995-01-02 19:13:30 +0000294 /* 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 }
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000303 }
304 }
305
Guido van Rossum437a0e61995-01-02 19:13:30 +0000306 /* close file and flush volume buffer */
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000307
Guido van Rossum437a0e61995-01-02 19:13:30 +0000308 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);
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000316 }
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000317 return(pb.ioResult);
318}
319
320
321/*
322 * replace - routine for doing CR/LF conversion
323 *
324 */
325
326static void
Guido van Rossum437a0e61995-01-02 19:13:30 +0000327replace(register unsigned char *s, register size_t n, register int c1, register int c2)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000328{
Guido van Rossum437a0e61995-01-02 19:13:30 +0000329#pragma options(honor_register)
Guido van Rossumdc0493a1994-05-06 14:16:55 +0000330 register unsigned char *t;
331
332 for (; n && (t = memchr(s, c1, n)); s = t) {
333 *t++ = c2;
334 n -= t - s;
335 }
336}