#if NET_2_0
using Microsoft.Win32.SafeHandles;
+using System.Security.AccessControl;
#endif
namespace System.IO
{
+#if NET_2_0
+ [ComVisible (true)]
+#endif
public class FileStream : Stream
{
// construct from handle
+#if NET_2_0_SAFEFILEHANDLE_ENABLED
+ [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access) instead")]
+#endif
public FileStream (IntPtr handle, FileAccess access)
: this (handle, access, true, DefaultBufferSize, false) {}
+#if NET_2_0_SAFEFILEHANDLE_ENABLED
+ [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access) instead")]
+#endif
public FileStream (IntPtr handle, FileAccess access, bool ownsHandle)
: this (handle, access, ownsHandle, DefaultBufferSize, false) {}
+#if NET_2_0_SAFEFILEHANDLE_ENABLED
+ [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead")]
+#endif
public FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
: this (handle, access, ownsHandle, bufferSize, false) {}
+#if NET_2_0_SAFEFILEHANDLE_ENABLED
+ [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead")]
+#endif
public FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
: this (handle, access, ownsHandle, bufferSize, isAsync, false) {}
this.canseek = true;
} else {
this.canseek = false;
- noBuffering = true;
- bufferSize = 0;
}
this.handle = handle;
InitBuffer (bufferSize, noBuffering);
+ if (canseek) {
+ buf_start = MonoIO.Seek (handle, 0, SeekOrigin.Current, out error);
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ throw MonoIO.GetException (name, error);
+ }
+ }
+
/* Can't set append mode */
this.append_startpos=0;
}
// construct from filename
- public FileStream (string name, FileMode mode)
- : this (name, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, false, false)
+ public FileStream (string path, FileMode mode)
+ : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, false, FileOptions.None)
+ {
+ }
+
+ public FileStream (string path, FileMode mode, FileAccess access)
+ : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, false, false)
+ {
+ }
+
+ public FileStream (string path, FileMode mode, FileAccess access, FileShare share)
+ : this (path, mode, access, share, DefaultBufferSize, false, FileOptions.None)
+ {
+ }
+
+ public FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
+ : this (path, mode, access, share, bufferSize, false, FileOptions.None)
{
}
- public FileStream (string name, FileMode mode, FileAccess access)
- : this (name, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, false, false)
+ public FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync)
+ : this (path, mode, access, share, bufferSize, isAsync, FileOptions.None)
{
}
- public FileStream (string name, FileMode mode, FileAccess access, FileShare share)
- : this (name, mode, access, share, DefaultBufferSize, false, false)
+#if NET_2_0
+ public FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
+ : this (path, mode, access, share, bufferSize, false, options)
+ {
+ }
+
+ public FileStream (SafeFileHandle handle, FileAccess access)
+ :this(handle, access, DefaultBufferSize, false)
+ {
+ }
+
+ public FileStream (SafeFileHandle handle, FileAccess access,
+ int bufferSize)
+ :this(handle, access, bufferSize, false)
{
}
- public FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize)
- : this (name, mode, access, share, bufferSize, false, false)
+ [MonoLimitationAttribute("Need to use SafeFileHandle instead of underlying handle")]
+ public FileStream (SafeFileHandle handle, FileAccess access,
+ int bufferSize, bool isAsync)
+ :this (handle.DangerousGetHandle (), access, false, bufferSize, isAsync)
{
}
- public FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync)
- : this (name, mode, access, share, bufferSize, isAsync, false)
+ public FileStream (string path, FileMode mode,
+ FileSystemRights rights, FileShare share,
+ int bufferSize, FileOptions options)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public FileStream (string path, FileMode mode,
+ FileSystemRights rights, FileShare share,
+ int bufferSize, FileOptions options,
+ FileSecurity fileSecurity)
{
+ throw new NotImplementedException ();
}
+#endif
- internal FileStream (string name, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync, bool anonymous)
+ internal FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync, bool anonymous)
+ : this (path, mode, access, share, bufferSize, anonymous, isAsync ? FileOptions.Asynchronous : FileOptions.None)
{
- if (name == null) {
- throw new ArgumentNullException ("name");
+ }
+
+ internal FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool anonymous, FileOptions options)
+ {
+ if (path == null) {
+ throw new ArgumentNullException ("path");
}
-
- if (name.Length == 0) {
- throw new ArgumentException ("Name is empty");
+
+ if (path.Length == 0) {
+ throw new ArgumentException ("Path is empty");
}
+#if NET_2_0
+ // ignore the Inheritable flag
+ share &= ~FileShare.Inheritable;
+
+#endif
+
if (bufferSize <= 0)
- throw new ArgumentOutOfRangeException ("Positive number required.");
+ throw new ArgumentOutOfRangeException ("bufferSize", "Positive number required.");
if (mode < FileMode.CreateNew || mode > FileMode.Append)
- throw new ArgumentOutOfRangeException ("mode");
+ throw new ArgumentOutOfRangeException ("mode", "Enum value was out of legal range.");
if (access < FileAccess.Read || access > FileAccess.ReadWrite)
- throw new ArgumentOutOfRangeException ("access");
+ throw new ArgumentOutOfRangeException ("access", "Enum value was out of legal range.");
+#if NET_2_0
+ if (share < FileShare.None || share > (FileShare.ReadWrite | FileShare.Delete))
+#else
if (share < FileShare.None || share > FileShare.ReadWrite)
- throw new ArgumentOutOfRangeException ("share");
+#endif
+ throw new ArgumentOutOfRangeException ("share", "Enum value was out of legal range.");
- if (name.IndexOfAny (Path.InvalidPathChars) != -1) {
+ if (path.IndexOfAny (Path.InvalidPathChars) != -1) {
throw new ArgumentException ("Name has invalid chars");
}
- if (Directory.Exists (name)) {
+ if (Directory.Exists (path)) {
// 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);
+ string fname = (anonymous) ? Path.GetFileName (path) : Path.GetFullPath (path);
throw new UnauthorizedAccessException (String.Format (msg, fname));
}
* docs)
*/
if (mode==FileMode.Append &&
- (access&FileAccess.Read)==FileAccess.Read) {
- throw new ArgumentException("Append streams can not be read");
+ (access&FileAccess.Read)==FileAccess.Read) {
+ throw new ArgumentException("Append access can be requested only in write-only mode.");
}
if ((access & FileAccess.Write) == 0 &&
- (mode != FileMode.Open && mode != FileMode.OpenOrCreate))
- throw new ArgumentException ("access and mode not compatible");
+ (mode != FileMode.Open && mode != FileMode.OpenOrCreate)) {
+ string msg = Locale.GetText ("Combining FileMode: {0} with " +
+ "FileAccess: {1} is invalid.");
+ throw new ArgumentException (string.Format (msg, access, mode));
+ }
- string dname = Path.GetDirectoryName (name);
+ string dname = Path.GetDirectoryName (path);
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;
+ string fname = (anonymous) ? dname : Path.GetFullPath (path);
throw new DirectoryNotFoundException (String.Format (msg, fname));
}
}
if (access == FileAccess.Read && mode != FileMode.Create && mode != FileMode.OpenOrCreate &&
- mode != FileMode.CreateNew && !File.Exists (name)) {
+ mode != FileMode.CreateNew && !File.Exists (path)) {
// 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;
+ string fname = (anonymous) ? Path.GetFileName (path) : Path.GetFullPath (path);
throw new FileNotFoundException (String.Format (msg, fname), fname);
}
// IsolatedStorage needs to keep the Name property to the default "[Unknown]"
if (!anonymous)
- this.name = name;
+ this.name = path;
// TODO: demand permissions
MonoIOError error;
- this.handle = MonoIO.Open (name, mode, access, share, false, out error);
+ this.handle = MonoIO.Open (path, mode, access, share, options, out error);
if (handle == MonoIO.InvalidHandle) {
// don't leak the path information for isolated storage
- string fname = (anonymous) ? Path.GetFileName (name) : name;
+ string fname = (anonymous) ? Path.GetFileName (path) : Path.GetFullPath (path);
throw MonoIO.GetException (fname, error);
}
if (MonoIO.GetFileType (handle, out error) == MonoFileType.Disk) {
this.canseek = true;
- this.async = isAsync;
+ this.async = (options & FileOptions.Asynchronous) != 0;
} else {
this.canseek = false;
this.async = false;
}
}
- public override bool CanWrite {
- get {
+ public override bool CanWrite {
+ get {
return access == FileAccess.Write ||
- access == FileAccess.ReadWrite;
- }
- }
+ access == FileAccess.ReadWrite;
+ }
+ }
public override bool CanSeek {
- get {
- return(canseek);
- }
- }
+ get {
+ return(canseek);
+ }
+ }
public virtual bool IsAsync {
get {
}
}
+#if NET_2_0
+ [Obsolete ("Use SafeFileHandle instead")]
+#endif
public virtual IntPtr Handle {
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
[SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
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;
return base.BeginRead (buffer, offset, count, cback, state);
ReadDelegate r = new ReadDelegate (ReadInternal);
- return r.BeginInvoke (buffer, offset, count, cback, state);
+ return r.BeginInvoke (buffer, offset, count, cback, state);
}
public override int EndRead (IAsyncResult async_result)
throw new IOException("Can't seek back over pre-existing data in append mode");
}
- if (buf_length > 0) {
- if (pos >= buf_start &&
- pos <= buf_start + buf_length) {
- buf_offset = (int) (pos - buf_start);
- return pos;
- }
- }
-
FlushBuffer ();
MonoIOError error;
//MonoIO.Flush (handle);
}
+#if !NET_2_0
public override void Close ()
{
Dispose (true);
- GC.SuppressFinalize (this); // remove from finalize queue
}
+#endif
public virtual void Lock (long position, long length)
{
Dispose (false);
}
- protected virtual void Dispose (bool disposing) {
+#if NET_2_0
+ protected override void Dispose (bool disposing)
+#else
+ protected virtual void Dispose (bool disposing)
+#endif
+ {
if (handle != MonoIO.InvalidHandle) {
FlushBuffer ();
if (disposing) {
buf = null;
}
+ if (disposing)
+ GC.SuppressFinalize (this);
}
+#if NET_2_0
+ public FileSecurity GetAccessControl ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void SetAccessControl (FileSecurity fileSecurity)
+ {
+ throw new NotImplementedException ();
+ }
+#endif
+
// private.
// ReadSegment, WriteSegment, FlushBuffer,
IntPtr handle; // handle to underlying file
}
}
-