mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 01:47:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			336 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			336 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /*
 | |
|  *  fopen.c
 | |
|  *
 | |
|  *  Copyright (c) 1991 Symantec Corporation.  All rights reserved.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <MacHeaders>
 | |
| 
 | |
| #include "stdio.h"
 | |
| #include "errno.h"
 | |
| #include "string.h"
 | |
| #include "ansi_private.h"
 | |
| 
 | |
| extern long _ftype, _fcreator;
 | |
| 
 | |
| #define fcbVPtr(fcb)		(* (VCB **) (fcb + 20))
 | |
| #define fcbDirID(fcb)		(* (long *) (fcb + 58))
 | |
| #define fcbCName(fcb)		(fcb + 62)
 | |
| 
 | |
| static void setfiletype(StringPtr, int);
 | |
| static void stdio_exit(void);
 | |
| static int fileio(FILE *, int);
 | |
| static int close(FILE *);
 | |
| static void replace(unsigned char *, size_t, int, int);
 | |
| 
 | |
| FILE *freopenRF();
 | |
| FILE *__openRF();
 | |
| 
 | |
| FILE *
 | |
| fopenRF(const char *filename, const char *mode)
 | |
| {
 | |
| 	return(freopenRF(filename, mode, __getfile()));
 | |
| }
 | |
| 
 | |
| 
 | |
| FILE *
 | |
| freopenRF(const char *filename, const char *mode, FILE *fp)
 | |
| {
 | |
| 	int omode, oflag;
 | |
| 	
 | |
| 		/*  interpret "rwa"  */
 | |
| 	
 | |
| 	if (mode[0] == 'r') {
 | |
| 		omode = fsRdPerm;
 | |
| 		oflag = 0;
 | |
| 	}
 | |
| 	else if (mode[0] == 'w') {
 | |
| 		omode = fsWrPerm;
 | |
| 		oflag = F_CREAT+F_TRUNC;
 | |
| 	}
 | |
| 	else if (mode[0] == 'a') {
 | |
| 		omode = fsWrPerm;
 | |
| 		oflag = F_CREAT+F_APPEND;
 | |
| 	}
 | |
| 	else {
 | |
| 		errno = EINVAL;
 | |
| 		return(NULL);
 | |
| 	}
 | |
| 		
 | |
| 		/*  interpret "b+"  */
 | |
| 		
 | |
| 	if (mode[1] == 'b') {
 | |
| 		oflag |= F_BINARY;
 | |
| 		if (mode[2] == '+')
 | |
| 			omode = fsRdWrPerm;
 | |
| 	}
 | |
| 	else if (mode[1] == '+') {
 | |
| 		omode = fsRdWrPerm;
 | |
| 		if (mode[2] == 'b')
 | |
| 			oflag |= F_BINARY;
 | |
| 	}
 | |
| 	
 | |
| 		/*  open the file  */
 | |
| 		
 | |
| 	return(__openRF(filename, omode, oflag, fp));
 | |
| }
 | |
| 
 | |
| 
 | |
| FILE *
 | |
| __openRF(const char *filename, int omode, int oflag, FILE *fp)
 | |
| {
 | |
| 	IOParam pb;
 | |
| 	char pname[FILENAME_MAX];
 | |
| 
 | |
| 	if (fp == NULL)
 | |
| 		return(NULL);
 | |
| 	fclose(fp);
 | |
| 	
 | |
| 		/*  set up pb  */
 | |
| 	
 | |
| 	pb.ioNamePtr = __c2p(filename, pname);
 | |
| 	pb.ioVRefNum = 0;
 | |
| 	pb.ioVersNum = 0;
 | |
| 	pb.ioPermssn = omode;
 | |
| 	pb.ioMisc = 0;
 | |
| 
 | |
| 		/*  create file  */
 | |
| 
 | |
| 	if (oflag & F_CREAT) {
 | |
| 		PBCreateSync((ParmBlkPtr)&pb);
 | |
| 		if (pb.ioResult == noErr)
 | |
| 			oflag &= ~F_TRUNC;
 | |
| 		else if (pb.ioResult == dupFNErr && !(oflag & F_EXCL))
 | |
| 			oflag &= ~F_CREAT;
 | |
| 		else {
 | |
| 			errno = pb.ioResult;
 | |
| 			return(NULL);
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 		/*  open file  */
 | |
| 		
 | |
| 	PBOpenRFSync((ParmBlkPtr)&pb);
 | |
| 	if (pb.ioResult) {
 | |
| 		errno = pb.ioResult;
 | |
| 		if (oflag & F_CREAT)
 | |
| 			PBDeleteSync((ParmBlkPtr)&pb);
 | |
| 		return(NULL);
 | |
| 	}
 | |
| 	fp->refnum = pb.ioRefNum;
 | |
| 	
 | |
| 		/*  get/set file length  */
 | |
| 		
 | |
| 	if (oflag & F_TRUNC)
 | |
| 		PBSetEOFSync((ParmBlkPtr)&pb);
 | |
| 	else if (!(oflag & F_CREAT))
 | |
| 		PBGetEOFSync((ParmBlkPtr)&pb);
 | |
| 	fp->len = (fpos_t) pb.ioMisc;
 | |
| 		
 | |
| 		/*  initialize rest of FILE structure  */
 | |
| 		
 | |
| 	if (oflag & F_APPEND) {
 | |
| 		fp->append = 1;
 | |
| 		fp->pos = fp->len;
 | |
| 	}
 | |
| 	if (oflag & F_BINARY)
 | |
| 		fp->binary = 1;
 | |
| 	setvbuf(fp, NULL, _IOFBF, BUFSIZ);
 | |
| 	fp->proc = fileio;
 | |
| 
 | |
| 		/*  set file type  */
 | |
| 
 | |
| 	if (oflag & (F_CREAT|F_TRUNC))
 | |
| 		setfiletype(pb.ioNamePtr, oflag);
 | |
| 		
 | |
| 		/*  done  */
 | |
| 		
 | |
| 	__atexit_stdio(stdio_exit);
 | |
| 	return(fp);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  setfiletype - set type/creator of new file
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static void
 | |
| setfiletype(StringPtr name, int oflag)
 | |
| {
 | |
| 	FileParam pb;
 | |
| 	
 | |
| 	pb.ioNamePtr = name;
 | |
| 	pb.ioVRefNum = 0;
 | |
| 	pb.ioFVersNum = 0;
 | |
| 	pb.ioFDirIndex = 0;
 | |
| 	if (PBGetFInfoSync((ParmBlkPtr)&pb) == noErr) {
 | |
| 		if (oflag & F_BINARY)
 | |
| 			pb.ioFlFndrInfo.fdType = _ftype;
 | |
| 		else
 | |
| 			pb.ioFlFndrInfo.fdType = 'TEXT';
 | |
| 		pb.ioFlFndrInfo.fdCreator = _fcreator;
 | |
| 		PBSetFInfoSync((ParmBlkPtr)&pb);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  stdio_exit - stdio shutdown routine
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static void
 | |
| stdio_exit(void)
 | |
| {
 | |
| 	register FILE *fp;
 | |
| 	int n;
 | |
| 	
 | |
| 	for (fp = &__file[0], n = FOPEN_MAX; n--; fp++)
 | |
| 		fclose(fp);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  fileio - I/O handler proc for files and devices
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static int
 | |
| fileio(FILE *fp, int i)
 | |
| {
 | |
| 	IOParam pb;
 | |
| 	
 | |
| 	pb.ioRefNum = fp->refnum;
 | |
| 	switch (i) {
 | |
| 	
 | |
| 				/*  read  */
 | |
| 			
 | |
| 		case 0:
 | |
| 			pb.ioBuffer = (Ptr) fp->ptr;
 | |
| 			pb.ioReqCount = fp->cnt;
 | |
| 			pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
 | |
| 			pb.ioPosOffset = fp->pos - fp->cnt;
 | |
| 			PBReadSync((ParmBlkPtr)&pb);
 | |
| 			if (pb.ioResult == eofErr) {
 | |
| 				fp->pos = pb.ioPosOffset;
 | |
| 				if (fp->cnt = pb.ioActCount)
 | |
| 					pb.ioResult = 0;
 | |
| 				else {
 | |
| 					fp->eof = 1;
 | |
| 					return(EOF);
 | |
| 				}
 | |
| 			}
 | |
| 			if (!pb.ioResult && !fp->binary)
 | |
| 				replace(fp->ptr, fp->cnt, '\r', '\n');
 | |
| 			break;
 | |
| 			
 | |
| 				/*  write  */
 | |
| 
 | |
| 		case 1:
 | |
| 			pb.ioBuffer = (Ptr) fp->ptr;
 | |
| 			pb.ioReqCount = fp->cnt;
 | |
| 			pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
 | |
| 			if ((pb.ioPosOffset = fp->pos - fp->cnt) > fp->len) {
 | |
| 				pb.ioMisc = (Ptr) pb.ioPosOffset;
 | |
| 				if (PBSetEOFSync((ParmBlkPtr)&pb) != noErr)
 | |
| 					break;
 | |
| 			}
 | |
| 			if (!fp->binary)
 | |
| 				replace(fp->ptr, fp->cnt, '\n', '\r');
 | |
| 			PBWriteSync((ParmBlkPtr)&pb);
 | |
| 			if (!pb.ioResult && pb.ioPosOffset > fp->len)
 | |
| 				fp->len = pb.ioPosOffset;
 | |
| 			break;
 | |
| 			
 | |
| 				/*  close  */
 | |
| 
 | |
| 		case 2:
 | |
| 			pb.ioResult = close(fp);
 | |
| 			break;
 | |
| 	}
 | |
| 	
 | |
| 		/*  done  */
 | |
| 		
 | |
| 	if (pb.ioResult) {
 | |
| 		if (i < 2) {
 | |
| 			fp->pos -= fp->cnt;
 | |
| 			fp->cnt = 0;
 | |
| 		}
 | |
| 		fp->err = 1;
 | |
| 		errno = pb.ioResult;
 | |
| 		return(EOF);
 | |
| 	}
 | |
| 	return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| close(FILE *fp)
 | |
| {
 | |
| 	HFileParam pb;
 | |
| 	Str255 buf;
 | |
| 	register char *fcb = FCBSPtr + fp->refnum;
 | |
| 	VCB *vcb = fcbVPtr(fcb);
 | |
| 	register char *s;
 | |
| 	enum { none, MFS, HFS } del = none;
 | |
| 	
 | |
| 	pb.ioVRefNum = vcb->vcbVRefNum;
 | |
| 	if (fp->remove) {
 | |
| 		pb.ioNamePtr = buf;
 | |
| 		pb.ioFVersNum = 0;
 | |
| 	
 | |
| 			/*  close temporary file - HFS  */
 | |
| 			
 | |
| 		if (vcb->vcbSigWord == 0x4244) {
 | |
| 			pb.ioDirID = fcbDirID(fcb);
 | |
| 			s = fcbCName(fcb);
 | |
| 			memcpy(buf, s, Length(s) + 1);
 | |
| 			del = HFS;
 | |
| 		}
 | |
| 		
 | |
| 			/*  close temporary file - MFS  */
 | |
| 			
 | |
| 		else if (vcb->vcbSigWord == 0xD2D7) {
 | |
| 			for (pb.ioFDirIndex = 1; PBGetFInfoSync((ParmBlkPtr)&pb) == noErr; pb.ioFDirIndex++) {
 | |
| 				if (pb.ioFRefNum == fp->refnum) {
 | |
| 					del = MFS;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 		/*  close file and flush volume buffer  */
 | |
| 	
 | |
| 	pb.ioFRefNum = fp->refnum;
 | |
| 	if (PBCloseSync((ParmBlkPtr)&pb) == noErr) {
 | |
| 		if (del == MFS)
 | |
| 			PBDeleteSync((ParmBlkPtr)&pb);
 | |
| 		else if (del == HFS)
 | |
| 			PBHDeleteSync((HParmBlkPtr)&pb);
 | |
| 		pb.ioNamePtr = 0;
 | |
| 		PBFlushVolSync((ParmBlkPtr)&pb);
 | |
| 	}
 | |
| 	return(pb.ioResult);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  replace - routine for doing CR/LF conversion
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static void
 | |
| replace(register unsigned char *s, register size_t n, register int c1, register int c2)
 | |
| {
 | |
| #pragma options(honor_register)
 | |
| 	register unsigned char *t;
 | |
| 	
 | |
| 	for (; n && (t = memchr(s, c1, n)); s = t) {
 | |
| 		*t++ = c2;
 | |
| 		n -= t - s;
 | |
| 	}
 | |
| }
 | 
