int asyncFileWriteStart(AsyncFile *f, int fPosition, void *bufferPtr, int bufferSize) { /* Start an asynchronous operation to write bufferSize bytes to the given file starting at the given file position. The file's semaphore will be signalled when the operation is complete. The client may then use asyncFileWriteResult() to find out if the operation succeeded and how many bytes were actually written. */ AsyncFileState *state; OSErr err; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return success(false); /* operation in progress */ if (!state->writable) return success(false); /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, bufferSize); if (state->bufferPtr == nil) return success(false); /* could not allocate buffer */ /* copy the squeak buffer into the file buffer */ memcpy(state->bufferPtr, bufferPtr, bufferSize); asyncFileInitPB(state, fPosition); err = PBWriteAsync(&state->pb); if (err != noErr) { state->status = IDLE; return success(false); } return 0; }
int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize) { /* Start an asynchronous operation to write bufferSize bytes to the given file starting at the given file position. The file''s semaphore will be signalled when the operation is complete. The client may then use asyncFileWriteResult() to find out if the operation succeeded and how many bytes were actually written. */ AsyncFileState *state = (AsyncFileState *) f->state; if (!asyncFileValid(f)) return success(false); if (state->status == BUSY) return success(false); /* operation in progress */ if (!state->writable) return success(false); /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, bufferSize); if (state->bufferPtr == NULL) return success(false); /* could not allocate buffer */ /* copy the squeak buffer into the file buffer */ MoveMemory((void*)state->bufferPtr, (void*) bufferPtr, bufferSize); state->dwPosition = fPosition; state->dwSize = bufferSize; state->status = BUSY; state->rFlag = FALSE; SetEvent(state->hEvent); return 1; }
int asyncFileReadStart(AsyncFile *f, int fPosition, int count) { /* Start an asynchronous operation to read count bytes from the given file starting at the given file position. The file's semaphore will be signalled when the operation is complete. The client may then use asyncFileReadResult() to find out if the operation succeeded and to get the data that was read. */ AsyncFileState *state; OSErr err; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return success(false); /* operation in progress */ /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, count); if (state->bufferPtr == nil) return success(false); /* could not allocate buffer */ asyncFileInitPB(state, fPosition); err = PBReadAsync(&state->pb); if (err != noErr) { state->status = IDLE; success(false); return 0; } return 0; }
int asyncFileClose(AsyncFile *f) { /* Close the given asynchronous file. */ AsyncFileState *state; short int volRefNum; OSErr err; if (!asyncFileValid(f)) return 0; /* already closed */ state = f->state; err = GetVRefNum(state->refNum, &volRefNum); success(err == noErr); err = FSClose(state->refNum); success(err == noErr); if (!interpreterProxy->failed()) err = FlushVol(NULL, volRefNum); success(err == noErr); if (asyncFileCompletionProc != nil) DisposeIOCompletionUPP(asyncFileCompletionProc); asyncFileCompletionProc = nil; if (state->bufferPtr != nil) DisposePtr(state->bufferPtr); DisposePtr((void *) f->state); f->state = nil; f->sessionID = 0; return 0; }
int asyncFileClose(AsyncFile *f) { /* Close the given asynchronous file. */ AsyncFileState *state; if (!asyncFileValid(f)) return 0; /* already closed */ state = (AsyncFileState*) f->state; if(!CloseHandle(state->hFile)) { printLastError(TEXT("AsyncFileClose failed")); success(false); } state->hFile = INVALID_HANDLE_VALUE; SetEvent(state->hEvent); WaitForSingleObject(state->hThread, 5000); if(state->hThread) { warnPrintf(TEXT("Terminating async thread")); TerminateThread(state->hThread,0); } CloseHandle(state->hEvent); if (state->bufferPtr != NULL) asyncFree(state->bufferPtr); free((void *) f->state); f->state = NULL; f->sessionID = 0; return 1; }
int asyncFileWriteResult(AsyncFile *f) { /* Return the number of bytes copied by the last write operation. Negative values indicate: -1 -- busy; the last operation has not finished yet -2 -- error; the last operation failed */ AsyncFileState *state = (AsyncFileState *) f->state; if (!asyncFileValid(f)) return success(false); if (state->status == BUSY) return -1; if (state->status == LAST_OP_FAILED) return -2; return state->bytesTransferred; }
int asyncFileReadStart(AsyncFile *f, int fPosition, int count) { /* Start an asynchronous operation to read count bytes from the given file starting at the given file position. The file''s semaphore will be signalled when the operation is complete. The client may then use asyncFileReadResult() to find out if the operation succeeded and to get the data that was read. */ AsyncFileState *state = (AsyncFileState *) f->state; if (!asyncFileValid(f)) return success(false); if (state->status == BUSY) return success(false); /* operation in progress */ /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, count); if (state->bufferPtr == NULL) return success(false); /* could not allocate buffer */ state->dwPosition = fPosition; state->dwSize = count; state->status = BUSY; state->rFlag = TRUE; SetEvent(state->hEvent); return 1; }
int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize) { /* Copy up to bufferSize bytes from the buffer of the last read operation into the given Squeak buffer, and return the number of bytes copied. Negative values indicate: -1 -- busy; the last operation has not finished yet -2 -- error; the last operation failed Note that a read operation may read fewer bytes than requested if, for example, there are fewer than the requested number of bytes between the starting file position of the read operation and the end-of-file. */ AsyncFileState *state = (AsyncFileState *) f->state; int bytesRead; if (!asyncFileValid(f)) return success(false); if (state->status == BUSY) return -1; if (state->status == LAST_OP_FAILED) return -2; /* copy the file buffer into the squeak buffer */ bytesRead = (bufferSize < state->bytesTransferred) ? bufferSize : state->bytesTransferred; MoveMemory((void *) bufferPtr, (void *)state->bufferPtr, bytesRead); return bytesRead; }
int asyncFileOpen(AsyncFile *f, char *fileNamePtr, int fileNameSize, int writeFlag, int semaIndex) { /* Opens the given file using the supplied AsyncFile structure to record its state. Fails with no side effects if f is already open. Files are always opened in binary mode. */ short int fileRefNum; AsyncFileState *state; OSErr err; void * ithisSessionfn; int thisSession; FSSpec theSpec; /* don't open an already open file */ if (asyncFileValid(f)) return success(false); /* build complete routine descriptor, if necessary */ if (asyncFileCompletionProc == nil) { #if TARGET_API_MAC_CARBON asyncFileCompletionProc = NewIOCompletionUPP((pascal void (*) (union ParamBlockRec *) )asyncFileCompletionRoutine); #else asyncFileCompletionProc = NewIOCompletionProc((pascal void (*) (union ParamBlockRec *) )asyncFileCompletionRoutine); #endif } /* copy the file name into a null-terminated C string */ if (fileNameSize > 1000) return success(false); makeFSSpec((char*) fileNamePtr, fileNameSize,&theSpec); f->sessionID = 0; if (writeFlag) { /* first try to open an existing file read/write: */ err = FSpOpenDF(&theSpec,fsRdWrPerm, &fileRefNum); if (err != noErr) { /* file does not exist; must create it. */ err = FSpCreate(&theSpec,'R*ch','TEXT',smSystemScript); if (err != noErr) return success(false); err = FSpOpenDF(&theSpec,fsRdWrPerm, &fileRefNum); if (err != noErr) return success(false); } } else { /* open the file read-only */ err = FSpOpenDF(&theSpec,fsRdPerm, &fileRefNum); if (err != noErr) return success(false); } f->state = (AsyncFileState *) NewPtr(sizeof(AsyncFileState)); /* allocate state record */ if (f->state == nil) { FSClose(fileRefNum); return success(false); } ithisSessionfn = interpreterProxy->ioLoadFunctionFrom("getThisSession", "FilePlugin"); if (ithisSessionfn != 0) thisSession = ((int (*) (void)) ithisSessionfn)(); else thisSession = 0; f->sessionID = thisSession; state = (AsyncFileState *) f->state; state->refNum = fileRefNum; state->writable = writeFlag; state->semaIndex = semaIndex; state->status = IDLE; state->bytesTransferred = 0; state->bufferSize = 0; state->bufferPtr = nil; return 0; }
int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex) { /* Opens the given file using the supplied AsyncFile structure to record its state. Fails with no side effects if f is already open. Files are always opened in binary mode. */ int i; char cFileName[256]; WCHAR wFileName[256]; AsyncFileState *state; HANDLE hFile; DWORD id; /* don''t open an already open file */ if (asyncFileValid(f)) return success(false); /* copy the file name into a null-terminated C string */ if (fileNameSize > 255) return success(false); for (i = 0; i < fileNameSize; i++) { cFileName[i] = *((char *) (fileNamePtr + i)); } cFileName[fileNameSize] = 0; /* Convert to Unicode */ MultiByteToWideChar(CP_UTF8, 0, cFileName, -1, wFileName, 255); f->sessionID = 0; hFile = CreateFileW(wFileName, writeFlag ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, writeFlag ? FILE_SHARE_READ : (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, /* No security descriptor */ writeFlag ? OPEN_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /* No template */); if(hFile == INVALID_HANDLE_VALUE) return success(false); f->state = (AsyncFileState *) calloc(1,sizeof(AsyncFileState)); /* allocate state record */ if (f->state == NULL) { CloseHandle(hFile); return success(false); } f->sessionID = thisSession; state = (AsyncFileState *) f->state; state->hFile = hFile; state->writable = writeFlag; state->semaIndex = semaIndex; state->status = IDLE; state->bytesTransferred = 0; state->bufferSize = 0; state->bufferPtr = NULL; state->hEvent = CreateEvent(NULL, 0, 0, NULL); state->hThread = CreateThread(NULL, /* No security descriptor */ 0, /* default stack size */ (LPTHREAD_START_ROUTINE) &sqAsyncFileThread, /* what to do */ (LPVOID) state, /* parameter for thread */ CREATE_SUSPENDED, /* create suspended */ &id); /* return value for thread id */ if(!state->hThread) { printLastError(TEXT("CreateThread() failed")); return success(false); } /* file operations run with high priority */ if(!SetThreadPriority(state->hThread, THREAD_PRIORITY_HIGHEST)) printLastError(TEXT("SetThreadPriority() failed")); if(!ResumeThread(state->hThread)) { printLastError(TEXT("ResumeThread() failed")); return success(false); } return 1; }