001: /* jcifs smb client library in Java
002: * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.knowgate.jcifs.smb;
020:
021: import java.net.URL;
022: import java.net.UnknownHostException;
023: import java.net.MalformedURLException;
024: import java.io.InputStream;
025: import java.io.IOException;
026:
027: import com.knowgate.debug.*;
028:
029: /**
030: * This InputStream can read bytes from a file on an SMB file server. Offsets are 64 bits.
031: */
032:
033: public class SmbFileInputStream extends InputStream {
034:
035: private SmbFile file;
036: private long fp;
037: private int readSize, openFlags;
038: private byte[] tmp = new byte[1];
039:
040: /**
041: * Creates an {@link java.io.InputStream} for reading bytes from a file on
042: * an SMB server addressed by the <code>url</code> parameter. See {@link
043: * jcifs.smb.SmbFile} for a detailed description and examples of the smb
044: * URL syntax.
045: *
046: * @param url An smb URL string representing the file to read from
047: * @return A new <code>InputStream</code> for the specified <code>SmbFile</code>
048: */
049:
050: public SmbFileInputStream(String url) throws SmbException,
051: MalformedURLException, UnknownHostException {
052: this (new SmbFile(url));
053: }
054:
055: /**
056: * Creates an {@link java.io.InputStream} for reading bytes from a file on
057: * an SMB server represented by the {@link jcifs.smb.SmbFile} parameter. See
058: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
059: * the smb URL syntax.
060: *
061: * @param url An smb URL string representing the file to write to
062: * @return A new <code>InputStream</code> for the specified <code>SmbFile</code>
063: */
064:
065: public SmbFileInputStream(SmbFile file) throws SmbException,
066: MalformedURLException, UnknownHostException {
067: this (file, SmbFile.O_RDONLY);
068: }
069:
070: SmbFileInputStream(SmbFile file, int openFlags)
071: throws SmbException, MalformedURLException,
072: UnknownHostException {
073: this .file = file;
074: this .openFlags = openFlags;
075: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
076: readSize = Math.min(
077: file.tree.session.transport.rcv_buf_size - 70,
078: file.tree.session.transport.server.maxBufferSize - 70);
079: }
080:
081: /**
082: * Closes this input stream and releases any system resources associated with the stream.
083: *
084: * @throws IOException if a network error occurs
085: */
086:
087: public void close() throws IOException {
088: file.close();
089: }
090:
091: /**
092: * Reads a byte of data from this input stream.
093: *
094: * @throws IOException if a network error occurs
095: */
096:
097: public int read() throws IOException {
098: // need oplocks to cache otherwise use BufferedInputStream
099: if (read(tmp, 0, 1) == -1) {
100: return -1;
101: }
102: return tmp[0] & 0xFF;
103: }
104:
105: /**
106: * Reads up to b.length bytes of data from this input stream into an array of bytes.
107: *
108: * @throws IOException if a network error occurs
109: */
110:
111: public int read(byte[] b) throws IOException {
112: return read(b, 0, b.length);
113: }
114:
115: /**
116: * Reads up to len bytes of data from this input stream into an array of bytes.
117: *
118: * @throws IOException if a network error occurs
119: */
120:
121: public int read(byte[] b, int off, int len) throws IOException {
122: if (len <= 0) {
123: return 0;
124: }
125: long start = fp;
126:
127: // ensure file is open
128: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
129:
130: /*
131: * Read AndX Request / Response
132: */
133:
134: if (DebugFile.trace)
135: DebugFile.writeln("read: fid=" + file.fid + ",off=" + off
136: + ",len=" + len);
137:
138: SmbComReadAndXResponse response = new SmbComReadAndXResponse(b,
139: off);
140:
141: if (file.type == SmbFile.TYPE_NAMED_PIPE) {
142: response.responseTimeout = 0;
143: }
144:
145: int r, n;
146: do {
147: r = len > readSize ? readSize : len;
148:
149: if (DebugFile.trace)
150: DebugFile.writeln("read: len=" + len + ",r=" + r
151: + ",fp=" + fp);
152:
153: try {
154: file.send(new SmbComReadAndX(file.fid, fp, r, null),
155: response);
156: } catch (SmbException se) {
157: if (file.type == SmbFile.TYPE_NAMED_PIPE
158: && se.getNtStatus() == NtStatus.NT_STATUS_PIPE_BROKEN) {
159: return -1;
160: }
161: throw se;
162: }
163: if ((n = response.dataLength) <= 0) {
164: return (int) ((fp - start) > 0L ? fp - start : -1);
165: }
166: fp += n;
167: len -= n;
168: response.off += n;
169: } while (len > 0 && n == r);
170:
171: return (int) (fp - start);
172: }
173:
174: public int available() throws IOException {
175: SmbNamedPipe pipe;
176: TransPeekNamedPipe req;
177: TransPeekNamedPipeResponse resp;
178:
179: if (file.type != SmbFile.TYPE_NAMED_PIPE) {
180: return 0;
181: }
182:
183: pipe = (SmbNamedPipe) file;
184: file.open((pipe.pipeType & 0xFF0000) | SmbFile.O_EXCL,
185: SmbFile.ATTR_NORMAL, 0);
186:
187: req = new TransPeekNamedPipe(file.unc, file.fid);
188: resp = new TransPeekNamedPipeResponse(pipe);
189:
190: pipe.sendTransaction(req, resp);
191: if (resp.status == TransPeekNamedPipeResponse.STATUS_DISCONNECTED
192: || resp.status == TransPeekNamedPipeResponse.STATUS_SERVER_END_CLOSED) {
193: file.opened = false;
194: return 0;
195: }
196: return resp.available;
197: }
198:
199: /**
200: * Skip n bytes of data on this stream. This operation will not result
201: * in any IO with the server. Unlink <tt>InputStream</tt> value less than
202: * the one provided will not be returned if it exceeds the end of the file
203: * (if this is a problem let us know).
204: */
205: public long skip(long n) throws IOException {
206: if (n > 0) {
207: fp += n;
208: return n;
209: }
210: return 0;
211: }
212: }
|