This is sqFilePrims.c in view mode; [Download] [Up]
#include "sq.h" /*** The state of a file is kept in the following structure, which is stored directly in a Squeak bytes object. NOTE: The Squeak side is responsible for creating an object with enough room to store sizeof(SQFile) bytes. The session ID is used to detect stale file objects-- files that were still open when an image was written. The file pointer of such files is meaningless. Files are always opened in binary mode; Smalltalk code does (or someday will do) line-end conversion if needed. Writeable files are opened read/write. The stdio spec requires that a positioning operation be done when switching between reading and writing of a read/write filestream. The lastOp field records whether the last operation was a read or write operation, allowing this positioning operation to be done automatically if needed. typedef struct { File *file; int sessionID; int writable; int fileSize; int lastOp; // 0 = uncommitted, 1 = read, 2 = write // } SQFile; ***/ /*** Constants ***/ #define UNCOMMITTED 0 #define READ_OP 1 #define WRITE_OP 2 #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif /*** Variables ***/ int thisSession = 0; int sqFileAtEnd(SQFile *f) { /* Return true if the file's read/write head is at the end of the file. */ if (!sqFileValid(f)) return success(false); return ftell(f->file) == f->fileSize; } int sqFileClose(SQFile *f) { /* Close the given file. */ if (!sqFileValid(f)) return success(false); fclose(f->file); f->file = NULL; f->sessionID = 0; f->writable = false; f->fileSize = 0; f->lastOp = UNCOMMITTED; } int sqFileDeleteNameSize(int sqFileNameIndex, int sqFileNameSize) { char cFileName[1000]; int i, err; if (sqFileNameSize >= 1000) { return success(false); } /* copy the file name into a null-terminated C string */ for (i = 0; i < sqFileNameSize; i++) { cFileName[i] = *((char *) (sqFileNameIndex + i)); } cFileName[sqFileNameSize] = 0; err = remove(cFileName); if (err) { return success(false); } } int sqFileGetPosition(SQFile *f) { /* Return the current position of the file's read/write head. */ int position; if (!sqFileValid(f)) return success(false); position = ftell(f->file); if (position < 0) return success(false); return position; } int sqFileInit(void) { /* Create a session ID that is unlikely to be repeated. Zero is never used for a valid session number. Should be called once at startup time. */ thisSession = clock() + time(NULL); if (thisSession == 0) thisSession = 1; /* don't use 0 */ } int sqFileOpen(SQFile *f, int sqFileNameIndex, int sqFileNameSize, int writeFlag) { /* Opens the given file using the supplied sqFile structure to record its state. Fails with no side effects if f is already open. Files are always opened in binary mode; Squeak must take care of any line-end character mapping. */ char cFileName[1001]; int i; /* don't open an already open file */ if (sqFileValid(f)) return success(false); /* copy the file name into a null-terminated C string */ if (sqFileNameSize > 1000) { return success(false); } for (i = 0; i < sqFileNameSize; i++) { cFileName[i] = *((char *) (sqFileNameIndex + i)); } cFileName[sqFileNameSize] = 0; if (writeFlag) { /* First try to open an existing file read/write: */ f->file = fopen(cFileName, "r+b"); if (f->file == NULL) { /* Previous call fails if file does not exist. In that case, try opening it in write mode to create a new, empty file. */ f->file = fopen(cFileName, "w+b"); if (f->file != NULL) { /* set the type and creator of newly created Mac files */ dir_SetMacFileTypeAndCreator(cFileName, strlen(cFileName), "TEXT", "R*ch"); } } f->writable = true; } else { f->file = fopen(cFileName, "rb"); f->writable = false; } if (f->file == NULL) { f->sessionID = 0; f->fileSize = 0; return success(false); } else { f->sessionID = thisSession; /* compute and cache file size */ fseek(f->file, 0, SEEK_END); f->fileSize = ftell(f->file); fseek(f->file, 0, SEEK_SET); } f->lastOp = UNCOMMITTED; } int sqFileReadIntoAt(SQFile *f, int count, int byteArrayIndex, int startIndex) { /* Read count bytes from the given file into byteArray starting at startIndex. byteArray is the address of the first byte of a Squeak bytes object (e.g. String or ByteArray). startIndex is a zero-based index; that is a startIndex of 0 starts writing at the first byte of byteArray. */ char *dst; int bytesRead; if (!sqFileValid(f)) return success(false); if (f->writable && (f->lastOp == WRITE_OP)) fseek(f->file, 0, SEEK_CUR); /* seek between writing and reading */ dst = (char *) (byteArrayIndex + startIndex); bytesRead = fread(dst, 1, count, f->file); f->lastOp = READ_OP; return bytesRead; } int sqFileRenameOldSizeNewSize(int oldNameIndex, int oldNameSize, int newNameIndex, int newNameSize) { char cOldName[1000], cNewName[1000]; int i, err; if ((oldNameSize >= 1000) || (newNameSize >= 1000)) { return success(false); } /* copy the file names into null-terminated C strings */ for (i = 0; i < oldNameSize; i++) { cOldName[i] = *((char *) (oldNameIndex + i)); } cOldName[oldNameSize] = 0; for (i = 0; i < newNameSize; i++) { cNewName[i] = *((char *) (newNameIndex + i)); } cNewName[newNameSize] = 0; err = rename(cOldName, cNewName); if (err) { return success(false); } } int sqFileSetPosition(SQFile *f, int position) { /* Set the file's read/write head to the given position. */ if (!sqFileValid(f)) return success(false); fseek(f->file, position, SEEK_SET); f->lastOp = UNCOMMITTED; } int sqFileSize(SQFile *f) { /* Return the length of the given file. */ if (!sqFileValid(f)) return success(false); return f->fileSize; } int sqFileValid(SQFile *f) { return ( (f != NULL) && (f->file != NULL) && (f->sessionID == thisSession)); } int sqFileWriteFromAt(SQFile *f, int count, int byteArrayIndex, int startIndex) { /* Write count bytes to the given writable file starting at startIndex in the given byteArray. (See comment in sqFileReadIntoAt for interpretation of byteArray and startIndex). */ char *src; int bytesWritten, position; if (!(sqFileValid(f) && f->writable)) return success(false); if (f->lastOp == READ_OP) fseek(f->file, 0, SEEK_CUR); /* seek between reading and writing */ src = (char *) (byteArrayIndex + startIndex); bytesWritten = fwrite(src, 1, count, f->file); position = ftell(f->file); if (position > f->fileSize) { f->fileSize = position; /* update file size */ } if (bytesWritten != count) { success(false); } f->lastOp = WRITE_OP; return bytesWritten; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.