/* Automatically generated from Squeak on #(21 October 2001 9:17:51 pm) */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Configuration options */
#include "sqConfig.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#include "FilePlugin.h"

/* memory access macros */
#define byteAt(i) (*((unsigned char *) (i)))
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
#define longAt(i) (*((int *) (i)))
#define longAtput(i, val) (*((int *) (i)) = val)

/*** Variables ***/
static struct VirtualMachine* interpreterProxy;
static const char *moduleName = "FilePlugin 21 October 2001 (i)";

/*** Function Prototypes ***/
static int asciiDirectoryDelimiter(void);
int fileRecordSize(void);
SQFile * fileValueOf(int objectPointer);
#pragma export on
EXPORT(const char*) FilePlugin_getModuleName(void);
EXPORT(int) FilePlugin_initialiseModule(void);
#pragma export off
static int makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, int entryNameSize, int createDate, int modifiedDate, int dirFlag, int fileSize);
#pragma export on
EXPORT(int) FilePlugin_primitiveDirectoryCreate(void);
EXPORT(int) FilePlugin_primitiveDirectoryDelete(void);
EXPORT(int) FilePlugin_primitiveDirectoryDelimitor(void);
EXPORT(int) FilePlugin_primitiveDirectoryGetMacTypeAndCreator(void);
EXPORT(int) FilePlugin_primitiveDirectoryLookup(void);
EXPORT(int) FilePlugin_primitiveDirectorySetMacTypeAndCreator(void);
EXPORT(int) FilePlugin_primitiveDisableFileAccess(void);
EXPORT(int) FilePlugin_primitiveFileAtEnd(void);
EXPORT(int) FilePlugin_primitiveFileClose(void);
EXPORT(int) FilePlugin_primitiveFileDelete(void);
EXPORT(int) FilePlugin_primitiveFileFlush(void);
EXPORT(int) FilePlugin_primitiveFileGetPosition(void);
EXPORT(int) FilePlugin_primitiveFileOpen(void);
EXPORT(int) FilePlugin_primitiveFileRead(void);
EXPORT(int) FilePlugin_primitiveFileRename(void);
EXPORT(int) FilePlugin_primitiveFileSetPosition(void);
EXPORT(int) FilePlugin_primitiveFileSize(void);
EXPORT(int) FilePlugin_primitiveFileTruncate(void);
EXPORT(int) FilePlugin_primitiveFileWrite(void);
EXPORT(int) FilePlugin_primitiveHasFileAccess(void);
EXPORT(int) FilePlugin_setInterpreter(struct VirtualMachine* anInterpreter);
EXPORT(int) FilePlugin_setMacFileTypeAndCreator(char * fileName, char * typeString, char * creatorString);
EXPORT(int) FilePlugin_shutdownModule(void);
#pragma export off

static int asciiDirectoryDelimiter(void) {
	return dir_Delimitor();
}


/*	Return the size of a Smalltalk file record in bytes. */

int fileRecordSize(void) {
	return sizeof(SQFile);
}


/*	Return a pointer to the first byte of of the file record within the given Smalltalk object, or nil if objectPointer is not a file record. */

SQFile * fileValueOf(int objectPointer) {
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		return null;
	}
	return interpreterProxy->firstIndexableField(objectPointer);
}


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

EXPORT(const char*) FilePlugin_getModuleName(void) {
	return moduleName;
}

EXPORT(int) FilePlugin_initialiseModule(void) {
	return sqFileInit();
}

static int makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, int entryNameSize, int createDate, int modifiedDate, int dirFlag, int fileSize) {
    char *stringPtr;
    int results;
    int i;
    int createDateOop;
    int modDateOop;
    int nameString;

	interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 5));
	interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), entryNameSize));
	interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(createDate));
	interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(modifiedDate));
	modDateOop = interpreterProxy->popRemappableOop();
	createDateOop = interpreterProxy->popRemappableOop();
	nameString = interpreterProxy->popRemappableOop();

	/* copy name into Smalltalk string */

	results = interpreterProxy->popRemappableOop();
	stringPtr = interpreterProxy->firstIndexableField(nameString);
	for (i = 0; i <= (entryNameSize - 1); i += 1) {
		stringPtr[i] = (entryName[i]);
	}
	interpreterProxy->storePointerofObjectwithValue(0, results, nameString);
	interpreterProxy->storePointerofObjectwithValue(1, results, createDateOop);
	interpreterProxy->storePointerofObjectwithValue(2, results, modDateOop);
	if (dirFlag) {
		interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->trueObject());
	} else {
		interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->falseObject());
	}
	interpreterProxy->storePointerofObjectwithValue(4, results, ((fileSize << 1) | 1));
	return results;
}

EXPORT(int) FilePlugin_primitiveDirectoryCreate(void) {
    int dirName;
    int dirNameSize;
    char * dirNameIndex;

	dirName = interpreterProxy->stackValue(0);
	if (!(interpreterProxy->isBytes(dirName))) {
		return interpreterProxy->primitiveFail();
	}
	dirNameIndex = interpreterProxy->firstIndexableField(dirName);
	dirNameSize = interpreterProxy->byteSizeOf(dirName);
	if (!(ioCanCreatePathOfSize(dirNameIndex, dirNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(dir_Create((char *) dirNameIndex, dirNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(1);
}

EXPORT(int) FilePlugin_primitiveDirectoryDelete(void) {
    int dirName;
    int dirNameSize;
    char * dirNameIndex;

	dirName = interpreterProxy->stackValue(0);
	if (!(interpreterProxy->isBytes(dirName))) {
		return interpreterProxy->primitiveFail();
	}
	dirNameIndex = interpreterProxy->firstIndexableField(dirName);
	dirNameSize = interpreterProxy->byteSizeOf(dirName);
	if (!(ioCanDeletePathOfSize(dirNameIndex, dirNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(dir_Delete((char *) dirNameIndex, dirNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(1);
}

EXPORT(int) FilePlugin_primitiveDirectoryDelimitor(void) {
    int ascii;

	ascii = asciiDirectoryDelimiter();
	if (!((ascii >= 0) && (ascii <= 255))) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(1);
	interpreterProxy->push(interpreterProxy->fetchPointerofObject(ascii, interpreterProxy->characterTable()));
}

EXPORT(int) FilePlugin_primitiveDirectoryGetMacTypeAndCreator(void) {
    int fileNameSize;
    int typeString;
    char * typeStringIndex;
    int fileName;
    char * creatorStringIndex;
    int creatorString;
    char * fileNameIndex;

	creatorString = interpreterProxy->stackValue(0);
	typeString = interpreterProxy->stackValue(1);
	fileName = interpreterProxy->stackValue(2);
	if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) {
		return interpreterProxy->primitiveFail();
	}
	if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(interpreterProxy->isBytes(fileName))) {
		return interpreterProxy->primitiveFail();
	}
	creatorStringIndex = interpreterProxy->firstIndexableField(creatorString);
	typeStringIndex = interpreterProxy->firstIndexableField(typeString);
	fileNameIndex = interpreterProxy->firstIndexableField(fileName);
	fileNameSize = interpreterProxy->byteSizeOf(fileName);
	if (!(ioCanGetFileTypeOfSize(fileNameIndex, fileNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(dir_GetMacFileTypeAndCreator(
			(char *) fileNameIndex, fileNameSize,
			(char *) typeStringIndex, (char *) creatorStringIndex))) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(3);
}

EXPORT(int) FilePlugin_primitiveDirectoryLookup(void) {
    char entryName[256];
    int pathNameSize;
    int status;
    int createDate;
    int dirFlag;
    int entryNameSize;
    int modifiedDate;
    int fileSize;
    int pathName;
    char * pathNameIndex;
    int index;

	index = interpreterProxy->stackIntegerValue(0);
	pathName = interpreterProxy->stackValue(1);
	if (!(interpreterProxy->isBytes(pathName))) {
		return interpreterProxy->primitiveFail();
	}
	pathNameIndex = interpreterProxy->firstIndexableField(pathName);
	pathNameSize = interpreterProxy->byteSizeOf(pathName);
	if (ioCanListPathOfSize(pathNameIndex, pathNameSize)) {
		status = dir_Lookup(
				(char *) pathNameIndex, pathNameSize, index,
				entryName, &entryNameSize, &createDate, &modifiedDate,
				&dirFlag, &fileSize);
	} else {
		status = 1;
	}
	if (interpreterProxy->failed()) {
		return null;
	}
	if (status == 1) {
		interpreterProxy->pop(3);
		interpreterProxy->push(interpreterProxy->nilObject());
		return null;
	}
	if (status == 2) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(3);
	interpreterProxy->push(makeDirEntryNamesizecreateDatemodDateisDirfileSize(entryName, entryNameSize, createDate, modifiedDate, dirFlag, fileSize));
}

EXPORT(int) FilePlugin_primitiveDirectorySetMacTypeAndCreator(void) {
    int fileNameSize;
    int typeString;
    char * typeStringIndex;
    int fileName;
    char * creatorStringIndex;
    int creatorString;
    char * fileNameIndex;

	creatorString = interpreterProxy->stackValue(0);
	typeString = interpreterProxy->stackValue(1);
	fileName = interpreterProxy->stackValue(2);
	if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) {
		return interpreterProxy->primitiveFail();
	}
	if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(interpreterProxy->isBytes(fileName))) {
		return interpreterProxy->primitiveFail();
	}
	creatorStringIndex = interpreterProxy->firstIndexableField(creatorString);
	typeStringIndex = interpreterProxy->firstIndexableField(typeString);
	fileNameIndex = interpreterProxy->firstIndexableField(fileName);
	fileNameSize = interpreterProxy->byteSizeOf(fileName);
	if (!(ioCanSetFileTypeOfSize(fileNameIndex, fileNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(dir_SetMacFileTypeAndCreator(
			(char *) fileNameIndex, fileNameSize,
			(char *) typeStringIndex, (char *) creatorStringIndex))) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop(3);
}

EXPORT(int) FilePlugin_primitiveDisableFileAccess(void) {
	ioDisableFileAccess();
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(1);
	}
}

EXPORT(int) FilePlugin_primitiveFileAtEnd(void) {
    int atEnd;
    SQFile * file;
    int objectPointer;

	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(0);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		atEnd = sqFileAtEnd(file);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
		interpreterProxy->pushBool(atEnd);
	}
}

EXPORT(int) FilePlugin_primitiveFileClose(void) {
    SQFile * file;
    int objectPointer;

	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(0);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		sqFileClose(file);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(1);
	}
}

EXPORT(int) FilePlugin_primitiveFileDelete(void) {
    char * nameIndex;
    int nameSize;
    int namePointer;

	namePointer = interpreterProxy->stackValue(0);
	if (!(interpreterProxy->isBytes(namePointer))) {
		return interpreterProxy->primitiveFail();
	}
	nameIndex = interpreterProxy->firstIndexableField(namePointer);
	nameSize = interpreterProxy->byteSizeOf(namePointer);
	if (!(ioCanDeleteFileOfSize(nameIndex, nameSize))) {
		return interpreterProxy->primitiveFail();
	}
	sqFileDeleteNameSize(((int) nameIndex), nameSize);
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(1);
	}
}

EXPORT(int) FilePlugin_primitiveFileFlush(void) {
    SQFile * file;
    int objectPointer;

	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(0);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		sqFileFlush(file);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(1);
	}
}

EXPORT(int) FilePlugin_primitiveFileGetPosition(void) {
    int position;
    SQFile * file;
    int objectPointer;

	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(0);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		position = sqFileGetPosition(file);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
		interpreterProxy->push(interpreterProxy->positive32BitIntegerFor(position));
	}
}

EXPORT(int) FilePlugin_primitiveFileOpen(void) {
    int writeFlag;
    char * nameIndex;
    int nameSize;
    int namePointer;
    int filePointer;
    SQFile * file;

	writeFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0));
	namePointer = interpreterProxy->stackValue(1);
	if (!(interpreterProxy->isBytes(namePointer))) {
		return interpreterProxy->primitiveFail();
	}
	filePointer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize());
	/* begin fileValueOf: */
	if (!((interpreterProxy->isBytes(filePointer)) && ((interpreterProxy->byteSizeOf(filePointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(filePointer);
l1:	/* end fileValueOf: */;
	nameIndex = interpreterProxy->firstIndexableField(namePointer);
	nameSize = interpreterProxy->byteSizeOf(namePointer);
	if (!(ioCanOpenFileOfSizeWritable(nameIndex, nameSize, writeFlag))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(interpreterProxy->failed())) {
		sqFileOpen(file, (int)nameIndex, nameSize, writeFlag);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(3);
		interpreterProxy->push(filePointer);
	}
}

EXPORT(int) FilePlugin_primitiveFileRead(void) {
    int byteSize;
    int bytesRead;
    int array;
    int startIndex;
    int count;
    char * arrayIndex;
    SQFile * file;
    int objectPointer;

	count = interpreterProxy->stackIntegerValue(0);
	startIndex = interpreterProxy->stackIntegerValue(1);
	array = interpreterProxy->stackValue(2);
	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(3);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->isWordsOrBytes(array))) {
		return interpreterProxy->primitiveFail();
	}
	if (interpreterProxy->isWords(array)) {
		byteSize = 4;
	} else {
		byteSize = 1;
	}
	if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) {
		return interpreterProxy->primitiveFail();
	}

	/* Note: adjust startIndex for zero-origin indexing */

	arrayIndex = interpreterProxy->firstIndexableField(array);
	bytesRead = sqFileReadIntoAt(file, count * byteSize, ((int) arrayIndex), (startIndex - 1) * byteSize);
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(5);
		interpreterProxy->pushInteger(bytesRead / byteSize);
	}
}

EXPORT(int) FilePlugin_primitiveFileRename(void) {
    char * newNameIndex;
    char * oldNameIndex;
    int newNamePointer;
    int oldNamePointer;
    int oldNameSize;
    int newNameSize;

	newNamePointer = interpreterProxy->stackValue(0);
	oldNamePointer = interpreterProxy->stackValue(1);
	if (!((interpreterProxy->isBytes(newNamePointer)) && (interpreterProxy->isBytes(oldNamePointer)))) {
		return interpreterProxy->primitiveFail();
	}
	newNameIndex = interpreterProxy->firstIndexableField(newNamePointer);
	newNameSize = interpreterProxy->byteSizeOf(newNamePointer);
	oldNameIndex = interpreterProxy->firstIndexableField(oldNamePointer);
	oldNameSize = interpreterProxy->byteSizeOf(oldNamePointer);
	if (!(ioCanRenameFileOfSize(oldNameIndex, oldNameSize))) {
		return interpreterProxy->primitiveFail();
	}
	sqFileRenameOldSizeNewSize(((int) oldNameIndex), oldNameSize, ((int) newNameIndex), newNameSize);
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
	}
}

EXPORT(int) FilePlugin_primitiveFileSetPosition(void) {
    int newPosition;
    SQFile * file;
    int objectPointer;

	newPosition = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0));
	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(1);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		sqFileSetPosition(file, newPosition);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
	}
}

EXPORT(int) FilePlugin_primitiveFileSize(void) {
    int size;
    SQFile * file;
    int objectPointer;

	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(0);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		size = sqFileSize(file);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
		interpreterProxy->push(interpreterProxy->positive32BitIntegerFor(size));
	}
}

EXPORT(int) FilePlugin_primitiveFileTruncate(void) {
    int truncatePosition;
    SQFile * file;
    int objectPointer;

	truncatePosition = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0));
	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(1);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->failed())) {
		sqFileTruncate(file, truncatePosition);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(2);
	}
}

EXPORT(int) FilePlugin_primitiveFileWrite(void) {
    int byteSize;
    int bytesWritten;
    int array;
    int startIndex;
    int count;
    char * arrayIndex;
    SQFile * file;
    int objectPointer;

	count = interpreterProxy->stackIntegerValue(0);
	startIndex = interpreterProxy->stackIntegerValue(1);
	array = interpreterProxy->stackValue(2);
	/* begin fileValueOf: */
	objectPointer = interpreterProxy->stackValue(3);
	if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) {
		interpreterProxy->primitiveFail();
		file = null;
		goto l1;
	}
	file = interpreterProxy->firstIndexableField(objectPointer);
l1:	/* end fileValueOf: */;
	if (!(interpreterProxy->isWordsOrBytes(array))) {
		return interpreterProxy->primitiveFail();
	}
	if (interpreterProxy->isWords(array)) {
		byteSize = 4;
	} else {
		byteSize = 1;
	}
	if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(interpreterProxy->failed())) {

		/* Note: adjust startIndex for zero-origin indexing */

		arrayIndex = interpreterProxy->firstIndexableField(array);
		bytesWritten = sqFileWriteFromAt(file, count * byteSize, ((int) arrayIndex), (startIndex - 1) * byteSize);
	}
	if (!(interpreterProxy->failed())) {
		interpreterProxy->pop(5);
		interpreterProxy->pushInteger(bytesWritten / byteSize);
	}
}

EXPORT(int) FilePlugin_primitiveHasFileAccess(void) {
	interpreterProxy->pop(1);
	interpreterProxy->pushBool(ioHasFileAccess());
}


/*	Note: This is coded so that is can be run from Squeak. */

EXPORT(int) FilePlugin_setInterpreter(struct VirtualMachine* anInterpreter) {
    int ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}


/*	Exported entry point for the VM. Needed for image saving only and no-op on anything but Macs. */

EXPORT(int) FilePlugin_setMacFileTypeAndCreator(char * fileName, char * typeString, char * creatorString) {
	return dir_SetMacFileTypeAndCreator(fileName, strlen(fileName), typeString, creatorString);
}

EXPORT(int) FilePlugin_shutdownModule(void) {
	return sqFileShutdown();
}
