// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// (C) 2001-2003 Ximian, Inc. http://www.ximian.com
-// (c) 2004 Novell, Inc. (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using System.Collections;
+using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
+using System.Security.Permissions;
using System.Threading;
+#if NET_2_0
+using Microsoft.Win32.SafeHandles;
+#endif
+
namespace System.IO
{
public class FileStream : Stream
public FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
: this (handle, access, ownsHandle, bufferSize, isAsync, false) {}
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
internal FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync, bool noBuffering)
{
this.handle = MonoIO.InvalidHandle;
+ if (handle == this.handle)
+ throw new ArgumentException ("handle", Locale.GetText ("Invalid."));
if (access < FileAccess.Read || access > FileAccess.ReadWrite)
throw new ArgumentOutOfRangeException ("access");
MonoIOError error;
MonoFileType ftype = MonoIO.GetFileType (handle, out error);
+
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ throw MonoIO.GetException (name, error);
+ }
if (ftype == MonoFileType.Unknown) {
throw new IOException ("Invalid handle.");
this.canseek = true;
} else {
this.canseek = false;
+ noBuffering = true;
+ bufferSize = 0;
}
this.handle = handle;
this.access = access;
this.owner = ownsHandle;
this.async = isAsync;
-
- if (isAsync)
- ThreadPool.BindHandle (handle);
+ this.anonymous = false;
InitBuffer (bufferSize, noBuffering);
// construct from filename
public FileStream (string name, FileMode mode)
- : this (name, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, false) { }
+ : this (name, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, false, false)
+ {
+ }
public FileStream (string name, FileMode mode, FileAccess access)
- : this (name, mode, access, FileShare.ReadWrite, DefaultBufferSize, false) { }
+ : this (name, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, false, false)
+ {
+ }
public FileStream (string name, FileMode mode, FileAccess access, FileShare share)
- : this (name, mode, access, share, DefaultBufferSize, false) { }
+ : this (name, mode, access, share, DefaultBufferSize, false, false)
+ {
+ }
public FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize)
- : this (name, mode, access, share, bufferSize, false) { }
+ : this (name, mode, access, share, bufferSize, false, false)
+ {
+ }
public FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync)
+ : this (name, mode, access, share, bufferSize, isAsync, false)
+ {
+ }
+
+ internal FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync, bool anonymous)
{
if (name == null) {
throw new ArgumentNullException ("name");
}
- if (name == "") {
+ if (name.Length == 0) {
throw new ArgumentException ("Name is empty");
}
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException ("Positive number required.");
+
if (mode < FileMode.CreateNew || mode > FileMode.Append)
throw new ArgumentOutOfRangeException ("mode");
}
if (Directory.Exists (name)) {
- throw new UnauthorizedAccessException ("Access to the path '" + Path.GetFullPath (name) + "' is denied.");
+ // don't leak the path information for isolated storage
+ string msg = Locale.GetText ("Access to the path '{0}' is denied.");
+ string fname = (anonymous) ? Path.GetFileName (name) : Path.GetFullPath (name);
+ throw new UnauthorizedAccessException (String.Format (msg, fname));
}
/* Append streams can't be read (see FileMode
(mode != FileMode.Open && mode != FileMode.OpenOrCreate))
throw new ArgumentException ("access and mode not compatible");
- if (access == FileAccess.Read && mode != FileMode.Create && mode != FileMode.OpenOrCreate &&
- mode != FileMode.CreateNew && !File.Exists (name))
- throw new FileNotFoundException ("Could not find file \"" + name + "\".");
+ string dname = Path.GetDirectoryName (name);
+ if (dname.Length > 0) {
+ string fp = Path.GetFullPath (dname);
+ if (!Directory.Exists (fp)) {
+ // don't leak the path information for isolated storage
+ string msg = Locale.GetText ("Could not find a part of the path \"{0}\".");
+ string fname = (anonymous) ? dname : fp;
+ throw new DirectoryNotFoundException (String.Format (msg, fname));
+ }
+ }
- if (mode == FileMode.CreateNew) {
- string dname = Path.GetDirectoryName (name);
- string fp = null; ;
- if (dname != "" && !Directory.Exists ((fp = Path.GetFullPath (dname))))
- throw new DirectoryNotFoundException ("Could not find a part of " +
- "the path \"" + fp + "\".");
+ if (access == FileAccess.Read && mode != FileMode.Create && mode != FileMode.OpenOrCreate &&
+ mode != FileMode.CreateNew && !File.Exists (name)) {
+ // don't leak the path information for isolated storage
+ string msg = Locale.GetText ("Could not find file \"{0}\".");
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw new FileNotFoundException (String.Format (msg, fname), fname);
}
- this.name = name;
+ // IsolatedStorage needs to keep the Name property to the default "[Unknown]"
+ if (!anonymous)
+ this.name = name;
// TODO: demand permissions
MonoIOError error;
- this.handle = MonoIO.Open (name, mode, access, share, isAsync, out error);
+ this.handle = MonoIO.Open (name, mode, access, share, false, out error);
if (handle == MonoIO.InvalidHandle) {
- throw MonoIO.GetException (name, error);
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
}
this.access = access;
this.owner = true;
+ this.anonymous = anonymous;
/* Can we open non-files by name? */
if (MonoIO.GetFileType (handle, out error) == MonoFileType.Disk) {
this.canseek = true;
this.async = isAsync;
- if (isAsync)
- ThreadPool.BindHandle (handle);
} else {
this.canseek = false;
this.async = false;
}
- if (mode==FileMode.Append) {
- this.Seek (0, SeekOrigin.End);
- this.append_startpos=this.Position;
- } else {
- this.append_startpos=0;
- }
-
if (access == FileAccess.Read && canseek && (bufferSize == DefaultBufferSize)) {
/* Avoid allocating a large buffer for small files */
long len = Length;
}
InitBuffer (bufferSize, false);
+
+ if (mode==FileMode.Append) {
+ this.Seek (0, SeekOrigin.End);
+ this.append_startpos=this.Position;
+ } else {
+ this.append_startpos=0;
+ }
}
// properties
if (handle == MonoIO.InvalidHandle)
throw new ObjectDisposedException ("Stream has been closed");
- if (!canseek)
+ if (!CanSeek)
throw new NotSupportedException ("The stream does not support seeking");
// Buffered data might change the length of the stream
FlushBufferIfDirty ();
MonoIOError error;
+ long length;
- return MonoIO.GetLength (handle, out error);
+ length = MonoIO.GetLength (handle, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
+
+ return(length);
}
}
return(buf_start + buf_offset);
}
set {
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+
if(CanSeek == false) {
throw new NotSupportedException("The stream does not support seeking");
}
}
public virtual IntPtr Handle {
+ [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+ [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
get {
return handle;
}
}
+#if NET_2_0
+ public virtual SafeFileHandle SafeFileHandle {
+ [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+ [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
+ get { throw new NotImplementedException (); }
+ }
+#endif
+
// methods
public override int ReadByte ()
if (buf_offset == buf_size)
FlushBuffer ();
+ if (buf_size == 0) { // No buffering
+ buf [0] = value;
+ buf_dirty = true;
+ buf_length = 1;
+ FlushBuffer ();
+ return;
+ }
+
buf [buf_offset ++] = value;
if (buf_offset > buf_length)
buf_length = buf_offset;
if (handle == MonoIO.InvalidHandle)
throw new ObjectDisposedException ("Stream has been closed");
if (dest == null)
- throw new ArgumentNullException ("destination array is null");
+ throw new ArgumentNullException ("destFile");
if (!CanRead)
throw new NotSupportedException ("Stream does not support reading");
int len = dest.Length;
- if (dest_offset < 0 || count < 0)
- throw new ArgumentException ("dest or count is negative");
+ if (dest_offset < 0)
+ throw new ArgumentOutOfRangeException ("dest_offset", "< 0");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "< 0");
if (dest_offset > len)
throw new ArgumentException ("destination offset is beyond array size");
- if ((dest_offset + count) > len)
+ // reordered to avoid possible integer overflow
+ if (dest_offset > len - count)
throw new ArgumentException ("Reading would overrun buffer");
if (async) {
public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
AsyncCallback cback, object state)
{
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+
if (!CanRead)
throw new NotSupportedException ("This stream does not support reading");
if (offset < 0)
throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
- if (count + offset > buffer.Length)
+ // reordered to avoid possible integer overflow
+ if (count > buffer.Length - offset)
throw new ArgumentException ("Buffer too small. count/offset wrong.");
if (!async)
return base.BeginRead (buffer, offset, count, cback, state);
- if (!MonoIO.SupportsAsync) {
- ReadDelegate r = new ReadDelegate (ReadInternal);
- return r.BeginInvoke (buffer, offset, count, cback, state);
- }
-
- FileStreamAsyncResult result = new FileStreamAsyncResult (cback, state);
- result.Count = count;
- result.OriginalCount = count;
- int buffered = ReadSegment (buffer, offset, count);
- if (buffered >= count) {
- result.SetComplete (null, buffered, true);
- return result;
- }
-
- result.Buffer = buffer;
- result.Offset = offset + buffered;
- result.Count -= buffered;
-
- KeepReference (result);
- MonoIO.BeginRead (handle, result);
-
- return result;
+ ReadDelegate r = new ReadDelegate (ReadInternal);
+ return r.BeginInvoke (buffer, offset, count, cback, state);
}
public override int EndRead (IAsyncResult async_result)
if (!async)
return base.EndRead (async_result);
- if (!MonoIO.SupportsAsync) {
- AsyncResult ares = async_result as AsyncResult;
- if (ares == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
- if (r == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- return r.EndInvoke (async_result);
- }
-
- FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
- if (result == null || result.BytesRead == -1)
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- RemoveReference (result);
- if (result.Done)
- throw new InvalidOperationException ("EndRead already called.");
-
- result.Done = true;
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne ();
-
- if (result.Exception != null)
- throw result.Exception;
+ ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
+ if (r == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- buf_start += result.BytesRead;
- return result.OriginalCount - result.Count + result.BytesRead;
+ return r.EndInvoke (async_result);
}
public override void Write (byte[] src, int src_offset, int count)
{
if (handle == MonoIO.InvalidHandle)
throw new ObjectDisposedException ("Stream has been closed");
-
if (src == null)
throw new ArgumentNullException ("src");
-
if (src_offset < 0)
- throw new ArgumentOutOfRangeException ("src_offset");
-
+ throw new ArgumentOutOfRangeException ("src_offset", "< 0");
if (count < 0)
- throw new ArgumentOutOfRangeException ("count");
-
+ throw new ArgumentOutOfRangeException ("count", "< 0");
+ // ordered to avoid possible integer overflow
+ if (src_offset > src.Length - count)
+ throw new ArgumentException ("Reading would overrun buffer");
if (!CanWrite)
throw new NotSupportedException ("Stream does not support writing");
FlushBuffer ();
MonoIO.Write (handle, src, src_offset, count, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
+
buf_start += count;
} else {
public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
AsyncCallback cback, object state)
{
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+
if (!CanWrite)
throw new NotSupportedException ("This stream does not support writing");
if (offset < 0)
throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
- if (count + offset > buffer.Length)
+ // reordered to avoid possible integer overflow
+ if (count > buffer.Length - offset)
throw new ArgumentException ("Buffer too small. count/offset wrong.");
if (!async)
return base.BeginWrite (buffer, offset, count, cback, state);
- byte [] bytes;
- int buffered = 0;
FileStreamAsyncResult result = new FileStreamAsyncResult (cback, state);
result.BytesRead = -1;
result.Count = count;
if (buf_dirty) {
MemoryStream ms = new MemoryStream ();
FlushBufferToStream (ms);
- buffered = (int) ms.Length;
ms.Write (buffer, offset, count);
- bytes = ms.GetBuffer ();
offset = 0;
count = (int) ms.Length;
- } else {
- bytes = buffer;
}
- if (!MonoIO.SupportsAsync) {
- WriteDelegate w = new WriteDelegate (WriteInternal);
- return w.BeginInvoke (buffer, offset, count, cback, state);
- }
-
- if (buffered >= count) {
- result.SetComplete (null, buffered, true);
- return result;
- }
-
- result.Buffer = buffer;
- result.Offset = offset;
- result.Count = count;
-
- KeepReference (result);
- MonoIO.BeginWrite (handle, result);
-
- return result;
+ WriteDelegate w = new WriteDelegate (WriteInternal);
+ return w.BeginInvoke (buffer, offset, count, cback, state);
}
public override void EndWrite (IAsyncResult async_result)
return;
}
- if (!MonoIO.SupportsAsync) {
- AsyncResult ares = async_result as AsyncResult;
- if (ares == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
- if (w == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- w.EndInvoke (async_result);
- return;
- }
-
- FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
- if (result == null || result.BytesRead != -1)
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- RemoveReference (result);
- if (result.Done)
- throw new InvalidOperationException ("EndWrite already called.");
-
- result.Done = true;
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne ();
-
- if (result.Exception != null)
- throw result.Exception;
+ WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
+ if (w == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- buf_start += result.Count;
- buf_offset = buf_length = 0;
+ w.EndInvoke (async_result);
+ return;
}
public override long Seek (long offset, SeekOrigin origin)
pos = Position + offset;
break;
- case SeekOrigin.Begin: default:
+ case SeekOrigin.Begin:
pos = offset;
break;
+
+ default:
+ throw new ArgumentException ("origin", "Invalid SeekOrigin");
}
if (pos < 0) {
buf_start = MonoIO.Seek (handle, pos,
SeekOrigin.Begin,
out error);
+
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
return(buf_start);
}
public override void SetLength (long length)
{
- if(CanSeek == false) {
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+
+ if(CanSeek == false)
throw new NotSupportedException("The stream does not support seeking");
- }
- if(CanWrite == false) {
+ if(CanWrite == false)
throw new NotSupportedException("The stream does not support writing");
- }
- if(length < 0) {
+ if(length < 0)
throw new ArgumentOutOfRangeException("Length is less than 0");
- }
Flush ();
MonoIOError error;
MonoIO.SetLength (handle, length, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
+
+ if (Position > length)
+ Position = length;
}
public override void Flush ()
GC.SuppressFinalize (this); // remove from finalize queue
}
- [MonoTODO]
public virtual void Lock (long position, long length)
{
- throw new NotImplementedException ();
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException ("position must not be negative");
+ }
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException ("length must not be negative");
+ }
+ if (handle == MonoIO.InvalidHandle) {
+ throw new ObjectDisposedException ("Stream has been closed");
+ }
+
+ MonoIOError error;
+
+ MonoIO.Lock (handle, position, length, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
}
- [MonoTODO]
public virtual void Unlock (long position, long length)
{
- throw new NotImplementedException ();
+ if (handle == MonoIO.InvalidHandle)
+ throw new ObjectDisposedException ("Stream has been closed");
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException ("position must not be negative");
+ }
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException ("length must not be negative");
+ }
+
+ MonoIOError error;
+
+ MonoIO.Unlock (handle, position, length, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
}
// protected
MonoIOError error;
MonoIO.Close (handle, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
handle = MonoIO.InvalidHandle;
}
MonoIO.Seek (handle, buf_start,
SeekOrigin.Begin,
out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
}
st.Write (buf, 0, buf_length);
}
MonoIO.Seek (handle, buf_start,
SeekOrigin.Begin,
out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
}
MonoIO.Write (handle, buf, 0,
buf_length, out error);
+
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
+ }
}
buf_start += buf_offset;
MonoIOError error;
int amount = 0;
- if (async) {
- // DO SOMETHING!!!
- error = 0;
- } else {
- amount = MonoIO.Read (handle, buf, offset, count, out error);
+ /* when async == true, if we get here we don't suport AIO or it's disabled
+ * and we're using the threadpool */
+ amount = MonoIO.Read (handle, buf, offset, count, out error);
+ if (error == MonoIOError.ERROR_BROKEN_PIPE) {
+ amount = 0; // might not be needed, but well...
+ } else if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ string fname = (anonymous) ? Path.GetFileName (name) : name;
+ throw MonoIO.GetException (fname, error);
}
/* Check for read error */
if(amount == -1) {
- /* Kludge around broken pipes */
- if(error == MonoIOError.ERROR_BROKEN_PIPE) {
- amount = 0;
- } else {
- throw new IOException ();
- }
+ throw new IOException ();
}
return(amount);
buf_dirty = false;
}
- static void KeepReference (object o)
- {
- lock (typeof (FileStream)) {
- if (asyncObjects == null)
- asyncObjects = new Hashtable ();
-
- asyncObjects [o] = o;
- }
- }
-
- static void RemoveReference (object o)
- {
- lock (typeof (FileStream)) {
- if (asyncObjects == null)
- return;
-
- asyncObjects.Remove (o);
- }
- }
-
// fields
- private static int DefaultBufferSize = 8192;
- private static Hashtable asyncObjects;
+ internal const int DefaultBufferSize = 8192;
private FileAccess access;
private bool owner;
private bool async;
private bool canseek;
private long append_startpos;
-
+ private bool anonymous;
private byte [] buf; // the buffer
private int buf_size; // capacity in bytes