FileStream.st
changeset 23539 d41c73151593
parent 23429 58f5170cac48
child 23894 2dcb46224ee8
equal deleted inserted replaced
23538:1266c7e94014 23539:d41c73151593
  1040 %{
  1040 %{
  1041     HFILE f;
  1041     HFILE f;
  1042     off_t currentPosition;
  1042     off_t currentPosition;
  1043 
  1043 
  1044     if (__INST(handle) != nil) {
  1044     if (__INST(handle) != nil) {
  1045 	do {
  1045         do {
  1046 	    f = __FILEVal(__INST(handle));
  1046             f = __FILEVal(__INST(handle));
  1047 #ifdef __win32__
  1047 #ifdef __win32__
  1048 	    __threadErrno = 0;
  1048             __threadErrno = 0;
  1049 	    if (__INST(buffered) == true) {
  1049             if (__INST(buffered) == true) {
  1050 # if 0
  1050 # if 0
  1051 		currentPosition = STX_C_CALL1( "ftell", ftell, f);
  1051                 currentPosition = STX_C_CALL1( "ftell", ftell, f);
  1052 # else
  1052 # else
  1053 		currentPosition = ftell(f);
  1053                 currentPosition = ftell(f);
  1054 		__threadErrno = errno;
  1054                 __threadErrno = errno;
  1055 # endif
  1055 # endif
  1056 	    } else {
  1056             } else {
  1057 		OBJ rA = __INST(readAhead);
  1057                 OBJ rA = __INST(readAhead);
  1058 		off_t offs = 0;
  1058                 off_t offs = 0;
  1059 
  1059 
  1060 		if (rA != nil) {
  1060                 if (rA != nil) {
  1061 		    __INST(readAhead) = nil;
  1061                     __INST(readAhead) = nil;
  1062 		    offs = -1;
  1062                     offs = -1;
  1063 		}
  1063                 }
  1064 # if 0
  1064 # if 0
  1065 		currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
  1065                 currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
  1066 # else
  1066 # else
  1067 		currentPosition = lseek(fileno(f), offs, SEEK_CUR);
  1067                 currentPosition = lseek(fileno(f), offs, SEEK_CUR);
  1068 		__threadErrno = errno;
  1068                 __threadErrno = errno;
  1069 # endif
  1069 # endif
  1070 	    }
  1070             }
  1071 #else /* !__win32__ */
  1071 #else /* !__win32__ */
  1072 	    if (__INST(buffered) == true) {
  1072             if (__INST(buffered) == true) {
  1073 #ifdef _LFS_LARGEFILE
  1073 #ifdef _LFS_LARGEFILE
  1074 		currentPosition = ftello(f);
  1074                 currentPosition = ftello(f);
  1075 #else
  1075 #else
  1076 		currentPosition = ftell(f);
  1076                 currentPosition = ftell(f);
  1077 #endif /* ! _LFS_LARGEFILE */
  1077 #endif /* ! _LFS_LARGEFILE */
  1078 	    } else {
  1078             } else {
  1079 		currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
  1079                 currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
  1080 	    }
  1080             }
  1081 #endif /* !WIN32 */
  1081 #endif /* !WIN32 */
  1082 	} while ((currentPosition < 0) && (__threadErrno == EINTR));
  1082         } while ((currentPosition < 0) && (__threadErrno == EINTR));
  1083 
  1083 
  1084 	if (currentPosition >= 0) {
  1084         if (currentPosition >= 0) {
  1085 	    OBJ rslt;
  1085             OBJ rslt;
  1086 
  1086 
  1087 	    if (sizeof(currentPosition) == 8) {
  1087             if (sizeof(currentPosition) == 8) {
  1088 		rslt = __MKINT64 (&currentPosition);
  1088                 rslt = __MKINT64 (&currentPosition);
  1089 	    } else {
  1089             } else {
  1090 		rslt = __MKINT(currentPosition);
  1090                 rslt = __MKINT(currentPosition);
  1091 	    }
  1091             }
  1092 	    RETURN ( rslt );
  1092             RETURN ( rslt );
  1093 	}
  1093         }
  1094 	error = __mkSmallInteger(__threadErrno);
  1094 # ifdef __win32__
       
  1095         __threadErrno = __WIN32_ERR(GetLastError());
       
  1096 # endif
       
  1097         error = __mkSmallInteger(__threadErrno);
  1095     }
  1098     }
  1096 %}.
  1099 %}.
  1097     error notNil ifTrue:[
  1100     error notNil ifTrue:[
  1098 	lastErrorNumber := error.
  1101         lastErrorNumber := error.
  1099 	^ self ioError:error.
  1102         ^ self ioError:error.
  1100     ].
  1103     ].
  1101     handle isNil ifTrue:[^ self errorNotOpen].
  1104     handle isNil ifTrue:[^ self errorNotOpen].
  1102     ^ self primitiveFailed
  1105     ^ self primitiveFailed
       
  1106 
       
  1107     "Modified: / 22-11-2018 / 14:54:09 / Stefan Vogel"
  1103 !
  1108 !
  1104 
  1109 
  1105 position:newPos
  1110 position:newPos
  1106     "set the read/write position in the file"
  1111     "set the read/write position in the file"
  1107 
  1112 
  1110     HFILE f;
  1115     HFILE f;
  1111     long ret;
  1116     long ret;
  1112     OBJ fp;
  1117     OBJ fp;
  1113 
  1118 
  1114     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
  1119     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
  1115 	if ((fp = __INST(handle)) != nil) {
  1120         if ((fp = __INST(handle)) != nil) {
  1116 
  1121 
  1117 #if defined(_LFS_LARGE_FILE) && !defined(__win32__)
  1122 #if defined(_LFS_LARGE_FILE) && !defined(__win32__)
  1118 # define FSEEK fseeko
  1123 # define FSEEK fseeko
  1119 	    off_t nP;
  1124             off_t nP;
  1120 #else
  1125 #else
  1121 #define FSEEK fseek
  1126 #define FSEEK fseek
  1122 	    long nP;
  1127             long nP;
  1123 #endif
  1128 #endif
  1124 
  1129 
  1125 	    if (__isSmallInteger(newPos)) {
  1130             if (__isSmallInteger(newPos)) {
  1126 		nP = __intVal(newPos);
  1131                 nP = __intVal(newPos);
  1127 		if (nP < 0) {
  1132                 if (nP < 0) {
  1128 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1133                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1129 		    goto getOutOfHere;
  1134                     goto getOutOfHere;
  1130 		}
  1135                 }
  1131 	    } else {
  1136             } else {
  1132 		nP = __signedLongIntVal(newPos);
  1137                 nP = __signedLongIntVal(newPos);
  1133 		if (nP < 0) {
  1138                 if (nP < 0) {
  1134 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1139                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1135 		    goto getOutOfHere;
  1140                     goto getOutOfHere;
  1136 		}
  1141                 }
  1137 		if (nP == 0) {
  1142                 if (nP == 0) {
  1138 		    if (sizeof(nP) == 8) {
  1143                     if (sizeof(nP) == 8) {
  1139 			if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1144                         if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1140 			    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1145                             __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1141 			    goto getOutOfHere;
  1146                             goto getOutOfHere;
  1142 			}
  1147                         }
  1143 		    } else {
  1148                     } else {
  1144 			__INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1149                         __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1145 			goto getOutOfHere;
  1150                         goto getOutOfHere;
  1146 		    }
  1151                     }
  1147 		}
  1152                 }
  1148 	    }
  1153             }
  1149 
  1154 
  1150 	    f = __FILEVal(fp);
  1155             f = __FILEVal(fp);
  1151 
  1156 
  1152 	    do {
  1157             do {
  1153 #if defined(DO_WRAP_CALL_FSEEK)
  1158 #if defined(DO_WRAP_CALL_FSEEK)
  1154 		__threadErrno = 0;
  1159                 __threadErrno = 0;
  1155 		if (__INST(buffered) == true) {
  1160                 if (__INST(buffered) == true) {
  1156 		    ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1161                     ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1157 		} else {
  1162                 } else {
  1158 		    __INST(readAhead) = nil;
  1163                     __INST(readAhead) = nil;
  1159 		    ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1164                     ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1160 		}
  1165                 }
  1161 #else
  1166 #else
  1162 		if (__INST(buffered) == true) {
  1167                 if (__INST(buffered) == true) {
  1163 		    ret = FSEEK(f, nP, SEEK_SET);
  1168                     ret = FSEEK(f, nP, SEEK_SET);
  1164 		} else {
  1169                 } else {
  1165 		    ret = lseek(fileno(f), nP, SEEK_SET);
  1170                     ret = lseek(fileno(f), nP, SEEK_SET);
  1166 		}
  1171                 }
  1167 		__threadErrno = errno;
  1172                 __threadErrno = errno;
  1168 #endif
  1173 #endif
  1169 	    } while ((ret < 0) && (__threadErrno == EINTR));
  1174             } while ((ret < 0) && (__threadErrno == EINTR));
  1170 	    if (ret >= 0) {
  1175             if (ret >= 0) {
  1171 		__INST(position) = newPos; __STORE(self, newPos);
  1176                 __INST(position) = newPos; __STORE(self, newPos);
  1172 		/*
  1177                 /*
  1173 		 * just to make certain ...
  1178                  * just to make certain ...
  1174 		 */
  1179                  */
  1175 		__INST(hitEOF) = false;
  1180                 __INST(hitEOF) = false;
  1176 		RETURN ( self );
  1181                 RETURN ( self );
  1177 	    }
  1182             }
  1178 	    error = __mkSmallInteger(__threadErrno);
  1183 # ifdef __win32__
  1179 	}
  1184             __threadErrno = __WIN32_ERR(GetLastError());
       
  1185 # endif
       
  1186             error = __mkSmallInteger(__threadErrno);
       
  1187         }
  1180     }
  1188     }
  1181     getOutOfHere: ;
  1189     getOutOfHere: ;
  1182 #undef FSEEK
  1190 #undef FSEEK
  1183 %}.
  1191 %}.
  1184     canPosition == false ifTrue:[
  1192     canPosition == false ifTrue:[
  1185 	"/ position by rewinding & re-reading everything up-to
  1193         "/ position by rewinding & re-reading everything up-to
  1186 	"/ that point.
  1194         "/ that point.
  1187 	^ self slowPosition:newPos
  1195         ^ self slowPosition:newPos
  1188     ].
  1196     ].
  1189     error notNil ifTrue:[
  1197     error notNil ifTrue:[
  1190 	lastErrorNumber := error.
  1198         lastErrorNumber := error.
  1191 	(OperatingSystem errorSymbolForNumber:error) == #EINVAL ifTrue:[
  1199         (OperatingSystem errorSymbolForNumber:error) == #EINVAL ifTrue:[
  1192 	    "/ invalid position
  1200             "/ invalid position
  1193 	    ^ self positionError.
  1201             ^ self positionError.
  1194 	].
  1202         ].
  1195 	"/ assume I/O error
  1203         "/ assume I/O error
  1196 	^ self ioError:error.
  1204         ^ self ioError:error.
  1197     ].
  1205     ].
  1198     handle isNil ifTrue:[^ self errorNotOpen].
  1206     handle isNil ifTrue:[^ self errorNotOpen].
  1199 
  1207 
  1200     rslt := self positionFile:handle position:newPos.
  1208     rslt := self positionFile:handle position:newPos.
  1201     rslt >= 0 ifTrue:[
  1209     rslt >= 0 ifTrue:[
  1202 	position := newPos.
  1210         position := newPos.
  1203     ] ifFalse:[
  1211     ] ifFalse:[
  1204 	hitEOF := true.
  1212         hitEOF := true.
  1205     ]
  1213     ]
       
  1214 
       
  1215     "Modified: / 22-11-2018 / 14:54:17 / Stefan Vogel"
  1206 !
  1216 !
  1207 
  1217 
  1208 reset
  1218 reset
  1209     "additionaly to setting the position to the beginning of the file,
  1219     "additionaly to setting the position to the beginning of the file,
  1210      re-open a previously closed file. This behavior is compatible
  1220      re-open a previously closed file. This behavior is compatible
  1231 %{
  1241 %{
  1232     HFILE f;
  1242     HFILE f;
  1233     off_t ret;
  1243     off_t ret;
  1234 
  1244 
  1235     if (__INST(handle) != nil) {
  1245     if (__INST(handle) != nil) {
  1236 	f = __FILEVal(__INST(handle));
  1246         f = __FILEVal(__INST(handle));
  1237 	__INST(position) = nil;    /* i.e. unknown */
  1247         __INST(position) = nil;    /* i.e. unknown */
  1238 	do {
  1248         do {
  1239 #ifdef __win32__
  1249 #ifdef __win32__
  1240 	    __threadErrno = 0;
  1250             __threadErrno = 0;
  1241 	    if (__INST(buffered) == true) {
  1251             if (__INST(buffered) == true) {
  1242 		ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);
  1252                 ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);
  1243 	    } else {
  1253             } else {
  1244 		__INST(readAhead) = nil;
  1254                 __INST(readAhead) = nil;
  1245 		ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
  1255                 ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
  1246 	    }
  1256             }
  1247 #else
  1257 #else
  1248 	    if (__INST(buffered) == true) {
  1258             if (__INST(buffered) == true) {
  1249 # ifdef _LFS_LARGE_FILE
  1259 # ifdef _LFS_LARGE_FILE
  1250 		ret = fseeko(f, (off_t)0, SEEK_END);
  1260                 ret = fseeko(f, (off_t)0, SEEK_END);
  1251 # else
  1261 # else
  1252 		ret = fseek(f, 0L, SEEK_END);
  1262                 ret = fseek(f, 0L, SEEK_END);
  1253 # endif
  1263 # endif
  1254 	    } else {
  1264             } else {
  1255 		ret = lseek(fileno(f), (off_t)0, SEEK_END);
  1265                 ret = lseek(fileno(f), (off_t)0, SEEK_END);
  1256 	    }
  1266             }
  1257 #endif
  1267 #endif
  1258 	} while ((ret < 0) && (__threadErrno == EINTR));
  1268         } while ((ret < 0) && (__threadErrno == EINTR));
  1259 	if (ret >= 0) {
  1269         if (ret >= 0) {
  1260 	    RETURN ( self );
  1270             RETURN ( self );
  1261 	}
  1271         }
  1262 	error = __mkSmallInteger(__threadErrno);
  1272 # ifdef __win32__
       
  1273         __threadErrno = __WIN32_ERR(GetLastError());
       
  1274 # endif
       
  1275         error = __mkSmallInteger(__threadErrno);
  1263     }
  1276     }
  1264 %}.
  1277 %}.
  1265     error notNil ifTrue:[
  1278     error notNil ifTrue:[
  1266 	lastErrorNumber := error.
  1279         lastErrorNumber := error.
  1267 	self ioError:error.
  1280         self ioError:error.
  1268 	^ self.
  1281         ^ self.
  1269     ].
  1282     ].
  1270     handle isNil ifTrue:[^ self errorNotOpen].
  1283     handle isNil ifTrue:[^ self errorNotOpen].
  1271     ^ self primitiveFailed
  1284     ^ self primitiveFailed
       
  1285 
       
  1286     "Modified: / 22-11-2018 / 14:54:29 / Stefan Vogel"
  1272 !
  1287 !
  1273 
  1288 
  1274 slowPosition:newPos
  1289 slowPosition:newPos
  1275     "position the file by re-reading everything up-to newPos.
  1290     "position the file by re-reading everything up-to newPos.
  1276      The effect is the same as that of #position:, but its much slower.
  1291      The effect is the same as that of #position:, but its much slower.
  1388 %{
  1403 %{
  1389     HFILE f = NULL;
  1404     HFILE f = NULL;
  1390     int pass = 0;
  1405     int pass = 0;
  1391 
  1406 
  1392     if (!__isNonNilObject(encodedPathName)
  1407     if (!__isNonNilObject(encodedPathName)
  1393 	|| !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1408         || !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1394 	    goto badArgument;
  1409             goto badArgument;
  1395 
  1410 
  1396 retry:
  1411 retry:
  1397 #ifdef __VMS__
  1412 #ifdef __VMS__
  1398       if (__isStringLike(encodedPathName)) {
  1413       if (__isStringLike(encodedPathName)) {
  1399 	do {
  1414         do {
  1400 	    /*
  1415             /*
  1401 	     * allow passing additional RMS arguments.
  1416              * allow passing additional RMS arguments.
  1402 	     * stupid: DEC does not seem to offer an interface for passing a char **.
  1417              * stupid: DEC does not seem to offer an interface for passing a char **.
  1403 	     */
  1418              */
  1404 	    __threadErrno = 0;
  1419             __threadErrno = 0;
  1405 
  1420 
  1406 	    {
  1421             {
  1407 		if (__isArrayLike(attributeSpec)) {
  1422                 if (__isArrayLike(attributeSpec)) {
  1408 		    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1423                     OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1409 		    int numAttrib = 0;
  1424                     int numAttrib = 0;
  1410 		    int i;
  1425                     int i;
  1411 
  1426 
  1412 		    numAttrib = __arraySize(attributeSpec);
  1427                     numAttrib = __arraySize(attributeSpec);
  1413 		    for (i=0; i<numAttrib;i++) {
  1428                     for (i=0; i<numAttrib;i++) {
  1414 			if (! __isStringLike(ap[i])) {
  1429                         if (! __isStringLike(ap[i])) {
  1415 			    __threadErrno = EINVAL; /* invalid argument */
  1430                             __threadErrno = EINVAL; /* invalid argument */
  1416 			    goto getOutOfHere;
  1431                             goto getOutOfHere;
  1417 			}
  1432                         }
  1418 		    }
  1433                     }
  1419 		    switch (numAttrib) {
  1434                     switch (numAttrib) {
  1420 			case 0:
  1435                         case 0:
  1421 			    __BEGIN_INTERRUPTABLE__
  1436                             __BEGIN_INTERRUPTABLE__
  1422 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1437                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1423 			    __END_INTERRUPTABLE__
  1438                             __END_INTERRUPTABLE__
  1424 			    break;
  1439                             break;
  1425 			case 1:
  1440                         case 1:
  1426 			    __BEGIN_INTERRUPTABLE__
  1441                             __BEGIN_INTERRUPTABLE__
  1427 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1442                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1428 				      __stringVal(ap[0]));
  1443                                       __stringVal(ap[0]));
  1429 			    __END_INTERRUPTABLE__
  1444                             __END_INTERRUPTABLE__
  1430 			    break;
  1445                             break;
  1431 			case 2:
  1446                         case 2:
  1432 			    __BEGIN_INTERRUPTABLE__
  1447                             __BEGIN_INTERRUPTABLE__
  1433 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1448                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1434 				      __stringVal(ap[0]), __stringVal(ap[1]));
  1449                                       __stringVal(ap[0]), __stringVal(ap[1]));
  1435 			    __END_INTERRUPTABLE__
  1450                             __END_INTERRUPTABLE__
  1436 			    break;
  1451                             break;
  1437 			case 3:
  1452                         case 3:
  1438 			    __BEGIN_INTERRUPTABLE__
  1453                             __BEGIN_INTERRUPTABLE__
  1439 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1454                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1440 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1455                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1441 			    __END_INTERRUPTABLE__
  1456                             __END_INTERRUPTABLE__
  1442 			    break;
  1457                             break;
  1443 			case 4:
  1458                         case 4:
  1444 			    __BEGIN_INTERRUPTABLE__
  1459                             __BEGIN_INTERRUPTABLE__
  1445 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1460                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1446 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1461                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1447 				      __stringVal(ap[3]));
  1462                                       __stringVal(ap[3]));
  1448 			    __END_INTERRUPTABLE__
  1463                             __END_INTERRUPTABLE__
  1449 			    break;
  1464                             break;
  1450 			case 5:
  1465                         case 5:
  1451 			    __BEGIN_INTERRUPTABLE__
  1466                             __BEGIN_INTERRUPTABLE__
  1452 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1467                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1453 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1468                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1454 				      __stringVal(ap[3]), __stringVal(ap[4]));
  1469                                       __stringVal(ap[3]), __stringVal(ap[4]));
  1455 			    __END_INTERRUPTABLE__
  1470                             __END_INTERRUPTABLE__
  1456 			    break;
  1471                             break;
  1457 			case 6:
  1472                         case 6:
  1458 			    __BEGIN_INTERRUPTABLE__
  1473                             __BEGIN_INTERRUPTABLE__
  1459 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1474                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1460 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1475                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1461 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1476                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1462 			    __END_INTERRUPTABLE__
  1477                             __END_INTERRUPTABLE__
  1463 			    break;
  1478                             break;
  1464 			case 7:
  1479                         case 7:
  1465 			    __BEGIN_INTERRUPTABLE__
  1480                             __BEGIN_INTERRUPTABLE__
  1466 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1481                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1467 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1482                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1468 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1483                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1469 				      __stringVal(ap[6]));
  1484                                       __stringVal(ap[6]));
  1470 			    __END_INTERRUPTABLE__
  1485                             __END_INTERRUPTABLE__
  1471 			    break;
  1486                             break;
  1472 			case 8:
  1487                         case 8:
  1473 			    __BEGIN_INTERRUPTABLE__
  1488                             __BEGIN_INTERRUPTABLE__
  1474 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1489                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1475 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1490                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1476 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1491                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1477 				      __stringVal(ap[6]), __stringVal(ap[7]));
  1492                                       __stringVal(ap[6]), __stringVal(ap[7]));
  1478 			    __END_INTERRUPTABLE__
  1493                             __END_INTERRUPTABLE__
  1479 			    break;
  1494                             break;
  1480 			case 9:
  1495                         case 9:
  1481 			    __BEGIN_INTERRUPTABLE__
  1496                             __BEGIN_INTERRUPTABLE__
  1482 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1497                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1483 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1498                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1484 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1499                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1485 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1500                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1486 			    __END_INTERRUPTABLE__
  1501                             __END_INTERRUPTABLE__
  1487 			    break;
  1502                             break;
  1488 			case 10:
  1503                         case 10:
  1489 			    __BEGIN_INTERRUPTABLE__
  1504                             __BEGIN_INTERRUPTABLE__
  1490 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1505                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1491 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1506                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1492 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1507                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1493 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1508                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1494 				      __stringVal(ap[9]));
  1509                                       __stringVal(ap[9]));
  1495 			    __END_INTERRUPTABLE__
  1510                             __END_INTERRUPTABLE__
  1496 			    break;
  1511                             break;
  1497 			default:
  1512                         default:
  1498 			    __threadErrno = E2BIG; /* too many args */
  1513                             __threadErrno = E2BIG; /* too many args */
  1499 			    goto getOutOfHere;
  1514                             goto getOutOfHere;
  1500 		    }
  1515                     }
  1501 		} else if (attributeSpec != nil) {
  1516                 } else if (attributeSpec != nil) {
  1502 		    __threadErrno = EINVAL; /* invalid argument */
  1517                     __threadErrno = EINVAL; /* invalid argument */
  1503 		    goto getOutOfHere;
  1518                     goto getOutOfHere;
  1504 		} else {
  1519                 } else {
  1505 		    /*
  1520                     /*
  1506 		     * create file as sequential streamLF by default.
  1521                      * create file as sequential streamLF by default.
  1507 		     */
  1522                      */
  1508 		    __BEGIN_INTERRUPTABLE__
  1523                     __BEGIN_INTERRUPTABLE__
  1509 		    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1524                     f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1510 		    __END_INTERRUPTABLE__
  1525                     __END_INTERRUPTABLE__
  1511 		}
  1526                 }
  1512 	    }
  1527             }
  1513 	} while ((f == NULL) && (__threadErrno == EINTR));
  1528         } while ((f == NULL) && (__threadErrno == EINTR));
  1514       }
  1529       }
  1515 #else /* not VMS */
  1530 #else /* not VMS */
  1516 
  1531 
  1517 # ifdef __win32__
  1532 # ifdef __win32__
  1518     {
  1533     {
  1519 	  DWORD share = 0, access = 0, create = 0, attr = 0;
  1534           DWORD share = 0, access = 0, create = 0, attr = 0;
  1520 	  char * __openmode;
  1535           char * __openmode;
  1521 	  HANDLE handle;
  1536           HANDLE handle;
  1522 	  SECURITY_ATTRIBUTES sa;
  1537           SECURITY_ATTRIBUTES sa;
  1523 
  1538 
  1524 	  if (__isStringLike(openmode)) {
  1539           if (__isStringLike(openmode)) {
  1525 	      share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1540               share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1526 	      __openmode = __stringVal(openmode);
  1541               __openmode = __stringVal(openmode);
  1527 	      if (strcmp(__openmode, "rb") == 0) {
  1542               if (strcmp(__openmode, "rb") == 0) {
  1528 		  access = GENERIC_READ;
  1543                   access = GENERIC_READ;
  1529 		  create = OPEN_EXISTING;
  1544                   create = OPEN_EXISTING;
  1530 	      } else if (strcmp(__openmode, "rb+") == 0) {
  1545               } else if (strcmp(__openmode, "rb+") == 0) {
  1531 		  access = GENERIC_READ | GENERIC_WRITE;
  1546                   access = GENERIC_READ | GENERIC_WRITE;
  1532 		  create = OPEN_EXISTING;
  1547                   create = OPEN_EXISTING;
  1533 	      } else if (strcmp(__openmode, "wb") == 0) {
  1548               } else if (strcmp(__openmode, "wb") == 0) {
  1534 		  access = GENERIC_WRITE;
  1549                   access = GENERIC_WRITE;
  1535 		  create = CREATE_ALWAYS;
  1550                   create = CREATE_ALWAYS;
  1536 	      } else if (strcmp(__openmode, "wb+") == 0) {
  1551               } else if (strcmp(__openmode, "wb+") == 0) {
  1537 		  access = GENERIC_READ | GENERIC_WRITE;
  1552                   access = GENERIC_READ | GENERIC_WRITE;
  1538 		  create = CREATE_ALWAYS;
  1553                   create = CREATE_ALWAYS;
  1539 	      } else if (strcmp(__openmode, "ab") == 0) {
  1554               } else if (strcmp(__openmode, "ab") == 0) {
  1540 		  access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1555                   access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1541 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1556                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1542 		  create = OPEN_ALWAYS;
  1557                   create = OPEN_ALWAYS;
  1543 	      } else if (strcmp(__openmode, "ab+") == 0) {
  1558               } else if (strcmp(__openmode, "ab+") == 0) {
  1544 		  access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1559                   access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1545 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1560                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1546 		  create = OPEN_ALWAYS;
  1561                   create = OPEN_ALWAYS;
  1547 	      } else {
  1562               } else {
  1548 		  console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1563                   console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1549 	      }
  1564               }
  1550 	  } else if (__isArrayLike(openmode)) {
  1565           } else if (__isArrayLike(openmode)) {
  1551 	      OBJ *ap = __arrayVal(openmode);
  1566               OBJ *ap = __arrayVal(openmode);
  1552 	      int numAttrib = __arraySize(openmode);
  1567               int numAttrib = __arraySize(openmode);
  1553 	      int i;
  1568               int i;
  1554 
  1569 
  1555 	      __openmode = "rb+";
  1570               __openmode = "rb+";
  1556 
  1571 
  1557 	      for (i=0; i<numAttrib; i++) {
  1572               for (i=0; i<numAttrib; i++) {
  1558 		  OBJ attrSym = ap[i];
  1573                   OBJ attrSym = ap[i];
  1559 
  1574 
  1560 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1575                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1561 		      share |= FILE_SHARE_READ;
  1576                       share |= FILE_SHARE_READ;
  1562 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1577                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1563 		      share |= FILE_SHARE_WRITE;
  1578                       share |= FILE_SHARE_WRITE;
  1564 
  1579 
  1565 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1580                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1566 		      access |= GENERIC_READ;
  1581                       access |= GENERIC_READ;
  1567 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1582                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1568 		      access |= GENERIC_WRITE;
  1583                       access |= GENERIC_WRITE;
  1569 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1584                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1570 		      access |= GENERIC_READ|GENERIC_WRITE;
  1585                       access |= GENERIC_READ|GENERIC_WRITE;
  1571 
  1586 
  1572 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1587                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1573 		      create |= CREATE_NEW;
  1588                       create |= CREATE_NEW;
  1574 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1589                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1575 		      create |= CREATE_ALWAYS;
  1590                       create |= CREATE_ALWAYS;
  1576 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1591                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1577 		      create |= OPEN_EXISTING;
  1592                       create |= OPEN_EXISTING;
  1578 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1593                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1579 		      create |= OPEN_ALWAYS;
  1594                       create |= OPEN_ALWAYS;
  1580 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1595                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1581 		      create |= TRUNCATE_EXISTING;
  1596                       create |= TRUNCATE_EXISTING;
  1582 
  1597 
  1583 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1598                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1584 		      attr |= FILE_ATTRIBUTE_HIDDEN;
  1599                       attr |= FILE_ATTRIBUTE_HIDDEN;
  1585 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1600                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1586 		      attr |= FILE_ATTRIBUTE_READONLY;
  1601                       attr |= FILE_ATTRIBUTE_READONLY;
  1587 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1602                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1588 		      attr |= FILE_FLAG_WRITE_THROUGH;
  1603                       attr |= FILE_FLAG_WRITE_THROUGH;
  1589 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1604                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1590 		      attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1605                       attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1591 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1606                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1592 		      attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1607                       attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1593 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1608                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1594 		      __openmode = __stringVal(attrSym);
  1609                       __openmode = __stringVal(attrSym);
  1595 		  } else {
  1610                   } else {
  1596 		      console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1611                       console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1597 		  }
  1612                   }
  1598 	      }
  1613               }
  1599 	  }
  1614           }
  1600 	  if (create == 0) {
  1615           if (create == 0) {
  1601 //              argumentError = @symbol(missingCreateMode);
  1616 //              argumentError = @symbol(missingCreateMode);
  1602 	      goto badArgument;
  1617               goto badArgument;
  1603 	  }
  1618           }
  1604 	  if (attr == 0) {
  1619           if (attr == 0) {
  1605 	      attr = FILE_ATTRIBUTE_NORMAL;
  1620               attr = FILE_ATTRIBUTE_NORMAL;
  1606 	  }
  1621           }
  1607 
  1622 
  1608 	  /*
  1623           /*
  1609 	   * create security attributes - make handle inheritable by subprocesses
  1624            * create security attributes - make handle inheritable by subprocesses
  1610 	   */
  1625            */
  1611 	  memset(&sa, 0, sizeof (sa));
  1626           memset(&sa, 0, sizeof (sa));
  1612 	  sa.nLength = sizeof( sa );
  1627           sa.nLength = sizeof( sa );
  1613 	  // sa.bInheritHandle = TRUE;
  1628           // sa.bInheritHandle = TRUE;
  1614 	  sa.bInheritHandle = FALSE;
  1629           sa.bInheritHandle = FALSE;
  1615 
  1630 
  1616 	  if (__isStringLike(pathName)) {
  1631           if (__isStringLike(pathName)) {
  1617 		char _aPathName[MAXPATHLEN];
  1632                 char _aPathName[MAXPATHLEN];
  1618 
  1633 
  1619 		strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1634                 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1620 		do {
  1635                 do {
  1621 		    __threadErrno = 0;
  1636                     __threadErrno = 0;
  1622 		    handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1637                     handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1623 		    if (__threadErrno == EINTR) {
  1638                     if (__threadErrno == EINTR) {
  1624 			handle = INVALID_HANDLE_VALUE;
  1639                         handle = INVALID_HANDLE_VALUE;
  1625 		    }
  1640                     }
  1626 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1641                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1627 	  } else if (__isUnicode16String(pathName)) {
  1642           } else if (__isUnicode16String(pathName)) {
  1628 		wchar_t _aPathName[MAXPATHLEN+1];
  1643                 wchar_t _aPathName[MAXPATHLEN+1];
  1629 		int i, l;
  1644                 int i, l;
  1630 
  1645 
  1631 		l = __unicode16StringSize(pathName);
  1646                 l = __unicode16StringSize(pathName);
  1632 		if (l > MAXPATHLEN) l = MAXPATHLEN;
  1647                 if (l > MAXPATHLEN) l = MAXPATHLEN;
  1633 		for (i=0; i<l; i++) {
  1648                 for (i=0; i<l; i++) {
  1634 		    _aPathName[i] = __unicode16StringVal(pathName)[i];
  1649                     _aPathName[i] = __unicode16StringVal(pathName)[i];
  1635 		}
  1650                 }
  1636 		_aPathName[i] = 0;
  1651                 _aPathName[i] = 0;
  1637 
  1652 
  1638 		do {
  1653                 do {
  1639 		    __threadErrno = 0;
  1654                     __threadErrno = 0;
  1640 		    handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1655                     handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1641 		    if (__threadErrno == EINTR) {
  1656                     if (__threadErrno == EINTR) {
  1642 			handle = INVALID_HANDLE_VALUE;
  1657                         handle = INVALID_HANDLE_VALUE;
  1643 		    }
  1658                     }
  1644 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1659                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1645 	  }
  1660           }
  1646 	  if (handle != INVALID_HANDLE_VALUE) {
  1661           if (handle != INVALID_HANDLE_VALUE) {
  1647 	      int fd;
  1662               int fd;
  1648 	      extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1663               extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1649 
  1664 
  1650 	      __stxWrapApiEnterCritical();
  1665               __stxWrapApiEnterCritical();
  1651 	      fd = _open_osfhandle((long)handle, O_BINARY);
  1666               fd = _open_osfhandle((long)handle, O_BINARY);
  1652 	      if (fd < 0) {
  1667               if (fd < 0) {
  1653 		  if (__threadErrno == 0) {
  1668                   if (__threadErrno == 0) {
  1654 		      // no more file descriptors
  1669                       // no more file descriptors
  1655 		      __threadErrno = EMFILE;
  1670                       __threadErrno = EMFILE;
  1656 		  }
  1671                   }
  1657 		  CloseHandle(handle);
  1672                   CloseHandle(handle);
  1658 	      } else {
  1673               } else {
  1659 		  f = fdopen(fd, __openmode);
  1674                   f = fdopen(fd, __openmode);
  1660 	      }
  1675               }
  1661 	      __stxWrapApiLeaveCritical();
  1676               __stxWrapApiLeaveCritical();
  1662 	  }  else {
  1677           }  else {
  1663 	    __threadErrno = __WIN32_ERR(GetLastError());
  1678             __threadErrno = __WIN32_ERR(GetLastError());
  1664 	  }
  1679           }
  1665       }
  1680       }
  1666 # else /* not WIN32 */
  1681 # else /* not WIN32 */
  1667 
  1682 
  1668       if (__isStringLike(encodedPathName)) {
  1683       if (__isStringLike(encodedPathName)) {
  1669 	  int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1684           int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1670 	  int flags = 0;
  1685           int flags = 0;
  1671 	  int fd;
  1686           int fd;
  1672 	  char * __openmode;
  1687           char * __openmode;
  1673 
  1688 
  1674 	  if (__isStringLike(openmode)) {
  1689           if (__isStringLike(openmode)) {
  1675 	      __openmode = __stringVal(openmode);
  1690               __openmode = __stringVal(openmode);
  1676 	      if (strcmp(__openmode, "r") == 0) {
  1691               if (strcmp(__openmode, "r") == 0) {
  1677 		  flags = O_RDONLY;
  1692                   flags = O_RDONLY;
  1678 	      } else if (strcmp(__openmode, "r+") == 0) {
  1693               } else if (strcmp(__openmode, "r+") == 0) {
  1679 		  flags = O_RDWR;
  1694                   flags = O_RDWR;
  1680 	      } else if (strcmp(__openmode, "w") == 0) {
  1695               } else if (strcmp(__openmode, "w") == 0) {
  1681 		  flags = O_WRONLY | O_CREAT | O_TRUNC;
  1696                   flags = O_WRONLY | O_CREAT | O_TRUNC;
  1682 	      } else if (strcmp(__openmode, "w+") == 0) {
  1697               } else if (strcmp(__openmode, "w+") == 0) {
  1683 		  flags = O_RDWR | O_CREAT | O_TRUNC;
  1698                   flags = O_RDWR | O_CREAT | O_TRUNC;
  1684 	      } else if (strcmp(__openmode, "a") == 0) {
  1699               } else if (strcmp(__openmode, "a") == 0) {
  1685 		  flags = O_WRONLY | O_CREAT | O_APPEND;
  1700                   flags = O_WRONLY | O_CREAT | O_APPEND;
  1686 	      } else if (strcmp(__openmode, "a+") == 0) {
  1701               } else if (strcmp(__openmode, "a+") == 0) {
  1687 		  flags = O_RDWR | O_CREAT| O_APPEND;
  1702                   flags = O_RDWR | O_CREAT| O_APPEND;
  1688 	      } else {
  1703               } else {
  1689 		  console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1704                   console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1690 	      }
  1705               }
  1691 	  } else if (__isArrayLike(openmode)) {
  1706           } else if (__isArrayLike(openmode)) {
  1692 	      OBJ *ap = __arrayVal(openmode);
  1707               OBJ *ap = __arrayVal(openmode);
  1693 	      int numAttrib = __arraySize(openmode);
  1708               int numAttrib = __arraySize(openmode);
  1694 	      int i;
  1709               int i;
  1695 
  1710 
  1696 	      __openmode = "r+";
  1711               __openmode = "r+";
  1697 
  1712 
  1698 	      for (i=0; i<numAttrib; i++) {
  1713               for (i=0; i<numAttrib; i++) {
  1699 		  OBJ attrSym = ap[i];
  1714                   OBJ attrSym = ap[i];
  1700 
  1715 
  1701 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1716                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1702 		      // ignore
  1717                       // ignore
  1703 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1718                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1704 		     // ignore
  1719                      // ignore
  1705 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1720                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1706 		      flags |= O_RDONLY;
  1721                       flags |= O_RDONLY;
  1707 		      __openmode = "r";
  1722                       __openmode = "r";
  1708 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1723                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1709 		      flags |= O_WRONLY;
  1724                       flags |= O_WRONLY;
  1710 		      __openmode = "w";
  1725                       __openmode = "w";
  1711 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1726                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1712 		      flags |= O_RDWR;
  1727                       flags |= O_RDWR;
  1713 		      __openmode = "r+";
  1728                       __openmode = "r+";
  1714 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1729                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1715 		      flags |= O_CREAT|O_EXCL;
  1730                       flags |= O_CREAT|O_EXCL;
  1716 		      accessMode = 0600;     // simulate mkstemp()
  1731                       accessMode = 0600;     // simulate mkstemp()
  1717 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1732                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1718 		      flags |= O_CREAT|O_TRUNC;
  1733                       flags |= O_CREAT|O_TRUNC;
  1719 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1734                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1720 		      // nothing to be set
  1735                       // nothing to be set
  1721 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1736                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1722 		      flags |= O_CREAT;
  1737                       flags |= O_CREAT;
  1723 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1738                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1724 		      flags |= O_TRUNC;
  1739                       flags |= O_TRUNC;
  1725 
  1740 
  1726 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1741                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1727 		      // ignore
  1742                       // ignore
  1728 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1743                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1729 		      accessMode &= 0444;
  1744                       accessMode &= 0444;
  1730 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1745                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1731 #ifdef O_DIRECT
  1746 #ifdef O_DIRECT
  1732 		      flags |= O_DIRECT;
  1747                       flags |= O_DIRECT;
  1733 #endif
  1748 #endif
  1734 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1749                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1735 		      // ignore
  1750                       // ignore
  1736 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1751                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1737 		      // ignore;
  1752                       // ignore;
  1738 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1753                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1739 		      __openmode = __stringVal(attrSym);
  1754                       __openmode = __stringVal(attrSym);
  1740 		  } else {
  1755                   } else {
  1741 		      console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1756                       console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1742 		  }
  1757                   }
  1743 	      }
  1758               }
  1744 	  }
  1759           }
  1745 	  do {
  1760           do {
  1746 	      __BEGIN_INTERRUPTABLE__
  1761               __BEGIN_INTERRUPTABLE__
  1747 	      fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1762               fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1748 	      __END_INTERRUPTABLE__
  1763               __END_INTERRUPTABLE__
  1749 	  } while ((fd < 0) && (__threadErrno == EINTR));
  1764           } while ((fd < 0) && (__threadErrno == EINTR));
  1750 
  1765 
  1751 	  if (fd >= 0) {
  1766           if (fd >= 0) {
  1752 	      __threadErrno = 0;
  1767               __threadErrno = 0;
  1753 	      f = fdopen(fd, __openmode);
  1768               f = fdopen(fd, __openmode);
  1754 	      if (f == NULL) {
  1769               if (f == NULL) {
  1755 		  close(fd);            // fdopen failed, close before retry.
  1770                   close(fd);            // fdopen failed, close before retry.
  1756 	      }
  1771               }
  1757 	  }
  1772           }
  1758       }
  1773       }
  1759 
  1774 
  1760 # endif /* not WIN32 */
  1775 # endif /* not WIN32 */
  1761 #endif /* not VMS */
  1776 #endif /* not VMS */
  1762 
  1777 
  1763 
  1778 
  1764     if (f == NULL) {
  1779     if (f == NULL) {
  1765 	/*
  1780         /*
  1766 	 * If no filedescriptors available, try to finalize
  1781          * If no filedescriptors available, try to finalize
  1767 	 * possibly collected fd's and try again.
  1782          * possibly collected fd's and try again.
  1768 	 */
  1783          */
  1769 	if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) {
  1784         if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) {
  1770 	    pass = 1;
  1785             pass = 1;
  1771 	    __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1786             __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1772 	    __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1787             __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1773 	    goto retry;
  1788             goto retry;
  1774 	}
  1789         }
  1775     badArgument:
  1790     badArgument:
  1776     getOutOfHere:
  1791     getOutOfHere:
  1777 	error = __mkSmallInteger(__threadErrno);
  1792 # ifdef __win32__
  1778 	__INST(position) = nil;
  1793         __threadErrno = __WIN32_ERR(GetLastError());
       
  1794 # endif
       
  1795         error = __mkSmallInteger(__threadErrno);
       
  1796         __INST(position) = nil;
  1779     } else {
  1797     } else {
  1780 #ifdef __VMS__
  1798 #ifdef __VMS__
  1781 	/*
  1799         /*
  1782 	 * check to see if this is positionable ...
  1800          * check to see if this is positionable ...
  1783 	 */
  1801          */
  1784 	__INST(canPosition) = false;
  1802         __INST(canPosition) = false;
  1785 # ifndef _POSIX_C_SOURCE
  1803 # ifndef _POSIX_C_SOURCE
  1786 	{
  1804         {
  1787 	    struct stat statBuffer;
  1805             struct stat statBuffer;
  1788 
  1806 
  1789 	    if (fstat(fileno(f), &statBuffer) >= 0) {
  1807             if (fstat(fileno(f), &statBuffer) >= 0) {
  1790 		switch (statBuffer.st_fab_rfm) {
  1808                 switch (statBuffer.st_fab_rfm) {
  1791 		    case FAB$C_UDF: /* undefined (also stream binary)   */
  1809                     case FAB$C_UDF: /* undefined (also stream binary)   */
  1792 		    case FAB$C_VAR: /* variable length records          */
  1810                     case FAB$C_VAR: /* variable length records          */
  1793 		    case FAB$C_VFC: /* variable fixed control           */
  1811                     case FAB$C_VFC: /* variable fixed control           */
  1794 		    case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1812                     case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1795 		    default:
  1813                     default:
  1796 			__INST(canPosition) = false;
  1814                         __INST(canPosition) = false;
  1797 			break;
  1815                         break;
  1798 
  1816 
  1799 		    case FAB$C_FIX: /* fixed length records             */
  1817                     case FAB$C_FIX: /* fixed length records             */
  1800 		    case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1818                     case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1801 		    case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1819                     case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1802 			__INST(canPosition) = true;
  1820                         __INST(canPosition) = true;
  1803 			break;
  1821                         break;
  1804 		}
  1822                 }
  1805 	    }
  1823             }
  1806 	}
  1824         }
  1807 # endif
  1825 # endif
  1808 #else /* not VMS */
  1826 #else /* not VMS */
  1809 	__INST(canPosition) = true;
  1827         __INST(canPosition) = true;
  1810 #endif /* not VMS */
  1828 #endif /* not VMS */
  1811 
  1829 
  1812 	if (@global(FileOpenTrace) == true) {
  1830         if (@global(FileOpenTrace) == true) {
  1813 	    console_fprintf(stderr, "fopen %s [FileStream] -> %"_lx_"\n", __stringVal(pathName), (INT)f);
  1831             console_fprintf(stderr, "fopen %s [FileStream] -> %"_lx_"\n", __stringVal(pathName), (INT)f);
  1814 	}
  1832         }
  1815 	if (f != NULL) {
  1833         if (f != NULL) {
  1816 	    OBJ fp;
  1834             OBJ fp;
  1817 
  1835 
  1818 	    wasBlocked = __BLOCKINTERRUPTS();
  1836             wasBlocked = __BLOCKINTERRUPTS();
  1819 #if 0
  1837 #if 0
  1820 	    // The original code was:
  1838             // The original code was:
  1821 	    __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1839             __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1822 	    // but for that, gcc generates wrong code, which loads self (volatile) into
  1840             // but for that, gcc generates wrong code, which loads self (volatile) into
  1823 	    // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1841             // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1824 	    // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1842             // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1825 	    // object.
  1843             // object.
  1826 #else
  1844 #else
  1827 	    fp = __MKEXTERNALADDRESS(f);
  1845             fp = __MKEXTERNALADDRESS(f);
  1828 	    __INST(handle) = fp;
  1846             __INST(handle) = fp;
  1829 	    __STORE(self, fp);
  1847             __STORE(self, fp);
  1830 #endif
  1848 #endif
  1831 	}
  1849         }
  1832     }
  1850     }
  1833 %}.
  1851 %}.
  1834     error notNil ifTrue:[
  1852     error notNil ifTrue:[
  1835 	lastErrorNumber := error.
  1853         lastErrorNumber := error.
  1836 	^ self openError:error.
  1854         ^ self openError:error.
  1837     ].
  1855     ].
  1838     handle isNil ifTrue:[
  1856     handle isNil ifTrue:[
  1839 	^ self openError:0.
  1857         ^ self openError:0.
  1840     ].
  1858     ].
  1841 
  1859 
  1842     buffered := true.   "default is buffered"
  1860     buffered := true.   "default is buffered"
  1843     position := 0.
  1861     position := 0.
  1844     handleType := #filePointer.
  1862     handleType := #filePointer.
  1845     self registerForFinalization.
  1863     self registerForFinalization.
  1846     wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1864     wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1847     ^ handle
  1865     ^ handle
       
  1866 
       
  1867     "Modified: / 22-11-2018 / 14:53:51 / Stefan Vogel"
  1848 !
  1868 !
  1849 
  1869 
  1850 openForAppending
  1870 openForAppending
  1851     "open the file for writeonly appending to the end.
  1871     "open the file for writeonly appending to the end.
  1852      If the file does not exist, raise OpenError;
  1872      If the file does not exist, raise OpenError;
  2018 
  2038 
  2019 #ifdef transputer
  2039 #ifdef transputer
  2020     unsigned int size;
  2040     unsigned int size;
  2021 
  2041 
  2022     if (__INST(handle) != nil) {
  2042     if (__INST(handle) != nil) {
  2023 	f = __FILEVal(__INST(handle));
  2043         f = __FILEVal(__INST(handle));
  2024 	if ((size = filesize(fileno(f))) >= 0) {
  2044         if ((size = filesize(fileno(f))) >= 0) {
  2025 	    RETURN ( __MKUINT(size) );
  2045             RETURN ( __MKUINT(size) );
  2026 	}
  2046         }
  2027     }
  2047     }
  2028 #else
  2048 #else
  2029     struct stat buf;
  2049     struct stat buf;
  2030     int ret;
  2050     int ret;
  2031     int fd;
  2051     int fd;
  2032 
  2052 
  2033     if (__INST(handle) != nil) {
  2053     if (__INST(handle) != nil) {
  2034 	f = __FILEVal(__INST(handle));
  2054         f = __FILEVal(__INST(handle));
  2035 	fd = fileno(f);
  2055         fd = fileno(f);
  2036 	do {
  2056         do {
  2037 	    ret = fstat(fd, &buf);
  2057             ret = fstat(fd, &buf);
  2038 	} while ((ret < 0) && (__threadErrno == EINTR));
  2058         } while ((ret < 0) && (__threadErrno == EINTR));
  2039 	if (ret >= 0) {
  2059         if (ret >= 0) {
  2040 	    OBJ rslt;
  2060             OBJ rslt;
  2041 
  2061 
  2042 	    if (sizeof(buf.st_size) == 8) {
  2062             if (sizeof(buf.st_size) == 8) {
  2043 		rslt = __MKINT64(&buf.st_size);
  2063                 rslt = __MKINT64(&buf.st_size);
  2044 	    } else {
  2064             } else {
  2045 		rslt = __MKINT(buf.st_size);
  2065                 rslt = __MKINT(buf.st_size);
  2046 	    }
  2066             }
  2047 	    RETURN(rslt);
  2067             RETURN(rslt);
  2048 	}
  2068         }
  2049 	error = __mkSmallInteger(__threadErrno);
  2069 # ifdef __win32__
       
  2070         __threadErrno = __WIN32_ERR(GetLastError());
       
  2071 # endif
       
  2072         error = __mkSmallInteger(__threadErrno);
  2050     }
  2073     }
  2051 #endif
  2074 #endif
  2052 %}.
  2075 %}.
  2053 
  2076 
  2054     "could add a fall-back here:
  2077     "could add a fall-back here:
  2055 
  2078 
  2056 	oldPosition := self position.
  2079         oldPosition := self position.
  2057 	self setToEnd.
  2080         self setToEnd.
  2058 	sz := self position.
  2081         sz := self position.
  2059 	self position:oldPosition.
  2082         self position:oldPosition.
  2060 	^ sz
  2083         ^ sz
  2061     "
  2084     "
  2062     error notNil ifTrue:[
  2085     error notNil ifTrue:[
  2063 	lastErrorNumber := error.
  2086         lastErrorNumber := error.
  2064 	self ioError:error.
  2087         self ioError:error.
  2065 	^ self.
  2088         ^ self.
  2066     ].
  2089     ].
  2067     handle isNil ifTrue:[^ self errorNotOpen].
  2090     handle isNil ifTrue:[^ self errorNotOpen].
  2068     ^ self primitiveFailed
  2091     ^ self primitiveFailed
       
  2092 
       
  2093     "Modified: / 22-11-2018 / 14:53:12 / Stefan Vogel"
  2069 !
  2094 !
  2070 
  2095 
  2071 isDirectory
  2096 isDirectory
  2072     ^ OperatingSystem isDirectory:pathName
  2097     ^ OperatingSystem isDirectory:pathName
  2073 !
  2098 !