| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 | // 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  USAusing 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(); }        }    }}
 |