jcifs.smb.SmbFileInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs Show documentation
Show all versions of jcifs Show documentation
JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java
/* jcifs smb client library in Java
* Copyright (C) 2000 "Michael B. Allen"
*
* This 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 of the License, or (at your option) any later version.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.smb;
import java.net.URL;
import java.net.UnknownHostException;
import java.net.MalformedURLException;
import java.io.InputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import jcifs.util.transport.TransportException;
/**
* This InputStream can read bytes from a file on an SMB file server. Offsets are 64 bits.
*/
public class SmbFileInputStream extends InputStream {
private long fp;
private int readSize, openFlags, access;
private byte[] tmp = new byte[1];
SmbFile file;
/**
* Creates an {@link java.io.InputStream} for reading bytes from a file on
* an SMB server addressed by the url
parameter. See {@link
* jcifs.smb.SmbFile} for a detailed description and examples of the smb
* URL syntax.
*
* @param url An smb URL string representing the file to read from
*/
public SmbFileInputStream( String url ) throws SmbException, MalformedURLException, UnknownHostException {
this( new SmbFile( url ));
}
/**
* Creates an {@link java.io.InputStream} for reading bytes from a file on
* an SMB server represented by the {@link jcifs.smb.SmbFile} parameter. See
* {@link jcifs.smb.SmbFile} for a detailed description and examples of
* the smb URL syntax.
*
* @param file An SmbFile
specifying the file to read from
*/
public SmbFileInputStream( SmbFile file ) throws SmbException, MalformedURLException, UnknownHostException {
this( file, SmbFile.O_RDONLY );
}
SmbFileInputStream( SmbFile file, int openFlags ) throws SmbException, MalformedURLException, UnknownHostException {
this.file = file;
this.openFlags = openFlags & 0xFFFF;
this.access = (openFlags >>> 16) & 0xFFFF;
if (file.type != SmbFile.TYPE_NAMED_PIPE) {
file.open( openFlags, access, SmbFile.ATTR_NORMAL, 0 );
this.openFlags &= ~(SmbFile.O_CREAT | SmbFile.O_TRUNC);
} else {
file.connect0();
}
readSize = Math.min( file.tree.session.transport.rcv_buf_size - 70,
file.tree.session.transport.server.maxBufferSize - 70 );
}
protected IOException seToIoe(SmbException se) {
IOException ioe = se;
Throwable root = se.getRootCause();
if (root instanceof TransportException) {
ioe = (TransportException)root;
root = ((TransportException)ioe).getRootCause();
}
if (root instanceof InterruptedException) {
ioe = new InterruptedIOException(root.getMessage());
ioe.initCause(root);
}
return ioe;
}
/**
* Closes this input stream and releases any system resources associated with the stream.
*
* @throws IOException if a network error occurs
*/
public void close() throws IOException {
try {
file.close();
tmp = null;
} catch (SmbException se) {
throw seToIoe(se);
}
}
/**
* Reads a byte of data from this input stream.
*
* @throws IOException if a network error occurs
*/
public int read() throws IOException {
// need oplocks to cache otherwise use BufferedInputStream
if( read( tmp, 0, 1 ) == -1 ) {
return -1;
}
return tmp[0] & 0xFF;
}
/**
* Reads up to b.length bytes of data from this input stream into an array of bytes.
*
* @throws IOException if a network error occurs
*/
public int read( byte[] b ) throws IOException {
return read( b, 0, b.length );
}
/**
* Reads up to len bytes of data from this input stream into an array of bytes.
*
* @throws IOException if a network error occurs
*/
public int read( byte[] b, int off, int len ) throws IOException {
return readDirect(b, off, len);
}
public int readDirect( byte[] b, int off, int len ) throws IOException {
if( len <= 0 ) {
return 0;
}
long start = fp;
if( tmp == null ) {
throw new IOException( "Bad file descriptor" );
}
// ensure file is open
file.open( openFlags, access, SmbFile.ATTR_NORMAL, 0 );
/*
* Read AndX Request / Response
*/
if( file.log.level >= 4 )
file.log.println( "read: fid=" + file.fid + ",off=" + off + ",len=" + len );
SmbComReadAndXResponse response = new SmbComReadAndXResponse( b, off );
if( file.type == SmbFile.TYPE_NAMED_PIPE ) {
response.responseTimeout = 0;
}
int r, n;
do {
r = len > readSize ? readSize : len;
if( file.log.level >= 4 )
file.log.println( "read: len=" + len + ",r=" + r + ",fp=" + fp );
try {
SmbComReadAndX request = new SmbComReadAndX( file.fid, fp, r, null );
if( file.type == SmbFile.TYPE_NAMED_PIPE ) {
request.minCount = request.maxCount = request.remaining = 1024;
}
file.send( request, response );
} catch( SmbException se ) {
if( file.type == SmbFile.TYPE_NAMED_PIPE &&
se.getNtStatus() == NtStatus.NT_STATUS_PIPE_BROKEN ) {
return -1;
}
throw seToIoe(se);
}
if(( n = response.dataLength ) <= 0 ) {
return (int)((fp - start) > 0L ? fp - start : -1);
}
fp += n;
len -= n;
response.off += n;
} while( len > 0 && n == r );
return (int)(fp - start);
}
/**
* This stream class is unbuffered. Therefore this method will always
* return 0 for streams connected to regular files. However, a
* stream created from a Named Pipe this method will query the server using a
* "peek named pipe" operation and return the number of available bytes
* on the server.
*/
public int available() throws IOException {
SmbNamedPipe pipe;
TransPeekNamedPipe req;
TransPeekNamedPipeResponse resp;
if( file.type != SmbFile.TYPE_NAMED_PIPE ) {
return 0;
}
try {
pipe = (SmbNamedPipe)file;
file.open(SmbFile.O_EXCL, pipe.pipeType & 0xFF0000, SmbFile.ATTR_NORMAL, 0 );
req = new TransPeekNamedPipe( file.unc, file.fid );
resp = new TransPeekNamedPipeResponse( pipe );
pipe.send( req, resp );
if( resp.status == TransPeekNamedPipeResponse.STATUS_DISCONNECTED ||
resp.status == TransPeekNamedPipeResponse.STATUS_SERVER_END_CLOSED ) {
file.opened = false;
return 0;
}
return resp.available;
} catch (SmbException se) {
throw seToIoe(se);
}
}
/**
* Skip n bytes of data on this stream. This operation will not result
* in any IO with the server. Unlink InputStream value less than
* the one provided will not be returned if it exceeds the end of the file
* (if this is a problem let us know).
*/
public long skip( long n ) throws IOException {
if (n > 0) {
fp += n;
return n;
}
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy