123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- // This code is derived from jcifs smb client library <jcifs at samba dot org>
- // Ported by J. Arturo <webmaster at komodosoft dot net>
- //
- // 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
- using System;
- using System.IO;
- using SharpCifs.Util.Sharpen;
- using SharpCifs.Util.Transport;
- namespace SharpCifs.Smb
- {
- /// <summary>This InputStream can read bytes from a file on an SMB file server.</summary>
- /// <remarks>This InputStream can read bytes from a file on an SMB file server. Offsets are 64 bits.
- /// </remarks>
- public class SmbFileInputStream : InputStream
- {
- private long _fp;
- private int _readSize;
- private int _openFlags;
- private int _access;
- private byte[] _tmp = new byte[1];
- internal SmbFile File;
- /// <summary>
- /// Creates an
- /// <see cref="System.IO.InputStream">System.IO.InputStream</see>
- /// for reading bytes from a file on
- /// an SMB server addressed by the <code>url</code> parameter. See
- /// <see cref="SmbFile">SmbFile</see>
- /// for a detailed description and examples of the smb
- /// URL syntax.
- /// </summary>
- /// <param name="url">An smb URL string representing the file to read from</param>
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- /// <exception cref="System.UriFormatException"></exception>
- /// <exception cref="UnknownHostException"></exception>
- public SmbFileInputStream(string url) : this(new SmbFile(url))
- {
- }
- /// <summary>
- /// Creates an
- /// <see cref="System.IO.InputStream">System.IO.InputStream</see>
- /// for reading bytes from a file on
- /// an SMB server represented by the
- /// <see cref="SmbFile">SmbFile</see>
- /// parameter. See
- /// <see cref="SmbFile">SmbFile</see>
- /// for a detailed description and examples of
- /// the smb URL syntax.
- /// </summary>
- /// <param name="file">An <code>SmbFile</code> specifying the file to read from</param>
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- /// <exception cref="System.UriFormatException"></exception>
- /// <exception cref="UnknownHostException"></exception>
- public SmbFileInputStream(SmbFile file) : this(file, SmbFile.ORdonly)
- {
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- /// <exception cref="System.UriFormatException"></exception>
- /// <exception cref="UnknownHostException"></exception>
- internal SmbFileInputStream(SmbFile file, int openFlags)
- {
- this.File = file;
- this._openFlags = openFlags & 0xFFFF;
- _access = ((int)(((uint)openFlags) >> 16)) & 0xFFFF;
- if (file.Type != SmbFile.TypeNamedPipe)
- {
- file.Open(openFlags, _access, SmbFile.AttrNormal, 0);
- this._openFlags &= ~(SmbFile.OCreat | SmbFile.OTrunc);
- }
- else
- {
- file.Connect0();
- }
- _readSize = Math.Min(file.Tree.Session.transport.RcvBufSize - 70, file.Tree.Session
- .transport.Server.MaxBufferSize - 70);
- }
- protected internal virtual IOException SeToIoe(SmbException se)
- {
- IOException ioe = se;
- Exception root = se.GetRootCause();
- if (root is TransportException)
- {
- ioe = (TransportException)root;
- root = ((TransportException)ioe).GetRootCause();
- }
- if (root is Exception)
- {
- ioe = new IOException(root.Message);
- ioe.InitCause(root);
- }
- return ioe;
- }
- /// <summary>Closes this input stream and releases any system resources associated with the stream.
- /// </summary>
- /// <remarks>Closes this input stream and releases any system resources associated with the stream.
- /// </remarks>
- /// <exception cref="System.IO.IOException">if a network error occurs</exception>
- public override void Close()
- {
- try
- {
- File.Close();
- _tmp = null;
- }
- catch (SmbException se)
- {
- throw SeToIoe(se);
- }
- }
- /// <summary>Reads a byte of data from this input stream.</summary>
- /// <remarks>Reads a byte of data from this input stream.</remarks>
- /// <exception cref="System.IO.IOException">if a network error occurs</exception>
- public override int Read()
- {
- // need oplocks to cache otherwise use BufferedInputStream
- if (Read(_tmp, 0, 1) == -1)
- {
- return -1;
- }
- return _tmp[0] & unchecked(0xFF);
- }
- /// <summary>Reads up to b.length bytes of data from this input stream into an array of bytes.
- /// </summary>
- /// <remarks>Reads up to b.length bytes of data from this input stream into an array of bytes.
- /// </remarks>
- /// <exception cref="System.IO.IOException">if a network error occurs</exception>
- public override int Read(byte[] b)
- {
- return Read(b, 0, b.Length);
- }
- /// <summary>Reads up to len bytes of data from this input stream into an array of bytes.
- /// </summary>
- /// <remarks>Reads up to len bytes of data from this input stream into an array of bytes.
- /// </remarks>
- /// <exception cref="System.IO.IOException">if a network error occurs</exception>
- public override int Read(byte[] b, int off, int len)
- {
- return ReadDirect(b, off, len);
- }
- /// <exception cref="System.IO.IOException"></exception>
- public virtual int ReadDirect(byte[] b, int off, int len)
- {
- 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.AttrNormal, 0);
- if (File.Log.Level >= 4)
- {
- File.Log.WriteLine("read: fid=" + File.Fid + ",off=" + off + ",len=" + len);
- }
- SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off);
- if (File.Type == SmbFile.TypeNamedPipe)
- {
- response.ResponseTimeout = 0;
- }
- int r;
- int n;
- do
- {
- r = len > _readSize ? _readSize : len;
- if (File.Log.Level >= 4)
- {
- File.Log.WriteLine("read: len=" + len + ",r=" + r + ",fp=" + _fp);
- }
- try
- {
- SmbComReadAndX request = new SmbComReadAndX(File.Fid, _fp, r, null);
- if (File.Type == SmbFile.TypeNamedPipe)
- {
- request.MinCount = request.MaxCount = request.Remaining = 1024;
- }
- //ここで読み込んでいるらしい。
- File.Send(request, response);
- }
- catch (SmbException se)
- {
- if (File.Type == SmbFile.TypeNamedPipe && se.GetNtStatus() == NtStatus.NtStatusPipeBroken)
- {
- 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);
- }
- /// <summary>This stream class is unbuffered.</summary>
- /// <remarks>
- /// 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.
- /// </remarks>
- /// <exception cref="System.IO.IOException"></exception>
- public override int Available()
- {
- SmbNamedPipe pipe;
- TransPeekNamedPipe req;
- TransPeekNamedPipeResponse resp;
- if (File.Type != SmbFile.TypeNamedPipe)
- {
- return 0;
- }
- try
- {
- pipe = (SmbNamedPipe)File;
- File.Open(SmbFile.OExcl, pipe.PipeType & 0xFF0000, SmbFile.AttrNormal
- , 0);
- req = new TransPeekNamedPipe(File.Unc, File.Fid);
- resp = new TransPeekNamedPipeResponse(pipe);
- pipe.Send(req, resp);
- if (resp.status == TransPeekNamedPipeResponse.StatusDisconnected || resp.status
- == TransPeekNamedPipeResponse.StatusServerEndClosed)
- {
- File.Opened = false;
- return 0;
- }
- return resp.Available;
- }
- catch (SmbException se)
- {
- throw SeToIoe(se);
- }
- }
- /// <summary>Skip n bytes of data on this stream.</summary>
- /// <remarks>
- /// Skip n bytes of data on this stream. This operation will not result
- /// in any IO with the server. Unlink <tt>InputStream</tt> 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).
- /// </remarks>
- /// <exception cref="System.IO.IOException"></exception>
- public override long Skip(long n)
- {
- if (n > 0)
- {
- _fp += n;
- return n;
- }
- return 0;
- }
- /// <summary>
- /// Position in Stream
- /// </summary>
- /// <remarks>
- /// Add by dobes
- /// mod interface to WrappedSystemStream readable, for random access.
- /// </remarks>
- internal override long Position {
- get { return this._fp; }
- set
- {
- var tmpPos = value;
- var length = File.Length();
- if (tmpPos < 0)
- tmpPos = 0;
- else if (length < tmpPos)
- tmpPos = length;
- this._fp = tmpPos;
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <returns></returns>
- /// <remarks>
- /// Add by dobes
- /// mod interface to WrappedSystemStream readable, for random access.
- /// </remarks>
- internal override bool CanSeek()
- {
- return (File.Length() >= 0);
- }
- /// <summary>
- /// Get file length
- /// </summary>
- public override long Length
- {
- get { return File.Length(); }
- }
-
- }
- }
|