FileStream.st
changeset 7872 634e73a5cdd9
parent 7871 5c357f1ba0c9
child 7874 5e0319ca5e60
equal deleted inserted replaced
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 (&currentPosition);
       
   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!