//
// (C) 2001-2003 Ximian, Inc. http://www.ximian.com
// Copyright (C) 2004-2005, 2008, 2010 Novell, Inc (http://www.novell.com)
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com).
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.Security;
using System.Security.Permissions;
using System.Threading;
-
using Microsoft.Win32.SafeHandles;
+
#if NET_2_1
using System.IO.IsolatedStorage;
#else
using System.Security.AccessControl;
#endif
+#if NET_4_5
+using System.Threading.Tasks;
+#endif
+
namespace System.IO
{
[ComVisible (true)]
}
this.handle = handle;
+ ExposeHandle ();
this.access = access;
this.owner = ownsHandle;
this.async = isAsync;
-#if MOONLIGHT
- // default the browser to 'all' anonymous files and let other usage (like smcs) with 'normal'
- // (i.e. non-anonymous except for isolated storage) files and paths
- this.anonymous = SecurityManager.SecurityEnabled;
-#else
this.anonymous = false;
-#endif
- InitBuffer (bufferSize, isZeroSize);
-
if (canseek) {
buf_start = MonoIO.Seek (handle, 0, SeekOrigin.Current, out error);
if (error != MonoIOError.ERROR_SUCCESS) {
}
if (access < FileAccess.Read || access > FileAccess.ReadWrite) {
-#if NET_2_1
- if (anonymous)
- throw new IsolatedStorageException ("Enum value for FileAccess was out of legal range.");
- else
-#endif
throw new ArgumentOutOfRangeException ("access", "Enum value was out of legal range.");
}
if (share < FileShare.None || share > (FileShare.ReadWrite | FileShare.Delete)) {
-#if NET_2_1
- if (anonymous)
- throw new IsolatedStorageException ("Enum value for FileShare was out of legal range.");
- else
-#endif
throw new ArgumentOutOfRangeException ("share", "Enum value was out of legal range.");
}
// 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 : Path.GetFullPath (path);
-#if NET_2_1
- // don't use GetSecureFileName for the directory name
- throw new IsolatedStorageException (String.Format (msg, fname));
-#else
throw new DirectoryNotFoundException (String.Format (msg, fname));
-#endif
}
}
// don't leak the path information for isolated storage
string msg = Locale.GetText ("Could not find file \"{0}\".");
string fname = GetSecureFileName (path);
-#if NET_2_1
- throw new IsolatedStorageException (String.Format (msg, fname));
-#else
throw new FileNotFoundException (String.Format (msg, fname), fname);
-#endif
}
// IsolatedStorage needs to keep the Name property to the default "[Unknown]"
public string Name {
get {
-#if MOONLIGHT
- return SecurityManager.CheckElevatedPermissions () ? name : "[Unknown]";
-#else
return name;
-#endif
}
}
if (handle == MonoIO.InvalidHandle)
throw new ObjectDisposedException ("Stream has been closed");
- if(CanSeek == false)
+ if (CanSeek == false)
throw new NotSupportedException("The stream does not support seeking");
-
+
+ if (safeHandle != null) {
+ // If the handle was leaked outside we always ask the real handle
+ MonoIOError error;
+
+ long ret = MonoIO.Seek (handle, 0,SeekOrigin.Current,out error);
+
+ if (error != MonoIOError.ERROR_SUCCESS) {
+ // don't leak the path information for isolated storage
+ throw MonoIO.GetException (GetSecureFileName (name), error);
+ }
+
+ return ret;
+ }
+
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");
- }
-
if(value < 0) {
throw new ArgumentOutOfRangeException("Attempt to set the position to a negative value");
}
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
[SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
get {
+ if (safeHandle == null) {
+ ExposeHandle ();
+ }
return handle;
}
}
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
[SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
get {
- SafeFileHandle ret;
-
- if (safeHandle != null)
- ret = safeHandle;
- else
- ret = new SafeFileHandle (handle, owner);
-
- FlushBuffer ();
- return ret;
+ if (safeHandle == null) {
+ ExposeHandle ();
+ }
+ return safeHandle;
}
}
// methods
+ void ExposeHandle ()
+ {
+ safeHandle = new SafeFileHandle (handle, false);
+ FlushBuffer ();
+ InitBuffer (0, true);
+ }
+
public override int ReadByte ()
{
if (handle == MonoIO.InvalidHandle)
FlushBuffer ();
}
-#if NET_4_0 || MOONLIGHT || MOBILE
+#if NET_4_0
public virtual void Flush (bool flushToDisk)
{
FlushBuffer ();
Exception exc = null;
if (handle != MonoIO.InvalidHandle) {
try {
+ // If the FileStream is in "exposed" status
+ // it means that we do not have a buffer(we write the data without buffering)
+ // therefor we don't and can't flush the buffer becouse we don't have one.
FlushBuffer ();
} catch (Exception e) {
exc = e;
#if !NET_2_1
public FileSecurity GetAccessControl ()
{
- throw new NotImplementedException ();
+ return new FileSecurity (SafeFileHandle,
+ AccessControlSections.Owner |
+ AccessControlSections.Group |
+ AccessControlSections.Access);
}
public void SetAccessControl (FileSecurity fileSecurity)
{
- throw new NotImplementedException ();
+ if (null == fileSecurity)
+ throw new ArgumentNullException ("fileSecurity");
+
+ fileSecurity.PersistModifications (SafeFileHandle);
+ }
+#endif
+
+#if NET_4_5
+ public override Task FlushAsync (CancellationToken cancellationToken)
+ {
+ return base.FlushAsync (cancellationToken);
+ }
+
+ public override Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return base.ReadAsync (buffer, offset, count, cancellationToken);
+ }
+
+ public override Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return base.WriteAsync (buffer, offset, count, cancellationToken);
}
#endif
if (buf_dirty) {
MonoIOError error;
- if (CanSeek == true) {
+ if (CanSeek == true && safeHandle == null) {
MonoIO.Seek (handle, buf_start,
SeekOrigin.Begin,
out error);
// fields
- internal const int DefaultBufferSize = 8192;
+ internal const int DefaultBufferSize = 4096;
// Input buffer ready for recycling
static byte[] buf_recycle;