--- a/Win32OperatingSystem.st Tue Dec 11 18:10:28 2001 +0100
+++ b/Win32OperatingSystem.st Tue Dec 11 18:43:56 2001 +0100
@@ -44,6 +44,20 @@
privateIn:Win32OperatingSystem
!
+OSFileHandle subclass:#Win32FILEHandle
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:Win32OperatingSystem
+!
+
+OSFileHandle subclass:#Win32Handle
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:Win32OperatingSystem
+!
+
!Win32OperatingSystem primitiveDefinitions!
%{
@@ -1173,7 +1187,7 @@
case ERROR_INVALID_HANDLE:
sym = @symbol(ERROR_INVALID_HANDLE);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_NOT_ENOUGH_MEMORY:
@@ -1188,12 +1202,12 @@
case ERROR_INVALID_DATA:
sym = @symbol(ERROR_INVALID_DATA);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_INVALID_NAME:
sym = @symbol(ERROR_INVALID_NAME);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_ARENA_TRASHED:
@@ -1252,7 +1266,7 @@
case ERROR_INVALID_PARAMETER:
sym = @symbol(ERROR_INVALID_PARAMETER);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_NET_WRITE_FAULT:
@@ -1297,7 +1311,7 @@
case ERROR_INVALID_DRIVE:
sym = @symbol(ERROR_INVALID_DRIVE);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_WRONG_DISK:
@@ -1307,7 +1321,7 @@
case ERROR_CURRENT_DIRECTORY:
sym = @symbol(ERROR_CURRENT_DIRECTORY);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
/*
@@ -1331,7 +1345,7 @@
case ERROR_NOT_DOS_DISK:
sym = @symbol(ERROR_NOT_DOS_DISK);
- typ = @symbol(invalidArgumentSignal);
+ typ = @symbol(invalidArgumentsSignal);
break;
case ERROR_OUT_OF_PAPER:
@@ -3111,6 +3125,14 @@
"Modified: 29.6.1996 / 14:06:54 / cg"
!
+createFileForReadAppend:pathName
+ ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
+createFileForReadWrite:pathName
+ ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
linkFile:oldPath to:newPath
"link the file 'oldPath' to 'newPath'. The link will be a hard link.
Return true if successful, false if not."
@@ -3132,6 +3154,125 @@
"
!
+openFile:pathName attributes:attributeSpec
+ "non public internal helper.
+ open a file, return an os specific fileHandle.
+ attributes is a collection of symbols specifying how the file is
+ to be opened."
+
+ |fileHandle errorNumber|
+
+ fileHandle := Win32Handle new.
+
+%{
+ HANDLE h;
+ char *name;
+ OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
+ int numAttrib = __arraySize(attributeSpec);
+ int i;
+ DWORD access, share, create, attr;
+
+ if (! __isString(pathName)) {
+ fileHandle = nil;
+ goto badArgument;
+ }
+ if (! __isArray(attributeSpec)) {
+ fileHandle = nil;
+ goto badArgument;
+ }
+
+ name = __stringVal(pathName);
+
+ share = 0;
+ access = 0;
+ create = 0;
+ attr = 0;
+
+ for (i=0; i<numAttrib;i++) {
+ OBJ attrSym = ap[i];
+
+ if (attrSym == @symbol(FILE_SHARE_READ)) {
+ share |= FILE_SHARE_READ;
+ } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
+ share |= FILE_SHARE_WRITE;
+
+ } else if (attrSym == @symbol(GENERIC_READ)) {
+ access |= GENERIC_READ;
+ } else if (attrSym == @symbol(GENERIC_WRITE)) {
+ access |= GENERIC_WRITE;
+
+ } else if (attrSym == @symbol(CREATE_NEW)) {
+ create |= CREATE_NEW;
+ } else if (attrSym == @symbol(CREATE_ALWAYS)) {
+ create |= CREATE_ALWAYS;
+ } else if (attrSym == @symbol(OPEN_EXISTING)) {
+ create |= OPEN_EXISTING;
+ } else if (attrSym == @symbol(OPEN_ALWAYS)) {
+ create |= OPEN_ALWAYS;
+ } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
+ create |= TRUNCATE_EXISTING;
+
+ } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
+ attr |= FILE_ATTRIBUTE_HIDDEN;
+ } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
+ attr |= FILE_ATTRIBUTE_READONLY;
+ } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
+ attr |= FILE_ATTRIBUTE_READONLY;
+ } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
+ attr |= FILE_FLAG_WRITE_THROUGH;
+ } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
+ attr |= FILE_FLAG_SEQUENTIAL_SCAN;
+ } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
+ attr |= FILE_FLAG_DELETE_ON_CLOSE;
+ } else {
+ fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
+ }
+ }
+fprintf(stderr, "name:<%s> access:%x share:%x create:%x attr:%x\n",
+ name, access, share, create, attr);
+
+ h = CreateFile(name, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
+ if (h != INVALID_HANDLE_VALUE) {
+ __externalAddressVal(fileHandle) = (void *)h;
+ } else {
+ fileHandle = nil;
+ errorNumber = __MKSMALLINT( __WIN32_ERR(GetLastError()) );
+ }
+
+badArgument: ;
+%}.
+ fileHandle notNil ifTrue:[
+ fileHandle registerForFinalization.
+ ^ fileHandle.
+ ].
+ errorNumber isNil ifTrue:[
+ self error:'invalid argument(s)'.
+ ] ifFalse:[
+ (self errorHolderForNumber:errorNumber) reportError
+ ].
+ self halt.
+!
+
+openFileForAppend:pathName
+ ^ self halt
+!
+
+openFileForRead:pathName
+ ^ self openFile:pathName attributes:#(#'GENERIC_READ')
+!
+
+openFileForReadAppend:pathName
+ ^ self halt
+!
+
+openFileForReadWrite:pathName
+ ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
+openFileForWrite:pathName
+ ^ self openFile:pathName attributes:#(#'GENERIC_WRITE')
+!
+
recursiveCopyDirectory:sourcePathName to:destination
"copy the directory named 'sourcePathName' and all contained files/directories to 'destination'.
Return true if successful."
@@ -8370,9 +8511,283 @@
"Created: / 19.5.1999 / 21:45:05 / cg"
! !
+!Win32OperatingSystem::Win32FILEHandle class methodsFor:'documentation'!
+
+documentation
+"
+ I represent a FILE*, as used in the stdio library.
+ Since most stdio libs are inherently buggy, thread-unsave
+ and hard to use in a multithreading environment,
+ these will no longer be used in future ST/X versions.
+ However, they may be useful when interfacing to external
+ libraries...
+"
+!
+
+version
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
+! !
+
+!Win32OperatingSystem::Win32FILEHandle methodsFor:'release'!
+
+closeFile
+ "close the file"
+
+%{
+ FILE *f = (FILE *)(__externalAddressVal(self));
+
+ if (f) {
+ __externalAddressVal(self) = NULL;
+ fclose(f);
+ }
+%}.
+! !
+
+!Win32OperatingSystem::Win32Handle class methodsFor:'documentation'!
+
+documentation
+"
+ I represent a generic HANDLE, which can be closed via CloseHandle.
+"
+!
+
+version
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
+! !
+
+!Win32OperatingSystem::Win32Handle methodsFor:'io'!
+
+readBytes:count into:aByteBuffer startingAt:firstIndex
+ "read count bytes into a byte-buffer;
+ Return the number of bytes read (negative on error)"
+
+%{
+#if 0
+ unsigned char *extPtr;
+ int nRead = -1;
+ INT fd = (INT)(__externalAddressVal(self));
+ INT cnt, offs;
+ int nInstBytes, objSize;
+
+ if (! __bothSmallInteger(count, firstIndex)) {
+ goto bad;
+ }
+ cnt = __smallIntegerVal(count);
+ offs = __smallIntegerVal(firstIndex) - 1;
+
+ if (fd < 0) {
+ goto bad;
+ }
+ if (__isExternalBytes(aByteBuffer)) {
+ OBJ sz;
+
+ nInstBytes = 0;
+ extPtr = (char *)(__externalBytesAddress(aByteBuffer));
+ sz = __externalBytesSize(aByteBuffer);
+ if (__isSmallInteger(sz)) {
+ objSize = __smallIntegerVal(sz);
+ } else {
+ objSize = -1; /* unknown */
+ }
+ } else {
+ OBJ oClass;
+ int nInstVars;
+
+ oClass = __Class(aByteBuffer);
+ switch (__smallIntegerVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+ case BYTEARRAY:
+ case WORDARRAY:
+ case LONGARRAY:
+ case SWORDARRAY:
+ case SLONGARRAY:
+ case FLOATARRAY:
+ case DOUBLEARRAY:
+ break;
+ default:
+ goto bad;
+ }
+ extPtr = (char *)0;
+ nInstVars = __smallIntegerVal(__ClassInstPtr(oClass)->c_ninstvars);
+ nInstBytes = __OBJS2BYTES__(nInstVars);
+ objSize = __Size(aByteBuffer) - OHDR_SIZE - nInstBytes;
+ }
+ if ((offs >= 0)
+ && (cnt >= 0)
+ && ((objSize == -1) || (objSize >= (cnt + offs)))) {
+ nRead = 0;
+
+ do {
+ int n;
+
+ if (extPtr) {
+ n = read(fd, extPtr+offs, cnt);
+ } else {
+ char *bp;
+
+ /*
+ * on interrupt, anObject may be moved to another location.
+ * So we recompute the byte-address here.
+ */
+ bp = __ByteArrayInstPtr(aByteBuffer)->ba_element + nInstBytes;
+
+ n = read(fd, bp + offs, cnt);
+ }
+ if (n > 0) {
+ cnt -= n;
+ offs += n;
+ nRead += n;
+ } else {
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+ }
+ } while (cnt > 0);
+
+ RETURN (__mkSmallInteger(nRead));
+ }
+bad: ;
+#endif
+%}.
+ ^ self primitiveFailed
+
+ "
+ |h buff n|
+
+ h := self basicNew.
+ h setFileDescriptor:0.
+ buff := ByteArray new:10. buff inspect.
+ n := h readBytes:10 into:buff startingAt:1.
+ Transcript show:n; space; showCR:buff.
+ "
+!
+
+writeBytes:count from:aByteBuffer startingAt:firstIndex
+ "write count bytes from a byte-buffer;
+ Return the number of bytes written (negative on error)"
+
+%{
+#if 0
+ unsigned char *extPtr;
+ int nWritten = -1;
+ INT fd = (INT)(__externalAddressVal(self));
+ INT cnt, offs;
+ int nInstBytes, objSize;
+
+ if (! __bothSmallInteger(count, firstIndex)) {
+ goto bad;
+ }
+ cnt = __smallIntegerVal(count);
+ offs = __smallIntegerVal(firstIndex) - 1;
+
+ if (fd < 0) {
+ goto bad;
+ }
+ if (__isExternalBytes(aByteBuffer)) {
+ OBJ sz;
+
+ nInstBytes = 0;
+ extPtr = (char *)(__externalBytesAddress(aByteBuffer));
+ sz = __externalBytesSize(aByteBuffer);
+ if (__isSmallInteger(sz)) {
+ objSize = __smallIntegerVal(sz);
+ } else {
+ objSize = -1; /* unknown */
+ }
+ } else {
+ OBJ oClass;
+ int nInstVars;
+
+ oClass = __Class(aByteBuffer);
+ switch (__smallIntegerVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+ case BYTEARRAY:
+ case WORDARRAY:
+ case LONGARRAY:
+ case SWORDARRAY:
+ case SLONGARRAY:
+ case FLOATARRAY:
+ case DOUBLEARRAY:
+ break;
+ default:
+ goto bad;
+ }
+ extPtr = (char *)0;
+ nInstVars = __smallIntegerVal(__ClassInstPtr(oClass)->c_ninstvars);
+ nInstBytes = __OBJS2BYTES__(nInstVars);
+ objSize = __Size(aByteBuffer) - OHDR_SIZE - nInstBytes;
+ }
+ if ((offs >= 0)
+ && (cnt >= 0)
+ && ((objSize == -1) || (objSize >= (cnt + offs)))) {
+ nWritten = 0;
+
+ do {
+ int n;
+
+ if (extPtr) {
+ n = write(fd, extPtr+offs, cnt);
+ } else {
+ char *bp;
+
+ /*
+ * on interrupt, anObject may be moved to another location.
+ * So we recompute the byte-address here.
+ */
+ bp = __ByteArrayInstPtr(aByteBuffer)->ba_element + nInstBytes;
+
+ n = write(fd, bp + offs, cnt);
+ }
+ if (n > 0) {
+ cnt -= n;
+ offs += n;
+ nWritten += n;
+ } else {
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+ }
+ } while (cnt > 0);
+
+ RETURN (__mkSmallInteger(nWritten));
+ }
+bad: ;
+#endif
+%}.
+ ^ self primitiveFailed
+
+ "
+ |h buff n|
+
+ h := self basicNew.
+ h setFileDescriptor:1.
+ buff := '12345678901234567890'.
+ n := h writeBytes:10 from:buff startingAt:1.
+ "
+! !
+
+!Win32OperatingSystem::Win32Handle methodsFor:'release'!
+
+closeFile
+ "close the handle"
+
+%{
+ HANDLE h = (HANDLE)(__externalAddressVal(self));
+
+ if (h) {
+ __externalAddressVal(self) = (HANDLE)0;
+ CloseHandle(h);
+ }
+%}.
+! !
+
!Win32OperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.101 2001-12-11 16:04:05 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
! !
Win32OperatingSystem initialize!