⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macio.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include <string.h>#include <Types.h>#include <Files.h>#include <Devices.h>#include <Folders.h>#include <Errors.h>#include <Resources.h>#include <Processes.h>#include <TextUtils.h>#include <fcntl.h>#include "FullPath.h"		/* MoreFiles */#include "primpl.h"#include "MacErrorHandling.h"#include "mdmac.h"#include "macio.h"/* forward declarations */extern unsigned long gJanuaryFirst1970Seconds;extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);extern void DoneWaitingOnThisThread(PRThread *thread);extern void AsyncNotify(PRThread *thread);/* PB for Read and Write */struct ExtendedParamBlock {	/* PB must be first so that the file system can get the right data. */ 	ParamBlockRec 	pb;	PRThread 		*thread;};typedef struct ExtendedParamBlock ExtendedParamBlock;/* XXX Not done yet for 68K *//* I/O completion routne for _MD_READ and _MD_WRITE */static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr){    _PRCPU *cpu = _PR_MD_CURRENT_CPU();    PRThread *thread = pbAsyncPtr->thread;        PRIntn is;        if (_PR_MD_GET_INTSOFF()) {        thread->md.missedIONotify = PR_TRUE;        cpu->u.missed[cpu->where] |= _PR_MISSED_IO;    } else {        _PR_INTSOFF(is);        thread->md.osErrCode = noErr;        DoneWaitingOnThisThread(thread);        _PR_FAST_INTSON(is);    }    SignalIdleSemaphore();}void  _MD_SetError(OSErr oserror){    PRErrorCode code;    switch (oserror) {      case memFullErr:        code = PR_OUT_OF_MEMORY_ERROR;        break;      case fnfErr:        code = PR_FILE_NOT_FOUND_ERROR;        break;      case dupFNErr:        code = PR_FILE_EXISTS_ERROR;        break;      case ioErr:        code = PR_IO_ERROR;        break;      case nsvErr:      case wrgVolTypErr:        code = PR_INVALID_DEVICE_STATE_ERROR;        break;      case bdNamErr:      case fsRnErr:        code = PR_NAME_TOO_LONG_ERROR;        break;      case tmfoErr:        code = PR_INSUFFICIENT_RESOURCES_ERROR;        break;      case opWrErr:      case wrPermErr:      case permErr:      case afpAccessDenied:        code = PR_NO_ACCESS_RIGHTS_ERROR;        break;      case afpObjectTypeErr:        code = PR_DIRECTORY_LOOKUP_ERROR;        break;      case wPrErr:      case vLckdErr:        code = PR_DEVICE_IS_LOCKED_ERROR;        break;      case fLckdErr:        code = PR_FILE_IS_LOCKED_ERROR;        break;      case dirNFErr:        code = PR_NOT_DIRECTORY_ERROR;        break;      case dirFulErr:        code = PR_MAX_DIRECTORY_ENTRIES_ERROR;        break;      case dskFulErr:        code = PR_NO_DEVICE_SPACE_ERROR;        break;      case rfNumErr:      case fnOpnErr:        code = PR_BAD_DESCRIPTOR_ERROR;        break;      case eofErr:        code = PR_END_OF_FILE_ERROR;        break;      case posErr:      case gfpErr:        code = PR_FILE_SEEK_ERROR;        break;      case fBsyErr:        code = PR_FILE_IS_BUSY_ERROR;        break;      case extFSErr:        code = PR_REMOTE_FILE_ERROR;        break;      case abortErr:        code = PR_PENDING_INTERRUPT_ERROR;        break;      case paramErr:        code = PR_INVALID_ARGUMENT_ERROR;        break;      case unimpErr:        code = PR_NOT_IMPLEMENTED_ERROR;        break;    }    PR_SetError(code, oserror);}void _MD_IOInterrupt(void){    PRCList *qp;    PRThread *thread, *me = _PR_MD_CURRENT_THREAD();    PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);    _PR_SLEEPQ_LOCK(me->cpu);    qp = _PR_PAUSEQ(me->cpu).next;    while (qp != &_PR_PAUSEQ(me->cpu)) {		thread = _PR_THREAD_PTR(qp);		PR_ASSERT(thread->flags & _PR_ON_PAUSEQ);		qp = qp->next;				if (thread->md.missedIONotify) {			thread->md.missedIONotify = PR_FALSE;			DoneWaitingOnThisThread(thread);		}		if (thread->md.missedAsyncNotify) {			thread->md.missedAsyncNotify = PR_FALSE;			AsyncNotify(thread);		}    }    qp = _PR_SLEEPQ(me->cpu).next;    while (qp != &_PR_SLEEPQ(me->cpu)) {		thread = _PR_THREAD_PTR(qp);		PR_ASSERT(thread->flags & _PR_ON_SLEEPQ);		qp = qp->next;				if (thread->md.missedIONotify) {			thread->md.missedIONotify = PR_FALSE;			DoneWaitingOnThisThread(thread);		}		if (thread->md.missedAsyncNotify) {			thread->md.missedAsyncNotify = PR_FALSE;			AsyncNotify(thread);		}    }	_PR_SLEEPQ_UNLOCK(thread->cpu);}/* ** All PR_read and PR_Write calls are synchronous from caller's perspective.** They are internally made asynchronous calls.  This gives cpu to other** user threads while the async io is in progress.*/PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op){	PRInt32 refNum = fd->secret->md.osfd;	OSErr				err;	ExtendedParamBlock 	pbAsync;	PRThread			*me = _PR_MD_CURRENT_THREAD();	_PRCPU *cpu = _PR_MD_CURRENT_CPU();	/* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */	/* note, if a user chooses "seek" or the like as an operation in another function */	/* this will not work */	if (refNum >= 0 && refNum < 3)	{		switch (refNum)		{				case 0:					/* stdin - not on a Mac for now */					err = paramErr;					goto ErrorExit;					break;				case 1: /* stdout */				case 2: /* stderr */					puts(buf);					break;		}				return (bytes);	}	else	{		static IOCompletionUPP	sCompletionUPP = NULL;				PRBool  doingAsync = PR_FALSE;				/* allocate the callback Universal Procedure Pointer (UPP). This actually allocates		   a 32 byte Ptr in the heap, so only do this once		*/		if (!sCompletionUPP)			sCompletionUPP = NewIOCompletionUPP((IOCompletionProcPtr)&AsyncIOCompletion);					/* grab the thread so we know which one to post to at completion */		pbAsync.thread	= me;		pbAsync.pb.ioParam.ioCompletion	= sCompletionUPP;		pbAsync.pb.ioParam.ioResult		= noErr;		pbAsync.pb.ioParam.ioRefNum		= refNum;		pbAsync.pb.ioParam.ioBuffer		= buf;		pbAsync.pb.ioParam.ioReqCount	= bytes;		pbAsync.pb.ioParam.ioPosMode	= fsAtMark;		pbAsync.pb.ioParam.ioPosOffset	= 0;		/* 		** Issue the async read call and wait for the io semaphore associated		** with this thread.		** Async file system calls *never* return error values, so ignore their		** results (see <http://developer.apple.com/technotes/fl/fl_515.html>);		** the completion routine is always called.		*/		me->io_fd = refNum;		me->md.osErrCode = noErr;		if (op == READ_ASYNC)		{			/*			**  Skanky optimization so that reads < 20K are actually done synchronously			**  to optimize performance on small reads (e.g. registry reads on startup)			*/			if ( bytes > 20480L )			{				doingAsync = PR_TRUE;				me->io_pending = PR_TRUE;								(void)PBReadAsync(&pbAsync.pb);			}			else			{				pbAsync.pb.ioParam.ioCompletion = NULL;				me->io_pending = PR_FALSE;								err = PBReadSync(&pbAsync.pb);				if (err != noErr && err != eofErr)					goto ErrorExit;			}		}		else		{			doingAsync = PR_TRUE;			me->io_pending = PR_TRUE;			/* writes are currently always async */			(void)PBWriteAsync(&pbAsync.pb);		}				if (doingAsync) {			WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);		}	}		err = me->md.osErrCode;	if (err != noErr)		goto ErrorExit;	err = pbAsync.pb.ioParam.ioResult;	if (err != noErr && err != eofErr)		goto ErrorExit;		return pbAsync.pb.ioParam.ioActCount;ErrorExit:	me->md.osErrCode = err;	_MD_SetError(err);	return -1;}/*Special WriteSyncProc for logging only.  IO occurs synchronously.  Otherwise,logging internal to NSPR causes ReadWriteProc above to recurse on PR_WaitSem logging.*/PRInt32 WriteSyncProc(PRFileDesc *fd, void *buf, PRUint32 bytes){	PRInt32				refNum = fd->secret->md.osfd;	OSErr				err; 	ParamBlockRec 		pb;	PRThread			*me = _PR_MD_CURRENT_THREAD();		if (refNum >= 0 && refNum < 3)	{		PR_ASSERT(FALSE);	/* writing to these is hazardous to a Mac's health (refNum 2 is the system file) */		err = paramErr;		goto ErrorExit;	}	pb.ioParam.ioCompletion	= NULL;	pb.ioParam.ioResult		= noErr;	pb.ioParam.ioRefNum		= refNum;	pb.ioParam.ioBuffer		= buf;	pb.ioParam.ioReqCount	= bytes;	pb.ioParam.ioPosMode	= fsAtMark;	pb.ioParam.ioPosOffset	= 0;	err = PBWriteSync(&pb);	if (err != noErr)		goto ErrorExit;	else		return pb.ioParam.ioActCount;ErrorExit:	me->md.osErrCode = err;	_MD_SetError(err);    return -1;}/* File I/O functions called by PR I/O routines */PRInt32 _MD_Open(const char *path, PRIntn flags, int mode){// Macintosh doesn't really have mode bits, just drop them#pragma unused (mode)	OSErr 				err; 	HParamBlockRec 		hpb; 	ParamBlockRec 		pb;	char	 			*macFileName = NULL;	Str255				pascalName;	PRInt8 				perm;    err = ConvertUnixPathToMacPath(path, &macFileName);		if (err != noErr)		goto ErrorExit;	hpb.ioParam.ioCompletion	= NULL;	PStrFromCStr(macFileName, pascalName);	PR_DELETE(macFileName);	hpb.ioParam.ioNamePtr 	= pascalName;	hpb.ioParam.ioVRefNum 	= 0;	hpb.ioParam.ioVersNum 	= 0;	hpb.fileParam.ioDirID	= 0;	if (flags & PR_RDWR)		perm = fsRdWrPerm;	else if (flags & PR_WRONLY)		perm = fsWrPerm;	else		perm = fsRdPerm;		hpb.ioParam.ioPermssn 	= perm;	    if (flags & PR_CREATE_FILE) {		err = PBHCreateSync(&hpb);                      /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */       if ((flags & PR_EXCL) &&  (err == dupFNErr)) {           err = PR_FILE_EXISTS_ERROR;           goto ErrorExit;       }              if ((err != noErr) && (err != dupFNErr))          goto ErrorExit;	}     err = PBHOpenDFSync(&hpb);	if (err != noErr)		goto ErrorExit;	if (flags & PR_TRUNCATE) {		pb.ioParam.ioCompletion = NULL;		pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;		pb.ioParam.ioMisc = NULL;		err = PBSetEOFSync(&pb);		if (err != noErr)			goto ErrorExit;	} else if (flags & PR_APPEND) {		pb.ioParam.ioCompletion = NULL;		pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;		pb.ioParam.ioPosMode = fsFromLEOF;		pb.ioParam.ioPosOffset = 0;		err = PBSetFPosSync(&pb);		if (err != noErr)			goto ErrorExit;	}	return hpb.ioParam.ioRefNum;		ErrorExit:	_PR_MD_CURRENT_THREAD()->md.osErrCode = err;	_MD_SetError(err);    return -1;}/* _MD_CLOSE_FILE, _MD_READ, _MD_WRITE, _MD_GET_FILE_ERROR are defined in _macos.h */PROffset32 _MD_LSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence how){	PRInt32 refNum = fd->secret->md.osfd;	OSErr 	err = noErr;	long	curPos, endPos;	/* compute new mark */	switch (how) {		case PR_SEEK_SET:			endPos = offset;			break;				case PR_SEEK_CUR:			err = GetFPos(refNum, &curPos);			endPos = curPos + offset;			break;				case PR_SEEK_END:			err = GetEOF(refNum, &curPos);			endPos = curPos + offset;			break;		default:			err = paramErr;			break;	}	/* set the new mark and extend the file if seeking beyond current EOF */	/* making sure to set the mark after any required extend */	if (err == noErr) {		err = SetFPos(refNum, fsFromStart, endPos);		if (err == eofErr) {			err = SetEOF(refNum, endPos);			if (err == noErr) {				err = SetFPos(refNum, fsFromStart, endPos);			}		}	}	if (err == noErr) {		return endPos;	} else {		_PR_MD_CURRENT_THREAD()->md.osErrCode = err;	    _MD_SetError(err);		return -1;	}}PRInt32 _MD_FSync(PRFileDesc *fd){	PRInt32 refNum = fd->secret->md.osfd;	OSErr 	err; 	ParamBlockRec 		pb;	pb.ioParam.ioCompletion		= NULL;	pb.ioParam.ioRefNum 		= refNum;	err = PBFlushFileSync(&pb);	if (err != noErr)		goto ErrorExit;			return 0;ErrorExit:	_PR_MD_CURRENT_THREAD()->md.osErrCode = err;	_MD_SetError(err);    return -1;	}#include "plstr.h"PRStatus _MD_OpenDir(_MDDir *mdDir,const char *name){	// Emulate the Unix opendir() routine.	OSErr 				err; 	CInfoPBRec 			pb;	char				*macDirName = NULL;	char				*position = NULL;	char				volumeName[32];	Str255				pascalName;	// Get the Macintosh path	err = ConvertUnixPathToMacPath(name, &macDirName);	if (err != noErr)		goto ErrorExit;		// Get the vRefNum	position = PL_strchr(macDirName, PR_PATH_SEPARATOR);	if ((position == macDirName) || (position == NULL))		mdDir->ioVRefNum = 0;										// Use application relative searching	else {		memset(volumeName, 0, sizeof(volumeName));		strncpy(volumeName, macDirName, position-macDirName);		mdDir->ioVRefNum = GetVolumeRefNumFromName(volumeName);	}	// Get info about the object.	PStrFromCStr(macDirName, pascalName);	PR_DELETE(macDirName);		pb.dirInfo.ioNamePtr = pascalName;	pb.dirInfo.ioVRefNum = mdDir->ioVRefNum;	pb.dirInfo.ioDrDirID = 0;	pb.dirInfo.ioFDirIndex = 0;	err = PBGetCatInfoSync(&pb);	if (err != noErr)		goto ErrorExit;			// Are we dealing with a directory?	if ((pb.dirInfo.ioFlAttrib & ioDirMask) == 0) {		err = dirNFErr;		goto ErrorExit;	}		/* This is a directory, store away the pertinent information.	** We post increment.  I.e. index is always the nth. item we 	** should get on the next call	*/	mdDir->ioDirID = pb.dirInfo.ioDrDirID;	mdDir->currentEntryName = NULL;	mdDir->ioFDirIndex = 1;	return PR_SUCCESS;	ErrorExit:	_PR_MD_CURRENT_THREAD()->md.osErrCode = err;	_MD_SetError(err);    return PR_FAILURE;}char *_MD_ReadDir(_MDDir *mdDir, PRIntn flags){	// Emulate the Unix readdir() routine.	// Mac doesn誸 have the concept of .(PR_SKIP_DOT) & ..(PR_SKIP_DOT_DOT)	OSErr 				err;	CInfoPBRec			pb;	char				*returnedCStr;	Str255				pascalName = "\p";	PRBool				foundEntry;		PR_ASSERT(mdDir != NULL);	do {	// Release the last name read.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -