FileStream.st
changeset 15620 264cf9877dda
parent 15573 36facee1072e
child 16109 0e7d694bfc7a
child 18084 ab5b38bd8f81
equal deleted inserted replaced
15619:3f2e6f5fab12 15620:264cf9877dda
   874     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   874     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   875      support mmap-like operations as from-fd.
   875      support mmap-like operations as from-fd.
   876      Therefore, this method is reimplemented here (from ExternalStream)"
   876      Therefore, this method is reimplemented here (from ExternalStream)"
   877 
   877 
   878     outStream isExternalStream ifTrue:[
   878     outStream isExternalStream ifTrue:[
   879 	pos := self position0Based.
   879         pos := self position.
   880 	n := self size - pos.
   880         n := self size - pos.
   881 	nWritten := OperatingSystem
   881         nWritten := OperatingSystem
   882 	    copyFromFd:(self fileDescriptor)
   882             copyFromFd:(self fileDescriptor)
   883 	    toFd:(outStream fileDescriptor)
   883             toFd:(outStream fileDescriptor)
   884 	    startIndex:pos
   884             startIndex:pos
   885 	    count:n.
   885             count:n.
   886 	nWritten = n ifTrue:[
   886         nWritten = n ifTrue:[
   887 	    ^ self
   887             ^ self
   888 	].
   888         ].
   889 	nWritten > 0 ifTrue:[
   889         nWritten > 0 ifTrue:[
   890 	    self position0Based:pos+nWritten.
   890             self position:pos+nWritten.
   891 	].
   891         ].
   892     ].
   892     ].
   893     ^ super copyToEndInto:outStream bufferSize:bufferSize.
   893     ^ super copyToEndInto:outStream bufferSize:bufferSize.
   894 
   894 
   895     "
   895     "
   896      |in out|
   896      |in out|
   902     "
   902     "
   903 ! !
   903 ! !
   904 
   904 
   905 !FileStream methodsFor:'positioning'!
   905 !FileStream methodsFor:'positioning'!
   906 
   906 
   907 position0Based
   907 position
   908     "return the read/write position in the file"
   908     "return the read/write position in the file"
   909 
   909 
   910 %{
   910 %{
   911 
   911 
   912     HFILE f;
   912     HFILE f;
   913     off_t currentPosition;
   913     off_t currentPosition;
   914 
   914 
   915     if (__INST(handle) != nil) {
   915     if (__INST(handle) != nil) {
   916 	do {
   916         do {
   917 	    f = __FILEVal(__INST(handle));
   917             f = __FILEVal(__INST(handle));
   918 #ifdef WIN32
   918 #ifdef WIN32
   919 	    __threadErrno = 0;
   919             __threadErrno = 0;
   920 	    if (__INST(buffered) == true) {
   920             if (__INST(buffered) == true) {
   921 # if 0
   921 # if 0
   922 		currentPosition = STX_C_CALL1( "ftell", ftell, f);
   922                 currentPosition = STX_C_CALL1( "ftell", ftell, f);
   923 # else
   923 # else
   924 		currentPosition = ftell(f);
   924                 currentPosition = ftell(f);
   925 # endif
   925 # endif
   926 	    } else {
   926             } else {
   927 		OBJ rA = __INST(readAhead);
   927                 OBJ rA = __INST(readAhead);
   928 		off_t offs = 0;
   928                 off_t offs = 0;
   929 
   929 
   930 		if (rA != nil) {
   930                 if (rA != nil) {
   931 		    __INST(readAhead) = nil;
   931                     __INST(readAhead) = nil;
   932 		    offs = -1;
   932                     offs = -1;
   933 		}
   933                 }
   934 # if 0
   934 # if 0
   935 		currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
   935                 currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
   936 # else
   936 # else
   937 		currentPosition = lseek(fileno(f), offs, SEEK_CUR);
   937                 currentPosition = lseek(fileno(f), offs, SEEK_CUR);
   938 # endif
   938 # endif
   939 	    }
   939             }
   940 #else /* !WIN32 */
   940 #else /* !WIN32 */
   941 	    if (__INST(buffered) == true) {
   941             if (__INST(buffered) == true) {
   942 #ifdef _LFS_LARGEFILE
   942 #ifdef _LFS_LARGEFILE
   943 		currentPosition = ftello(f);
   943                 currentPosition = ftello(f);
   944 #else
   944 #else
   945 		currentPosition = ftell(f);
   945                 currentPosition = ftell(f);
   946 #endif /* ! _LFS_LARGEFILE */
   946 #endif /* ! _LFS_LARGEFILE */
   947 	    } else {
   947             } else {
   948 		currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
   948                 currentPosition = lseek(fileno(f), (off_t)0, SEEK_CUR);
   949 	    }
   949             }
   950 #endif /* !WIN32 */
   950 #endif /* !WIN32 */
   951 	} while ((currentPosition < 0) && (__threadErrno == EINTR));
   951         } while ((currentPosition < 0) && (__threadErrno == EINTR));
   952 
   952 
   953 	if (currentPosition >= 0) {
   953         if (currentPosition >= 0) {
   954 	    OBJ rslt;
   954             OBJ rslt;
   955 
   955 
   956 	    if (sizeof(currentPosition) == 8) {
   956             if (sizeof(currentPosition) == 8) {
   957 		rslt = __MKINT64 (&currentPosition);
   957                 rslt = __MKINT64 (&currentPosition);
   958 	    } else {
   958             } else {
   959 		rslt = __MKINT(currentPosition);
   959                 rslt = __MKINT(currentPosition);
   960 	    }
   960             }
   961 	    RETURN ( rslt );
   961             RETURN ( rslt );
   962 	}
   962         }
   963 	__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
   963         __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
   964     }
   964     }
   965 %}.
   965 %}.
   966     lastErrorNumber notNil ifTrue:[^ self ioError].
   966     lastErrorNumber notNil ifTrue:[^ self ioError].
   967     handle isNil ifTrue:[^ self errorNotOpen].
   967     handle isNil ifTrue:[^ self errorNotOpen].
   968     ^ self primitiveFailed
   968     ^ self primitiveFailed
   969 !
   969 !
   970 
   970 
   971 position0Based:newPos
   971 position:newPos
   972     "set the read/write position in the file"
   972     "set the read/write position in the file"
   973 
   973 
   974     |rslt|
   974     |rslt|
   975 %{
   975 %{
   976 
   976 
   977     HFILE f;
   977     HFILE f;
   978     long ret;
   978     long ret;
   979     OBJ fp;
   979     OBJ fp;
   980 
   980 
   981     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
   981     if ((__INST(canPosition) != false) || (newPos == __mkSmallInteger(0))) {
   982 	if ((fp = __INST(handle)) != nil) {
   982         if ((fp = __INST(handle)) != nil) {
   983 
   983 
   984 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
   984 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
   985 # define FSEEK fseeko
   985 # define FSEEK fseeko
   986 	    off_t nP;
   986             off_t nP;
   987 #else
   987 #else
   988 #define FSEEK fseek
   988 #define FSEEK fseek
   989 	    long nP;
   989             long nP;
   990 #endif
   990 #endif
   991 
   991 
   992 	    if (__isSmallInteger(newPos)) {
   992             if (__isSmallInteger(newPos)) {
   993 		nP = __intVal(newPos);
   993                 nP = __intVal(newPos);
   994 		if (nP < 0) {
   994                 if (nP < 0) {
   995 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
   995                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
   996 		    goto getOutOfHere;
   996                     goto getOutOfHere;
   997 		}
   997                 }
   998 	    } else {
   998             } else {
   999 		nP = __signedLongIntVal(newPos);
   999                 nP = __signedLongIntVal(newPos);
  1000 		if (nP < 0) {
  1000                 if (nP < 0) {
  1001 		    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1001                     __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1002 		    goto getOutOfHere;
  1002                     goto getOutOfHere;
  1003 		}
  1003                 }
  1004 		if (nP == 0) {
  1004                 if (nP == 0) {
  1005 		    if (sizeof(nP) == 8) {
  1005                     if (sizeof(nP) == 8) {
  1006 			if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1006                         if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
  1007 			    __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1007                             __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1008 			    goto getOutOfHere;
  1008                             goto getOutOfHere;
  1009 			}
  1009                         }
  1010 		    } else {
  1010                     } else {
  1011 			__INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1011                         __INST(lastErrorNumber) = __mkSmallInteger(EINVAL);
  1012 			goto getOutOfHere;
  1012                         goto getOutOfHere;
  1013 		    }
  1013                     }
  1014 		}
  1014                 }
  1015 	    }
  1015             }
  1016 
  1016 
  1017 	    f = __FILEVal(fp);
  1017             f = __FILEVal(fp);
  1018 
  1018 
  1019 	    do {
  1019             do {
  1020 #if defined(DO_WRAP_CALL_FSEEK)
  1020 #if defined(DO_WRAP_CALL_FSEEK)
  1021 		__threadErrno = 0;
  1021                 __threadErrno = 0;
  1022 		if (__INST(buffered) == true) {
  1022                 if (__INST(buffered) == true) {
  1023 		    ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1023                     ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
  1024 		} else {
  1024                 } else {
  1025 		    __INST(readAhead) = nil;
  1025                     __INST(readAhead) = nil;
  1026 		    ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1026                     ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
  1027 		}
  1027                 }
  1028 #else
  1028 #else
  1029 		if (__INST(buffered) == true) {
  1029                 if (__INST(buffered) == true) {
  1030 		    ret = FSEEK(f, nP, SEEK_SET);
  1030                     ret = FSEEK(f, nP, SEEK_SET);
  1031 		} else {
  1031                 } else {
  1032 		    ret = lseek(fileno(f), nP, SEEK_SET);
  1032                     ret = lseek(fileno(f), nP, SEEK_SET);
  1033 		}
  1033                 }
  1034 		__threadErrno = errno;
  1034                 __threadErrno = errno;
  1035 #endif
  1035 #endif
  1036 	    } while ((ret < 0) && (__threadErrno == EINTR));
  1036             } while ((ret < 0) && (__threadErrno == EINTR));
  1037 	    if (ret >= 0) {
  1037             if (ret >= 0) {
  1038 		__INST(position) = newPos; __STORE(self, newPos);
  1038                 __INST(position) = newPos; __STORE(self, newPos);
  1039 		/*
  1039                 /*
  1040 		 * just to make certain ...
  1040                  * just to make certain ...
  1041 		 */
  1041                  */
  1042 		__INST(hitEOF) = false;
  1042                 __INST(hitEOF) = false;
  1043 		RETURN ( self );
  1043                 RETURN ( self );
  1044 	    }
  1044             }
  1045 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  1045             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  1046 	}
  1046         }
  1047     }
  1047     }
  1048     getOutOfHere: ;
  1048     getOutOfHere: ;
  1049 #undef FSEEK
  1049 #undef FSEEK
  1050 %}.
  1050 %}.
  1051     canPosition == false ifTrue:[
  1051     canPosition == false ifTrue:[
  1052 	"/ position by rewinding & re-reading everything up-to
  1052         "/ position by rewinding & re-reading everything up-to
  1053 	"/ that point.
  1053         "/ that point.
  1054 	^ self slowPosition0Based:newPos
  1054         ^ self slowPosition:newPos
  1055     ].
  1055     ].
  1056     lastErrorNumber notNil ifTrue:[
  1056     lastErrorNumber notNil ifTrue:[
  1057 	(OperatingSystem errorSymbolForNumber:lastErrorNumber) == #EINVAL ifTrue:[
  1057         (OperatingSystem errorSymbolForNumber:lastErrorNumber) == #EINVAL ifTrue:[
  1058 	    "/ invalid position
  1058             "/ invalid position
  1059 	    ^ self positionError
  1059             ^ self positionError
  1060 	].
  1060         ].
  1061 	"/ assume I/O error
  1061         "/ assume I/O error
  1062 	^ self ioError
  1062         ^ self ioError
  1063     ].
  1063     ].
  1064     handle isNil ifTrue:[^ self errorNotOpen].
  1064     handle isNil ifTrue:[^ self errorNotOpen].
  1065 
  1065 
  1066     rslt := self positionFile:handle position:newPos.
  1066     rslt := self positionFile:handle position:newPos.
  1067     rslt >= 0 ifTrue:[
  1067     rslt >= 0 ifTrue:[
  1068 	position := newPos.
  1068         position := newPos.
  1069     ] ifFalse:[
  1069     ] ifFalse:[
  1070 	hitEOF := true.
  1070         hitEOF := true.
  1071     ]
  1071     ]
  1072 !
  1072 !
  1073 
  1073 
  1074 reset
  1074 reset
  1075     "additionaly to setting the position to the beginning of the file,
  1075     "additionaly to setting the position to the beginning of the file,
  1130     lastErrorNumber notNil ifTrue:[^ self ioError].
  1130     lastErrorNumber notNil ifTrue:[^ self ioError].
  1131     handle isNil ifTrue:[^ self errorNotOpen].
  1131     handle isNil ifTrue:[^ self errorNotOpen].
  1132     ^ self primitiveFailed
  1132     ^ self primitiveFailed
  1133 !
  1133 !
  1134 
  1134 
  1135 slowPosition0Based:newPos
       
  1136     "position the file by re-reading everything up-to newPos.
       
  1137      The effect is the same as that of #position:, but its much slower.
       
  1138      This is required to reposition nonPositionable streams, such
       
  1139      as tape-streams or variable-record-RMS files under VMS.
       
  1140      Caveat:
       
  1141 	 This should really be done transparently by the stdio library."
       
  1142 
       
  1143     |buffer amount pos0Based|
       
  1144 
       
  1145     self isReadable ifFalse:[
       
  1146 	"/ sorry
       
  1147 	^ self positionError
       
  1148     ].
       
  1149 
       
  1150     buffer := ByteArray new:8*1024.
       
  1151 
       
  1152     (position isNil "/ i.e. unknown
       
  1153     or:[newPos < (pos0Based := self position0Based)]) ifTrue:[
       
  1154 	self reset.
       
  1155 	pos0Based := self position0Based.
       
  1156     ].
       
  1157     [pos0Based < newPos] whileTrue:[
       
  1158 	amount := (buffer size) min:(newPos-pos0Based).
       
  1159 	(self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
       
  1160 	    ^ self positionError
       
  1161 	].
       
  1162 	pos0Based := self position0Based.
       
  1163     ].
       
  1164     "/ ('FileStream [info]: slow position - please convert ''' , pathName printString , ''' to streamLF format') infoPrintCR.
       
  1165 !
       
  1166 
       
  1167 slowPosition:newPos
  1135 slowPosition:newPos
  1168     "position the file by re-reading everything up-to newPos.
  1136     "position the file by re-reading everything up-to newPos.
  1169      The effect is the same as that of #position:, but its much slower.
  1137      The effect is the same as that of #position:, but its much slower.
  1170      This is required to reposition nonPositionable streams, such
  1138      This is required to reposition nonPositionable streams, such
  1171      as tape-streams or variable-record-RMS files under VMS.
  1139      as tape-streams or variable-record-RMS files under VMS.
  1172      Caveat:
  1140      Caveat:
  1173 	 This should really be done transparently by the stdio library."
  1141          This should really be done transparently by the stdio library."
  1174 
  1142 
  1175     ^ self slowPosition0Based:newPos
  1143     |buffer amount pos0Based|
       
  1144 
       
  1145     self isReadable ifFalse:[
       
  1146         "/ sorry
       
  1147         ^ self positionError
       
  1148     ].
       
  1149 
       
  1150     buffer := ByteArray new:8*1024.
       
  1151 
       
  1152     (position isNil "/ i.e. unknown
       
  1153     or:[newPos < (pos0Based := self position)]) ifTrue:[
       
  1154         self reset.
       
  1155         pos0Based := self position.
       
  1156     ].
       
  1157     [pos0Based < newPos] whileTrue:[
       
  1158         amount := (buffer size) min:(newPos-pos0Based).
       
  1159         (self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
       
  1160             ^ self positionError
       
  1161         ].
       
  1162         pos0Based := self position.
       
  1163     ].
       
  1164     "/ ('FileStream [info]: slow position - please convert ''' , pathName printString , ''' to streamLF format') infoPrintCR.
  1176 ! !
  1165 ! !
  1177 
  1166 
  1178 !FileStream methodsFor:'printing & storing'!
  1167 !FileStream methodsFor:'printing & storing'!
  1179 
  1168 
  1180 printOn:aStream
  1169 printOn:aStream
  1996 ! !
  1985 ! !
  1997 
  1986 
  1998 !FileStream class methodsFor:'documentation'!
  1987 !FileStream class methodsFor:'documentation'!
  1999 
  1988 
  2000 version
  1989 version
  2001     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.168 2013-07-29 08:11:37 stefan Exp $'
  1990     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.169 2013-08-10 11:32:53 stefan Exp $'
  2002 !
  1991 !
  2003 
  1992 
  2004 version_CVS
  1993 version_CVS
  2005     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.168 2013-07-29 08:11:37 stefan Exp $'
  1994     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.169 2013-08-10 11:32:53 stefan Exp $'
  2006 ! !
  1995 ! !
  2007 
  1996 
  2008 
  1997 
  2009 FileStream initialize!
  1998 FileStream initialize!