FileStream.st
branchjv
changeset 18678 a9b30d72dff9
parent 18421 5e7e40d367f2
parent 18651 36567dd3b8d1
child 18786 237a87b4fe8f
equal deleted inserted replaced
18677:1cb0a8a0b66b 18678:a9b30d72dff9
   233     (stupid enough, this is the default for textfiles as created by some tools ...)
   233     (stupid enough, this is the default for textfiles as created by some tools ...)
   234     Therefore, the instance variable canPosition is set according to
   234     Therefore, the instance variable canPosition is set according to
   235     this and an error is raised, if a position: is attemted.
   235     this and an error is raised, if a position: is attemted.
   236     I know, this is ugly, but what else could we do ?
   236     I know, this is ugly, but what else could we do ?
   237     Late note: who cares for VMS these days?
   237     Late note: who cares for VMS these days?
   238                (and how much useless effort has been put in the past,
   238 	       (and how much useless effort has been put in the past,
   239                 to support lousy operating systems?)
   239 		to support lousy operating systems?)
   240 
   240 
   241     [instance variables:]
   241     [instance variables:]
   242         pathName        <String>        the file's path (if known)
   242 	pathName        <String>        the file's path (if known)
   243         canPosition     <Boolean>       positionable - read above comment
   243 	canPosition     <Boolean>       positionable - read above comment
   244 
   244 
   245     [author:]
   245     [author:]
   246         Claus Gittinger
   246 	Claus Gittinger
   247 
   247 
   248     [see also:]
   248     [see also:]
   249         Filename DirectoryStream PipeStream Socket
   249 	Filename DirectoryStream PipeStream Socket
   250 "
   250 "
   251 !
   251 !
   252 
   252 
   253 examples
   253 examples
   254 "
   254 "
   447      See also: #newTemporary which looks for a good temp directory."
   447      See also: #newTemporary which looks for a good temp directory."
   448 
   448 
   449     |nameString random prevRandom prevNameString newTempFilename stream|
   449     |nameString random prevRandom prevNameString newTempFilename stream|
   450 
   450 
   451     [
   451     [
   452         prevRandom := random.
   452 	prevRandom := random.
   453         prevNameString := nameString.
   453 	prevNameString := nameString.
   454 
   454 
   455         "Use random numbers in order to improve the security
   455 	"Use random numbers in order to improve the security
   456          by making the generated names less predictable"
   456 	 by making the generated names less predictable"
   457         [
   457 	[
   458             random := RandomGenerator new nextInteger.
   458 	    random := RandomGenerator new nextInteger.
   459         ] doWhile:[random = prevRandom].
   459 	] doWhile:[random = prevRandom].
   460 
   460 
   461         nameString := template bindWith:(OperatingSystem getProcessId) with:random.
   461 	nameString := template bindWith:(OperatingSystem getProcessId) with:random.
   462 
   462 
   463         aDirectoryOrNil isNil ifTrue:[
   463 	aDirectoryOrNil isNil ifTrue:[
   464             newTempFilename := nameString.
   464 	    newTempFilename := nameString.
   465         ] ifFalse:[
   465 	] ifFalse:[
   466             newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
   466 	    newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
   467         ].
   467 	].
   468 
   468 
   469         [
   469 	[
   470             stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE).
   470 	    stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE).
   471         ] on:OpenError do:[:ex|
   471 	] on:OpenError do:[:ex|
   472            ex errorCategory ~~ #existingReferentSignal ifTrue:[
   472 	   ex errorCategory ~~ #existingReferentSignal ifTrue:[
   473                 "some fundamental error, raise exception"
   473 		"some fundamental error, raise exception"
   474                 ex reject.
   474 		ex reject.
   475             ].
   475 	    ].
   476             prevNameString = nameString ifTrue:[
   476 	    prevNameString = nameString ifTrue:[
   477                 "no more names - probably a bad template"
   477 		"no more names - probably a bad template"
   478                 ex reject.
   478 		ex reject.
   479             ].
   479 	    ].
   480             "file exists, retry another one"
   480 	    "file exists, retry another one"
   481         ].
   481 	].
   482     ] doWhile:[
   482     ] doWhile:[
   483         stream isNil and:[prevNameString ~= nameString]   "/ if namestring didn't change, the template is bad
   483 	stream isNil and:[prevNameString ~= nameString]   "/ if namestring didn't change, the template is bad
   484     ].
   484     ].
   485     ^ stream
   485     ^ stream
   486 
   486 
   487     "temp files in '/tmp':
   487     "temp files in '/tmp':
   488 
   488 
   489         FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
   489 	FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
   490 
   490 
   491      This must fail on the second try:
   491      This must fail on the second try:
   492         FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
   492 	FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
   493         FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
   493 	FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
   494     "
   494     "
   495 
   495 
   496     "temp files somewhere
   496     "temp files somewhere
   497      (not recommended - use above since it can be controlled via shell variables):
   497      (not recommended - use above since it can be controlled via shell variables):
   498 
   498 
   891     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   891     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   892      support mmap-like operations as from-fd.
   892      support mmap-like operations as from-fd.
   893      Therefore, this method is reimplemented here (from ExternalStream)"
   893      Therefore, this method is reimplemented here (from ExternalStream)"
   894 
   894 
   895     outStream isExternalStream ifTrue:[
   895     outStream isExternalStream ifTrue:[
   896         pos := self position.
   896 	pos := self position.
   897         n := self size - pos.
   897 	n := self size - pos.
   898         nWritten := OperatingSystem
   898 	nWritten := OperatingSystem
   899                         copyFromFd:self fileDescriptor
   899 			copyFromFd:self fileDescriptor
   900                         toFd:outStream fileDescriptor
   900 			toFd:outStream fileDescriptor
   901                         startIndex:pos
   901 			startIndex:pos
   902                         count:n.
   902 			count:n.
   903         nWritten > 0 ifTrue:[
   903 	nWritten > 0 ifTrue:[
   904             self position:pos+nWritten.
   904 	    self position:pos+nWritten.
   905         ].
   905 	].
   906         nWritten = n ifTrue:[
   906 	nWritten = n ifTrue:[
   907             ^ self
   907 	    ^ self
   908         ].
   908 	].
   909     ].
   909     ].
   910     ^ super copyToEndInto:outStream bufferSize:bufferSize.
   910     ^ super copyToEndInto:outStream bufferSize:bufferSize.
   911 
   911 
   912     "
   912     "
   913      |in out|
   913      |in out|
   934     OBJ fp = __INST(handle);
   934     OBJ fp = __INST(handle);
   935     FILE *f;
   935     FILE *f;
   936     off_t truncateSize;
   936     off_t truncateSize;
   937 
   937 
   938     if ((fp != nil) && (__INST(mode) != @symbol(readonly))) {
   938     if ((fp != nil) && (__INST(mode) != @symbol(readonly))) {
   939         if (__isSmallInteger(newSize)) {
   939 	if (__isSmallInteger(newSize)) {
   940             truncateSize = __intVal(newSize);
   940 	    truncateSize = __intVal(newSize);
   941             if (truncateSize < 0) {
   941 	    if (truncateSize < 0) {
   942                 goto getOutOfHere;
   942 		goto getOutOfHere;
   943             }
   943 	    }
   944         } else {
   944 	} else {
   945             truncateSize = __signedLongIntVal(newSize);
   945 	    truncateSize = __signedLongIntVal(newSize);
   946             if (truncateSize < 0) {
   946 	    if (truncateSize < 0) {
   947                 goto getOutOfHere;
   947 		goto getOutOfHere;
   948             }
   948 	    }
   949             if (truncateSize == 0) {
   949 	    if (truncateSize == 0) {
   950                 if (sizeof(truncateSize) == 8) {
   950 		if (sizeof(truncateSize) == 8) {
   951                     if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
   951 		    if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
   952                         goto getOutOfHere;
   952 			goto getOutOfHere;
   953                     }
   953 		    }
   954                 } else {
   954 		} else {
   955                     goto getOutOfHere;
   955 		    goto getOutOfHere;
   956                 }
   956 		}
   957             }
   957 	    }
   958         }
   958 	}
   959 
   959 
   960         f = __FILEVal(fp);
   960 	f = __FILEVal(fp);
   961 
   961 
   962         if (__INST(buffered) == true) {
   962 	if (__INST(buffered) == true) {
   963             fflush(f);
   963 	    fflush(f);
   964             fseek(f, 0L, SEEK_END); /* needed in stdio */
   964 	    fseek(f, 0L, SEEK_END); /* needed in stdio */
   965         }
   965 	}
   966         ftruncate(fileno(f), truncateSize);
   966 	ftruncate(fileno(f), truncateSize);
   967         RETURN (self);
   967 	RETURN (self);
   968     }
   968     }
   969 getOutOfHere: ;
   969 getOutOfHere: ;
   970 #endif
   970 #endif
   971 %}.
   971 %}.
   972     handle isNil ifTrue:[self errorNotOpen. ^ self].
   972     handle isNil ifTrue:[self errorNotOpen. ^ self].
   973     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
   973     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
   974     newSize < 0 ifTrue:[
   974     newSize < 0 ifTrue:[
   975         self error:'wrong arg'.
   975 	self error:'wrong arg'.
   976     ].
   976     ].
   977     self errorUnsupportedOperation
   977     self errorUnsupportedOperation
   978 
   978 
   979     "
   979     "
   980      |f s|
   980      |f s|
   984      s next:1000 put:$a.
   984      s next:1000 put:$a.
   985      s truncateTo:100.
   985      s truncateTo:100.
   986      s close.
   986      s close.
   987 
   987 
   988      Transcript showCR:(f fileSize).
   988      Transcript showCR:(f fileSize).
   989      f remove.   
   989      f remove.
   990     "
   990     "
   991 ! !
   991 ! !
   992 
   992 
   993 !FileStream methodsFor:'positioning'!
   993 !FileStream methodsFor:'positioning'!
   994 
   994 
   999 %{
   999 %{
  1000     HFILE f;
  1000     HFILE f;
  1001     off_t currentPosition;
  1001     off_t currentPosition;
  1002 
  1002 
  1003     if (__INST(handle) != nil) {
  1003     if (__INST(handle) != nil) {
  1004         do {
  1004 	do {
  1005             f = __FILEVal(__INST(handle));
  1005 	    f = __FILEVal(__INST(handle));
  1006 #ifdef WIN32
  1006 #ifdef WIN32
  1007             __threadErrno = 0;
  1007 	    __threadErrno = 0;
  1008             if (__INST(buffered) == true) {
  1008 	    if (__INST(buffered) == true) {
  1009 # if 0
  1009 # if 0
  1010                 currentPosition = STX_C_CALL1( "ftell", ftell, f);
  1010 		currentPosition = STX_C_CALL1( "ftell", ftell, f);
  1011 # else
  1011 # else
  1012                 currentPosition = ftell(f);
  1012 		currentPosition = ftell(f);
  1013                 __threadErrno = errno;
  1013 		__threadErrno = errno;
  1014 # endif
  1014 # endif
  1015             } else {
  1015 	    } else {
  1016                 OBJ rA = __INST(readAhead);
  1016 		OBJ rA = __INST(readAhead);
  1017                 off_t offs = 0;
  1017 		off_t offs = 0;
  1018 
  1018 
  1019                 if (rA != nil) {
  1019 		if (rA != nil) {
  1020                     __INST(readAhead) = nil;
  1020 		    __INST(readAhead) = nil;
  1021                     offs = -1;
  1021 		    offs = -1;
  1022                 }
  1022 		}
  1023 # if 0
  1023 # if 0
  1024                 currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
  1024 		currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
  1025 # else
  1025 # else
  1026                 currentPosition = lseek(fileno(f), offs, SEEK_CUR);
  1026 		currentPosition = lseek(fileno(f), offs, SEEK_CUR);
  1027                 __threadErrno = errno;
  1027 		__threadErrno = errno;
  1028 # endif
  1028 # endif
  1029             }
  1029 	    }
  1030 #else /* !WIN32 */
  1030 #else /* !WIN32 */
  1031             if (__INST(buffered) == true) {
  1031 	    if (__INST(buffered) == true) {
  1032 #ifdef _LFS_LARGEFILE
  1032 #ifdef _LFS_LARGEFILE
  1033                 currentPosition = ftello(f);
  1033 		currentPosition = ftello(f);
  1034 #else
  1034 #else
  1035                 currentPosition = ftell(f);
  1035 		currentPosition = ftell(f);
  1036 #endif /* ! _LFS_LARGEFILE */
  1036 #endif /* ! _LFS_LARGEFILE */
  1037             } else {
  1037 	    } else {
  1038 		if (sizeof(off_t) == 8) {
  1038 		if (sizeof(off_t) == 8) {
  1039                     currentPosition = lseek64(fileno(f), (off_t)0, SEEK_CUR);
  1039                     currentPosition = lseek64(fileno(f), (off_t)0, SEEK_CUR);
  1040                 } else {
  1040                 } else {
  1041                     currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
  1041                     currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
  1042                 }
  1042                 }
  1043             }
  1043             }
  1044 #endif /* !WIN32 */
  1044 #endif /* !WIN32 */
  1045         } while ((currentPosition < 0) && (__threadErrno == EINTR));
  1045 	} while ((currentPosition < 0) && (__threadErrno == EINTR));
  1046 
  1046 
  1047         if (currentPosition >= 0) {
  1047 	if (currentPosition >= 0) {
  1048             OBJ rslt;
  1048 	    OBJ rslt;
  1049 
  1049 
  1050             if (sizeof(currentPosition) == 8) {
  1050 	    if (sizeof(currentPosition) == 8) {
  1051                 rslt = __MKINT64 (&currentPosition);
  1051 		rslt = __MKINT64 (&currentPosition);
  1052             } else {
  1052 	    } else {
  1053                 rslt = __MKINT(currentPosition);
  1053 		rslt = __MKINT(currentPosition);
  1054             }
  1054 	    }
  1055             RETURN ( rslt );
  1055 	    RETURN ( rslt );
  1056         }
  1056 	}
  1057         error = __mkSmallInteger(__threadErrno);
  1057 	error = __mkSmallInteger(__threadErrno);
  1058     }
  1058     }
  1059 %}.
  1059 %}.
  1060     error notNil ifTrue:[
  1060     error notNil ifTrue:[
  1061         lastErrorNumber := error.
  1061 	lastErrorNumber := error.
  1062         ^ self ioError:error.
  1062 	^ self ioError:error.
  1063     ].
  1063     ].
  1064     handle isNil ifTrue:[^ self errorNotOpen].
  1064     handle isNil ifTrue:[^ self errorNotOpen].
  1065     ^ self primitiveFailed
  1065     ^ self primitiveFailed
  1066 !
  1066 !
  1067 
  1067 
  1073     HFILE f;
  1073     HFILE f;
  1074     long ret;
  1074     long ret;
  1075     OBJ fp;
  1075     OBJ fp;
  1076 
  1076 
  1077     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
  1077     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
  1078         if ((fp = __INST(handle)) != nil) {
  1078 	if ((fp = __INST(handle)) != nil) {
  1079 
  1079 
  1080 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
  1080 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
  1081 # define FSEEK fseeko
  1081 # define FSEEK fseeko
  1082             off_t nP;
  1082 	    off_t nP;
  1083 #else
  1083 #else
  1084 #define FSEEK fseek
  1084 #define FSEEK fseek
  1085             long nP;
  1085 	    long nP;
  1086 #endif
  1086 #endif
  1087 
  1087 
  1088             if (__isSmallInteger(newPos)) {
  1088 	    if (__isSmallInteger(newPos)) {
  1089                 nP = __intVal(newPos);
  1089 		nP = __intVal(newPos);
  1090                 if (nP < 0) {
  1090 		if (nP < 0) {
  1091                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1091 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1092                     goto getOutOfHere;
  1092 		    goto getOutOfHere;
  1093                 }
  1093 		}
  1094             } else {
  1094 	    } else {
  1095                 nP = __signedLongIntVal(newPos);
  1095 		nP = __signedLongIntVal(newPos);
  1096                 if (nP < 0) {
  1096 		if (nP < 0) {
  1097                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1097 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1098                     goto getOutOfHere;
  1098 		    goto getOutOfHere;
  1099                 }
  1099 		}
  1100                 if (nP == 0) {
  1100 		if (nP == 0) {
  1101                     if (sizeof(nP) == 8) {
  1101 		    if (sizeof(nP) == 8) {
  1102                         if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1102 			if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1103                             __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1103 			    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1104                             goto getOutOfHere;
  1104 			    goto getOutOfHere;
  1105                         }
  1105 			}
  1106                     } else {
  1106 		    } else {
  1107                         __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1107 			__INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1108                         goto getOutOfHere;
  1108 			goto getOutOfHere;
  1109                     }
  1109 		    }
  1110                 }
  1110 		}
  1111             }
  1111 	    }
  1112 
  1112 
  1113             f = __FILEVal(fp);
  1113 	    f = __FILEVal(fp);
  1114 
  1114 
  1115             do {
  1115 	    do {
  1116 #if defined(DO_WRAP_CALL_FSEEK)
  1116 #if defined(DO_WRAP_CALL_FSEEK)
  1117                 __threadErrno = 0;
  1117 		__threadErrno = 0;
  1118                 if (__INST(buffered) == true) {
  1118 		if (__INST(buffered) == true) {
  1119                     ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1119 		    ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1120                 } else {
  1120 		} else {
  1121                     __INST(readAhead) = nil;
  1121 		    __INST(readAhead) = nil;
  1122                     ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1122 		    ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1123                 }
  1123 		}
  1124 #else
  1124 #else
  1125                 if (__INST(buffered) == true) {
  1125 		if (__INST(buffered) == true) {
  1126                     ret = FSEEK(f, nP, SEEK_SET);
  1126 		    ret = FSEEK(f, nP, SEEK_SET);
  1127                 } else {
  1127 		} else {
  1128  #if !defined(__BORLANDC__)                
  1128  #if !defined(__BORLANDC__)                
  1129                     if (sizeof(nP) == 8)
  1129                     if (sizeof(nP) == 8)
  1130                         ret = lseek64(fileno(f), nP, SEEK_SET);
  1130                         ret = lseek64(fileno(f), nP, SEEK_SET);
  1131                     else
  1131                     else
  1132 #endif
  1132 #endif
  1133                         ret = lseek(fileno(f), nP, SEEK_SET);      
  1133 		    ret = lseek(fileno(f), nP, SEEK_SET);
  1134                 }
  1134 		}
  1135                 __threadErrno = errno;
  1135 		__threadErrno = errno;
  1136 #endif
  1136 #endif
  1137             } while ((ret < 0) && (__threadErrno == EINTR));
  1137 	    } while ((ret < 0) && (__threadErrno == EINTR));
  1138             if (ret >= 0) {
  1138 	    if (ret >= 0) {
  1139                 __INST(position) = newPos; __STORE(self, newPos);
  1139 		__INST(position) = newPos; __STORE(self, newPos);
  1140                 /*
  1140 		/*
  1141                  * just to make certain ...
  1141 		 * just to make certain ...
  1142                  */
  1142 		 */
  1143                 __INST(hitEOF) = false;
  1143 		__INST(hitEOF) = false;
  1144                 RETURN ( self );
  1144 		RETURN ( self );
  1145             }
  1145 	    }
  1146             error = __mkSmallInteger(__threadErrno);
  1146 	    error = __mkSmallInteger(__threadErrno);
  1147         }
  1147 	}
  1148     }
  1148     }
  1149     getOutOfHere: ;
  1149     getOutOfHere: ;
  1150 #undef FSEEK
  1150 #undef FSEEK
  1151 %}.
  1151 %}.
  1152     canPosition == false ifTrue:[
  1152     canPosition == false ifTrue:[
  1153         "/ position by rewinding & re-reading everything up-to
  1153 	"/ position by rewinding & re-reading everything up-to
  1154         "/ that point.
  1154 	"/ that point.
  1155         ^ self slowPosition:newPos
  1155 	^ self slowPosition:newPos
  1156     ].
  1156     ].
  1157     error notNil ifTrue:[
  1157     error notNil ifTrue:[
  1158         lastErrorNumber := error.
  1158 	lastErrorNumber := error.
  1159         (OperatingSystem errorSymbolForNumber:error) == #EINVAL ifTrue:[
  1159 	(OperatingSystem errorSymbolForNumber:error) == #EINVAL ifTrue:[
  1160             "/ invalid position
  1160 	    "/ invalid position
  1161             ^ self positionError.
  1161 	    ^ self positionError.
  1162         ].
  1162 	].
  1163         "/ assume I/O error
  1163 	"/ assume I/O error
  1164         ^ self ioError:error.
  1164 	^ self ioError:error.
  1165     ].
  1165     ].
  1166     handle isNil ifTrue:[^ self errorNotOpen].
  1166     handle isNil ifTrue:[^ self errorNotOpen].
  1167 
  1167 
  1168     rslt := self positionFile:handle position:newPos.
  1168     rslt := self positionFile:handle position:newPos.
  1169     rslt >= 0 ifTrue:[
  1169     rslt >= 0 ifTrue:[
  1170         position := newPos.
  1170 	position := newPos.
  1171     ] ifFalse:[
  1171     ] ifFalse:[
  1172         hitEOF := true.
  1172 	hitEOF := true.
  1173     ]
  1173     ]
  1174 !
  1174 !
  1175 
  1175 
  1176 reset
  1176 reset
  1177     "additionaly to setting the position to the beginning of the file,
  1177     "additionaly to setting the position to the beginning of the file,
  1199 %{
  1199 %{
  1200     HFILE f;
  1200     HFILE f;
  1201     off_t ret;
  1201     off_t ret;
  1202 
  1202 
  1203     if (__INST(handle) != nil) {
  1203     if (__INST(handle) != nil) {
  1204         f = __FILEVal(__INST(handle));
  1204 	f = __FILEVal(__INST(handle));
  1205         __INST(position) = nil;    /* i.e. unknown */
  1205 	__INST(position) = nil;    /* i.e. unknown */
  1206         do {
  1206 	do {
  1207 #ifdef WIN32
  1207 #ifdef WIN32
  1208             __threadErrno = 0;
  1208 	    __threadErrno = 0;
  1209             if (__INST(buffered) == true) {
  1209 	    if (__INST(buffered) == true) {
  1210                 ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);
  1210 		ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);
  1211             } else {
  1211 	    } else {
  1212                 __INST(readAhead) = nil;
  1212 		__INST(readAhead) = nil;
  1213                 ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
  1213 		ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
  1214             }
  1214 	    }
  1215 #else
  1215 #else
  1216             if (__INST(buffered) == true) {
  1216 	    if (__INST(buffered) == true) {
  1217 #ifdef _LFS_LARGE_FILE
  1217 #ifdef _LFS_LARGE_FILE
  1218                 ret = fseeko(f, (off_t)0, SEEK_END);
  1218 		ret = fseeko(f, (off_t)0, SEEK_END);
  1219 #else
  1219 #else
  1220                 ret = fseek(f, 0L, SEEK_END);
  1220 		ret = fseek(f, 0L, SEEK_END);
  1221 #endif
  1221 #endif
  1222             } else {
  1222 	    } else {
  1223                 if (sizeof(off_t) == 8) {
  1223                 if (sizeof(off_t) == 8) {
  1224                     ret = lseek64(fileno(f), (off_t)0, SEEK_END);
  1224                     ret = lseek64(fileno(f), (off_t)0, SEEK_END);
  1225                 } else {
  1225                 } else {
  1226                     ret = lseek(fileno(f), (off_t)0, SEEK_END);
  1226 		ret = lseek(fileno(f), (off_t)0, SEEK_END);
  1227                 }
  1227                 }
  1228             }
  1228 	    }
  1229 #endif
  1229 #endif
  1230         } while ((ret < 0) && (__threadErrno == EINTR));
  1230 	} while ((ret < 0) && (__threadErrno == EINTR));
  1231         if (ret >= 0) {
  1231 	if (ret >= 0) {
  1232             RETURN ( self );
  1232 	    RETURN ( self );
  1233         }
  1233 	}
  1234         error = __mkSmallInteger(__threadErrno);
  1234 	error = __mkSmallInteger(__threadErrno);
  1235     }
  1235     }
  1236 %}.
  1236 %}.
  1237     error notNil ifTrue:[
  1237     error notNil ifTrue:[
  1238         lastErrorNumber := error.
  1238 	lastErrorNumber := error.
  1239         self ioError:error.
  1239 	self ioError:error.
  1240         ^ self.    
  1240 	^ self.
  1241     ].
  1241     ].
  1242     handle isNil ifTrue:[^ self errorNotOpen].
  1242     handle isNil ifTrue:[^ self errorNotOpen].
  1243     ^ self primitiveFailed
  1243     ^ self primitiveFailed
  1244 !
  1244 !
  1245 
  1245 
  1247     "position the file by re-reading everything up-to newPos.
  1247     "position the file by re-reading everything up-to newPos.
  1248      The effect is the same as that of #position:, but its much slower.
  1248      The effect is the same as that of #position:, but its much slower.
  1249      This is required to reposition nonPositionable streams, such
  1249      This is required to reposition nonPositionable streams, such
  1250      as tape-streams or variable-record-RMS files under VMS.
  1250      as tape-streams or variable-record-RMS files under VMS.
  1251      Caveat:
  1251      Caveat:
  1252          This should really be done transparently by the stdio library."
  1252 	 This should really be done transparently by the stdio library."
  1253 
  1253 
  1254     |buffer amount pos0Based|
  1254     |buffer amount pos0Based|
  1255 
  1255 
  1256     self isReadable ifFalse:[
  1256     self isReadable ifFalse:[
  1257         "/ sorry
  1257 	"/ sorry
  1258         ^ self positionError
  1258 	^ self positionError
  1259     ].
  1259     ].
  1260 
  1260 
  1261     buffer := ByteArray new:8*1024.
  1261     buffer := ByteArray new:8*1024.
  1262 
  1262 
  1263     (position isNil "/ i.e. unknown
  1263     (position isNil "/ i.e. unknown
  1264     or:[newPos < (pos0Based := self position)]) ifTrue:[
  1264     or:[newPos < (pos0Based := self position)]) ifTrue:[
  1265         self reset.
  1265 	self reset.
  1266         pos0Based := self position.
  1266 	pos0Based := self position.
  1267     ].
  1267     ].
  1268     [pos0Based < newPos] whileTrue:[
  1268     [pos0Based < newPos] whileTrue:[
  1269         amount := (buffer size) min:(newPos-pos0Based).
  1269 	amount := (buffer size) min:(newPos-pos0Based).
  1270         (self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
  1270 	(self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
  1271             ^ self positionError
  1271 	    ^ self positionError
  1272         ].
  1272 	].
  1273         pos0Based := self position.
  1273 	pos0Based := self position.
  1274     ].
  1274     ].
  1275     "/ ('FileStream [info]: slow position - please convert ''' , pathName printString , ''' to streamLF format') infoPrintCR.
  1275     "/ ('FileStream [info]: slow position - please convert ''' , pathName printString , ''' to streamLF format') infoPrintCR.
  1276 ! !
  1276 ! !
  1277 
  1277 
  1278 !FileStream methodsFor:'printing & storing'!
  1278 !FileStream methodsFor:'printing & storing'!
  1360 %{
  1360 %{
  1361     HFILE f = NULL;
  1361     HFILE f = NULL;
  1362     int pass = 0;
  1362     int pass = 0;
  1363 
  1363 
  1364     if (!__isNonNilObject(encodedPathName)
  1364     if (!__isNonNilObject(encodedPathName)
  1365         || !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1365 	|| !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1366             goto badArgument;
  1366 	    goto badArgument;
  1367 
  1367 
  1368 retry:
  1368 retry:
  1369 #ifdef __VMS__
  1369 #ifdef __VMS__
  1370       if (__isStringLike(encodedPathName)) {
  1370       if (__isStringLike(encodedPathName)) {
  1371         do {
  1371 	do {
  1372             /*
  1372 	    /*
  1373              * allow passing additional RMS arguments.
  1373 	     * allow passing additional RMS arguments.
  1374              * stupid: DEC does not seem to offer an interface for passing a char **.
  1374 	     * stupid: DEC does not seem to offer an interface for passing a char **.
  1375              */
  1375 	     */
  1376             __threadErrno = 0;
  1376 	    __threadErrno = 0;
  1377 
  1377 
  1378             {
  1378 	    {
  1379                 if (__isArray(attributeSpec)) {
  1379 		if (__isArray(attributeSpec)) {
  1380                     OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1380 		    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1381                     int numAttrib = 0;
  1381 		    int numAttrib = 0;
  1382                     int i;
  1382 		    int i;
  1383 
  1383 
  1384                     numAttrib = __arraySize(attributeSpec);
  1384 		    numAttrib = __arraySize(attributeSpec);
  1385                     for (i=0; i<numAttrib;i++) {
  1385 		    for (i=0; i<numAttrib;i++) {
  1386                         if (! __isStringLike(ap[i])) {
  1386 			if (! __isStringLike(ap[i])) {
  1387                             __threadErrno = EINVAL; /* invalid argument */
  1387 			    __threadErrno = EINVAL; /* invalid argument */
  1388                             goto getOutOfHere;
  1388 			    goto getOutOfHere;
  1389                         }
  1389 			}
  1390                     }
  1390 		    }
  1391                     switch (numAttrib) {
  1391 		    switch (numAttrib) {
  1392                         case 0:
  1392 			case 0:
  1393                             __BEGIN_INTERRUPTABLE__
  1393 			    __BEGIN_INTERRUPTABLE__
  1394                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1394 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1395                             __END_INTERRUPTABLE__
  1395 			    __END_INTERRUPTABLE__
  1396                             break;
  1396 			    break;
  1397                         case 1:
  1397 			case 1:
  1398                             __BEGIN_INTERRUPTABLE__
  1398 			    __BEGIN_INTERRUPTABLE__
  1399                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1399 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1400                                       __stringVal(ap[0]));
  1400 				      __stringVal(ap[0]));
  1401                             __END_INTERRUPTABLE__
  1401 			    __END_INTERRUPTABLE__
  1402                             break;
  1402 			    break;
  1403                         case 2:
  1403 			case 2:
  1404                             __BEGIN_INTERRUPTABLE__
  1404 			    __BEGIN_INTERRUPTABLE__
  1405                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1405 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1406                                       __stringVal(ap[0]), __stringVal(ap[1]));
  1406 				      __stringVal(ap[0]), __stringVal(ap[1]));
  1407                             __END_INTERRUPTABLE__
  1407 			    __END_INTERRUPTABLE__
  1408                             break;
  1408 			    break;
  1409                         case 3:
  1409 			case 3:
  1410                             __BEGIN_INTERRUPTABLE__
  1410 			    __BEGIN_INTERRUPTABLE__
  1411                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1411 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1412                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1412 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1413                             __END_INTERRUPTABLE__
  1413 			    __END_INTERRUPTABLE__
  1414                             break;
  1414 			    break;
  1415                         case 4:
  1415 			case 4:
  1416                             __BEGIN_INTERRUPTABLE__
  1416 			    __BEGIN_INTERRUPTABLE__
  1417                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1417 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1418                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1418 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1419                                       __stringVal(ap[3]));
  1419 				      __stringVal(ap[3]));
  1420                             __END_INTERRUPTABLE__
  1420 			    __END_INTERRUPTABLE__
  1421                             break;
  1421 			    break;
  1422                         case 5:
  1422 			case 5:
  1423                             __BEGIN_INTERRUPTABLE__
  1423 			    __BEGIN_INTERRUPTABLE__
  1424                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1424 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1425                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1425 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1426                                       __stringVal(ap[3]), __stringVal(ap[4]));
  1426 				      __stringVal(ap[3]), __stringVal(ap[4]));
  1427                             __END_INTERRUPTABLE__
  1427 			    __END_INTERRUPTABLE__
  1428                             break;
  1428 			    break;
  1429                         case 6:
  1429 			case 6:
  1430                             __BEGIN_INTERRUPTABLE__
  1430 			    __BEGIN_INTERRUPTABLE__
  1431                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1431 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1432                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1432 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1433                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1433 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1434                             __END_INTERRUPTABLE__
  1434 			    __END_INTERRUPTABLE__
  1435                             break;
  1435 			    break;
  1436                         case 7:
  1436 			case 7:
  1437                             __BEGIN_INTERRUPTABLE__
  1437 			    __BEGIN_INTERRUPTABLE__
  1438                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1438 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1439                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1439 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1440                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1440 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1441                                       __stringVal(ap[6]));
  1441 				      __stringVal(ap[6]));
  1442                             __END_INTERRUPTABLE__
  1442 			    __END_INTERRUPTABLE__
  1443                             break;
  1443 			    break;
  1444                         case 8:
  1444 			case 8:
  1445                             __BEGIN_INTERRUPTABLE__
  1445 			    __BEGIN_INTERRUPTABLE__
  1446                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1446 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1447                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1447 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1448                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1448 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1449                                       __stringVal(ap[6]), __stringVal(ap[7]));
  1449 				      __stringVal(ap[6]), __stringVal(ap[7]));
  1450                             __END_INTERRUPTABLE__
  1450 			    __END_INTERRUPTABLE__
  1451                             break;
  1451 			    break;
  1452                         case 9:
  1452 			case 9:
  1453                             __BEGIN_INTERRUPTABLE__
  1453 			    __BEGIN_INTERRUPTABLE__
  1454                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1454 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1455                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1455 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1456                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1456 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1457                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1457 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1458                             __END_INTERRUPTABLE__
  1458 			    __END_INTERRUPTABLE__
  1459                             break;
  1459 			    break;
  1460                         case 10:
  1460 			case 10:
  1461                             __BEGIN_INTERRUPTABLE__
  1461 			    __BEGIN_INTERRUPTABLE__
  1462                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1462 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1463                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1463 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1464                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1464 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1465                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1465 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1466                                       __stringVal(ap[9]));
  1466 				      __stringVal(ap[9]));
  1467                             __END_INTERRUPTABLE__
  1467 			    __END_INTERRUPTABLE__
  1468                             break;
  1468 			    break;
  1469                         default:
  1469 			default:
  1470                             __threadErrno = E2BIG; /* too many args */
  1470 			    __threadErrno = E2BIG; /* too many args */
  1471                             goto getOutOfHere;
  1471 			    goto getOutOfHere;
  1472                     }
  1472 		    }
  1473                 } else if (attributeSpec != nil) {
  1473 		} else if (attributeSpec != nil) {
  1474                     __threadErrno = EINVAL; /* invalid argument */
  1474 		    __threadErrno = EINVAL; /* invalid argument */
  1475                     goto getOutOfHere;
  1475 		    goto getOutOfHere;
  1476                 } else {
  1476 		} else {
  1477                     /*
  1477 		    /*
  1478                      * create file as sequential streamLF by default.
  1478 		     * create file as sequential streamLF by default.
  1479                      */
  1479 		     */
  1480                     __BEGIN_INTERRUPTABLE__
  1480 		    __BEGIN_INTERRUPTABLE__
  1481                     f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1481 		    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1482                     __END_INTERRUPTABLE__
  1482 		    __END_INTERRUPTABLE__
  1483                 }
  1483 		}
  1484             }
  1484 	    }
  1485         } while ((f == NULL) && (__threadErrno == EINTR));
  1485 	} while ((f == NULL) && (__threadErrno == EINTR));
  1486       }
  1486       }
  1487 #else /* not VMS */
  1487 #else /* not VMS */
  1488 
  1488 
  1489 # ifdef WIN32
  1489 # ifdef WIN32
  1490     {
  1490     {
  1491           DWORD share = 0, access = 0, create = 0, attr = 0;
  1491 	  DWORD share = 0, access = 0, create = 0, attr = 0;
  1492           char * __openmode;
  1492 	  char * __openmode;
  1493           HANDLE handle;
  1493 	  HANDLE handle;
  1494           SECURITY_ATTRIBUTES sa;
  1494 	  SECURITY_ATTRIBUTES sa;
  1495 
  1495 
  1496           if (__isStringLike(openmode)) {
  1496 	  if (__isStringLike(openmode)) {
  1497               share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1497 	      share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1498               __openmode = __stringVal(openmode);
  1498 	      __openmode = __stringVal(openmode);
  1499               if (strcmp(__openmode, "rb") == 0) {
  1499 	      if (strcmp(__openmode, "rb") == 0) {
  1500                   access = GENERIC_READ;
  1500 		  access = GENERIC_READ;
  1501                   create = OPEN_EXISTING;
  1501 		  create = OPEN_EXISTING;
  1502               } else if (strcmp(__openmode, "rb+") == 0) {
  1502 	      } else if (strcmp(__openmode, "rb+") == 0) {
  1503                   access = GENERIC_READ | GENERIC_WRITE;
  1503 		  access = GENERIC_READ | GENERIC_WRITE;
  1504                   create = OPEN_EXISTING;
  1504 		  create = OPEN_EXISTING;
  1505               } else if (strcmp(__openmode, "wb") == 0) {
  1505 	      } else if (strcmp(__openmode, "wb") == 0) {
  1506                   access = GENERIC_WRITE;
  1506 		  access = GENERIC_WRITE;
  1507                   create = CREATE_ALWAYS;
  1507 		  create = CREATE_ALWAYS;
  1508               } else if (strcmp(__openmode, "wb+") == 0) {
  1508 	      } else if (strcmp(__openmode, "wb+") == 0) {
  1509                   access = GENERIC_READ | GENERIC_WRITE;
  1509 		  access = GENERIC_READ | GENERIC_WRITE;
  1510                   create = CREATE_ALWAYS;
  1510 		  create = CREATE_ALWAYS;
  1511               } else if (strcmp(__openmode, "ab") == 0) {
  1511 	      } else if (strcmp(__openmode, "ab") == 0) {
  1512                   access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1512 		  access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1513                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1513 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1514                   create = OPEN_ALWAYS;
  1514 		  create = OPEN_ALWAYS;
  1515               } else if (strcmp(__openmode, "ab+") == 0) {
  1515 	      } else if (strcmp(__openmode, "ab+") == 0) {
  1516                   access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1516 		  access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1517                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1517 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1518                   create = OPEN_ALWAYS;
  1518 		  create = OPEN_ALWAYS;
  1519               } else {
  1519 	      } else {
  1520                   console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1520 		  console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1521               }
  1521 	      }
  1522           } else if (__isArrayLike(openmode)) {
  1522 	  } else if (__isArrayLike(openmode)) {
  1523               OBJ *ap = __arrayVal(openmode);
  1523 	      OBJ *ap = __arrayVal(openmode);
  1524               int numAttrib = __arraySize(openmode);
  1524 	      int numAttrib = __arraySize(openmode);
  1525               int i;
  1525 	      int i;
  1526 
  1526 
  1527               __openmode = "rb+";
  1527 	      __openmode = "rb+";
  1528 
  1528 
  1529               for (i=0; i<numAttrib; i++) {
  1529 	      for (i=0; i<numAttrib; i++) {
  1530                   OBJ attrSym = ap[i];
  1530 		  OBJ attrSym = ap[i];
  1531 
  1531 
  1532                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1532 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1533                       share |= FILE_SHARE_READ;
  1533 		      share |= FILE_SHARE_READ;
  1534                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1534 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1535                       share |= FILE_SHARE_WRITE;
  1535 		      share |= FILE_SHARE_WRITE;
  1536 
  1536 
  1537                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1537 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1538                       access |= GENERIC_READ;
  1538 		      access |= GENERIC_READ;
  1539                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1539 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1540                       access |= GENERIC_WRITE;
  1540 		      access |= GENERIC_WRITE;
  1541                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1541 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1542                       access |= GENERIC_READ|GENERIC_WRITE;
  1542 		      access |= GENERIC_READ|GENERIC_WRITE;
  1543 
  1543 
  1544                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1544 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1545                       create |= CREATE_NEW;
  1545 		      create |= CREATE_NEW;
  1546                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1546 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1547                       create |= CREATE_ALWAYS;
  1547 		      create |= CREATE_ALWAYS;
  1548                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1548 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1549                       create |= OPEN_EXISTING;
  1549 		      create |= OPEN_EXISTING;
  1550                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1550 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1551                       create |= OPEN_ALWAYS;
  1551 		      create |= OPEN_ALWAYS;
  1552                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1552 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1553                       create |= TRUNCATE_EXISTING;
  1553 		      create |= TRUNCATE_EXISTING;
  1554 
  1554 
  1555                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1555 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1556                       attr |= FILE_ATTRIBUTE_HIDDEN;
  1556 		      attr |= FILE_ATTRIBUTE_HIDDEN;
  1557                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1557 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1558                       attr |= FILE_ATTRIBUTE_READONLY;
  1558 		      attr |= FILE_ATTRIBUTE_READONLY;
  1559                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1559 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1560                       attr |= FILE_FLAG_WRITE_THROUGH;
  1560 		      attr |= FILE_FLAG_WRITE_THROUGH;
  1561                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1561 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1562                       attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1562 		      attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1563                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1563 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1564                       attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1564 		      attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1565                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1565 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1566                       __openmode = __stringVal(attrSym);
  1566 		      __openmode = __stringVal(attrSym);
  1567                   } else {
  1567 		  } else {
  1568                       console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1568 		      console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1569                   }
  1569 		  }
  1570               }
  1570 	      }
  1571           }
  1571 	  }
  1572           if (create == 0) {
  1572 	  if (create == 0) {
  1573 //              argumentError = @symbol(missingCreateMode);
  1573 //              argumentError = @symbol(missingCreateMode);
  1574               goto badArgument;
  1574 	      goto badArgument;
  1575           }
  1575 	  }
  1576           if (attr == 0) {
  1576 	  if (attr == 0) {
  1577               attr = FILE_ATTRIBUTE_NORMAL;
  1577 	      attr = FILE_ATTRIBUTE_NORMAL;
  1578           }
  1578 	  }
  1579 
  1579 
  1580           /*
  1580 	  /*
  1581            * create security attributes - make handle inheritable by subprocesses
  1581 	   * create security attributes - make handle inheritable by subprocesses
  1582            */
  1582 	   */
  1583           memset(&sa, 0, sizeof (sa));
  1583 	  memset(&sa, 0, sizeof (sa));
  1584           sa.nLength = sizeof( sa );
  1584 	  sa.nLength = sizeof( sa );
  1585           // sa.bInheritHandle = TRUE;
  1585 	  // sa.bInheritHandle = TRUE;
  1586           sa.bInheritHandle = FALSE;
  1586 	  sa.bInheritHandle = FALSE;
  1587 
  1587 
  1588           if (__isStringLike(pathName)) {
  1588 	  if (__isStringLike(pathName)) {
  1589                 char _aPathName[MAXPATHLEN];
  1589 		char _aPathName[MAXPATHLEN];
  1590 
  1590 
  1591                 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1591 		strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1592                 do {
  1592 		do {
  1593                     __threadErrno = 0;
  1593 		    __threadErrno = 0;
  1594                     handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1594 		    handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1595                     if (__threadErrno == EINTR) {
  1595 		    if (__threadErrno == EINTR) {
  1596                         handle = INVALID_HANDLE_VALUE;
  1596 			handle = INVALID_HANDLE_VALUE;
  1597                     }
  1597 		    }
  1598                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1598 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1599           } else if (__isUnicode16String(pathName)) {
  1599 	  } else if (__isUnicode16String(pathName)) {
  1600                 wchar_t _aPathName[MAXPATHLEN+1];
  1600 		wchar_t _aPathName[MAXPATHLEN+1];
  1601                 int i, l;
  1601 		int i, l;
  1602 
  1602 
  1603                 l = __unicode16StringSize(pathName);
  1603 		l = __unicode16StringSize(pathName);
  1604                 if (l > MAXPATHLEN) l = MAXPATHLEN;
  1604 		if (l > MAXPATHLEN) l = MAXPATHLEN;
  1605                 for (i=0; i<l; i++) {
  1605 		for (i=0; i<l; i++) {
  1606                     _aPathName[i] = __unicode16StringVal(pathName)[i];
  1606 		    _aPathName[i] = __unicode16StringVal(pathName)[i];
  1607                 }
  1607 		}
  1608                 _aPathName[i] = 0;
  1608 		_aPathName[i] = 0;
  1609 
  1609 
  1610                 do {
  1610 		do {
  1611                     __threadErrno = 0;
  1611 		    __threadErrno = 0;
  1612                     handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1612 		    handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1613                     if (__threadErrno == EINTR) {
  1613 		    if (__threadErrno == EINTR) {
  1614                         handle = INVALID_HANDLE_VALUE;
  1614 			handle = INVALID_HANDLE_VALUE;
  1615                     }
  1615 		    }
  1616                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1616 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1617           }
  1617 	  }
  1618           if (handle != INVALID_HANDLE_VALUE) {
  1618 	  if (handle != INVALID_HANDLE_VALUE) {
  1619               int fd;
  1619 	      int fd;
  1620               extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1620 	      extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1621 
  1621 
  1622               __stxWrapApiEnterCritical();
  1622 	      __stxWrapApiEnterCritical();
  1623               fd = _open_osfhandle((long)handle, O_BINARY);
  1623 	      fd = _open_osfhandle((long)handle, O_BINARY);
  1624               if (fd < 0) {
  1624 	      if (fd < 0) {
  1625                   if (__threadErrno == 0) {
  1625 		  if (__threadErrno == 0) {
  1626                       // no more file descriptors
  1626 		      // no more file descriptors
  1627                       __threadErrno = EMFILE;
  1627 		      __threadErrno = EMFILE;
  1628                   }
  1628 		  }
  1629                   CloseHandle(handle);
  1629 		  CloseHandle(handle);
  1630               } else {
  1630 	      } else {
  1631                   f = fdopen(fd, __openmode);
  1631 		  f = fdopen(fd, __openmode);
  1632               }
  1632 	      }
  1633               __stxWrapApiLeaveCritical();
  1633 	      __stxWrapApiLeaveCritical();
  1634           }  else {
  1634 	  }  else {
  1635             __threadErrno = __WIN32_ERR(GetLastError());
  1635 	    __threadErrno = __WIN32_ERR(GetLastError());
  1636           }
  1636 	  }
  1637       }
  1637       }
  1638 # else /* not WIN32 */
  1638 # else /* not WIN32 */
  1639 
  1639 
  1640       if (__isStringLike(encodedPathName)) {
  1640       if (__isStringLike(encodedPathName)) {
  1641           int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1641 	  int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1642           int flags = 0;
  1642 	  int flags = 0;
  1643           int fd;
  1643 	  int fd;
  1644           char * __openmode;
  1644 	  char * __openmode;
  1645 
  1645 
  1646           if (__isStringLike(openmode)) {
  1646 	  if (__isStringLike(openmode)) {
  1647               __openmode = __stringVal(openmode);
  1647 	      __openmode = __stringVal(openmode);
  1648               if (strcmp(__openmode, "r") == 0) {
  1648 	      if (strcmp(__openmode, "r") == 0) {
  1649                   flags = O_RDONLY;
  1649 		  flags = O_RDONLY;
  1650               } else if (strcmp(__openmode, "r+") == 0) {
  1650 	      } else if (strcmp(__openmode, "r+") == 0) {
  1651                   flags = O_RDWR;
  1651 		  flags = O_RDWR;
  1652               } else if (strcmp(__openmode, "w") == 0) {
  1652 	      } else if (strcmp(__openmode, "w") == 0) {
  1653                   flags = O_WRONLY | O_CREAT | O_TRUNC;
  1653 		  flags = O_WRONLY | O_CREAT | O_TRUNC;
  1654               } else if (strcmp(__openmode, "w+") == 0) {
  1654 	      } else if (strcmp(__openmode, "w+") == 0) {
  1655                   flags = O_RDWR | O_CREAT | O_TRUNC;
  1655 		  flags = O_RDWR | O_CREAT | O_TRUNC;
  1656               } else if (strcmp(__openmode, "a") == 0) {
  1656 	      } else if (strcmp(__openmode, "a") == 0) {
  1657                   flags = O_WRONLY | O_CREAT | O_APPEND;
  1657 		  flags = O_WRONLY | O_CREAT | O_APPEND;
  1658               } else if (strcmp(__openmode, "a+") == 0) {
  1658 	      } else if (strcmp(__openmode, "a+") == 0) {
  1659                   flags = O_RDWR | O_CREAT| O_APPEND;
  1659 		  flags = O_RDWR | O_CREAT| O_APPEND;
  1660               } else {
  1660 	      } else {
  1661                   console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1661 		  console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1662               }
  1662 	      }
  1663           } else if (__isArrayLike(openmode)) {
  1663 	  } else if (__isArrayLike(openmode)) {
  1664               OBJ *ap = __arrayVal(openmode);
  1664 	      OBJ *ap = __arrayVal(openmode);
  1665               int numAttrib = __arraySize(openmode);
  1665 	      int numAttrib = __arraySize(openmode);
  1666               int i;
  1666 	      int i;
  1667 
  1667 
  1668               __openmode = "r+";
  1668 	      __openmode = "r+";
  1669 
  1669 
  1670               for (i=0; i<numAttrib; i++) {
  1670 	      for (i=0; i<numAttrib; i++) {
  1671                   OBJ attrSym = ap[i];
  1671 		  OBJ attrSym = ap[i];
  1672 
  1672 
  1673                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1673 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1674                       // ignore
  1674 		      // ignore
  1675                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1675 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1676                      // ignore
  1676 		     // ignore
  1677                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1677 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1678                       flags |= O_RDONLY;
  1678 		      flags |= O_RDONLY;
  1679                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1679 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1680                       flags |= O_WRONLY;
  1680 		      flags |= O_WRONLY;
  1681                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1681 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1682                       flags |= O_RDWR;
  1682 		      flags |= O_RDWR;
  1683 
  1683 
  1684                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1684 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1685                       flags |= O_CREAT|O_EXCL;
  1685 		      flags |= O_CREAT|O_EXCL;
  1686                       accessMode = 0600;     // simulate mkstemp()
  1686 		      accessMode = 0600;     // simulate mkstemp()
  1687                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1687 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1688                       flags |= O_CREAT|O_TRUNC;
  1688 		      flags |= O_CREAT|O_TRUNC;
  1689                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1689 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1690                       // nothing to be set
  1690 		      // nothing to be set
  1691                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1691 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1692                       flags |= O_CREAT;
  1692 		      flags |= O_CREAT;
  1693                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1693 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1694                       flags |= O_TRUNC;
  1694 		      flags |= O_TRUNC;
  1695 
  1695 
  1696                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1696 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1697                       // ignore
  1697 		      // ignore
  1698                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1698 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1699                       accessMode &= 0444;
  1699 		      accessMode &= 0444;
  1700                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1700 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1701 #ifdef O_DIRECT
  1701 #ifdef O_DIRECT
  1702                       flags |= O_DIRECT;
  1702 		      flags |= O_DIRECT;
  1703 #endif
  1703 #endif
  1704                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1704 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1705                       // ignore
  1705 		      // ignore
  1706                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1706 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1707                       // ignore;
  1707 		      // ignore;
  1708                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1708 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1709                       __openmode = __stringVal(attrSym);
  1709 		      __openmode = __stringVal(attrSym);
  1710                   } else {
  1710 		  } else {
  1711                       console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1711 		      console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1712                   }
  1712 		  }
  1713               }
  1713 	      }
  1714           }
  1714 	  }
  1715           do {
  1715 	  do {
  1716               __BEGIN_INTERRUPTABLE__
  1716 	      __BEGIN_INTERRUPTABLE__
  1717               fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1717 	      fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1718               __END_INTERRUPTABLE__
  1718 	      __END_INTERRUPTABLE__
  1719           } while ((fd < 0) && (__threadErrno == EINTR));
  1719 	  } while ((fd < 0) && (__threadErrno == EINTR));
  1720 
  1720 
  1721           if (fd >= 0) {
  1721 	  if (fd >= 0) {
  1722               __threadErrno = 0;
  1722 	      __threadErrno = 0;
  1723               f = fdopen(fd, __openmode);
  1723 	      f = fdopen(fd, __openmode);
  1724               if (f == NULL) {
  1724 	      if (f == NULL) {
  1725                   close(fd);            // fdopen failed, close before retry.
  1725 		  close(fd);            // fdopen failed, close before retry.
  1726               }
  1726 	      }
  1727           }
  1727 	  }
  1728       }
  1728       }
  1729 
  1729 
  1730 # endif /* not WIN32 */
  1730 # endif /* not WIN32 */
  1731 #endif /* not VMS */
  1731 #endif /* not VMS */
  1732 
  1732 
  1733 
  1733 
  1734     if (f == NULL) {
  1734     if (f == NULL) {
  1735         /*
  1735 	/*
  1736          * If no filedescriptors available, try to finalize
  1736 	 * If no filedescriptors available, try to finalize
  1737          * possibly collected fd's and try again.
  1737 	 * possibly collected fd's and try again.
  1738          */
  1738 	 */
  1739         if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) {
  1739 	if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) {
  1740             pass = 1;
  1740 	    pass = 1;
  1741             __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1741 	    __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1742             __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1742 	    __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1743             goto retry;
  1743 	    goto retry;
  1744         }
  1744 	}
  1745     badArgument:
  1745     badArgument:
  1746     getOutOfHere:
  1746     getOutOfHere:
  1747         error = __mkSmallInteger(__threadErrno);
  1747 	error = __mkSmallInteger(__threadErrno);
  1748         __INST(position) = nil;
  1748 	__INST(position) = nil;
  1749     } else {
  1749     } else {
  1750 #ifdef __VMS__
  1750 #ifdef __VMS__
  1751         /*
  1751 	/*
  1752          * check to see if this is positionable ...
  1752 	 * check to see if this is positionable ...
  1753          */
  1753 	 */
  1754         __INST(canPosition) = false;
  1754 	__INST(canPosition) = false;
  1755 # ifndef _POSIX_C_SOURCE
  1755 # ifndef _POSIX_C_SOURCE
  1756         {
  1756 	{
  1757             struct stat statBuffer;
  1757 	    struct stat statBuffer;
  1758 
  1758 
  1759             if (fstat(fileno(f), &statBuffer) >= 0) {
  1759 	    if (fstat(fileno(f), &statBuffer) >= 0) {
  1760                 switch (statBuffer.st_fab_rfm) {
  1760 		switch (statBuffer.st_fab_rfm) {
  1761                     case FAB$C_UDF: /* undefined (also stream binary)   */
  1761 		    case FAB$C_UDF: /* undefined (also stream binary)   */
  1762                     case FAB$C_VAR: /* variable length records          */
  1762 		    case FAB$C_VAR: /* variable length records          */
  1763                     case FAB$C_VFC: /* variable fixed control           */
  1763 		    case FAB$C_VFC: /* variable fixed control           */
  1764                     case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1764 		    case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1765                     default:
  1765 		    default:
  1766                         __INST(canPosition) = false;
  1766 			__INST(canPosition) = false;
  1767                         break;
  1767 			break;
  1768 
  1768 
  1769                     case FAB$C_FIX: /* fixed length records             */
  1769 		    case FAB$C_FIX: /* fixed length records             */
  1770                     case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1770 		    case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1771                     case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1771 		    case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1772                         __INST(canPosition) = true;
  1772 			__INST(canPosition) = true;
  1773                         break;
  1773 			break;
  1774                 }
  1774 		}
  1775             }
  1775 	    }
  1776         }
  1776 	}
  1777 # endif
  1777 # endif
  1778 #else /* not VMS */
  1778 #else /* not VMS */
  1779         __INST(canPosition) = true;
  1779 	__INST(canPosition) = true;
  1780 #endif /* not VMS */
  1780 #endif /* not VMS */
  1781 
  1781 
  1782         if (@global(FileOpenTrace) == true) {
  1782 	if (@global(FileOpenTrace) == true) {
  1783             console_fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
  1783 	    console_fprintf(stderr, "fopen %s [FileStream] -> %"_lx_"\n", __stringVal(pathName), (INT)f);
  1784         }
  1784 	}
  1785         if (f != NULL) {
  1785 	if (f != NULL) {
  1786             OBJ fp;
  1786 	    OBJ fp;
  1787 
  1787 
  1788             wasBlocked = __BLOCKINTERRUPTS();
  1788 	    wasBlocked = __BLOCKINTERRUPTS();
  1789 #if 0
  1789 #if 0
  1790             // The original code was:
  1790 	    // The original code was:
  1791             __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1791 	    __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1792             // but for that, gcc generates wrong code, which loads self (volatile) into
  1792 	    // but for that, gcc generates wrong code, which loads self (volatile) into
  1793             // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1793 	    // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1794             // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1794 	    // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1795             // object.
  1795 	    // object.
  1796 #else
  1796 #else
  1797             fp = __MKEXTERNALADDRESS(f);
  1797 	    fp = __MKEXTERNALADDRESS(f);
  1798             __INST(handle) = fp;
  1798 	    __INST(handle) = fp;
  1799             __STORE(self, fp);
  1799 	    __STORE(self, fp);
  1800 #endif
  1800 #endif
  1801         }
  1801 	}
  1802     }
  1802     }
  1803 %}.
  1803 %}.
  1804     error notNil ifTrue:[
  1804     error notNil ifTrue:[
  1805         lastErrorNumber := error.
  1805 	lastErrorNumber := error.
  1806         ^ self openError:error.
  1806 	^ self openError:error.
  1807     ].
  1807     ].
  1808     handle isNil ifTrue:[
  1808     handle isNil ifTrue:[
  1809         ^ self openError:0.
  1809 	^ self openError:0.
  1810     ].
  1810     ].
  1811 
  1811 
  1812     position := 0.
  1812     position := 0.
  1813     handleType := #filePointer.
  1813     handleType := #filePointer.
  1814     Lobby register:self.
  1814     Lobby register:self.
  1884 
  1884 
  1885     handle notNil ifTrue:[^ self errorAlreadyOpen].
  1885     handle notNil ifTrue:[^ self errorAlreadyOpen].
  1886 
  1886 
  1887     handle := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1887     handle := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1888     handle isNil ifTrue:[
  1888     handle isNil ifTrue:[
  1889         "this happens, if proceeding from an OpenError raised in #openFile..."
  1889 	"this happens, if proceeding from an OpenError raised in #openFile..."
  1890         ^ nil.
  1890 	^ nil.
  1891     ].
  1891     ].
  1892     position := 0.
  1892     position := 0.
  1893     buffered isNil ifTrue:[
  1893     buffered isNil ifTrue:[
  1894         buffered := true.       "default is buffered"
  1894 	buffered := true.       "default is buffered"
  1895     ].
  1895     ].
  1896 !
  1896 !
  1897 
  1897 
  1898 pathName:filename
  1898 pathName:filename
  1899     "set the pathname"
  1899     "set the pathname"
  2024 
  2024 
  2025 #ifdef transputer
  2025 #ifdef transputer
  2026     unsigned int size;
  2026     unsigned int size;
  2027 
  2027 
  2028     if (__INST(handle) != nil) {
  2028     if (__INST(handle) != nil) {
  2029         f = __FILEVal(__INST(handle));
  2029 	f = __FILEVal(__INST(handle));
  2030         if ((size = filesize(fileno(f))) >= 0) {
  2030 	if ((size = filesize(fileno(f))) >= 0) {
  2031             RETURN ( __MKUINT(size) );
  2031 	    RETURN ( __MKUINT(size) );
  2032         }
  2032 	}
  2033     }
  2033     }
  2034 #else
  2034 #else
  2035     struct stat buf;
  2035     struct stat buf;
  2036     int ret;
  2036     int ret;
  2037     int fd;
  2037     int fd;
  2038 
  2038 
  2039     if (__INST(handle) != nil) {
  2039     if (__INST(handle) != nil) {
  2040         f = __FILEVal(__INST(handle));
  2040 	f = __FILEVal(__INST(handle));
  2041         fd = fileno(f);
  2041 	fd = fileno(f);
  2042         do {
  2042 	do {
  2043             ret = fstat(fd, &buf);
  2043 	    ret = fstat(fd, &buf);
  2044         } while ((ret < 0) && (__threadErrno == EINTR));
  2044 	} while ((ret < 0) && (__threadErrno == EINTR));
  2045         if (ret >= 0) {
  2045 	if (ret >= 0) {
  2046             OBJ rslt;
  2046 	    OBJ rslt;
  2047 
  2047 
  2048             if (sizeof(buf.st_size) == 8) {
  2048 	    if (sizeof(buf.st_size) == 8) {
  2049                 rslt = __MKINT64(&buf.st_size);
  2049 		rslt = __MKINT64(&buf.st_size);
  2050             } else {
  2050 	    } else {
  2051                 rslt = __MKINT(buf.st_size);
  2051 		rslt = __MKINT(buf.st_size);
  2052             }
  2052 	    }
  2053             RETURN(rslt);
  2053 	    RETURN(rslt);
  2054         }
  2054 	}
  2055         error = __mkSmallInteger(__threadErrno);
  2055 	error = __mkSmallInteger(__threadErrno);
  2056     }
  2056     }
  2057 #endif
  2057 #endif
  2058 %}.
  2058 %}.
  2059 
  2059 
  2060     "could add a fall-back here:
  2060     "could add a fall-back here:
  2061 
  2061 
  2062         oldPosition := self position.
  2062 	oldPosition := self position.
  2063         self setToEnd.
  2063 	self setToEnd.
  2064         sz := self position.
  2064 	sz := self position.
  2065         self position:oldPosition.
  2065 	self position:oldPosition.
  2066         ^ sz
  2066 	^ sz
  2067     "
  2067     "
  2068     error notNil ifTrue:[
  2068     error notNil ifTrue:[
  2069         lastErrorNumber := error.
  2069 	lastErrorNumber := error.
  2070         self ioError:error.
  2070 	self ioError:error.
  2071         ^ self.    
  2071 	^ self.
  2072     ].
  2072     ].
  2073     handle isNil ifTrue:[^ self errorNotOpen].
  2073     handle isNil ifTrue:[^ self errorNotOpen].
  2074     ^ self primitiveFailed
  2074     ^ self primitiveFailed
  2075 !
  2075 !
  2076 
  2076 
  2117 ! !
  2117 ! !
  2118 
  2118 
  2119 !FileStream class methodsFor:'documentation'!
  2119 !FileStream class methodsFor:'documentation'!
  2120 
  2120 
  2121 version
  2121 version
  2122     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.180 2015-03-12 13:52:37 stefan Exp $'
  2122     ^ '$Header$'
  2123 !
  2123 !
  2124 
  2124 
  2125 version_CVS
  2125 version_CVS
  2126     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.180 2015-03-12 13:52:37 stefan Exp $'
  2126     ^ '$Header$'
  2127 ! !
  2127 ! !
  2128 
  2128 
  2129 
  2129 
  2130 FileStream initialize!
  2130 FileStream initialize!