changeset 7872 | 634e73a5cdd9 |
parent 7871 | 5c357f1ba0c9 |
child 7874 | 5e0319ca5e60 |
7871:5c357f1ba0c9 | 7872:634e73a5cdd9 |
---|---|
1 " |
1 " |
2 COPYRIGHT (c) 1989 by Claus Gittinger |
2 COPYRIGHT (c) 1989 by Claus Gittinger |
3 All Rights Reserved |
3 All Rights Reserved |
4 |
4 |
5 This software is furnished under a license and may be used |
5 This software is furnished under a license and may be used |
6 only in accordance with the terms of that license and with the |
6 only in accordance with the terms of that license and with the |
7 inclusion of the above copyright notice. This software may not |
7 inclusion of the above copyright notice. This software may not |
8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
11 " |
11 " |
12 |
12 |
13 "{ Package: 'stx:libbasic' }" |
13 "{ Package: 'stx:libbasic' }" |
14 |
14 |
15 ExternalStream subclass:#FileStream |
15 ExternalStream subclass:#FileStream |
16 instanceVariableNames:'pathName canPosition removeOnClose' |
16 instanceVariableNames:'pathName canPosition removeOnClose' |
17 classVariableNames:'UserInitiatedFileSaveQuerySignal' |
17 classVariableNames:'UserInitiatedFileSaveQuerySignal' |
18 poolDictionaries:'' |
18 poolDictionaries:'' |
19 category:'Streams-External' |
19 category:'Streams-External' |
20 ! |
20 ! |
21 |
21 |
22 !FileStream primitiveDefinitions! |
22 !FileStream primitiveDefinitions! |
23 %{ |
23 %{ |
24 |
24 |
198 !FileStream class methodsFor:'documentation'! |
198 !FileStream class methodsFor:'documentation'! |
199 |
199 |
200 copyright |
200 copyright |
201 " |
201 " |
202 COPYRIGHT (c) 1989 by Claus Gittinger |
202 COPYRIGHT (c) 1989 by Claus Gittinger |
203 All Rights Reserved |
203 All Rights Reserved |
204 |
204 |
205 This software is furnished under a license and may be used |
205 This software is furnished under a license and may be used |
206 only in accordance with the terms of that license and with the |
206 only in accordance with the terms of that license and with the |
207 inclusion of the above copyright notice. This software may not |
207 inclusion of the above copyright notice. This software may not |
208 be provided or otherwise made available to, or used by, any |
208 be provided or otherwise made available to, or used by, any |
229 Therefore, the instance variable canPosition is set according to |
229 Therefore, the instance variable canPosition is set according to |
230 this and an error is raised, if a position: is attemted. |
230 this and an error is raised, if a position: is attemted. |
231 I know, this is ugly, but what else could we do ? |
231 I know, this is ugly, but what else could we do ? |
232 |
232 |
233 [instance variables:] |
233 [instance variables:] |
234 pathName <String> the files path (if known) |
234 pathName <String> the files path (if known) |
235 canPosition <Boolean> positionable - read above comment |
235 canPosition <Boolean> positionable - read above comment |
236 |
236 |
237 [author:] |
237 [author:] |
238 Claus Gittinger |
238 Claus Gittinger |
239 |
239 |
240 [see also:] |
240 [see also:] |
241 Filename DirectoryStream PipeStream Socket |
241 Filename DirectoryStream PipeStream Socket |
242 " |
242 " |
243 ! |
243 ! |
244 |
244 |
245 examples |
245 examples |
246 " |
246 " |
251 as described in the 'creat' RTL Library documentation. |
251 as described in the 'creat' RTL Library documentation. |
252 |
252 |
253 For example, to create a file with fixed records and recordLength of 100, |
253 For example, to create a file with fixed records and recordLength of 100, |
254 use: |
254 use: |
255 |
255 |
256 |newFile| |
256 |newFile| |
257 |
257 |
258 newFile := FileStream new pathName:'<nameOfFile>'. |
258 newFile := FileStream new pathName:'<nameOfFile>'. |
259 newFile setMode:#writeonly. |
259 newFile setMode:#writeonly. |
260 newFile openWithMode:'w' attributes:#('rfm=fix' 'fsz=100'). |
260 newFile openWithMode:'w' attributes:#('rfm=fix' 'fsz=100'). |
261 |
261 |
262 since all of the above is private protocol, and it is considered bad style to |
262 since all of the above is private protocol, and it is considered bad style to |
263 access these from user programs, we recommend subclassing FileStream as |
263 access these from user programs, we recommend subclassing FileStream as |
264 something like VMSFixedRecordFileStream, and redefine the instance creation |
264 something like VMSFixedRecordFileStream, and redefine the instance creation |
265 method(s) there as appropriate. |
265 method(s) there as appropriate. |
511 |
511 |
512 |s| |
512 |s| |
513 |
513 |
514 s := self readOnlyFileNamed:filename. |
514 s := self readOnlyFileNamed:filename. |
515 text ifTrue:[ |
515 text ifTrue:[ |
516 s text |
516 s text |
517 ] ifFalse:[ |
517 ] ifFalse:[ |
518 s binary |
518 s binary |
519 ]. |
519 ]. |
520 ^ s |
520 ^ s |
521 ! |
521 ! |
522 |
522 |
523 write:filename mode:modeSymbol |
523 write:filename mode:modeSymbol |
542 |
542 |
543 |s| |
543 |s| |
544 |
544 |
545 s := self newFileNamed:filename. |
545 s := self newFileNamed:filename. |
546 s notNil ifTrue:[ |
546 s notNil ifTrue:[ |
547 textModeBoolean ifTrue:[ |
547 textModeBoolean ifTrue:[ |
548 s text |
548 s text |
549 ] ifFalse:[ |
549 ] ifFalse:[ |
550 s binary |
550 s binary |
551 ] |
551 ] |
552 ]. |
552 ]. |
553 ^ s |
553 ^ s |
554 ! ! |
554 ! ! |
555 |
555 |
556 !FileStream class methodsFor:'Compatibility-Squeak'! |
556 !FileStream class methodsFor:'Compatibility-Squeak'! |
664 closeFile |
664 closeFile |
665 "low level close - may be redefined in subclasses" |
665 "low level close - may be redefined in subclasses" |
666 |
666 |
667 super closeFile. |
667 super closeFile. |
668 removeOnClose == true ifTrue:[ |
668 removeOnClose == true ifTrue:[ |
669 pathName asFilename remove. |
669 pathName asFilename remove. |
670 ] |
670 ] |
671 |
671 |
672 "Created: / 13.8.1998 / 12:11:22 / cg" |
672 "Created: / 13.8.1998 / 12:11:22 / cg" |
673 ! ! |
673 ! ! |
674 |
674 |
678 "return the read/write position in the file" |
678 "return the read/write position in the file" |
679 |
679 |
680 %{ |
680 %{ |
681 |
681 |
682 HFILE f; |
682 HFILE f; |
683 long currentPosition; |
683 off_t currentPosition; |
684 |
684 |
685 if (__INST(filePointer) != nil) { |
685 if (__INST(filePointer) != nil) { |
686 do { |
686 do { |
687 f = __FILEVal(__INST(filePointer)); |
687 f = __FILEVal(__INST(filePointer)); |
688 #ifdef WIN32 |
688 #ifdef WIN32 |
715 } |
715 } |
716 #endif |
716 #endif |
717 } while ((currentPosition < 0) && (__threadErrno == EINTR)); |
717 } while ((currentPosition < 0) && (__threadErrno == EINTR)); |
718 |
718 |
719 if (currentPosition >= 0) { |
719 if (currentPosition >= 0) { |
720 RETURN ( __MKINT(currentPosition) ); |
720 OBJ rslt; |
721 |
|
722 if (sizeof(currentPosition) == 8) { |
|
723 rslt = __MKINT64 (¤tPosition); |
|
724 } else { |
|
725 rslt = __MKINT(currentPosition); |
|
726 } |
|
727 RETURN ( rslt ); |
|
721 } |
728 } |
722 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
729 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
723 } |
730 } |
724 %}. |
731 %}. |
725 lastErrorNumber notNil ifTrue:[^ self ioError]. |
732 lastErrorNumber notNil ifTrue:[^ self ioError]. |
852 %{ |
859 %{ |
853 HFILE f; |
860 HFILE f; |
854 long ret; |
861 long ret; |
855 |
862 |
856 if (__INST(filePointer) != nil) { |
863 if (__INST(filePointer) != nil) { |
857 f = __FILEVal(__INST(filePointer)); |
864 f = __FILEVal(__INST(filePointer)); |
858 __INST(position) = nil; /* i.e. unknown */ |
865 __INST(position) = nil; /* i.e. unknown */ |
859 do { |
866 do { |
860 #ifdef WIN32 |
867 #ifdef WIN32 |
861 __threadErrno = 0; |
868 __threadErrno = 0; |
862 if (__INST(buffered) == true) { |
869 if (__INST(buffered) == true) { |
863 ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END); |
870 ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END); |
864 } else { |
871 } else { |
865 __INST(readAhead) = nil; |
872 __INST(readAhead) = nil; |
866 ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END); |
873 ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END); |
867 } |
874 } |
868 #else |
875 #else |
869 if (__INST(buffered) == true) { |
876 if (__INST(buffered) == true) { |
870 ret = fseek(f, 0L, SEEK_END); |
877 ret = fseek(f, 0L, SEEK_END); |
871 } else { |
878 } else { |
872 ret = lseek(fileno(f), 0L, SEEK_END); |
879 ret = lseek(fileno(f), 0L, SEEK_END); |
873 } |
880 } |
874 #endif |
881 #endif |
875 } while ((ret < 0) && (__threadErrno == EINTR)); |
882 } while ((ret < 0) && (__threadErrno == EINTR)); |
876 if (ret >= 0) { |
883 if (ret >= 0) { |
877 RETURN ( self ); |
884 RETURN ( self ); |
878 } |
885 } |
879 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
886 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
880 } |
887 } |
881 %}. |
888 %}. |
882 lastErrorNumber notNil ifTrue:[^ self ioError]. |
889 lastErrorNumber notNil ifTrue:[^ self ioError]. |
883 filePointer isNil ifTrue:[^ self errorNotOpen]. |
890 filePointer isNil ifTrue:[^ self errorNotOpen]. |
884 ^ self primitiveFailed |
891 ^ self primitiveFailed |
945 from which a copy can be reconstructed later." |
952 from which a copy can be reconstructed later." |
946 |
953 |
947 aStream nextPutAll:'(FileStream oldFileNamed:'. |
954 aStream nextPutAll:'(FileStream oldFileNamed:'. |
948 aStream nextPutAll:pathName storeString. |
955 aStream nextPutAll:pathName storeString. |
949 (self position ~~ ZeroPosition) ifTrue:[ |
956 (self position ~~ ZeroPosition) ifTrue:[ |
950 aStream nextPutAll:'; position:'. |
957 aStream nextPutAll:'; position:'. |
951 self position storeOn:aStream |
958 self position storeOn:aStream |
952 ]. |
959 ]. |
953 aStream nextPut:$) |
960 aStream nextPut:$) |
954 |
961 |
955 "Modified: 30.7.1997 / 16:43:50 / cg" |
962 "Modified: 30.7.1997 / 16:43:50 / cg" |
956 ! ! |
963 ! ! |
977 open |
984 open |
978 "open the file" |
985 "open the file" |
979 |
986 |
980 pathName isNil ifTrue:[^nil]. |
987 pathName isNil ifTrue:[^nil]. |
981 (mode == #readonly) ifTrue: [ |
988 (mode == #readonly) ifTrue: [ |
982 didWrite := false. |
989 didWrite := false. |
983 ^ self openWithMode:ReadMode |
990 ^ self openWithMode:ReadMode |
984 ]. |
991 ]. |
985 (mode == #writeonly) ifTrue: [ |
992 (mode == #writeonly) ifTrue: [ |
986 didWrite := true. |
993 didWrite := true. |
987 ^ self openWithMode:WriteMode |
994 ^ self openWithMode:WriteMode |
988 ]. |
995 ]. |
989 ^ self openWithMode:ReadWriteMode |
996 ^ self openWithMode:ReadWriteMode |
990 ! |
997 ! |
991 |
998 |
992 openFile:pathName withMode:openmode attributes:attributeSpec |
999 openFile:pathName withMode:openmode attributes:attributeSpec |
1013 int pass = 0; |
1020 int pass = 0; |
1014 |
1021 |
1015 retry: |
1022 retry: |
1016 if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) { |
1023 if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) { |
1017 #ifdef __VMS__ |
1024 #ifdef __VMS__ |
1018 do { |
1025 do { |
1019 /* |
1026 /* |
1020 * allow passing additional RMS arguments. |
1027 * allow passing additional RMS arguments. |
1021 * stupid: DEC does not seem to offer an interface for passing a char **. |
1028 * stupid: DEC does not seem to offer an interface for passing a char **. |
1022 */ |
1029 */ |
1023 __threadErrno = 0; |
1030 __threadErrno = 0; |
1024 |
1031 |
1025 { |
1032 { |
1026 if (__isArray(attributeSpec)) { |
1033 if (__isArray(attributeSpec)) { |
1027 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1034 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1028 int numAttrib = 0; |
1035 int numAttrib = 0; |
1029 int i; |
1036 int i; |
1030 |
1037 |
1031 numAttrib = __arraySize(attributeSpec); |
1038 numAttrib = __arraySize(attributeSpec); |
1032 for (i=0; i<numAttrib;i++) { |
1039 for (i=0; i<numAttrib;i++) { |
1033 if (! __isString(ap[i])) { |
1040 if (! __isString(ap[i])) { |
1034 f = NULL; |
1041 f = NULL; |
1035 __threadErrno = EINVAL; /* invalid argument */ |
1042 __threadErrno = EINVAL; /* invalid argument */ |
1036 goto getOutOfHere; |
1043 goto getOutOfHere; |
1037 } |
1044 } |
1038 } |
1045 } |
1039 switch (numAttrib) { |
1046 switch (numAttrib) { |
1040 case 0: |
1047 case 0: |
1041 __BEGIN_INTERRUPTABLE__ |
1048 __BEGIN_INTERRUPTABLE__ |
1042 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1049 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1043 __END_INTERRUPTABLE__ |
1050 __END_INTERRUPTABLE__ |
1044 break; |
1051 break; |
1045 case 1: |
1052 case 1: |
1046 __BEGIN_INTERRUPTABLE__ |
1053 __BEGIN_INTERRUPTABLE__ |
1047 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1054 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1048 __stringVal(ap[0])); |
1055 __stringVal(ap[0])); |
1049 __END_INTERRUPTABLE__ |
1056 __END_INTERRUPTABLE__ |
1050 break; |
1057 break; |
1051 case 2: |
1058 case 2: |
1052 __BEGIN_INTERRUPTABLE__ |
1059 __BEGIN_INTERRUPTABLE__ |
1053 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1060 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1054 __stringVal(ap[0]), __stringVal(ap[1])); |
1061 __stringVal(ap[0]), __stringVal(ap[1])); |
1055 __END_INTERRUPTABLE__ |
1062 __END_INTERRUPTABLE__ |
1056 break; |
1063 break; |
1057 case 3: |
1064 case 3: |
1058 __BEGIN_INTERRUPTABLE__ |
1065 __BEGIN_INTERRUPTABLE__ |
1059 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1066 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1060 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1067 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1061 __END_INTERRUPTABLE__ |
1068 __END_INTERRUPTABLE__ |
1062 break; |
1069 break; |
1063 case 4: |
1070 case 4: |
1064 __BEGIN_INTERRUPTABLE__ |
1071 __BEGIN_INTERRUPTABLE__ |
1065 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1072 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1066 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1073 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1067 __stringVal(ap[3])); |
1074 __stringVal(ap[3])); |
1068 __END_INTERRUPTABLE__ |
1075 __END_INTERRUPTABLE__ |
1069 break; |
1076 break; |
1070 case 5: |
1077 case 5: |
1071 __BEGIN_INTERRUPTABLE__ |
1078 __BEGIN_INTERRUPTABLE__ |
1072 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1079 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1073 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1080 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1074 __stringVal(ap[3]), __stringVal(ap[4])); |
1081 __stringVal(ap[3]), __stringVal(ap[4])); |
1075 __END_INTERRUPTABLE__ |
1082 __END_INTERRUPTABLE__ |
1076 break; |
1083 break; |
1077 case 6: |
1084 case 6: |
1078 __BEGIN_INTERRUPTABLE__ |
1085 __BEGIN_INTERRUPTABLE__ |
1079 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1086 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1080 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1087 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1081 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1088 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1082 __END_INTERRUPTABLE__ |
1089 __END_INTERRUPTABLE__ |
1083 break; |
1090 break; |
1084 case 7: |
1091 case 7: |
1085 __BEGIN_INTERRUPTABLE__ |
1092 __BEGIN_INTERRUPTABLE__ |
1086 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1093 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1087 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1094 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1088 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1095 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1089 __stringVal(ap[6])); |
1096 __stringVal(ap[6])); |
1090 __END_INTERRUPTABLE__ |
1097 __END_INTERRUPTABLE__ |
1091 break; |
1098 break; |
1092 case 8: |
1099 case 8: |
1093 __BEGIN_INTERRUPTABLE__ |
1100 __BEGIN_INTERRUPTABLE__ |
1094 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1101 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1095 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1102 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1096 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1103 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1097 __stringVal(ap[6]), __stringVal(ap[7])); |
1104 __stringVal(ap[6]), __stringVal(ap[7])); |
1098 __END_INTERRUPTABLE__ |
1105 __END_INTERRUPTABLE__ |
1099 break; |
1106 break; |
1100 case 9: |
1107 case 9: |
1101 __BEGIN_INTERRUPTABLE__ |
1108 __BEGIN_INTERRUPTABLE__ |
1102 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1109 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1103 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1110 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1104 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1111 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1105 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1112 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1106 __END_INTERRUPTABLE__ |
1113 __END_INTERRUPTABLE__ |
1107 break; |
1114 break; |
1108 case 10: |
1115 case 10: |
1109 __BEGIN_INTERRUPTABLE__ |
1116 __BEGIN_INTERRUPTABLE__ |
1110 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1117 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1111 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1118 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1112 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1119 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1113 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1120 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1114 __stringVal(ap[9])); |
1121 __stringVal(ap[9])); |
1115 __END_INTERRUPTABLE__ |
1122 __END_INTERRUPTABLE__ |
1116 break; |
1123 break; |
1117 default: |
1124 default: |
1118 f = NULL; |
1125 f = NULL; |
1119 __threadErrno = E2BIG; /* too many args */ |
1126 __threadErrno = E2BIG; /* too many args */ |
1120 goto getOutOfHere; |
1127 goto getOutOfHere; |
1121 } |
1128 } |
1122 } else if (attributeSpec != nil) { |
1129 } else if (attributeSpec != nil) { |
1123 f = NULL; |
1130 f = NULL; |
1124 __threadErrno = EINVAL; /* invalid argument */ |
1131 __threadErrno = EINVAL; /* invalid argument */ |
1125 goto getOutOfHere; |
1132 goto getOutOfHere; |
1126 } else { |
1133 } else { |
1127 /* |
1134 /* |
1128 * create file as sequential streamLF by default. |
1135 * create file as sequential streamLF by default. |
1129 */ |
1136 */ |
1130 __BEGIN_INTERRUPTABLE__ |
1137 __BEGIN_INTERRUPTABLE__ |
1131 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1138 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1132 __END_INTERRUPTABLE__ |
1139 __END_INTERRUPTABLE__ |
1133 } |
1140 } |
1134 } |
1141 } |
1135 } while ((f == NULL) && (__threadErrno == EINTR)); |
1142 } while ((f == NULL) && (__threadErrno == EINTR)); |
1136 |
1143 |
1137 #else /* not VMS */ |
1144 #else /* not VMS */ |
1138 |
1145 |
1139 # ifdef WIN32 |
1146 # ifdef WIN32 |
1140 |
1147 |
1141 do { |
1148 do { |
1142 __threadErrno = 0; |
1149 __threadErrno = 0; |
1143 f = STX_C_CALL2( "fopen", fopen, (char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1150 f = STX_C_CALL2( "fopen", fopen, (char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1144 if (__threadErrno == EINTR) { |
1151 if (__threadErrno == EINTR) { |
1145 f = NULL; |
1152 f = NULL; |
1146 } |
1153 } |
1147 } while ((f == NULL) && (__threadErrno == EINTR)); |
1154 } while ((f == NULL) && (__threadErrno == EINTR)); |
1148 |
1155 |
1149 # else /* not WIN32 */ |
1156 # else /* not WIN32 */ |
1150 |
1157 |
1151 do { |
1158 do { |
1152 __BEGIN_INTERRUPTABLE__ |
1159 __BEGIN_INTERRUPTABLE__ |
1153 # ifdef LINUX |
1160 # ifdef LINUX |
1154 /* |
1161 /* |
1155 * LINUX may ret a non-NULL f even when interrupted. |
1162 * LINUX may ret a non-NULL f even when interrupted. |
1156 * Therefore, check errno and fake a null-ret. |
1163 * Therefore, check errno and fake a null-ret. |
1157 */ |
1164 */ |
1158 __threadErrno = 0; |
1165 __threadErrno = 0; |
1159 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1166 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1160 if (__threadErrno == EINTR) |
1167 if (__threadErrno == EINTR) |
1161 f = NULL; |
1168 f = NULL; |
1162 # else /* not LINUX */ |
1169 # else /* not LINUX */ |
1163 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1170 f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode)); |
1164 # endif /* not LINUX */ |
1171 # endif /* not LINUX */ |
1165 __END_INTERRUPTABLE__ |
1172 __END_INTERRUPTABLE__ |
1166 } while ((f == NULL) && (__threadErrno == EINTR)); |
1173 } while ((f == NULL) && (__threadErrno == EINTR)); |
1167 |
1174 |
1168 # endif /* not WIN32 */ |
1175 # endif /* not WIN32 */ |
1169 #endif /* not VMS */ |
1176 #endif /* not VMS */ |
1170 |
1177 |
1171 if (f == NULL) { |
1178 if (f == NULL) { |
1172 /* |
1179 /* |
1173 * If no filedescriptors available, try to finalize |
1180 * If no filedescriptors available, try to finalize |
1174 * possibly collected fd's and try again. |
1181 * possibly collected fd's and try again. |
1175 */ |
1182 */ |
1176 if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) { |
1183 if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) { |
1177 pass = 1; |
1184 pass = 1; |
1178 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1185 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1179 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1186 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1180 goto retry; |
1187 goto retry; |
1181 } |
1188 } |
1182 getOutOfHere: ; |
1189 getOutOfHere: ; |
1183 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1190 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1184 __INST(position) = nil; |
1191 __INST(position) = nil; |
1185 } else { |
1192 } else { |
1186 #ifdef __VMS__ |
1193 #ifdef __VMS__ |
1187 /* |
1194 /* |
1188 * check to see if this is positionable ... |
1195 * check to see if this is positionable ... |
1189 */ |
1196 */ |
1190 __INST(canPosition) = false; |
1197 __INST(canPosition) = false; |
1191 # ifndef _POSIX_C_SOURCE |
1198 # ifndef _POSIX_C_SOURCE |
1192 { |
1199 { |
1193 struct stat statBuffer; |
1200 struct stat statBuffer; |
1194 |
1201 |
1195 if (fstat(fileno(f), &statBuffer) >= 0) { |
1202 if (fstat(fileno(f), &statBuffer) >= 0) { |
1196 switch (statBuffer.st_fab_rfm) { |
1203 switch (statBuffer.st_fab_rfm) { |
1197 case FAB$C_UDF: /* undefined (also stream binary) */ |
1204 case FAB$C_UDF: /* undefined (also stream binary) */ |
1198 case FAB$C_VAR: /* variable length records */ |
1205 case FAB$C_VAR: /* variable length records */ |
1199 case FAB$C_VFC: /* variable fixed control */ |
1206 case FAB$C_VFC: /* variable fixed control */ |
1200 case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */ |
1207 case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */ |
1201 default: |
1208 default: |
1202 __INST(canPosition) = false; |
1209 __INST(canPosition) = false; |
1203 break; |
1210 break; |
1204 |
1211 |
1205 case FAB$C_FIX: /* fixed length records */ |
1212 case FAB$C_FIX: /* fixed length records */ |
1206 case FAB$C_STMLF: /* LF stream (valid only for sequential> */ |
1213 case FAB$C_STMLF: /* LF stream (valid only for sequential> */ |
1207 case FAB$C_STMCR: /* CR stream (valid only for sequential> */ |
1214 case FAB$C_STMCR: /* CR stream (valid only for sequential> */ |
1208 __INST(canPosition) = true; |
1215 __INST(canPosition) = true; |
1209 break; |
1216 break; |
1210 } |
1217 } |
1211 } |
1218 } |
1212 } |
1219 } |
1213 # endif |
1220 # endif |
1214 #else /* not VMS */ |
1221 #else /* not VMS */ |
1215 __INST(canPosition) = true; |
1222 __INST(canPosition) = true; |
1216 #endif /* poor VMS */ |
1223 #endif /* poor VMS */ |
1217 |
1224 |
1218 if (@global(FileOpenTrace) == true) { |
1225 if (@global(FileOpenTrace) == true) { |
1219 fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f); |
1226 fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f); |
1220 } |
1227 } |
1221 |
1228 |
1222 filePointer = __MKOBJ((INT)f); |
1229 filePointer = __MKOBJ((INT)f); |
1223 __INST(position) = @global(PositionableStream:ZeroPosition); |
1230 __INST(position) = @global(PositionableStream:ZeroPosition); |
1224 } |
1231 } |
1225 } |
1232 } |
1226 %}. |
1233 %}. |
1227 ^ filePointer |
1234 ^ filePointer |
1228 ! |
1235 ! |
1229 |
1236 |
1294 |
1301 |
1295 filePointer notNil ifTrue:[^ self errorAlreadyOpen]. |
1302 filePointer notNil ifTrue:[^ self errorAlreadyOpen]. |
1296 |
1303 |
1297 filePointer := self openFile:pathName withMode:openmode attributes:attributeSpec. |
1304 filePointer := self openFile:pathName withMode:openmode attributes:attributeSpec. |
1298 filePointer isNil ifTrue:[ |
1305 filePointer isNil ifTrue:[ |
1299 " |
1306 " |
1300 the open failed for some reason ... |
1307 the open failed for some reason ... |
1301 " |
1308 " |
1302 ^ self openError |
1309 ^ self openError |
1303 ]. |
1310 ]. |
1304 position := ZeroPosition. |
1311 position := ZeroPosition. |
1305 buffered := true. "default is buffered" |
1312 buffered := true. "default is buffered" |
1306 Lobby register:self. |
1313 Lobby register:self. |
1307 ! |
1314 ! |
1326 "sent after snapin to reopen streams" |
1333 "sent after snapin to reopen streams" |
1327 |
1334 |
1328 |oldPos| |
1335 |oldPos| |
1329 |
1336 |
1330 filePointer notNil ifTrue:[ |
1337 filePointer notNil ifTrue:[ |
1331 "it was open, when snapped-out" |
1338 "it was open, when snapped-out" |
1332 filePointer := nil. |
1339 filePointer := nil. |
1333 Lobby unregister:self. |
1340 Lobby unregister:self. |
1334 oldPos := position. |
1341 oldPos := position. |
1335 self open. |
1342 self open. |
1336 filePointer isNil ifTrue:[ |
1343 filePointer isNil ifTrue:[ |
1337 "/ this happens, if after a restart, |
1344 "/ this happens, if after a restart, |
1338 "/ the file is no longer present or accessable ..." |
1345 "/ the file is no longer present or accessable ..." |
1339 |
1346 |
1340 (self class name , ' [warning]: could not reOpen file: ', pathName) errorPrintCR. |
1347 (self class name , ' [warning]: could not reOpen file: ', pathName) errorPrintCR. |
1341 ] ifFalse:[ |
1348 ] ifFalse:[ |
1342 oldPos notNil ifTrue:[ |
1349 oldPos notNil ifTrue:[ |
1343 self position:oldPos. |
1350 self position:oldPos. |
1344 ] |
1351 ] |
1345 ] |
1352 ] |
1346 ] |
1353 ] |
1347 |
1354 |
1348 "Modified: 10.1.1997 / 17:50:51 / cg" |
1355 "Modified: 10.1.1997 / 17:50:51 / cg" |
1349 ! |
1356 ! |
1350 |
1357 |
1363 |
1370 |
1364 #ifdef transputer |
1371 #ifdef transputer |
1365 int size; |
1372 int size; |
1366 |
1373 |
1367 if (__INST(filePointer) != nil) { |
1374 if (__INST(filePointer) != nil) { |
1368 f = __FILEVal(__INST(filePointer)); |
1375 f = __FILEVal(__INST(filePointer)); |
1369 if ((size = filesize(fileno(f))) >= 0) { |
1376 if ((size = filesize(fileno(f))) >= 0) { |
1370 RETURN ( __MKSMALLINT(size) ); |
1377 RETURN ( __MKSMALLINT(size) ); |
1371 } |
1378 } |
1372 } |
1379 } |
1373 #else |
1380 #else |
1374 struct stat buf; |
1381 struct stat buf; |
1375 int ret; |
1382 int ret; |
1376 int fd; |
1383 int fd; |
1377 |
1384 |
1378 if (__INST(filePointer) != nil) { |
1385 if (__INST(filePointer) != nil) { |
1379 f = __FILEVal(__INST(filePointer)); |
1386 f = __FILEVal(__INST(filePointer)); |
1380 fd = fileno(f); |
1387 fd = fileno(f); |
1381 do { |
1388 do { |
1382 ret = fstat(fd, &buf); |
1389 ret = fstat(fd, &buf); |
1383 } while ((ret < 0) && (__threadErrno == EINTR)); |
1390 } while ((ret < 0) && (__threadErrno == EINTR)); |
1384 if (ret >= 0) { |
1391 if (ret >= 0) { |
1385 RETURN ( __MKSMALLINT( (int)(buf.st_size) ) ); |
1392 RETURN ( __MKSMALLINT( (int)(buf.st_size) ) ); |
1386 } |
1393 } |
1387 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1394 __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno); |
1388 } |
1395 } |
1389 #endif |
1396 #endif |
1390 %}. |
1397 %}. |
1391 |
1398 |
1392 "could add a fall-back here: |
1399 "could add a fall-back here: |
1393 |
1400 |
1394 oldPosition := self position. |
1401 oldPosition := self position. |
1395 self setToEnd. |
1402 self setToEnd. |
1396 sz := self position. |
1403 sz := self position. |
1397 self position:oldPosition. |
1404 self position:oldPosition. |
1398 ^ sz |
1405 ^ sz |
1399 " |
1406 " |
1400 lastErrorNumber notNil ifTrue:[^ self ioError]. |
1407 lastErrorNumber notNil ifTrue:[^ self ioError]. |
1401 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1408 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1402 ^ self primitiveFailed |
1409 ^ self primitiveFailed |
1403 ! |
1410 ! |
1432 ! ! |
1439 ! ! |
1433 |
1440 |
1434 !FileStream class methodsFor:'documentation'! |
1441 !FileStream class methodsFor:'documentation'! |
1435 |
1442 |
1436 version |
1443 version |
1437 ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.99 2004-02-05 11:52:51 cg Exp $' |
1444 ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.100 2004-02-05 11:57:29 cg Exp $' |
1438 ! ! |
1445 ! ! |
1439 |
1446 |
1440 FileStream initialize! |
1447 FileStream initialize! |