"====================================================================== | | UnixStream (raw file access) | | $Revision: 1.7.5$ | $Date: 2000/05/28 16:56:52$ | $Author: pb$ | ======================================================================" "====================================================================== | | Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc. | Written by Steve Byrne and Paolo Bonzini. | | This file is part of the GNU Smalltalk class library. | | The GNU Smalltalk class library is free software; you can redistribute it | and/or modify it under the terms of the GNU Lesser General Public License | as published by the Free Software Foundation; either version 2.1, or (at | your option) any later version. | | The GNU Smalltalk class library is distributed in the hope that it will be | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | General Public License for more details. | | You should have received a copy of the GNU Lesser General Public License | along with the GNU Smalltalk class library; see the file COPYING.LESSER. | If not, write to the Free Software Foundation, 59 Temple Place - Suite | 330, Boston, MA 02111-1307, USA. | ======================================================================" PositionableStream subclass: #UnixStream instanceVariableNames: 'fd' classVariableNames: '' poolDictionaries: '' category: 'Sockets-Protocols' ! UnixStream comment: 'I provide an interface to Unix file descriptors, so that Smalltalk methods may perform most of the I/O operations that C programs can. I am quite proud of my contribution to the GNU Smalltalk project, and look forward to serving the project better in the future.' ! UnixStream defineCFunc: 'open' withSelectorArgs: 'open: aFileName flags: flagsInteger mode: anInteger' returning: #int args: #(string int int) ! UnixStream defineCFunc: 'available' withSelectorArgs: 'available: socket reading: forReading' returning: #int args: #(int int) ! UnixStream defineCFunc: 'close' withSelectorArgs: 'close: fileDescriptor' returning: #int args: #(int) ! UnixStream defineCFunc: 'read' withSelectorArgs: 'read: fileDescriptor into: buf bytes: anInteger' returning: #int args: #(int byteArrayOut int) ! UnixStream defineCFunc: 'read' withSelectorArgs: 'read: fileDescriptor into: buf chars: anInteger' returning: #int args: #(int stringOut int) ! UnixStream defineCFunc: 'write' withSelectorArgs: 'write: fileDescriptor from: buf bytes: anInteger' returning: #int args: #(int byteArray int) ! UnixStream defineCFunc: 'lseek' withSelectorArgs: 'lseek: fileDescriptor offset: anInteger whence: cObject' returning: #int args: #(int int int) ! "====================================================================== | | Type specific I/O routines | ======================================================================" UnixStream defineCFunc: 'readChar' withSelectorArgs: 'readChar: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readUChar' withSelectorArgs: 'readUChar: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readShort' withSelectorArgs: 'readShort: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readUShort' withSelectorArgs: 'readUShort: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readLong' withSelectorArgs: 'readLong: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readULong' withSelectorArgs: 'readULong: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readFloat' withSelectorArgs: 'readFloat: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'readDouble' withSelectorArgs: 'readDouble: fileDescriptor' returning: #smalltalk args: #(int) ! UnixStream defineCFunc: 'writeChar' withSelectorArgs: 'write: fileDescriptor char: aChar' returning: #void args: #(int char) ! UnixStream defineCFunc: 'writeShort' withSelectorArgs: 'write: fileDescriptor short: aShort' returning: #void args: #(int int) ! UnixStream defineCFunc: 'writeLong' withSelectorArgs: 'write: fileDescriptor long: aLong' returning: #void args: #(int long) ! UnixStream defineCFunc: 'writeDouble' withSelectorArgs: 'write: fileDescriptor double: aDouble' returning: #void args: #(int double) ! !UnixStream class methodsFor: 'instance creation'! open: fileName dir: anInteger ^self open: fileName dir: anInteger mode: 0 ! open: fileName dir: anInteger mode: intMode ^self new init: fileName dir: anInteger mode: intMode ! on: fd ^self new initFd: fd ! ! !UnixStream class methodsFor: 'constants'! seekSet ^0 ! seekCurr ^1 ! seekEnd ^2 ! readOnly ^0 ! writeOnly ^1 ! readWrite ^2 ! "Other modifiers (like O_APPEND) may be added in the future as needs warrant" ! !UnixStream methodsFor: 'basic accessing'! close | result | result := self close: fd. fd := -1. ^result ! canRead | result | self isOpen ifFalse: [ ^false ]. result := self available: self fd reading: 1. result == -1 ifTrue: [ self nowDead; close ]. ^result == 1 ! canWrite | result | self isOpen ifFalse: [ ^false ]. result := self available: self fd reading: 0. result == -1 ifTrue: [ self nowDead; close ]. ^result == 1 ! isOpen ^fd isInteger and: [ fd positive ] ! read: byteArray | result | result := self read: fd into: byteArray bytes: byteArray size. result == -1 ifTrue: [ self nowDead; close ]. ^result ! read: byteArray numBytes: anInteger | result | result := self read: fd into: byteArray bytes: anInteger. result == -1 ifTrue: [ self nowDead; close ]. ^result ! write: byteArray | result | result := self write: byteArray numBytes: byteArray size. result == -1 ifTrue: [ self nowDead; close ]. ^result ! write: byteArray numBytes: anInteger | result | result := self write: fd from: byteArray bytes: anInteger. result == -1 ifTrue: [ self nowDead; close ]. ^result ! tell ^self lseek: fd offset: 0 whence: 1 "Curr" ! ioctl: number arg: randomArg ^self ioctl: fd request: number arg: randomArg ! readChar ^self readChar: fd ! readUChar ^self readUChar: fd ! readShort ^self readShort: fd ! readUShort ^self readUShort: fd ! readLong ^self readLong: fd ! readULong ^self readULong: fd ! readFloat ^self readFloat: fd ! readDouble ^self readDouble: fd ! writeChar: aChar ^self write: fd char: aChar ! writeShort: aShort "really an integer" ^self write: fd short: aShort ! writeLong: aLong ^self write: fd long: aLong ! writeDouble: aDouble ^self write: fd double: aDouble ! readString: numChars | string numRead str | string := String new: numChars. numRead := self read: string. ^numRead = numChars ifTrue: [ string ] ifFalse: [ string copyFrom: 1 to: numRead ] ! readBytes: numBytes | byteArray numRead str | byteArray := ByteArray new: numBytes. numRead := self read: byteArray. ^numRead = numBytes ifTrue: [ byteArray ] ifFalse: [ byteArray copyFrom: 1 to: numRead ] ! ! !UnixStream methodsFor: 'call back'! nowDead File checkError. ! ! !UnixStream methodsFor: 'accessing'! position ^1 + (self lseek: fd offset: 0 whence: 1) "Curr" ! position: anInteger ^self lseek: fd offset: anInteger - 1 whence: 0 "Set" ! next ^self readChar ! next: anInteger ^self readString: anInteger ! nextPut: aValue (self writeChar: aValue) == -1 ifTrue: [ self nowDead; close ]. ! nextPutAll: aString (self write: aString) == -1 ifTrue: [ self nowDead; close ]. ! contents | curPos result size | curPos := self tell. size := self lseek: fd offset: 0 whence: 2. "To end" self lseek: fd offset: 0 whence: 0. result := self readString: size. self lseek: fd offset: curPos whence: 0. ^curPos ! atEnd "Poor man's atEnd function" | curPos size | curPos := self tell. size := self lseek: fd offset: 0 whence: 2. "To end" self lseek: fd offset: curPos whence: 0. ^curPos >= size ! size "Poor man's size function" | curPos size | curPos := self tell. size := self lseek: fd offset: 0 whence: 2. "To end" self lseek: fd offset: curPos whence: 0. ^size ! skip: anInteger "Skip n bytes on the file. N can be positive or negative" ^self lseek: fd offset: anInteger whence: 1 "Cur" ! ! !UnixStream methodsFor: 'private'! fd ^fd ! init: fileName dir: anInteger mode: intMode fd := self open: fileName flags: anInteger mode: intMode. access := anInteger + 1. fd < 0 ifTrue: [ ^nil ] ! initFd: anFd fd := anFd. access := 3. ! !