// This code is derived from jcifs smb client library // Ported by J. Arturo // // 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 System.Text; using SharpCifs.Util; using SharpCifs.Util.Sharpen; namespace SharpCifs.Smb { public class SmbRandomAccessFile //: DataOutput, DataInput { private const int WriteOptions = unchecked(0x0842); private SmbFile _file; private long _fp; private int _openFlags; private int _access; private int _readSize; private int _writeSize; private int _ch; private int _options; private byte[] _tmp = new byte[8]; private SmbComWriteAndXResponse _writeAndxResp; /// /// /// public SmbRandomAccessFile(string url, string mode, int shareAccess) : this(new SmbFile (url, string.Empty, null, shareAccess), mode) { } /// /// /// public SmbRandomAccessFile(SmbFile file, string mode) { this._file = file; if (mode.Equals("r")) { _openFlags = SmbFile.OCreat | SmbFile.ORdonly; } else { if (mode.Equals("rw")) { _openFlags = SmbFile.OCreat | SmbFile.ORdwr | SmbFile.OAppend; _writeAndxResp = new SmbComWriteAndXResponse(); _options = WriteOptions; _access = SmbConstants.FileReadData | SmbConstants.FileWriteData; } else { throw new ArgumentException("Invalid mode"); } } file.Open(_openFlags, _access, SmbFile.AttrNormal, _options); _readSize = file.Tree.Session.transport.RcvBufSize - 70; _writeSize = file.Tree.Session.transport.SndBufSize - 70; _fp = 0L; } /// public virtual int Read() { if (Read(_tmp, 0, 1) == -1) { return -1; } return _tmp[0] & unchecked(0xFF); } /// public virtual int Read(byte[] b) { return Read(b, 0, b.Length); } /// public virtual int Read(byte[] b, int off, int len) { if (len <= 0) { return 0; } long start = _fp; // ensure file is open if (_file.IsOpen() == false) { _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); } int r; int n; SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); do { r = len > _readSize ? _readSize : len; _file.Send(new SmbComReadAndX(_file.Fid, _fp, r, null), response); 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); } /// public void ReadFully(byte[] b) { ReadFully(b, 0, b.Length); } /// public void ReadFully(byte[] b, int off, int len) { int n = 0; int count; do { count = Read(b, off + n, len - n); if (count < 0) { throw new SmbException("EOF"); } n += count; _fp += count; } while (n < len); } /// public virtual int SkipBytes(int n) { if (n > 0) { _fp += n; return n; } return 0; } /// public virtual void Write(int b) { _tmp[0] = unchecked((byte)b); Write(_tmp, 0, 1); } /// public virtual void Write(byte[] b) { Write(b, 0, b.Length); } /// public virtual void Write(byte[] b, int off, int len) { if (len <= 0) { return; } // ensure file is open if (_file.IsOpen() == false) { _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); } int w; do { w = len > _writeSize ? _writeSize : len; _file.Send(new SmbComWriteAndX(_file.Fid, _fp, len - w, b, off, w, null), _writeAndxResp ); _fp += _writeAndxResp.Count; len -= (int)_writeAndxResp.Count; off += (int)_writeAndxResp.Count; } while (len > 0); } /// public virtual long GetFilePointer() { return _fp; } /// public virtual void Seek(long pos) { _fp = pos; } /// public virtual long Length() { return _file.Length(); } /// public virtual void SetLength(long newLength) { // ensure file is open if (_file.IsOpen() == false) { _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); } SmbComWriteResponse rsp = new SmbComWriteResponse(); _file.Send(new SmbComWrite(_file.Fid, (int)(newLength & unchecked(0xFFFFFFFFL)), 0, _tmp, 0, 0), rsp); } /// public virtual void Close() { _file.Close(); } /// public bool ReadBoolean() { if ((Read(_tmp, 0, 1)) < 0) { throw new SmbException("EOF"); } return _tmp[0] != unchecked(unchecked(0x00)); } /// public byte ReadByte() { if ((Read(_tmp, 0, 1)) < 0) { throw new SmbException("EOF"); } return _tmp[0]; } /// public int ReadUnsignedByte() { if ((Read(_tmp, 0, 1)) < 0) { throw new SmbException("EOF"); } return _tmp[0] & unchecked(0xFF); } /// public short ReadShort() { if ((Read(_tmp, 0, 2)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_uint16be(_tmp, 0); } /// public int ReadUnsignedShort() { if ((Read(_tmp, 0, 2)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_uint16be(_tmp, 0) & unchecked(0xFFFF); } /// public char ReadChar() { if ((Read(_tmp, 0, 2)) < 0) { throw new SmbException("EOF"); } return (char)Encdec.Dec_uint16be(_tmp, 0); } /// public int ReadInt() { if ((Read(_tmp, 0, 4)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_uint32be(_tmp, 0); } /// public long ReadLong() { if ((Read(_tmp, 0, 8)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_uint64be(_tmp, 0); } /// public float ReadFloat() { if ((Read(_tmp, 0, 4)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_floatbe(_tmp, 0); } /// public double ReadDouble() { if ((Read(_tmp, 0, 8)) < 0) { throw new SmbException("EOF"); } return Encdec.Dec_doublebe(_tmp, 0); } /// public string ReadLine() { StringBuilder input = new StringBuilder(); int c = -1; bool eol = false; while (!eol) { switch (c = Read()) { case -1: case '\n': { eol = true; break; } case '\r': { eol = true; long cur = _fp; if (Read() != '\n') { _fp = cur; } break; } default: { input.Append((char)c); break; } } } if ((c == -1) && (input.Length == 0)) { return null; } return input.ToString(); } /// public string ReadUtf() { int size = ReadUnsignedShort(); byte[] b = new byte[size]; Read(b, 0, size); try { return Encdec.Dec_utf8(b, 0, size); } catch (IOException ioe) { throw new SmbException(string.Empty, ioe); } } /// public void WriteBoolean(bool v) { _tmp[0] = unchecked((byte)(v ? 1 : 0)); Write(_tmp, 0, 1); } /// public void WriteByte(int v) { _tmp[0] = unchecked((byte)v); Write(_tmp, 0, 1); } /// public void WriteShort(int v) { Encdec.Enc_uint16be((short)v, _tmp, 0); Write(_tmp, 0, 2); } /// public void WriteChar(int v) { Encdec.Enc_uint16be((short)v, _tmp, 0); Write(_tmp, 0, 2); } /// public void WriteInt(int v) { Encdec.Enc_uint32be(v, _tmp, 0); Write(_tmp, 0, 4); } /// public void WriteLong(long v) { Encdec.Enc_uint64be(v, _tmp, 0); Write(_tmp, 0, 8); } /// public void WriteFloat(float v) { Encdec.Enc_floatbe(v, _tmp, 0); Write(_tmp, 0, 4); } /// public void WriteDouble(double v) { Encdec.Enc_doublebe(v, _tmp, 0); Write(_tmp, 0, 8); } /// public void WriteBytes(string s) { byte[] b = Runtime.GetBytesForString(s); Write(b, 0, b.Length); } /// /* public void WriteChars(string s) { int clen = s.Length; int blen = 2 * clen; byte[] b = new byte[blen]; char[] c = new char[clen]; Sharpen.Runtime.GetCharsForString(s, 0, clen, c, 0); for (int i = 0, j = 0; i < clen; i++) { b[j++] = unchecked((byte)((char)(((uchar)c[i]) >> 8))); b[j++] = unchecked((byte)((char)(((uchar)c[i]) >> 0))); } Write(b, 0, blen); }*/ /// public void WriteUtf(string str) { int len = str.Length; int ch; int size = 0; byte[] dst; for (int i = 0; i < len; i++) { ch = str[i]; size += ch > unchecked(0x07F) ? (ch > unchecked(0x7FF) ? 3 : 2) : 1; } dst = new byte[size]; WriteShort(size); try { Encdec.Enc_utf8(str, dst, 0, size); } catch (IOException ioe) { throw new SmbException(string.Empty, ioe); } Write(dst, 0, size); } } }