999 This argument is ignored in UNIX & MSDOS systems. |
999 This argument is ignored in UNIX & MSDOS systems. |
1000 |
1000 |
1001 This is a private entry, but maybe useful to open/create a file in a special mode, |
1001 This is a private entry, but maybe useful to open/create a file in a special mode, |
1002 which is proprietrary to the operatingSystem." |
1002 which is proprietrary to the operatingSystem." |
1003 |
1003 |
1004 |filePointer| |
1004 |wasBlocked| |
1005 |
1005 |
1006 %{ |
1006 %{ |
1007 HFILE f; |
1007 HFILE f; |
1008 HFILE fopen(); |
1008 HFILE fopen(); |
1009 OBJ fp; |
1009 OBJ fp; |
1010 int pass = 0; |
1010 int pass = 0; |
1011 |
1011 |
1012 retry: |
1012 retry: |
1013 if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) { |
1013 if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) { |
1014 #ifdef __VMS__ |
1014 #ifdef __VMS__ |
1015 do { |
1015 do { |
1016 /* |
1016 /* |
1017 * allow passing additional RMS arguments. |
1017 * allow passing additional RMS arguments. |
1018 * stupid: DEC does not seem to offer an interface for passing a char **. |
1018 * stupid: DEC does not seem to offer an interface for passing a char **. |
1019 */ |
1019 */ |
1020 __threadErrno = 0; |
1020 __threadErrno = 0; |
1021 |
1021 |
1022 { |
1022 { |
1023 if (__isArray(attributeSpec)) { |
1023 if (__isArray(attributeSpec)) { |
1024 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1024 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1025 int numAttrib = 0; |
1025 int numAttrib = 0; |
1026 int i; |
1026 int i; |
1027 |
1027 |
1028 numAttrib = __arraySize(attributeSpec); |
1028 numAttrib = __arraySize(attributeSpec); |
1029 for (i=0; i<numAttrib;i++) { |
1029 for (i=0; i<numAttrib;i++) { |
1030 if (! __isString(ap[i])) { |
1030 if (! __isString(ap[i])) { |
1031 f = NULL; |
1031 f = NULL; |
1032 __threadErrno = EINVAL; /* invalid argument */ |
1032 __threadErrno = EINVAL; /* invalid argument */ |
1033 goto getOutOfHere; |
1033 goto getOutOfHere; |
1034 } |
1034 } |
1035 } |
1035 } |
1036 switch (numAttrib) { |
1036 switch (numAttrib) { |
1037 case 0: |
1037 case 0: |
1038 __BEGIN_INTERRUPTABLE__ |
1038 __BEGIN_INTERRUPTABLE__ |
1039 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1039 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1040 __END_INTERRUPTABLE__ |
1040 __END_INTERRUPTABLE__ |
1041 break; |
1041 break; |
1042 case 1: |
1042 case 1: |
1043 __BEGIN_INTERRUPTABLE__ |
1043 __BEGIN_INTERRUPTABLE__ |
1044 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1044 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1045 __stringVal(ap[0])); |
1045 __stringVal(ap[0])); |
1046 __END_INTERRUPTABLE__ |
1046 __END_INTERRUPTABLE__ |
1047 break; |
1047 break; |
1048 case 2: |
1048 case 2: |
1049 __BEGIN_INTERRUPTABLE__ |
1049 __BEGIN_INTERRUPTABLE__ |
1050 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1050 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1051 __stringVal(ap[0]), __stringVal(ap[1])); |
1051 __stringVal(ap[0]), __stringVal(ap[1])); |
1052 __END_INTERRUPTABLE__ |
1052 __END_INTERRUPTABLE__ |
1053 break; |
1053 break; |
1054 case 3: |
1054 case 3: |
1055 __BEGIN_INTERRUPTABLE__ |
1055 __BEGIN_INTERRUPTABLE__ |
1056 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1056 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1057 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1057 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1058 __END_INTERRUPTABLE__ |
1058 __END_INTERRUPTABLE__ |
1059 break; |
1059 break; |
1060 case 4: |
1060 case 4: |
1061 __BEGIN_INTERRUPTABLE__ |
1061 __BEGIN_INTERRUPTABLE__ |
1062 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1062 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1063 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1063 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1064 __stringVal(ap[3])); |
1064 __stringVal(ap[3])); |
1065 __END_INTERRUPTABLE__ |
1065 __END_INTERRUPTABLE__ |
1066 break; |
1066 break; |
1067 case 5: |
1067 case 5: |
1068 __BEGIN_INTERRUPTABLE__ |
1068 __BEGIN_INTERRUPTABLE__ |
1069 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1069 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1070 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1070 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1071 __stringVal(ap[3]), __stringVal(ap[4])); |
1071 __stringVal(ap[3]), __stringVal(ap[4])); |
1072 __END_INTERRUPTABLE__ |
1072 __END_INTERRUPTABLE__ |
1073 break; |
1073 break; |
1074 case 6: |
1074 case 6: |
1075 __BEGIN_INTERRUPTABLE__ |
1075 __BEGIN_INTERRUPTABLE__ |
1076 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1076 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1077 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1077 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1078 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1078 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1079 __END_INTERRUPTABLE__ |
1079 __END_INTERRUPTABLE__ |
1080 break; |
1080 break; |
1081 case 7: |
1081 case 7: |
1082 __BEGIN_INTERRUPTABLE__ |
1082 __BEGIN_INTERRUPTABLE__ |
1083 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1083 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1084 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1084 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1085 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1085 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1086 __stringVal(ap[6])); |
1086 __stringVal(ap[6])); |
1087 __END_INTERRUPTABLE__ |
1087 __END_INTERRUPTABLE__ |
1088 break; |
1088 break; |
1089 case 8: |
1089 case 8: |
1090 __BEGIN_INTERRUPTABLE__ |
1090 __BEGIN_INTERRUPTABLE__ |
1091 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1091 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1092 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1092 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1093 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1093 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1094 __stringVal(ap[6]), __stringVal(ap[7])); |
1094 __stringVal(ap[6]), __stringVal(ap[7])); |
1095 __END_INTERRUPTABLE__ |
1095 __END_INTERRUPTABLE__ |
1096 break; |
1096 break; |
1097 case 9: |
1097 case 9: |
1098 __BEGIN_INTERRUPTABLE__ |
1098 __BEGIN_INTERRUPTABLE__ |
1099 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1099 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1100 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1100 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1101 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1101 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1102 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1102 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1103 __END_INTERRUPTABLE__ |
1103 __END_INTERRUPTABLE__ |
1104 break; |
1104 break; |
1105 case 10: |
1105 case 10: |
1106 __BEGIN_INTERRUPTABLE__ |
1106 __BEGIN_INTERRUPTABLE__ |
1107 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1107 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1108 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1108 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1109 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1109 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1110 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1110 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1111 __stringVal(ap[9])); |
1111 __stringVal(ap[9])); |
1112 __END_INTERRUPTABLE__ |
1112 __END_INTERRUPTABLE__ |
1113 break; |
1113 break; |
1114 default: |
1114 default: |
1115 f = NULL; |
1115 f = NULL; |
1116 __threadErrno = E2BIG; /* too many args */ |
1116 __threadErrno = E2BIG; /* too many args */ |
1117 goto getOutOfHere; |
1117 goto getOutOfHere; |
1118 } |
1118 } |
1119 } else if (attributeSpec != nil) { |
1119 } else if (attributeSpec != nil) { |
1120 f = NULL; |
1120 f = NULL; |
1121 __threadErrno = EINVAL; /* invalid argument */ |
1121 __threadErrno = EINVAL; /* invalid argument */ |
1122 goto getOutOfHere; |
1122 goto getOutOfHere; |
1123 } else { |
1123 } else { |
1124 /* |
1124 /* |
1125 * create file as sequential streamLF by default. |
1125 * create file as sequential streamLF by default. |
1126 */ |
1126 */ |
1127 __BEGIN_INTERRUPTABLE__ |
1127 __BEGIN_INTERRUPTABLE__ |
1128 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1128 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1129 __END_INTERRUPTABLE__ |
1129 __END_INTERRUPTABLE__ |
1130 } |
1130 } |
1131 } |
1131 } |
1132 } while ((f == NULL) && (__threadErrno == EINTR)); |
1132 } while ((f == NULL) && (__threadErrno == EINTR)); |
1133 |
1133 |
1134 #else /* not VMS */ |
1134 #else /* not VMS */ |
1135 |
1135 |
1136 # ifdef WIN32 |
1136 # ifdef WIN32 |
1137 { |
1137 { |
1138 char _aPathName[MAXPATHLEN]; |
1138 char _aPathName[MAXPATHLEN]; |
1139 char _openMode[64]; |
1139 char _openMode[64]; |
1140 |
1140 |
1141 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; |
1141 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; |
1142 strncpy(_openMode, __stringVal(openmode), sizeof(_openMode)-1); _openMode[sizeof(_openMode)-1] = '\0'; |
1142 strncpy(_openMode, __stringVal(openmode), sizeof(_openMode)-1); _openMode[sizeof(_openMode)-1] = '\0'; |
1143 do { |
1143 do { |
1144 __threadErrno = 0; |
1144 __threadErrno = 0; |
1145 f = STX_C_CALL2( "fopen", fopen, _aPathName, _openMode); |
1145 f = STX_C_CALL2( "fopen", fopen, _aPathName, _openMode); |
1146 if (__threadErrno == EINTR) { |
1146 if (__threadErrno == EINTR) { |
1147 f = NULL; |
1147 f = NULL; |
1148 } |
1148 } |
1149 } while ((f == NULL) && (__threadErrno == EINTR)); |
1149 } while ((f == NULL) && (__threadErrno == EINTR)); |
1150 } |
1150 } |
1151 # else /* not WIN32 */ |
1151 # else /* not WIN32 */ |
1152 |
1152 |
1153 do { |
1153 do { |
1154 __BEGIN_INTERRUPTABLE__ |
1154 __BEGIN_INTERRUPTABLE__ |
1155 # ifdef LINUX |
1155 # ifdef LINUX |
1156 /* |
1156 /* |
1157 * LINUX may ret a non-NULL f even when interrupted. |
1157 * LINUX may ret a non-NULL f even when interrupted. |
1158 * Therefore, check errno and fake a null-ret. |
1158 * Therefore, check errno and fake a null-ret. |
1159 */ |
1159 */ |
1160 __threadErrno = 0; |
1160 __threadErrno = 0; |
1161 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1161 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1162 if (__threadErrno == EINTR) |
1162 if (__threadErrno == EINTR) |
1163 f = NULL; |
1163 f = NULL; |
1164 # else /* not LINUX */ |
1164 # else /* not LINUX */ |
1165 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1165 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1166 # endif /* not LINUX */ |
1166 # endif /* not LINUX */ |
1167 __END_INTERRUPTABLE__ |
1167 __END_INTERRUPTABLE__ |
1168 } while ((f == NULL) && (__threadErrno == EINTR)); |
1168 } while ((f == NULL) && (__threadErrno == EINTR)); |
1169 |
1169 |
1170 # endif /* not WIN32 */ |
1170 # endif /* not WIN32 */ |
1171 #endif /* not VMS */ |
1171 #endif /* not VMS */ |
1172 |
1172 |
1173 if (f == NULL) { |
1173 if (f == NULL) { |
1174 /* |
1174 /* |
1175 * If no filedescriptors available, try to finalize |
1175 * If no filedescriptors available, try to finalize |
1176 * possibly collected fd's and try again. |
1176 * possibly collected fd's and try again. |
1177 */ |
1177 */ |
1178 if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) { |
1178 if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) { |
1179 pass = 1; |
1179 pass = 1; |
1180 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1180 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1181 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1181 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1182 goto retry; |
1182 goto retry; |
1183 } |
1183 } |
1184 getOutOfHere: ; |
1184 getOutOfHere: ; |
1185 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1185 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1186 __INST(position) = nil; |
1186 __INST(position) = nil; |
1187 } else { |
1187 } else { |
1188 #ifdef __VMS__ |
1188 #ifdef __VMS__ |
1189 /* |
1189 /* |
1190 * check to see if this is positionable ... |
1190 * check to see if this is positionable ... |
1191 */ |
1191 */ |
1192 __INST(canPosition) = false; |
1192 __INST(canPosition) = false; |
1193 # ifndef _POSIX_C_SOURCE |
1193 # ifndef _POSIX_C_SOURCE |
1194 { |
1194 { |
1195 struct stat statBuffer; |
1195 struct stat statBuffer; |
1196 |
1196 |
1197 if (fstat(fileno(f), &statBuffer) >= 0) { |
1197 if (fstat(fileno(f), &statBuffer) >= 0) { |
1198 switch (statBuffer.st_fab_rfm) { |
1198 switch (statBuffer.st_fab_rfm) { |
1199 case FAB$C_UDF: /* undefined (also stream binary) */ |
1199 case FAB$C_UDF: /* undefined (also stream binary) */ |
1200 case FAB$C_VAR: /* variable length records */ |
1200 case FAB$C_VAR: /* variable length records */ |
1201 case FAB$C_VFC: /* variable fixed control */ |
1201 case FAB$C_VFC: /* variable fixed control */ |
1202 case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */ |
1202 case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */ |
1203 default: |
1203 default: |
1204 __INST(canPosition) = false; |
1204 __INST(canPosition) = false; |
1205 break; |
1205 break; |
1206 |
1206 |
1207 case FAB$C_FIX: /* fixed length records */ |
1207 case FAB$C_FIX: /* fixed length records */ |
1208 case FAB$C_STMLF: /* LF stream (valid only for sequential> */ |
1208 case FAB$C_STMLF: /* LF stream (valid only for sequential> */ |
1209 case FAB$C_STMCR: /* CR stream (valid only for sequential> */ |
1209 case FAB$C_STMCR: /* CR stream (valid only for sequential> */ |
1210 __INST(canPosition) = true; |
1210 __INST(canPosition) = true; |
1211 break; |
1211 break; |
1212 } |
1212 } |
1213 } |
1213 } |
1214 } |
1214 } |
1215 # endif |
1215 # endif |
1216 #else /* not VMS */ |
1216 #else /* not VMS */ |
1217 __INST(canPosition) = true; |
1217 __INST(canPosition) = true; |
1218 #endif /* poor VMS */ |
1218 #endif /* poor VMS */ |
1219 |
1219 |
1220 if (@global(FileOpenTrace) == true) { |
1220 if (@global(FileOpenTrace) == true) { |
1221 fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f); |
1221 fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f); |
1222 } |
1222 } |
1223 |
1223 if (f != NULL) { |
1224 filePointer = __MKOBJ((INT)f); |
1224 wasBlocked = __BLOCKINTERRUPTS(); |
1225 __INST(position) = @global(PositionableStream:ZeroPosition); |
1225 __INST(filePointer) = __MKOBJ((INT)f); |
1226 } |
1226 } |
|
1227 __INST(position) = @global(PositionableStream:ZeroPosition); |
|
1228 } |
1227 } |
1229 } |
1228 %}. |
1230 %}. |
|
1231 filePointer notNil ifTrue:[ |
|
1232 Lobby register:self. |
|
1233 wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts]. |
|
1234 ]. |
1229 ^ filePointer |
1235 ^ filePointer |
1230 ! |
1236 ! |
1231 |
1237 |
1232 openForAppending |
1238 openForAppending |
1233 "open the file for writeonly appending to the end. |
1239 "open the file for writeonly appending to the end. |