huge refactoring
This commit is contained in:
		
							parent
							
								
									6b5d3e07cc
								
							
						
					
					
						commit
						2f0ae844d0
					
				@ -1,136 +1,138 @@
 | 
				
			|||||||
//
 | 
					using System;
 | 
				
			||||||
// Consts.cs.in
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Author:
 | 
					// Consts.cs.in
 | 
				
			||||||
//   Kornél Pál <http://www.kornelpal.hu/>
 | 
					//
 | 
				
			||||||
//
 | 
					// Author:
 | 
				
			||||||
// Copyright (C) 2005-2006 Kornél Pál
 | 
					//   Kornél Pál <http://www.kornelpal.hu/>
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (C) 2005-2006 Kornél Pál
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// 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
 | 
					// Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
// without limitation the rights to use, copy, modify, merge, publish,
 | 
					// a copy of this software and associated documentation files (the
 | 
				
			||||||
// distribute, sublicense, and/or sell copies of the Software, and to
 | 
					// "Software"), to deal in the Software without restriction, including
 | 
				
			||||||
// permit persons to whom the Software is furnished to do so, subject to
 | 
					// without limitation the rights to use, copy, modify, merge, publish,
 | 
				
			||||||
// the following conditions:
 | 
					// 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 above copyright notice and this permission notice shall be
 | 
					// the following conditions:
 | 
				
			||||||
// included in all copies or substantial portions of the Software.
 | 
					//
 | 
				
			||||||
//
 | 
					// The above copyright notice and this permission notice shall be
 | 
				
			||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
					// included in all copies or substantial portions of the Software.
 | 
				
			||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
					//
 | 
				
			||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
					// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
					// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
					// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
				
			||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
					// 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.
 | 
				
			||||||
static partial class Consts
 | 
					//
 | 
				
			||||||
{
 | 
					
 | 
				
			||||||
	public const string MonoCorlibVersion = "@MONO_CORLIB_VERSION@";
 | 
					static partial class Consts
 | 
				
			||||||
}
 | 
					{
 | 
				
			||||||
 | 
					  public const String MonoCorlibVersion = "@MONO_CORLIB_VERSION@";
 | 
				
			||||||
#if !NETCORE
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static partial class Consts
 | 
					#if !NETCORE
 | 
				
			||||||
{
 | 
					
 | 
				
			||||||
	//
 | 
					static partial class Consts
 | 
				
			||||||
	// Use these assembly version constants to make code more maintainable.
 | 
					{
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
 | 
					  // Use these assembly version constants to make code more maintainable.
 | 
				
			||||||
	public const string MonoVersion = "@MONO_VERSION@";
 | 
					  //
 | 
				
			||||||
	public const string MonoCompany = "Mono development team";
 | 
					
 | 
				
			||||||
	public const string MonoProduct = "Mono Common Language Infrastructure";
 | 
					  public const String MonoVersion = "@MONO_VERSION@";
 | 
				
			||||||
	public const string MonoCopyright = "(c) Various Mono authors";
 | 
					  public const String MonoCompany = "Mono development team";
 | 
				
			||||||
 | 
					  public const String MonoProduct = "Mono Common Language Infrastructure";
 | 
				
			||||||
#if MOBILE
 | 
					  public const String MonoCopyright = "(c) Various Mono authors";
 | 
				
			||||||
	// Versions of .NET Framework for Silverlight 4.0
 | 
					
 | 
				
			||||||
	public const string FxVersion = "2.0.5.0";
 | 
					#if MOBILE
 | 
				
			||||||
	public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation
 | 
					  // Versions of .NET Framework for Silverlight 4.0
 | 
				
			||||||
	public const string FxFileVersion = "4.0.50524.0";
 | 
					  public const string FxVersion = "2.0.5.0";
 | 
				
			||||||
	public const string EnvironmentVersion = FxFileVersion;
 | 
					  public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation
 | 
				
			||||||
	
 | 
					  public const string FxFileVersion = "4.0.50524.0";
 | 
				
			||||||
	public const string VsFileVersion = "9.0.50727.42"; // unused, but needed for compilation
 | 
					  public const string EnvironmentVersion = FxFileVersion;
 | 
				
			||||||
#elif NET_4_6
 | 
					  
 | 
				
			||||||
	public const string FxVersion = "4.0.0.0";
 | 
					  public const string VsFileVersion = "9.0.50727.42"; // unused, but needed for compilation
 | 
				
			||||||
	public const string FxFileVersion = "4.6.57.0";
 | 
					#elif NET_4_6
 | 
				
			||||||
	public const string EnvironmentVersion = "4.0.30319.42000";
 | 
					  public const String FxVersion = "4.0.0.0";
 | 
				
			||||||
 | 
					  public const String FxFileVersion = "4.6.57.0";
 | 
				
			||||||
	public const string VsVersion = "0.0.0.0"; // Useless ?
 | 
					  public const String EnvironmentVersion = "4.0.30319.42000";
 | 
				
			||||||
	public const string VsFileVersion = "11.0.0.0"; // TODO:
 | 
					
 | 
				
			||||||
#elif NET_4_5
 | 
					  public const String VsVersion = "0.0.0.0"; // Useless ?
 | 
				
			||||||
	public const string FxVersion = "4.0.0.0";
 | 
					  public const String VsFileVersion = "11.0.0.0"; // TODO:
 | 
				
			||||||
	public const string FxFileVersion = "4.0.30319.17020";
 | 
					#elif NET_4_5
 | 
				
			||||||
	public const string EnvironmentVersion = FxFileVersion;
 | 
					  public const string FxVersion = "4.0.0.0";
 | 
				
			||||||
 | 
					  public const string FxFileVersion = "4.0.30319.17020";
 | 
				
			||||||
	public const string VsVersion = "0.0.0.0"; // Useless ?
 | 
					  public const string EnvironmentVersion = FxFileVersion;
 | 
				
			||||||
	public const string VsFileVersion = "11.0.0.0"; // TODO:
 | 
					
 | 
				
			||||||
#elif NETCORE
 | 
					  public const string VsVersion = "0.0.0.0"; // Useless ?
 | 
				
			||||||
	public const string FxVersion = "";
 | 
					  public const string VsFileVersion = "11.0.0.0"; // TODO:
 | 
				
			||||||
	public const string FxFileVersion = "";
 | 
					#elif NETCORE
 | 
				
			||||||
	public const string EnvironmentVersion = FxFileVersion;
 | 
					  public const string FxVersion = "";
 | 
				
			||||||
 | 
					  public const string FxFileVersion = "";
 | 
				
			||||||
	public const string VsVersion = "";
 | 
					  public const string EnvironmentVersion = FxFileVersion;
 | 
				
			||||||
	public const string VsFileVersion = "";
 | 
					
 | 
				
			||||||
#elif NET_4_0
 | 
					  public const string VsVersion = "";
 | 
				
			||||||
	#error Profile NET_4_0 is not supported.
 | 
					  public const string VsFileVersion = "";
 | 
				
			||||||
#elif NET_3_5
 | 
					#elif NET_4_0
 | 
				
			||||||
	#error Profile NET_3_5 is not supported.
 | 
					  #error Profile NET_4_0 is not supported.
 | 
				
			||||||
#elif NET_3_0
 | 
					#elif NET_3_5
 | 
				
			||||||
	#error Profile NET_3_0 is not supported.
 | 
					  #error Profile NET_3_5 is not supported.
 | 
				
			||||||
#elif NET_2_0
 | 
					#elif NET_3_0
 | 
				
			||||||
	#error Profile NET_2_0 is not supported.
 | 
					  #error Profile NET_3_0 is not supported.
 | 
				
			||||||
#elif NET_1_1
 | 
					#elif NET_2_0
 | 
				
			||||||
	#error Profile NET_1_1 is not supported.
 | 
					  #error Profile NET_2_0 is not supported.
 | 
				
			||||||
#elif NET_1_0
 | 
					#elif NET_1_1
 | 
				
			||||||
	#error Profile NET_1_0 is not supported.
 | 
					  #error Profile NET_1_1 is not supported.
 | 
				
			||||||
#else
 | 
					#elif NET_1_0
 | 
				
			||||||
#error No profile symbols defined.
 | 
					  #error Profile NET_1_0 is not supported.
 | 
				
			||||||
#endif
 | 
					#else
 | 
				
			||||||
 | 
					#error No profile symbols defined.
 | 
				
			||||||
#if MOBILE
 | 
					#endif
 | 
				
			||||||
	const string PublicKeyToken = "7cec85d7bea7798e";
 | 
					
 | 
				
			||||||
#else
 | 
					#if MOBILE
 | 
				
			||||||
	const string PublicKeyToken = "b77a5c561934e089";
 | 
					  const string PublicKeyToken = "7cec85d7bea7798e";
 | 
				
			||||||
#endif
 | 
					#else
 | 
				
			||||||
 | 
					  const String PublicKeyToken = "b77a5c561934e089";
 | 
				
			||||||
	//
 | 
					#endif
 | 
				
			||||||
	// Use these assembly name constants to make code more maintainable.
 | 
					
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
 | 
					  // Use these assembly name constants to make code more maintainable.
 | 
				
			||||||
	public const string AssemblyI18N = "I18N, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
					  //
 | 
				
			||||||
	public const string AssemblyMicrosoft_JScript = "Microsoft.JScript, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					
 | 
				
			||||||
	public const string AssemblyMicrosoft_VisualStudio = "Microsoft.VisualStudio, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblyI18N = "I18N, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
				
			||||||
	public const string AssemblyMicrosoft_VisualStudio_Web = "Microsoft.VisualStudio.Web, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblyMicrosoft_JScript = "Microsoft.JScript, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblyMicrosoft_VSDesigner = "Microsoft.VSDesigner, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblyMicrosoft_VisualStudio = "Microsoft.VisualStudio, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblyMono_Http = "Mono.Http, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
					  public const String AssemblyMicrosoft_VisualStudio_Web = "Microsoft.VisualStudio.Web, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblyMono_Posix = "Mono.Posix, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
					  public const String AssemblyMicrosoft_VSDesigner = "Microsoft.VSDesigner, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblyMono_Security = "Mono.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
					  public const String AssemblyMono_Http = "Mono.Http, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
				
			||||||
	public const string AssemblyMono_Messaging_RabbitMQ = "Mono.Messaging.RabbitMQ, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
					  public const String AssemblyMono_Posix = "Mono.Posix, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
				
			||||||
	public const string AssemblyCorlib = "mscorlib, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
					  public const String AssemblyMono_Security = "Mono.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
				
			||||||
	public const string AssemblySystem = "System, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
					  public const String AssemblyMono_Messaging_RabbitMQ = "Mono.Messaging.RabbitMQ, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
 | 
				
			||||||
	public const string AssemblySystem_Data = "System.Data, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
					  public const String AssemblyCorlib = "mscorlib, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
				
			||||||
	public const string AssemblySystem_Design = "System.Design, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem = "System, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
				
			||||||
	public const string AssemblySystem_DirectoryServices = "System.DirectoryServices, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Data = "System.Data, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
				
			||||||
	public const string AssemblySystem_Drawing = "System.Drawing, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Design = "System.Design, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_Drawing_Design = "System.Drawing.Design, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_DirectoryServices = "System.DirectoryServices, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_Messaging = "System.Messaging, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Drawing = "System.Drawing, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_Security = "System.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Drawing_Design = "System.Drawing.Design, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_ServiceProcess = "System.ServiceProcess, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Messaging = "System.Messaging, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_Web = "System.Web, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
					  public const String AssemblySystem_Security = "System.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_Windows_Forms = "System.Windows.Forms, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
					  public const String AssemblySystem_ServiceProcess = "System.ServiceProcess, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystem_2_0 = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
					  public const String AssemblySystem_Web = "System.Web, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
 | 
				
			||||||
	public const string AssemblySystemCore_3_5 = "System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
					  public const String AssemblySystem_Windows_Forms = "System.Windows.Forms, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
				
			||||||
	public const string AssemblySystem_Core = "System.Core, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
					  public const String AssemblySystem_2_0 = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
				
			||||||
	public const string WindowsBase_3_0 = "WindowsBase, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35";
 | 
					  public const String AssemblySystemCore_3_5 = "System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
				
			||||||
	public const string AssemblyWindowsBase = "WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
					  public const String AssemblySystem_Core = "System.Core, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
 | 
				
			||||||
	public const string AssemblyPresentationCore_3_5 = "PresentationCore, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
					  public const String WindowsBase_3_0 = "WindowsBase, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35";
 | 
				
			||||||
	public const string AssemblyPresentationCore_4_0 = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
					  public const String AssemblyWindowsBase = "WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
				
			||||||
	public const string AssemblyPresentationFramework_3_5 = "PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
					  public const String AssemblyPresentationCore_3_5 = "PresentationCore, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
				
			||||||
	public const string AssemblySystemServiceModel_3_0 = "System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
					  public const String AssemblyPresentationCore_4_0 = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
				
			||||||
}
 | 
					  public const String AssemblyPresentationFramework_3_5 = "PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
 | 
				
			||||||
 | 
					  public const String AssemblySystemServiceModel_3_0 = "System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -35,17 +35,11 @@ using System;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
internal sealed class Locale {
 | 
					internal sealed class Locale {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Locale ()
 | 
					  private Locale ()
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static string GetText (string msg)
 | 
					  public static String GetText(String msg) => msg;
 | 
				
			||||||
	{
 | 
					
 | 
				
			||||||
		return msg;
 | 
					  public static String GetText(String fmt, params Object[] args) => String.Format(fmt, args);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public static string GetText (string fmt, params object [] args)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return String.Format (fmt, args);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,56 +31,62 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Posix {
 | 
					namespace Mono.Posix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[Obsolete ("Use Mono.Unix.Catalog")]
 | 
					  [Obsolete ("Use Mono.Unix.Catalog")]
 | 
				
			||||||
	public class Catalog {
 | 
					  public class Catalog {
 | 
				
			||||||
		[DllImport("intl")]
 | 
					    [DllImport("intl")]
 | 
				
			||||||
		static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		[DllImport("intl")]
 | 
					    static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
 | 
				
			||||||
		static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
 | 
					    [DllImport("intl")]
 | 
				
			||||||
			IntPtr codeset);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		[DllImport("intl")]
 | 
					    static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
 | 
				
			||||||
		static extern IntPtr textdomain (IntPtr domainname);
 | 
					      IntPtr codeset);
 | 
				
			||||||
		
 | 
					    [DllImport("intl")]
 | 
				
			||||||
		public static void Init (String package, String localedir)
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		{
 | 
					    static extern IntPtr textdomain (IntPtr domainname);
 | 
				
			||||||
			IntPtr ipackage = Marshal.StringToHGlobalAuto (package);
 | 
					    
 | 
				
			||||||
			IntPtr ilocaledir = Marshal.StringToHGlobalAuto (localedir);
 | 
					    public static void Init (String package, String localedir)
 | 
				
			||||||
			IntPtr iutf8 = Marshal.StringToHGlobalAuto ("UTF-8");
 | 
					    {
 | 
				
			||||||
			bindtextdomain (ipackage, ilocaledir);
 | 
					      IntPtr ipackage = Marshal.StringToHGlobalAuto (package);
 | 
				
			||||||
			bind_textdomain_codeset (ipackage, iutf8);
 | 
					      IntPtr ilocaledir = Marshal.StringToHGlobalAuto (localedir);
 | 
				
			||||||
			textdomain (ipackage);
 | 
					      IntPtr iutf8 = Marshal.StringToHGlobalAuto ("UTF-8");
 | 
				
			||||||
			Marshal.FreeHGlobal (ipackage);
 | 
					      _ = bindtextdomain(ipackage, ilocaledir);
 | 
				
			||||||
			Marshal.FreeHGlobal (ilocaledir);
 | 
					      _ = bind_textdomain_codeset(ipackage, iutf8);
 | 
				
			||||||
			Marshal.FreeHGlobal (iutf8);
 | 
					      _ = textdomain(ipackage);
 | 
				
			||||||
		}
 | 
					      Marshal.FreeHGlobal (ipackage);
 | 
				
			||||||
	
 | 
					      Marshal.FreeHGlobal (ilocaledir);
 | 
				
			||||||
		[DllImport("intl")]
 | 
					      Marshal.FreeHGlobal (iutf8);
 | 
				
			||||||
		static extern IntPtr gettext (IntPtr instring);
 | 
					    }
 | 
				
			||||||
		
 | 
					  
 | 
				
			||||||
		public static String GetString (String s)
 | 
					    [DllImport("intl")]
 | 
				
			||||||
		{
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
			IntPtr ints = Marshal.StringToHGlobalAuto (s);
 | 
					    static extern IntPtr gettext (IntPtr instring);
 | 
				
			||||||
			String t = Marshal.PtrToStringAuto (gettext (ints));
 | 
					    
 | 
				
			||||||
			Marshal.FreeHGlobal (ints);
 | 
					    public static String GetString (String s)
 | 
				
			||||||
			return t;
 | 
					    {
 | 
				
			||||||
		}
 | 
					      IntPtr ints = Marshal.StringToHGlobalAuto (s);
 | 
				
			||||||
	
 | 
					      String t = Marshal.PtrToStringAuto (gettext (ints));
 | 
				
			||||||
		[DllImport("intl")]
 | 
					      Marshal.FreeHGlobal (ints);
 | 
				
			||||||
		static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
 | 
					      return t;
 | 
				
			||||||
		
 | 
					    }
 | 
				
			||||||
		public static String GetPluralString (String s, String p, Int32 n)
 | 
					  
 | 
				
			||||||
		{
 | 
					    [DllImport("intl")]
 | 
				
			||||||
			IntPtr ints = Marshal.StringToHGlobalAuto (s);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
			IntPtr intp = Marshal.StringToHGlobalAuto (p);
 | 
					    static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
 | 
				
			||||||
			String t = Marshal.PtrToStringAnsi (ngettext (ints, intp, n));
 | 
					    
 | 
				
			||||||
			Marshal.FreeHGlobal (ints);
 | 
					    public static String GetPluralString (String s, String p, Int32 n)
 | 
				
			||||||
			Marshal.FreeHGlobal (intp);
 | 
					    {
 | 
				
			||||||
			return t;
 | 
					      IntPtr ints = Marshal.StringToHGlobalAuto (s);
 | 
				
			||||||
		}
 | 
					      IntPtr intp = Marshal.StringToHGlobalAuto (p);
 | 
				
			||||||
	
 | 
					      String t = Marshal.PtrToStringAnsi (ngettext (ints, intp, n));
 | 
				
			||||||
	}
 | 
					      Marshal.FreeHGlobal (ints);
 | 
				
			||||||
 | 
					      Marshal.FreeHGlobal (intp);
 | 
				
			||||||
 | 
					      return t;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -34,48 +34,36 @@ using System.Net.Sockets;
 | 
				
			|||||||
namespace Mono.Posix
 | 
					namespace Mono.Posix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#pragma warning disable 649
 | 
					#pragma warning disable 649
 | 
				
			||||||
	internal struct PeerCredData {
 | 
					  internal struct PeerCredData {
 | 
				
			||||||
		public int pid;
 | 
					    public Int32 pid;
 | 
				
			||||||
		public int uid;
 | 
					    public Int32 uid;
 | 
				
			||||||
		public int gid;
 | 
					    public Int32 gid;
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
#pragma warning restore 649
 | 
					#pragma warning restore 649
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[Obsolete ("Use Mono.Unix.PeerCred")]
 | 
					  [Obsolete ("Use Mono.Unix.PeerCred")]
 | 
				
			||||||
	public class PeerCred
 | 
					  public class PeerCred
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		/* Make sure this doesn't clash with anything in
 | 
					    /* Make sure this doesn't clash with anything in
 | 
				
			||||||
		 * SocketOptionName, and keep it synchronised with the
 | 
					     * SocketOptionName, and keep it synchronised with the
 | 
				
			||||||
		 * runtime
 | 
					     * runtime
 | 
				
			||||||
		 */
 | 
					     */
 | 
				
			||||||
		private const int so_peercred=10001;
 | 
					    private const Int32 so_peercred =10001;
 | 
				
			||||||
		private PeerCredData data;
 | 
					    private PeerCredData data;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public PeerCred (Socket sock) {
 | 
					    public PeerCred (Socket sock) {
 | 
				
			||||||
			if (sock.AddressFamily != AddressFamily.Unix) {
 | 
					      if (sock.AddressFamily != AddressFamily.Unix) {
 | 
				
			||||||
				throw new ArgumentException ("Only Unix sockets are supported", "sock");
 | 
					        throw new ArgumentException ("Only Unix sockets are supported", "sock");
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			data = (PeerCredData)sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
 | 
					      this.data = (PeerCredData)sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public int ProcessID {
 | 
					    public Int32 ProcessID => this.data.pid;
 | 
				
			||||||
			get {
 | 
					
 | 
				
			||||||
				return(data.pid);
 | 
					    public Int32 UserID => this.data.uid;
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Int32 GroupID => this.data.gid;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public int UserID {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return(data.uid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public int GroupID {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return(data.gid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -34,85 +34,79 @@ using System.Text;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Posix
 | 
					namespace Mono.Posix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	[Serializable]
 | 
					  [Serializable]
 | 
				
			||||||
	[Obsolete ("Use Mono.Unix.UnixEndPoint")]
 | 
					  [Obsolete ("Use Mono.Unix.UnixEndPoint")]
 | 
				
			||||||
	public class UnixEndPoint : EndPoint
 | 
					  public class UnixEndPoint : EndPoint
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		string filename;
 | 
					    String filename;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public UnixEndPoint (string filename)
 | 
					    public UnixEndPoint (String filename)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (filename == null)
 | 
					      if (filename == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("filename");
 | 
					        throw new ArgumentNullException ("filename");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (filename == "") {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("Cannot be empty.", "filename");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.filename = filename;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public String Filename {
 | 
				
			||||||
 | 
					      get => this.filename;
 | 
				
			||||||
 | 
					      set => this.filename = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override AddressFamily AddressFamily => AddressFamily.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override EndPoint Create (SocketAddress socketAddress)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /*
 | 
				
			||||||
 | 
					       * Should also check this
 | 
				
			||||||
 | 
					       *
 | 
				
			||||||
 | 
					      int addr = (int) AddressFamily.Unix;
 | 
				
			||||||
 | 
					      if (socketAddress [0] != (addr & 0xFF))
 | 
				
			||||||
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (filename == "")
 | 
					      if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
				
			||||||
				throw new ArgumentException ("Cannot be empty.", "filename");
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
			this.filename = filename;
 | 
					       */
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		
 | 
					      Byte[] bytes = new Byte[socketAddress.Size - 2];
 | 
				
			||||||
		public string Filename {
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
			get {
 | 
					        bytes [i] = socketAddress [i + 2];
 | 
				
			||||||
				return(filename);
 | 
					      }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			set {
 | 
					      String name = Encoding.Default.GetString (bytes);
 | 
				
			||||||
				filename=value;
 | 
					      return new UnixEndPoint (name);
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override AddressFamily AddressFamily {
 | 
					    public override SocketAddress Serialize ()
 | 
				
			||||||
			get { return AddressFamily.Unix; }
 | 
					    {
 | 
				
			||||||
		}
 | 
					      Byte[] bytes = Encoding.Default.GetBytes (this.filename);
 | 
				
			||||||
 | 
					      SocketAddress sa = new SocketAddress (this.AddressFamily, bytes.Length + 2);
 | 
				
			||||||
		public override EndPoint Create (SocketAddress socketAddress)
 | 
					      // sa [0] -> family low byte, sa [1] -> family high byte
 | 
				
			||||||
		{
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
			/*
 | 
					        sa [i + 2] = bytes [i];
 | 
				
			||||||
			 * Should also check this
 | 
					      }
 | 
				
			||||||
			 *
 | 
					
 | 
				
			||||||
			int addr = (int) AddressFamily.Unix;
 | 
					      return sa;
 | 
				
			||||||
			if (socketAddress [0] != (addr & 0xFF))
 | 
					    }
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					
 | 
				
			||||||
 | 
					    public override String ToString() => this.filename;
 | 
				
			||||||
			if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
					
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					    public override Int32 GetHashCode() => this.filename.GetHashCode();
 | 
				
			||||||
			 */
 | 
					
 | 
				
			||||||
 | 
					    public override Boolean Equals (Object o)
 | 
				
			||||||
			byte [] bytes = new byte [socketAddress.Size - 2];
 | 
					    {
 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++) {
 | 
					      UnixEndPoint other = o as UnixEndPoint;
 | 
				
			||||||
				bytes [i] = socketAddress [i + 2];
 | 
					      if (other == null) {
 | 
				
			||||||
			}
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
			string name = Encoding.Default.GetString (bytes);
 | 
					
 | 
				
			||||||
			return new UnixEndPoint (name);
 | 
					      return other.filename == this.filename;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public override SocketAddress Serialize ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			byte [] bytes = Encoding.Default.GetBytes (filename);
 | 
					 | 
				
			||||||
			SocketAddress sa = new SocketAddress (AddressFamily, bytes.Length + 2);
 | 
					 | 
				
			||||||
			// sa [0] -> family low byte, sa [1] -> family high byte
 | 
					 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++)
 | 
					 | 
				
			||||||
				sa [i + 2] = bytes [i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return sa;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override string ToString() {
 | 
					 | 
				
			||||||
			return(filename);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override int GetHashCode ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return filename.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override bool Equals (object o)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UnixEndPoint other = o as UnixEndPoint;
 | 
					 | 
				
			||||||
			if (other == null)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (other.filename == filename);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -39,129 +39,111 @@ using System.Runtime.Serialization.Formatters.Binary;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class UnixBinaryClientFormatterSink : IClientFormatterSink, IMessageSink, IClientChannelSink, IChannelSinkBase
 | 
					  internal class UnixBinaryClientFormatterSink : IClientFormatterSink, IMessageSink, IClientChannelSink, IChannelSinkBase
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
 | 
					    UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
 | 
				
			||||||
		IClientChannelSink _nextInChain;
 | 
					    IClientChannelSink _nextInChain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixBinaryClientFormatterSink(IClientChannelSink nextSink) => this._nextInChain = nextSink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal UnixBinaryCore BinaryCore {
 | 
				
			||||||
 | 
					      get => this._binaryCore;
 | 
				
			||||||
 | 
					      set => this._binaryCore = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IClientChannelSink NextChannelSink => this._nextInChain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IMessageSink NextSink =>
 | 
				
			||||||
 | 
					        // This is the last sink in the IMessageSink sink chain
 | 
				
			||||||
 | 
					        null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IDictionary Properties => null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AsyncProcessRequest(IClientChannelSinkStack sinkStack,
 | 
				
			||||||
 | 
					             IMessage msg,
 | 
				
			||||||
 | 
					             ITransportHeaders headers,
 | 
				
			||||||
 | 
					             Stream stream) =>
 | 
				
			||||||
 | 
					      // never called because the formatter sink is
 | 
				
			||||||
 | 
					      // always the first in the chain
 | 
				
			||||||
 | 
					      throw new NotSupportedException("UnixBinaryClientFormatterSink must be the first sink in the IClientChannelSink chain");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
 | 
				
			||||||
 | 
					              Object state,
 | 
				
			||||||
 | 
					              ITransportHeaders headers,
 | 
				
			||||||
 | 
					              Stream stream)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      IMessage replyMessage = (IMessage)this._binaryCore.Deserializer.DeserializeMethodResponse (stream, null, (IMethodCallMessage)state);
 | 
				
			||||||
 | 
					      sinkStack.DispatchReplyMessage (replyMessage);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Stream GetRequestStream(IMessage msg,
 | 
				
			||||||
 | 
					            ITransportHeaders headers) =>
 | 
				
			||||||
 | 
					      // never called
 | 
				
			||||||
 | 
					      throw new NotSupportedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void ProcessMessage(IMessage msg,
 | 
				
			||||||
 | 
					              ITransportHeaders requestHeaders,
 | 
				
			||||||
 | 
					              Stream requestStream,
 | 
				
			||||||
 | 
					              out ITransportHeaders responseHeaders,
 | 
				
			||||||
 | 
					              out Stream responseStream) =>
 | 
				
			||||||
 | 
					      // never called because the formatter sink is
 | 
				
			||||||
 | 
					      // always the first in the chain
 | 
				
			||||||
 | 
					      throw new NotSupportedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IMessageCtrl AsyncProcessMessage (IMessage msg,
 | 
				
			||||||
 | 
					      IMessageSink replySink)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ITransportHeaders transportHeaders = new TransportHeaders();
 | 
				
			||||||
 | 
					      Stream stream = this._nextInChain.GetRequestStream(msg, transportHeaders);
 | 
				
			||||||
 | 
					      if (stream == null) {
 | 
				
			||||||
 | 
					        stream = new MemoryStream ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this._binaryCore.Serializer.Serialize (stream, msg, null);
 | 
				
			||||||
 | 
					      if (stream is MemoryStream) {
 | 
				
			||||||
 | 
					        stream.Position = 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ClientChannelSinkStack stack = new ClientChannelSinkStack(replySink);
 | 
				
			||||||
 | 
					      stack.Push (this, msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this._nextInChain.AsyncProcessRequest (stack, msg, transportHeaders, stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixBinaryClientFormatterSink (IClientChannelSink nextSink)
 | 
					      // FIXME: No idea about how to implement IMessageCtrl
 | 
				
			||||||
		{
 | 
					      return null;	
 | 
				
			||||||
			_nextInChain = nextSink;
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixBinaryCore BinaryCore
 | 
					    public IMessage SyncProcessMessage (IMessage msg)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			get { return _binaryCore; }
 | 
					      try {
 | 
				
			||||||
			set { _binaryCore = value; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IClientChannelSink NextChannelSink
 | 
					        ITransportHeaders call_headers = new TransportHeaders();
 | 
				
			||||||
		{
 | 
					        call_headers["__RequestUri"] = ((IMethodCallMessage)msg).Uri;
 | 
				
			||||||
			get {
 | 
					        call_headers["Content-Type"] = "application/octet-stream";
 | 
				
			||||||
				return _nextInChain;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IMessageSink NextSink
 | 
					        Stream call_stream = this._nextInChain.GetRequestStream(msg, call_headers);
 | 
				
			||||||
		{
 | 
					        if (call_stream == null) {
 | 
				
			||||||
			get {
 | 
					          call_stream = new MemoryStream ();
 | 
				
			||||||
				// This is the last sink in the IMessageSink sink chain
 | 
					        }
 | 
				
			||||||
				return null;
 | 
					
 | 
				
			||||||
			}
 | 
					        // Serialize msg to the stream
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					        this._binaryCore.Serializer.Serialize (call_stream, msg, null);
 | 
				
			||||||
		public IDictionary Properties
 | 
					        if (call_stream is MemoryStream) {
 | 
				
			||||||
		{
 | 
					          call_stream.Position = 0;
 | 
				
			||||||
			get {
 | 
					        }
 | 
				
			||||||
				return null;
 | 
					
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					        this._nextInChain.ProcessMessage(msg, call_headers, call_stream, out ITransportHeaders response_headers,
 | 
				
			||||||
 | 
					                  out Stream response_stream);
 | 
				
			||||||
		public void AsyncProcessRequest (IClientChannelSinkStack sinkStack,
 | 
					
 | 
				
			||||||
						 IMessage msg,
 | 
					        // Deserialize response_stream
 | 
				
			||||||
						 ITransportHeaders headers,
 | 
					
 | 
				
			||||||
						 Stream stream)
 | 
					        return (IMessage)this._binaryCore.Deserializer.DeserializeMethodResponse (response_stream, null, (IMethodCallMessage)msg);
 | 
				
			||||||
	        {
 | 
					        
 | 
				
			||||||
			// never called because the formatter sink is
 | 
					      } catch (Exception e) {
 | 
				
			||||||
			// always the first in the chain
 | 
					         return new ReturnMessage (e, (IMethodCallMessage)msg);
 | 
				
			||||||
			throw new NotSupportedException("UnixBinaryClientFormatterSink must be the first sink in the IClientChannelSink chain");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
 | 
					 | 
				
			||||||
						  object state,
 | 
					 | 
				
			||||||
						  ITransportHeaders headers,
 | 
					 | 
				
			||||||
						  Stream stream)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			IMessage replyMessage = (IMessage)_binaryCore.Deserializer.DeserializeMethodResponse (stream, null, (IMethodCallMessage)state);
 | 
					 | 
				
			||||||
			sinkStack.DispatchReplyMessage (replyMessage);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Stream GetRequestStream (IMessage msg,
 | 
					 | 
				
			||||||
						ITransportHeaders headers)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// never called
 | 
					 | 
				
			||||||
			throw new NotSupportedException ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void ProcessMessage (IMessage msg,
 | 
					 | 
				
			||||||
					    ITransportHeaders requestHeaders,
 | 
					 | 
				
			||||||
					    Stream requestStream,
 | 
					 | 
				
			||||||
					    out ITransportHeaders responseHeaders,
 | 
					 | 
				
			||||||
					    out Stream responseStream)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// never called because the formatter sink is
 | 
					 | 
				
			||||||
			// always the first in the chain
 | 
					 | 
				
			||||||
			throw new NotSupportedException ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IMessageCtrl AsyncProcessMessage (IMessage msg,
 | 
					 | 
				
			||||||
			IMessageSink replySink)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ITransportHeaders transportHeaders = new TransportHeaders();
 | 
					 | 
				
			||||||
			Stream stream = _nextInChain.GetRequestStream(msg, transportHeaders);
 | 
					 | 
				
			||||||
			if (stream == null) stream = new MemoryStream ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			_binaryCore.Serializer.Serialize (stream, msg, null);
 | 
					 | 
				
			||||||
			if (stream is MemoryStream) stream.Position = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			ClientChannelSinkStack stack = new ClientChannelSinkStack(replySink);
 | 
					 | 
				
			||||||
			stack.Push (this, msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			_nextInChain.AsyncProcessRequest (stack, msg, transportHeaders, stream);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// FIXME: No idea about how to implement IMessageCtrl
 | 
					 | 
				
			||||||
			return null;	
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IMessage SyncProcessMessage (IMessage msg)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				ITransportHeaders call_headers = new TransportHeaders();
 | 
					 | 
				
			||||||
				call_headers["__RequestUri"] = ((IMethodCallMessage)msg).Uri;
 | 
					 | 
				
			||||||
				call_headers["Content-Type"] = "application/octet-stream";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Stream call_stream = _nextInChain.GetRequestStream(msg, call_headers);
 | 
					 | 
				
			||||||
				if (call_stream == null) call_stream = new MemoryStream ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Serialize msg to the stream
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				_binaryCore.Serializer.Serialize (call_stream, msg, null);
 | 
					 | 
				
			||||||
				if (call_stream is MemoryStream) call_stream.Position = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Stream response_stream;
 | 
					 | 
				
			||||||
				ITransportHeaders response_headers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				_nextInChain.ProcessMessage (msg, call_headers, call_stream, out response_headers,
 | 
					 | 
				
			||||||
							    out response_stream);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Deserialize response_stream
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				return (IMessage) _binaryCore.Deserializer.DeserializeMethodResponse (response_stream, null, (IMethodCallMessage)msg);
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
			} catch (Exception e) {
 | 
					 | 
				
			||||||
				 return new ReturnMessage (e, (IMethodCallMessage)msg);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -33,48 +33,38 @@ using System.Runtime.Remoting.Channels;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class UnixBinaryClientFormatterSinkProvider: IClientFormatterSinkProvider, IClientChannelSinkProvider
 | 
					  internal class UnixBinaryClientFormatterSinkProvider: IClientFormatterSinkProvider, IClientChannelSinkProvider
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		IClientChannelSinkProvider next = null;
 | 
					    IClientChannelSinkProvider next = null;
 | 
				
			||||||
		UnixBinaryCore _binaryCore;
 | 
					    UnixBinaryCore _binaryCore;
 | 
				
			||||||
		static string[] allowedProperties = new string [] { "includeVersions", "strictBinding" };
 | 
					    static System.String[] allowedProperties = new System.String[] { "includeVersions", "strictBinding" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixBinaryClientFormatterSinkProvider() => this._binaryCore = UnixBinaryCore.DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixBinaryClientFormatterSinkProvider(IDictionary properties,
 | 
				
			||||||
 | 
					                ICollection providerData) => this._binaryCore = new UnixBinaryCore(this, properties, allowedProperties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IClientChannelSinkProvider Next {
 | 
				
			||||||
 | 
					      get => this.next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      set => this.next = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IClientChannelSink CreateSink (IChannelSender channel,
 | 
				
			||||||
 | 
					                  System.String url,
 | 
				
			||||||
 | 
					                  System.Object remoteChannelData)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      IClientChannelSink next_sink = null;
 | 
				
			||||||
 | 
					      UnixBinaryClientFormatterSink result;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (this.next != null) {
 | 
				
			||||||
 | 
					        next_sink = this.next.CreateSink (channel, url, remoteChannelData);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      result = new UnixBinaryClientFormatterSink (next_sink);
 | 
				
			||||||
 | 
					      result.BinaryCore = this._binaryCore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixBinaryClientFormatterSinkProvider ()
 | 
					      return result;
 | 
				
			||||||
		{
 | 
					    }		
 | 
				
			||||||
			_binaryCore = UnixBinaryCore.DefaultInstance;
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixBinaryClientFormatterSinkProvider (IDictionary properties,
 | 
					 | 
				
			||||||
							  ICollection providerData)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_binaryCore = new UnixBinaryCore (this, properties, allowedProperties);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IClientChannelSinkProvider Next
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return next;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			set {
 | 
					 | 
				
			||||||
				next = value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IClientChannelSink CreateSink (IChannelSender channel,
 | 
					 | 
				
			||||||
						      string url,
 | 
					 | 
				
			||||||
						      object remoteChannelData)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			IClientChannelSink next_sink = null;
 | 
					 | 
				
			||||||
			UnixBinaryClientFormatterSink result;
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			if (next != null)
 | 
					 | 
				
			||||||
				next_sink = next.CreateSink (channel, url, remoteChannelData);
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			result = new UnixBinaryClientFormatterSink (next_sink);
 | 
					 | 
				
			||||||
			result.BinaryCore = _binaryCore;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return result;
 | 
					 | 
				
			||||||
		}		
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -35,114 +35,116 @@ using System.Runtime.Remoting.Messaging;
 | 
				
			|||||||
using System.Runtime.Serialization;
 | 
					using System.Runtime.Serialization;
 | 
				
			||||||
using System.Runtime.Serialization.Formatters;
 | 
					using System.Runtime.Serialization.Formatters;
 | 
				
			||||||
using System.Runtime.Serialization.Formatters.Binary;
 | 
					using System.Runtime.Serialization.Formatters.Binary;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class UnixBinaryCore
 | 
					  internal class UnixBinaryCore
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		BinaryFormatter _serializationFormatter;
 | 
					    BinaryFormatter _serializationFormatter;
 | 
				
			||||||
		BinaryFormatter _deserializationFormatter;
 | 
					    BinaryFormatter _deserializationFormatter;
 | 
				
			||||||
		bool _includeVersions = true;
 | 
					    Boolean _includeVersions = true;
 | 
				
			||||||
		bool _strictBinding = false;
 | 
					    Boolean _strictBinding = false;
 | 
				
			||||||
		IDictionary _properties;
 | 
					    IDictionary _properties;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public static UnixBinaryCore DefaultInstance = new UnixBinaryCore ();
 | 
					    public static UnixBinaryCore DefaultInstance = new UnixBinaryCore ();
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public UnixBinaryCore (object owner, IDictionary properties, string[] allowedProperties)
 | 
					    public UnixBinaryCore (Object owner, IDictionary properties, String[] allowedProperties)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			_properties = properties;
 | 
					      this._properties = properties;
 | 
				
			||||||
			
 | 
					      
 | 
				
			||||||
			foreach(DictionaryEntry property in properties)
 | 
					      foreach(DictionaryEntry property in properties)
 | 
				
			||||||
			{
 | 
					      {
 | 
				
			||||||
				string key = (string) property.Key;
 | 
					        String key = (String) property.Key;
 | 
				
			||||||
				if (Array.IndexOf (allowedProperties, key) == -1)
 | 
					        if (Array.IndexOf (allowedProperties, key) == -1) {
 | 
				
			||||||
					throw new RemotingException (owner.GetType().Name + " does not recognize '" + key + "' configuration property");
 | 
					          throw new RemotingException (owner.GetType().Name + " does not recognize '" + key + "' configuration property");
 | 
				
			||||||
				
 | 
					        }
 | 
				
			||||||
				switch (key)
 | 
					
 | 
				
			||||||
				{
 | 
					        switch (key)
 | 
				
			||||||
					case "includeVersions": 
 | 
					        {
 | 
				
			||||||
						_includeVersions = Convert.ToBoolean (property.Value);
 | 
					          case "includeVersions":
 | 
				
			||||||
						break;
 | 
					            this._includeVersions = Convert.ToBoolean (property.Value);
 | 
				
			||||||
						
 | 
					            break;
 | 
				
			||||||
					case "strictBinding":
 | 
					            
 | 
				
			||||||
						_strictBinding = Convert.ToBoolean (property.Value);
 | 
					          case "strictBinding":
 | 
				
			||||||
						break;
 | 
					            this._strictBinding = Convert.ToBoolean (property.Value);
 | 
				
			||||||
				}
 | 
					            break;
 | 
				
			||||||
			}
 | 
					        }
 | 
				
			||||||
			
 | 
					      }
 | 
				
			||||||
			Init ();
 | 
					
 | 
				
			||||||
		}
 | 
					      this.Init ();
 | 
				
			||||||
		
 | 
					    }
 | 
				
			||||||
		public UnixBinaryCore ()
 | 
					    
 | 
				
			||||||
		{
 | 
					    public UnixBinaryCore ()
 | 
				
			||||||
			_properties = new Hashtable ();
 | 
					    {
 | 
				
			||||||
			Init ();
 | 
					      this._properties = new Hashtable ();
 | 
				
			||||||
		}
 | 
					      this.Init ();
 | 
				
			||||||
		
 | 
					    }
 | 
				
			||||||
		public void Init ()
 | 
					    
 | 
				
			||||||
		{
 | 
					    public void Init ()
 | 
				
			||||||
			RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector ();
 | 
					    {
 | 
				
			||||||
			StreamingContext context = new StreamingContext (StreamingContextStates.Remoting, null);
 | 
					      RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector ();
 | 
				
			||||||
 | 
					      StreamingContext context = new StreamingContext (StreamingContextStates.Remoting, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this._serializationFormatter = new BinaryFormatter (surrogateSelector, context);
 | 
				
			||||||
 | 
					      this._deserializationFormatter = new BinaryFormatter (null, context);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (!this._includeVersions)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        this._serializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
 | 
				
			||||||
 | 
					        this._deserializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			_serializationFormatter = new BinaryFormatter (surrogateSelector, context);
 | 
					      if (!this._strictBinding)
 | 
				
			||||||
			_deserializationFormatter = new BinaryFormatter (null, context);
 | 
					      {
 | 
				
			||||||
			
 | 
					        this._serializationFormatter.Binder = SimpleBinder.Instance;
 | 
				
			||||||
			if (!_includeVersions)
 | 
					        this._deserializationFormatter.Binder = SimpleBinder.Instance;
 | 
				
			||||||
			{
 | 
					      }
 | 
				
			||||||
				_serializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
 | 
					    }
 | 
				
			||||||
				_deserializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
 | 
					
 | 
				
			||||||
			}
 | 
					    public BinaryFormatter Serializer => this._serializationFormatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!_strictBinding)
 | 
					    public BinaryFormatter Deserializer => this._deserializationFormatter;
 | 
				
			||||||
			{
 | 
					
 | 
				
			||||||
				_serializationFormatter.Binder = SimpleBinder.Instance;
 | 
					    public IDictionary Properties => this._properties;
 | 
				
			||||||
				_deserializationFormatter.Binder = SimpleBinder.Instance;
 | 
					  }
 | 
				
			||||||
			}
 | 
					  
 | 
				
			||||||
		}
 | 
					  
 | 
				
			||||||
		
 | 
					  internal class SimpleBinder: SerializationBinder
 | 
				
			||||||
		public BinaryFormatter Serializer
 | 
					  {
 | 
				
			||||||
		{
 | 
					    public static SimpleBinder Instance = new SimpleBinder ();
 | 
				
			||||||
			get { return _serializationFormatter; }
 | 
					
 | 
				
			||||||
		}
 | 
					    [SuppressMessage("Microsoft.Design", "CS0618", Justification = "Someone do shit")]
 | 
				
			||||||
		
 | 
					    public override Type BindToType (String assemblyName, String typeName)
 | 
				
			||||||
		public BinaryFormatter Deserializer
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Assembly asm;
 | 
				
			||||||
			get { return _deserializationFormatter; }
 | 
					      
 | 
				
			||||||
		}
 | 
					      if (assemblyName.IndexOf (',') != -1)
 | 
				
			||||||
		
 | 
					      {
 | 
				
			||||||
		public IDictionary Properties
 | 
					        // Try using the full name
 | 
				
			||||||
		{
 | 
					        try
 | 
				
			||||||
			get { return _properties; }
 | 
					        {
 | 
				
			||||||
		}
 | 
					          asm = Assembly.Load (assemblyName);
 | 
				
			||||||
	}
 | 
					          if (asm == null) {
 | 
				
			||||||
	
 | 
					            return null;
 | 
				
			||||||
	
 | 
					          }
 | 
				
			||||||
	internal class SimpleBinder: SerializationBinder
 | 
					
 | 
				
			||||||
	{
 | 
					          Type t = asm.GetType (typeName);
 | 
				
			||||||
		public static SimpleBinder Instance = new SimpleBinder ();
 | 
					          if (t != null) {
 | 
				
			||||||
		 
 | 
					            return t;
 | 
				
			||||||
		public override Type BindToType (String assemblyName, string typeName)
 | 
					          }
 | 
				
			||||||
		{
 | 
					        }
 | 
				
			||||||
			Assembly asm;
 | 
					        catch {}
 | 
				
			||||||
			
 | 
					      }
 | 
				
			||||||
			if (assemblyName.IndexOf (',') != -1)
 | 
					      
 | 
				
			||||||
			{
 | 
					      // Try using the simple name
 | 
				
			||||||
				// Try using the full name
 | 
					      asm = Assembly.LoadWithPartialName (assemblyName);
 | 
				
			||||||
				try
 | 
					      if (asm == null) {
 | 
				
			||||||
				{
 | 
					        return null;
 | 
				
			||||||
					asm = Assembly.Load (assemblyName);
 | 
					      }
 | 
				
			||||||
					if (asm == null) return null;
 | 
					
 | 
				
			||||||
					Type t = asm.GetType (typeName);
 | 
					      return asm.GetType (typeName, true);
 | 
				
			||||||
					if (t != null) return t;
 | 
					    }
 | 
				
			||||||
				}
 | 
					  }
 | 
				
			||||||
				catch {}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			// Try using the simple name
 | 
					 | 
				
			||||||
			asm = Assembly.LoadWithPartialName (assemblyName);
 | 
					 | 
				
			||||||
			if (asm == null) return null;
 | 
					 | 
				
			||||||
			return asm.GetType (typeName, true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -40,124 +40,123 @@ using System.Runtime.InteropServices;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix {
 | 
					namespace Mono.Remoting.Channels.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class UnixBinaryServerFormatterSink : IServerChannelSink, IChannelSinkBase
 | 
					  internal class UnixBinaryServerFormatterSink : IServerChannelSink, IChannelSinkBase
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
 | 
					    UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		IServerChannelSink next_sink;
 | 
					    IServerChannelSink next_sink;
 | 
				
			||||||
		IChannelReceiver receiver;
 | 
					    IChannelReceiver receiver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixBinaryServerFormatterSink (IServerChannelSink nextSink, IChannelReceiver receiver)
 | 
					    public UnixBinaryServerFormatterSink (IServerChannelSink nextSink, IChannelReceiver receiver)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.next_sink = nextSink;
 | 
					      this.next_sink = nextSink;
 | 
				
			||||||
			this.receiver = receiver;
 | 
					      this.receiver = receiver;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixBinaryCore BinaryCore
 | 
					    internal UnixBinaryCore BinaryCore {
 | 
				
			||||||
		{
 | 
					      get => this._binaryCore;
 | 
				
			||||||
			get { return _binaryCore; }
 | 
					      set => this._binaryCore = value;
 | 
				
			||||||
			set { _binaryCore = value; }
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		
 | 
					    public IServerChannelSink NextChannelSink => this.next_sink;
 | 
				
			||||||
		public IServerChannelSink NextChannelSink {
 | 
					
 | 
				
			||||||
			get {
 | 
					    public IDictionary Properties => null;
 | 
				
			||||||
				return next_sink;
 | 
					
 | 
				
			||||||
			}
 | 
					    public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, Object state,
 | 
				
			||||||
		}
 | 
					              IMessage message, ITransportHeaders headers, Stream stream)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ITransportHeaders responseHeaders = new TransportHeaders();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IDictionary Properties {
 | 
					      if (sinkStack != null) {
 | 
				
			||||||
			get {
 | 
					        stream = sinkStack.GetResponseStream (message, responseHeaders);
 | 
				
			||||||
				return null;
 | 
					      }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					      if (stream == null) {
 | 
				
			||||||
 | 
					        stream = new MemoryStream();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this._binaryCore.Serializer.Serialize (stream, message, null);
 | 
				
			||||||
 | 
					      if (stream is MemoryStream) {
 | 
				
			||||||
 | 
					        stream.Position = 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      sinkStack.AsyncProcessResponse (message, responseHeaders, stream);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state,
 | 
				
			||||||
 | 
					            IMessage msg, ITransportHeaders headers) => null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
 | 
				
			||||||
 | 
					              IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
 | 
				
			||||||
 | 
					              out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      sinkStack.Push (this, null);
 | 
				
			||||||
 | 
					      ServerProcessing res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
 | 
					      try
 | 
				
			||||||
						  IMessage message, ITransportHeaders headers, Stream stream)
 | 
					      {
 | 
				
			||||||
		{
 | 
					        String url = (String)requestHeaders["__RequestUri"];
 | 
				
			||||||
			ITransportHeaders responseHeaders = new TransportHeaders();
 | 
					        _ = this.receiver.Parse(url, out String uri);
 | 
				
			||||||
 | 
					        if (uri == null) {
 | 
				
			||||||
 | 
					          uri = url;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MethodCallHeaderHandler mhh = new MethodCallHeaderHandler(uri);
 | 
				
			||||||
 | 
					        requestMsg = (IMessage)this._binaryCore.Deserializer.Deserialize (requestStream, new HeaderHandler(mhh.HandleHeaders));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (sinkStack != null) stream = sinkStack.GetResponseStream (message, responseHeaders);
 | 
					        res = this.next_sink.ProcessMessage (sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);
 | 
				
			||||||
			if (stream == null) stream = new MemoryStream();
 | 
					      }
 | 
				
			||||||
 | 
					      catch (Exception ex)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
 | 
				
			||||||
 | 
					        res = ServerProcessing.Complete;
 | 
				
			||||||
 | 
					        responseHeaders = null;
 | 
				
			||||||
 | 
					        responseStream = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (res == ServerProcessing.Complete)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        for (Int32 n =0; n<3; n++) {
 | 
				
			||||||
 | 
					          responseStream = null;
 | 
				
			||||||
 | 
					          responseHeaders = new TransportHeaders();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			_binaryCore.Serializer.Serialize (stream, message, null);
 | 
					          if (sinkStack != null) {
 | 
				
			||||||
			if (stream is MemoryStream) stream.Position = 0;
 | 
					            responseStream = sinkStack.GetResponseStream (responseMsg, responseHeaders);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (responseStream == null) {
 | 
				
			||||||
 | 
					            responseStream = new MemoryStream();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          try {
 | 
				
			||||||
 | 
					            this._binaryCore.Serializer.Serialize (responseStream, responseMsg);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          } catch (Exception ex) {
 | 
				
			||||||
 | 
					            if (n == 2) {
 | 
				
			||||||
 | 
					              throw ex;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (responseStream is MemoryStream) {
 | 
				
			||||||
 | 
					          responseStream.Position = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = sinkStack.Pop(this);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return res;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sinkStack.AsyncProcessResponse (message, responseHeaders, stream);
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
 | 
					  internal class MethodCallHeaderHandler
 | 
				
			||||||
						IMessage msg, ITransportHeaders headers)
 | 
					  {
 | 
				
			||||||
		{
 | 
					    String _uri;
 | 
				
			||||||
			return null;
 | 
					
 | 
				
			||||||
		}
 | 
					    public MethodCallHeaderHandler(String uri) => this._uri = uri;
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
 | 
					    public Object HandleHeaders(Header[] headers) => this._uri;
 | 
				
			||||||
							IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
 | 
					  }
 | 
				
			||||||
							out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			sinkStack.Push (this, null);
 | 
					 | 
				
			||||||
			ServerProcessing res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			try
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				string url = (string)requestHeaders["__RequestUri"];
 | 
					 | 
				
			||||||
				string uri;
 | 
					 | 
				
			||||||
				receiver.Parse (url, out uri);
 | 
					 | 
				
			||||||
				if (uri == null) uri = url;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				MethodCallHeaderHandler mhh = new MethodCallHeaderHandler(uri);
 | 
					 | 
				
			||||||
				requestMsg = (IMessage) _binaryCore.Deserializer.Deserialize (requestStream, new HeaderHandler(mhh.HandleHeaders));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				res = next_sink.ProcessMessage (sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch (Exception ex)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
 | 
					 | 
				
			||||||
				res = ServerProcessing.Complete;
 | 
					 | 
				
			||||||
				responseHeaders = null;
 | 
					 | 
				
			||||||
				responseStream = null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			if (res == ServerProcessing.Complete)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				for (int n=0; n<3; n++) {
 | 
					 | 
				
			||||||
					responseStream = null;
 | 
					 | 
				
			||||||
					responseHeaders = new TransportHeaders();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (sinkStack != null) responseStream = sinkStack.GetResponseStream (responseMsg, responseHeaders);
 | 
					 | 
				
			||||||
					if (responseStream == null) responseStream = new MemoryStream();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					try {
 | 
					 | 
				
			||||||
						_binaryCore.Serializer.Serialize (responseStream, responseMsg);
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					} catch (Exception ex) {
 | 
					 | 
				
			||||||
						if (n == 2) throw ex;
 | 
					 | 
				
			||||||
						else responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
				if (responseStream is MemoryStream) responseStream.Position = 0;
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				sinkStack.Pop (this);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return res;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	internal class MethodCallHeaderHandler
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		string _uri;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public MethodCallHeaderHandler (string uri)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_uri = uri;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public object HandleHeaders (Header[] headers)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return _uri;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -35,51 +35,41 @@ using System.Runtime.Remoting.Channels;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class UnixBinaryServerFormatterSinkProvider: IServerFormatterSinkProvider, IServerChannelSinkProvider
 | 
					  internal class UnixBinaryServerFormatterSinkProvider: IServerFormatterSinkProvider, IServerChannelSinkProvider
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		IServerChannelSinkProvider next = null;
 | 
					    IServerChannelSinkProvider next = null;
 | 
				
			||||||
		UnixBinaryCore _binaryCore;
 | 
					    UnixBinaryCore _binaryCore;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		internal static string[] AllowedProperties = new string [] { "includeVersions", "strictBinding" };
 | 
					    internal static System.String[] AllowedProperties = new System.String[] { "includeVersions", "strictBinding" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixBinaryServerFormatterSinkProvider() => this._binaryCore = UnixBinaryCore.DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixBinaryServerFormatterSinkProvider(IDictionary properties, ICollection providerData) => this._binaryCore = new UnixBinaryCore(this, properties, AllowedProperties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IServerChannelSinkProvider Next {
 | 
				
			||||||
 | 
					      get => this.next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      set => this.next = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IServerChannelSink CreateSink (IChannelReceiver channel)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      IServerChannelSink next_sink = null;
 | 
				
			||||||
 | 
					      UnixBinaryServerFormatterSink result;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (this.next != null) {
 | 
				
			||||||
 | 
					        next_sink = this.next.CreateSink (channel);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      result = new UnixBinaryServerFormatterSink (next_sink, channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixBinaryServerFormatterSinkProvider ()
 | 
					      result.BinaryCore = this._binaryCore;
 | 
				
			||||||
		{
 | 
					      return result;
 | 
				
			||||||
			_binaryCore = UnixBinaryCore.DefaultInstance;
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixBinaryServerFormatterSinkProvider (IDictionary properties, ICollection providerData)
 | 
					    public void GetChannelData (IChannelDataStore channelData)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			_binaryCore = new UnixBinaryCore (this, properties, AllowedProperties);
 | 
					      // Nothing to add here
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public IServerChannelSinkProvider Next
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return next;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			set {
 | 
					 | 
				
			||||||
				next = value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IServerChannelSink CreateSink (IChannelReceiver channel)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			IServerChannelSink next_sink = null;
 | 
					 | 
				
			||||||
			UnixBinaryServerFormatterSink result;
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			if (next != null)
 | 
					 | 
				
			||||||
				next_sink = next.CreateSink (channel);
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			result = new UnixBinaryServerFormatterSink (next_sink, channel);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			result.BinaryCore = _binaryCore;
 | 
					 | 
				
			||||||
			return result;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void GetChannelData (IChannelDataStore channelData)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Nothing to add here
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -40,104 +40,109 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private UnixClientChannel _clientChannel;
 | 
					        private UnixClientChannel _clientChannel;
 | 
				
			||||||
        private UnixServerChannel _serverChannel = null;
 | 
					        private UnixServerChannel _serverChannel = null;
 | 
				
			||||||
        private string _name = "unix";
 | 
					        private String _name = "unix";
 | 
				
			||||||
        private int _priority = 1;
 | 
					        private Int32 _priority = 1;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        public UnixChannel (): this (null)
 | 
					        public UnixChannel (): this (null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnixChannel (string path)
 | 
					        public UnixChannel (String path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Hashtable ht = new Hashtable();
 | 
					            Hashtable ht = new Hashtable();
 | 
				
			||||||
            ht["path"] = path;
 | 
					            ht["path"] = path;
 | 
				
			||||||
            Init(ht, null, null);
 | 
					      this.Init(ht, null, null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void Init (IDictionary properties, IClientChannelSinkProvider clientSink, IServerChannelSinkProvider serverSink)
 | 
					        void Init (IDictionary properties, IClientChannelSinkProvider clientSink, IServerChannelSinkProvider serverSink)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					      this._clientChannel = new UnixClientChannel (properties,clientSink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(properties["path"] != null) {
 | 
				
			||||||
 | 
					        this._serverChannel = new UnixServerChannel(properties, serverSink);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Object val = properties ["name"];
 | 
				
			||||||
 | 
					            if (val != null) {
 | 
				
			||||||
 | 
					        this._name = val as String;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      val = properties ["priority"];
 | 
				
			||||||
 | 
					            if (val != null) {
 | 
				
			||||||
 | 
					        this._priority = Convert.ToInt32 (val);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixChannel(IDictionary properties,
 | 
				
			||||||
 | 
					                        IClientChannelSinkProvider clientSinkProvider,
 | 
				
			||||||
 | 
					                        IServerChannelSinkProvider serverSinkProvider) => this.Init(properties, clientSinkProvider, serverSinkProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI) => this._clientChannel.CreateMessageSink(url, remoteChannelData, out objectURI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String ChannelName => this._name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int32 ChannelPriority => this._priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void StartListening (Object data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _clientChannel = new UnixClientChannel (properties,clientSink);
 | 
					            if (this._serverChannel != null) {
 | 
				
			||||||
 | 
					        this._serverChannel.StartListening (data);
 | 
				
			||||||
            if(properties["path"] != null)
 | 
					      }
 | 
				
			||||||
                _serverChannel = new UnixServerChannel(properties, serverSink);
 | 
					    }
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            object val = properties ["name"];
 | 
					 | 
				
			||||||
            if (val != null) _name = val as string;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            val = properties ["priority"];
 | 
					 | 
				
			||||||
            if (val != null) _priority = Convert.ToInt32 (val);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public UnixChannel (IDictionary properties,
 | 
					 | 
				
			||||||
                            IClientChannelSinkProvider clientSinkProvider,
 | 
					 | 
				
			||||||
                            IServerChannelSinkProvider serverSinkProvider)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Init (properties, clientSinkProvider, serverSinkProvider);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return _clientChannel.CreateMessageSink(url, remoteChannelData, out objectURI);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public string ChannelName
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get { return _name; }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public int ChannelPriority
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get { return _priority; }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public void StartListening (object data)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (_serverChannel != null) _serverChannel.StartListening (data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public void StopListening (object data)
 | 
					        public void StopListening (Object data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (_serverChannel != null) _serverChannel.StopListening(data);
 | 
					            if (this._serverChannel != null) {
 | 
				
			||||||
        }
 | 
					        this._serverChannel.StopListening(data);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string[] GetUrlsForUri (string uri)
 | 
					        public String[] GetUrlsForUri (String uri)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (_serverChannel != null) return _serverChannel.GetUrlsForUri(uri);
 | 
					            if (this._serverChannel != null) {
 | 
				
			||||||
            else return null;
 | 
					        return this._serverChannel.GetUrlsForUri(uri);
 | 
				
			||||||
        }
 | 
					      } else {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public object ChannelData
 | 
					        public Object ChannelData
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get 
 | 
					            get 
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (_serverChannel != null) return _serverChannel.ChannelData;
 | 
					                if (this._serverChannel != null) {
 | 
				
			||||||
                else return null;
 | 
					          return this._serverChannel.ChannelData;
 | 
				
			||||||
            }
 | 
					        } else {
 | 
				
			||||||
        }
 | 
					          return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        public string Parse (string url, out string objectURI)
 | 
					      }
 | 
				
			||||||
        {
 | 
					        }
 | 
				
			||||||
            return UnixChannel.ParseUnixURL (url, out objectURI);
 | 
					
 | 
				
			||||||
        }
 | 
					    public String Parse(String url, out String objectURI) => UnixChannel.ParseUnixURL(url, out objectURI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal static string ParseUnixURL (string url, out string objectURI)
 | 
					    internal static String ParseUnixURL (String url, out String objectURI)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // format: "unix:///path/to/unix/socket?/path/to/object"
 | 
					            // format: "unix:///path/to/unix/socket?/path/to/object"
 | 
				
			||||||
			
 | 
					      
 | 
				
			||||||
            objectURI = null;
 | 
					            objectURI = null;
 | 
				
			||||||
			
 | 
					      
 | 
				
			||||||
			if (!url.StartsWith ("unix://")) return null;
 | 
					      if (!url.StartsWith ("unix://")) {
 | 
				
			||||||
			
 | 
					        return null;
 | 
				
			||||||
			int i = url.IndexOf ('?');
 | 
					      }
 | 
				
			||||||
			if (i == -1) return url.Substring (7);
 | 
					
 | 
				
			||||||
			
 | 
					      Int32 i = url.IndexOf ('?');
 | 
				
			||||||
			objectURI = url.Substring (i+1);
 | 
					      if (i == -1) {
 | 
				
			||||||
			
 | 
					        return url.Substring (7);
 | 
				
			||||||
            if (objectURI.Length == 0)
 | 
					      }
 | 
				
			||||||
                objectURI = null;
 | 
					
 | 
				
			||||||
				
 | 
					      objectURI = url.Substring (i+1);
 | 
				
			||||||
			return url.Substring (7, i - 7);
 | 
					      
 | 
				
			||||||
 | 
					            if (objectURI.Length == 0) {
 | 
				
			||||||
 | 
					        objectURI = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return url.Substring (7, i - 7);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,96 +39,95 @@ using System.Threading;
 | 
				
			|||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class UnixClientChannel : IChannelSender, IChannel
 | 
					    public class UnixClientChannel : IChannelSender, IChannel
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int priority = 1;                    
 | 
					    Int32 priority = 1;
 | 
				
			||||||
        string name = "unix";
 | 
					    String name = "unix";
 | 
				
			||||||
        IClientChannelSinkProvider _sinkProvider;
 | 
					        IClientChannelSinkProvider _sinkProvider;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public UnixClientChannel ()
 | 
					        public UnixClientChannel ()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
 | 
					      this._sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
 | 
				
			||||||
            _sinkProvider.Next = new UnixClientTransportSinkProvider ();
 | 
					      this._sinkProvider.Next = new UnixClientTransportSinkProvider ();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnixClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
 | 
					        public UnixClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            object val = properties ["name"];
 | 
					      Object val = properties ["name"];
 | 
				
			||||||
            if (val != null) name = val as string;
 | 
					            if (val != null) {
 | 
				
			||||||
            
 | 
					        this.name = val as String;
 | 
				
			||||||
            val = properties ["priority"];
 | 
					      }
 | 
				
			||||||
            if (val != null) priority = Convert.ToInt32 (val);
 | 
					
 | 
				
			||||||
            
 | 
					      val = properties ["priority"];
 | 
				
			||||||
            if (sinkProvider != null)
 | 
					            if (val != null) {
 | 
				
			||||||
            {
 | 
					        this.priority = Convert.ToInt32 (val);
 | 
				
			||||||
                _sinkProvider = sinkProvider;
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (sinkProvider != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					        this._sinkProvider = sinkProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // add the unix provider at the end of the chain
 | 
					                // add the unix provider at the end of the chain
 | 
				
			||||||
                IClientChannelSinkProvider prov = sinkProvider;
 | 
					                IClientChannelSinkProvider prov = sinkProvider;
 | 
				
			||||||
                while (prov.Next != null) prov = prov.Next;
 | 
					                while (prov.Next != null) {
 | 
				
			||||||
                prov.Next = new UnixClientTransportSinkProvider ();
 | 
					          prov = prov.Next;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        prov.Next = new UnixClientTransportSinkProvider ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Note: a default formatter is added only when
 | 
					                // Note: a default formatter is added only when
 | 
				
			||||||
                // no sink providers are specified in the config file.
 | 
					                // no sink providers are specified in the config file.
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
 | 
					        this._sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
 | 
				
			||||||
                _sinkProvider.Next = new UnixClientTransportSinkProvider ();
 | 
					        this._sinkProvider.Next = new UnixClientTransportSinkProvider ();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnixClientChannel (string name, IClientChannelSinkProvider sinkProvider)
 | 
					        public UnixClientChannel (String name, IClientChannelSinkProvider sinkProvider)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.name = name;
 | 
					            this.name = name;
 | 
				
			||||||
            _sinkProvider = sinkProvider;
 | 
					      this._sinkProvider = sinkProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add the unix provider at the end of the chain
 | 
					            // add the unix provider at the end of the chain
 | 
				
			||||||
            IClientChannelSinkProvider prov = sinkProvider;
 | 
					            IClientChannelSinkProvider prov = sinkProvider;
 | 
				
			||||||
            while (prov.Next != null) prov = prov.Next;
 | 
					            while (prov.Next != null) {
 | 
				
			||||||
            prov.Next = new UnixClientTransportSinkProvider ();
 | 
					        prov = prov.Next;
 | 
				
			||||||
        }
 | 
					      }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        public string ChannelName
 | 
					      prov.Next = new UnixClientTransportSinkProvider ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String ChannelName => this.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int32 ChannelPriority => this.priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IMessageSink CreateMessageSink (String url,
 | 
				
			||||||
 | 
					                                               Object remoteChannelData,
 | 
				
			||||||
 | 
					                                               out String objectURI)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get {
 | 
					            if (url != null && this.Parse (url, out objectURI) != null) {
 | 
				
			||||||
                return name;
 | 
					        return (IMessageSink)this._sinkProvider.CreateSink (this, url, remoteChannelData);
 | 
				
			||||||
            }
 | 
					      }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					      if (remoteChannelData != null) {
 | 
				
			||||||
        public int ChannelPriority
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get {
 | 
					 | 
				
			||||||
                return priority;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public IMessageSink CreateMessageSink (string url,
 | 
					 | 
				
			||||||
                                               object remoteChannelData,
 | 
					 | 
				
			||||||
                                               out string objectURI)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (url != null && Parse (url, out objectURI) != null)
 | 
					 | 
				
			||||||
                return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
 | 
					 | 
				
			||||||
                                                                                
 | 
					 | 
				
			||||||
            if (remoteChannelData != null) {
 | 
					 | 
				
			||||||
                IChannelDataStore ds = remoteChannelData as IChannelDataStore;
 | 
					                IChannelDataStore ds = remoteChannelData as IChannelDataStore;
 | 
				
			||||||
                if (ds != null && ds.ChannelUris.Length > 0)
 | 
					                if (ds != null && ds.ChannelUris.Length > 0) {
 | 
				
			||||||
                    url = ds.ChannelUris [0];
 | 
					          url = ds.ChannelUris [0];
 | 
				
			||||||
                else {
 | 
					        } else {
 | 
				
			||||||
                    objectURI = null;
 | 
					                    objectURI = null;
 | 
				
			||||||
                    return null;
 | 
					                    return null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            if (Parse (url, out objectURI) == null)
 | 
					            if (this.Parse (url, out objectURI) == null) {
 | 
				
			||||||
                return null;
 | 
					        return null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
            return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
 | 
					
 | 
				
			||||||
        }
 | 
					      return (IMessageSink)this._sinkProvider.CreateSink (this, url, remoteChannelData);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        public string Parse (string url, out string objectURI)
 | 
					
 | 
				
			||||||
        {
 | 
					    public String Parse(String url, out String objectURI) => UnixChannel.ParseUnixURL(url, out objectURI);
 | 
				
			||||||
            return UnixChannel.ParseUnixURL (url, out objectURI);
 | 
					  }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -38,156 +38,156 @@ using System.Runtime.Remoting;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class UnixClientTransportSink : IClientChannelSink
 | 
					  internal class UnixClientTransportSink : IClientChannelSink
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
        string _path;
 | 
					    String _path;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public UnixClientTransportSink (string url)
 | 
					    public UnixClientTransportSink (String url)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			string objectUri;
 | 
					      this._path = UnixChannel.ParseUnixURL(url, out String objectUri);
 | 
				
			||||||
            _path = UnixChannel.ParseUnixURL (url, out objectUri);
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public IDictionary Properties => null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IClientChannelSink NextChannelSink =>
 | 
				
			||||||
 | 
					        // we are the last one
 | 
				
			||||||
 | 
					        null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
 | 
				
			||||||
 | 
					      ITransportHeaders headers, Stream requestStream)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      UnixConnection connection = null;
 | 
				
			||||||
 | 
					      Boolean isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IDictionary Properties
 | 
					      try
 | 
				
			||||||
		{
 | 
					      {
 | 
				
			||||||
			get 
 | 
					        if (headers == null) {
 | 
				
			||||||
			{
 | 
					          headers = new TransportHeaders();
 | 
				
			||||||
				return null;
 | 
					        }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					        headers ["__RequestUri"] = ((IMethodMessage)msg).Uri;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Sends the stream using a connection from the pool
 | 
				
			||||||
 | 
					        // and creates a WorkItem that will wait for the
 | 
				
			||||||
 | 
					        // response of the server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IClientChannelSink NextChannelSink
 | 
					        connection = UnixConnectionPool.GetConnection (this._path);
 | 
				
			||||||
		{
 | 
					        UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
 | 
				
			||||||
			get 
 | 
					        connection.Stream.Flush ();
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// we are the last one
 | 
					 | 
				
			||||||
				return null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
 | 
					        if (!isOneWay) 
 | 
				
			||||||
			ITransportHeaders headers, Stream requestStream)
 | 
					        {
 | 
				
			||||||
		{
 | 
					          sinkStack.Push (this, connection);
 | 
				
			||||||
			UnixConnection connection = null;
 | 
					          _ = ThreadPool.QueueUserWorkItem(new WaitCallback(data => {
 | 
				
			||||||
			bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
 | 
					            try {
 | 
				
			||||||
 | 
					              this.ReadAsyncUnixMessage(data);
 | 
				
			||||||
 | 
					            } catch { }
 | 
				
			||||||
 | 
					          }), sinkStack);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					          connection.Release();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      catch
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        if (connection != null) {
 | 
				
			||||||
 | 
					          connection.Release();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!isOneWay) {
 | 
				
			||||||
 | 
					          throw;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
					    private void ReadAsyncUnixMessage(Object data)
 | 
				
			||||||
			{
 | 
					    {
 | 
				
			||||||
				if (headers == null) headers = new TransportHeaders();
 | 
					      // This method is called by a new thread to asynchronously
 | 
				
			||||||
				headers ["__RequestUri"] = ((IMethodMessage)msg).Uri;
 | 
					      // read the response to a request
 | 
				
			||||||
				
 | 
					 | 
				
			||||||
				// Sends the stream using a connection from the pool
 | 
					 | 
				
			||||||
				// and creates a WorkItem that will wait for the
 | 
					 | 
				
			||||||
				// response of the server
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				connection = UnixConnectionPool.GetConnection (_path);
 | 
					      // The stack was provided as state data in QueueUserWorkItem
 | 
				
			||||||
				UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
 | 
					      IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
 | 
				
			||||||
				connection.Stream.Flush ();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (!isOneWay) 
 | 
					      // The first sink in the stack is this sink. Pop it and
 | 
				
			||||||
				{
 | 
					      // get the status data, which is the UnixConnection used to send
 | 
				
			||||||
					sinkStack.Push (this, connection);
 | 
					      // the request
 | 
				
			||||||
					ThreadPool.QueueUserWorkItem (new WaitCallback(data => {
 | 
					      UnixConnection connection = (UnixConnection)stack.Pop(this);
 | 
				
			||||||
						try {
 | 
					 | 
				
			||||||
							ReadAsyncUnixMessage (data);
 | 
					 | 
				
			||||||
						} catch {}
 | 
					 | 
				
			||||||
						}), sinkStack);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					connection.Release();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (connection != null) connection.Release();
 | 
					 | 
				
			||||||
				if (!isOneWay) throw;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void ReadAsyncUnixMessage(object data)
 | 
					      try
 | 
				
			||||||
		{
 | 
					      {
 | 
				
			||||||
			// This method is called by a new thread to asynchronously
 | 
					
 | 
				
			||||||
			// read the response to a request
 | 
					        // Read the response, blocking if necessary
 | 
				
			||||||
 | 
					        MessageStatus status = UnixMessageIO.ReceiveMessageStatus(connection.Stream, connection.Buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (status != MessageStatus.MethodMessage) {
 | 
				
			||||||
 | 
					          throw new RemotingException ("Unknown response message from server");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out ITransportHeaders responseHeaders, connection.Buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// The stack was provided as state data in QueueUserWorkItem
 | 
					        // Free the connection, so it can be reused
 | 
				
			||||||
			IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
 | 
					        connection.Release();
 | 
				
			||||||
 | 
					        connection = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// The first sink in the stack is this sink. Pop it and
 | 
					        // Ok, proceed with the other sinks
 | 
				
			||||||
			// get the status data, which is the UnixConnection used to send
 | 
					        stack.AsyncProcessResponse (responseHeaders, responseStream);
 | 
				
			||||||
			// the request
 | 
					      }
 | 
				
			||||||
			UnixConnection connection = (UnixConnection)stack.Pop(this);
 | 
					      catch
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        if (connection != null) {
 | 
				
			||||||
 | 
					          connection.Release();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack,
 | 
				
			||||||
 | 
					      Object state, ITransportHeaders headers,
 | 
				
			||||||
 | 
					      Stream stream) =>
 | 
				
			||||||
 | 
					      // Should never be called
 | 
				
			||||||
 | 
					      throw new NotSupportedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Stream GetRequestStream(IMessage msg, ITransportHeaders headers) => null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void ProcessMessage (IMessage msg,
 | 
				
			||||||
 | 
					      ITransportHeaders requestHeaders,
 | 
				
			||||||
 | 
					      Stream requestStream,
 | 
				
			||||||
 | 
					      out ITransportHeaders responseHeaders,
 | 
				
			||||||
 | 
					      out Stream responseStream)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      UnixConnection connection = null;
 | 
				
			||||||
 | 
					      try
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        if (requestHeaders == null) {
 | 
				
			||||||
 | 
					          requestHeaders = new TransportHeaders();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        requestHeaders ["__RequestUri"] = ((IMethodMessage)msg).Uri;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Sends the message
 | 
				
			||||||
 | 
					        connection = UnixConnectionPool.GetConnection (this._path);
 | 
				
			||||||
 | 
					        UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
 | 
				
			||||||
 | 
					        connection.Stream.Flush ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
					        // Reads the response
 | 
				
			||||||
			{
 | 
					        MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
 | 
				
			||||||
				ITransportHeaders responseHeaders;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Read the response, blocking if necessary
 | 
					        if (status != MessageStatus.MethodMessage) {
 | 
				
			||||||
				MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
 | 
					          throw new RemotingException ("Unknown response message from server");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      finally
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        if (connection != null) {
 | 
				
			||||||
 | 
					          connection.Release();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (status != MessageStatus.MethodMessage)
 | 
					  }
 | 
				
			||||||
					throw new RemotingException ("Unknown response message from server");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Free the connection, so it can be reused
 | 
					 | 
				
			||||||
				connection.Release();
 | 
					 | 
				
			||||||
				connection = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Ok, proceed with the other sinks
 | 
					 | 
				
			||||||
				stack.AsyncProcessResponse (responseHeaders, responseStream);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (connection != null) connection.Release();
 | 
					 | 
				
			||||||
				throw;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
 | 
					 | 
				
			||||||
			object state, ITransportHeaders headers,
 | 
					 | 
				
			||||||
			Stream stream)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Should never be called
 | 
					 | 
				
			||||||
			throw new NotSupportedException();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return null;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public void ProcessMessage (IMessage msg,
 | 
					 | 
				
			||||||
			ITransportHeaders requestHeaders,
 | 
					 | 
				
			||||||
			Stream requestStream,
 | 
					 | 
				
			||||||
			out ITransportHeaders responseHeaders,
 | 
					 | 
				
			||||||
			out Stream responseStream)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UnixConnection connection = null;
 | 
					 | 
				
			||||||
			try
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (requestHeaders == null) requestHeaders = new TransportHeaders();
 | 
					 | 
				
			||||||
				requestHeaders ["__RequestUri"] = ((IMethodMessage)msg).Uri;
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
				// Sends the message
 | 
					 | 
				
			||||||
				connection = UnixConnectionPool.GetConnection (_path);
 | 
					 | 
				
			||||||
				UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
 | 
					 | 
				
			||||||
				connection.Stream.Flush ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Reads the response
 | 
					 | 
				
			||||||
				MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (status != MessageStatus.MethodMessage)
 | 
					 | 
				
			||||||
					throw new RemotingException ("Unknown response message from server");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			finally
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (connection != null) 
 | 
					 | 
				
			||||||
					connection.Release();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -40,23 +40,15 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
            // what should we do here ?
 | 
					            // what should we do here ?
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IClientChannelSinkProvider Next
 | 
					        public IClientChannelSinkProvider Next {
 | 
				
			||||||
        {
 | 
					      get => null;
 | 
				
			||||||
            get 
 | 
					
 | 
				
			||||||
            {
 | 
					      set {
 | 
				
			||||||
                return null;
 | 
					        // ignore, we are always the last in the chain 
 | 
				
			||||||
            }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
            set 
 | 
					
 | 
				
			||||||
            {
 | 
					    public IClientChannelSink CreateSink(IChannelSender channel, String url,
 | 
				
			||||||
                // ignore, we are always the last in the chain 
 | 
					                                          Object remoteChannelData) => new UnixClientTransportSink(url);
 | 
				
			||||||
            }
 | 
					  }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public IClientChannelSink CreateSink (IChannelSender channel, string url,
 | 
					 | 
				
			||||||
                                              object remoteChannelData)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return new UnixClientTransportSink (url);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,275 +37,254 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// This is a pool of Unix connections. Connections requested
 | 
					  // This is a pool of Unix connections. Connections requested
 | 
				
			||||||
	// by the TCP channel are pooled after their use, and can
 | 
					  // by the TCP channel are pooled after their use, and can
 | 
				
			||||||
	// be reused later. Connections are automaticaly closed
 | 
					  // be reused later. Connections are automaticaly closed
 | 
				
			||||||
	// if not used after some time, specified in KeepAliveSeconds.
 | 
					  // if not used after some time, specified in KeepAliveSeconds.
 | 
				
			||||||
	// The number of allowed open connections can also be specified
 | 
					  // The number of allowed open connections can also be specified
 | 
				
			||||||
	// in MaxOpenConnections. The limit is per host.
 | 
					  // in MaxOpenConnections. The limit is per host.
 | 
				
			||||||
	// If a thread requests a connection and the limit has been 
 | 
					  // If a thread requests a connection and the limit has been 
 | 
				
			||||||
	// reached, the thread is suspended until one is released.
 | 
					  // reached, the thread is suspended until one is released.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class UnixConnectionPool
 | 
					  internal class UnixConnectionPool
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		// Table of pools. There is a HostConnectionPool 
 | 
					    // Table of pools. There is a HostConnectionPool 
 | 
				
			||||||
		// instance for each host
 | 
					    // instance for each host
 | 
				
			||||||
		static Hashtable _pools = new Hashtable();
 | 
					    static Hashtable _pools = new Hashtable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static int _maxOpenConnections = int.MaxValue;
 | 
					    static Int32 _maxOpenConnections = Int32.MaxValue;
 | 
				
			||||||
		static int _keepAliveSeconds = 15;
 | 
					    static Int32 _keepAliveSeconds = 15;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static Thread _poolThread;
 | 
					    static Thread _poolThread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static UnixConnectionPool()
 | 
					    static UnixConnectionPool()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			// This thread will close unused connections
 | 
					      // This thread will close unused connections
 | 
				
			||||||
			_poolThread = new Thread (new ThreadStart (ConnectionCollector));
 | 
					      _poolThread = new Thread (new ThreadStart (ConnectionCollector));
 | 
				
			||||||
			_poolThread.Start();
 | 
					      _poolThread.Start();
 | 
				
			||||||
			_poolThread.IsBackground = true;
 | 
					      _poolThread.IsBackground = true;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void Shutdown ()
 | 
					    public static void Shutdown ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (_poolThread != null)
 | 
					      if (_poolThread != null) {
 | 
				
			||||||
				_poolThread.Abort();
 | 
					        _poolThread.Abort();
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static int MaxOpenConnections
 | 
					    public static Int32 MaxOpenConnections {
 | 
				
			||||||
		{
 | 
					      get => _maxOpenConnections;
 | 
				
			||||||
			get { return _maxOpenConnections; }
 | 
					      set {
 | 
				
			||||||
			set 
 | 
					        if(value < 1) {
 | 
				
			||||||
			{ 
 | 
					          throw new RemotingException("MaxOpenConnections must be greater than zero");
 | 
				
			||||||
				if (value < 1) throw new RemotingException ("MaxOpenConnections must be greater than zero");
 | 
					        }
 | 
				
			||||||
				_maxOpenConnections = value; 
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static int KeepAliveSeconds
 | 
					        _maxOpenConnections = value;
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			get { return _keepAliveSeconds; }
 | 
					    }
 | 
				
			||||||
			set { _keepAliveSeconds = value; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixConnection GetConnection (string path)
 | 
					    public static Int32 KeepAliveSeconds {
 | 
				
			||||||
		{
 | 
					      get => _keepAliveSeconds;
 | 
				
			||||||
			HostConnectionPool hostPool;
 | 
					      set => _keepAliveSeconds = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			lock (_pools)
 | 
					    public static UnixConnection GetConnection (String path)
 | 
				
			||||||
			{
 | 
					    {
 | 
				
			||||||
				hostPool = (HostConnectionPool) _pools[path];
 | 
					      HostConnectionPool hostPool;
 | 
				
			||||||
				if (hostPool == null)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					hostPool = new HostConnectionPool(path);
 | 
					 | 
				
			||||||
					_pools[path] = hostPool;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return hostPool.GetConnection();
 | 
					      lock (_pools)
 | 
				
			||||||
		}
 | 
					      {
 | 
				
			||||||
 | 
					        hostPool = (HostConnectionPool) _pools[path];
 | 
				
			||||||
 | 
					        if (hostPool == null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          hostPool = new HostConnectionPool(path);
 | 
				
			||||||
 | 
					          _pools[path] = hostPool;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void ConnectionCollector ()
 | 
					      return hostPool.GetConnection();
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
			while (true)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				Thread.Sleep(3000);
 | 
					 | 
				
			||||||
				lock (_pools)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					ICollection values = _pools.Values;
 | 
					 | 
				
			||||||
					foreach (HostConnectionPool pool in values)
 | 
					 | 
				
			||||||
						pool.PurgeConnections();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class ReusableUnixClient : UnixClient
 | 
					    private static void ConnectionCollector ()
 | 
				
			||||||
	{
 | 
					    {
 | 
				
			||||||
		public ReusableUnixClient (string path): base (path)
 | 
					      while (true)
 | 
				
			||||||
		{
 | 
					      {
 | 
				
			||||||
		}
 | 
					        Thread.Sleep(3000);
 | 
				
			||||||
		
 | 
					        lock (_pools)
 | 
				
			||||||
		public bool IsAlive
 | 
					        {
 | 
				
			||||||
		{
 | 
					          ICollection values = _pools.Values;
 | 
				
			||||||
			get
 | 
					          foreach (HostConnectionPool pool in values) {
 | 
				
			||||||
			{
 | 
					            pool.PurgeConnections();
 | 
				
			||||||
				// This Poll will return true if there is data pending to
 | 
					          }
 | 
				
			||||||
				// be read. It prob. means that a client object using this
 | 
					        }
 | 
				
			||||||
				// connection got an exception and did not finish to read
 | 
					      }
 | 
				
			||||||
				// the data. It can also mean that the connection has been
 | 
					    }
 | 
				
			||||||
				// closed in the server. In both cases, the connection cannot
 | 
					  }
 | 
				
			||||||
				// be reused.
 | 
					 | 
				
			||||||
				return !Client.Poll (0, SelectMode.SelectRead);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class UnixConnection
 | 
					  internal class ReusableUnixClient : UnixClient
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		DateTime _controlTime;
 | 
					    public ReusableUnixClient (String path): base (path)
 | 
				
			||||||
		Stream _stream;
 | 
					    {
 | 
				
			||||||
		ReusableUnixClient _client;
 | 
					    }
 | 
				
			||||||
		HostConnectionPool _pool;
 | 
					 | 
				
			||||||
		byte[] _buffer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixConnection (HostConnectionPool pool, ReusableUnixClient client)
 | 
					    public Boolean IsAlive =>
 | 
				
			||||||
		{
 | 
					        // This Poll will return true if there is data pending to
 | 
				
			||||||
			_pool = pool;
 | 
					        // be read. It prob. means that a client object using this
 | 
				
			||||||
			_client = client;
 | 
					        // connection got an exception and did not finish to read
 | 
				
			||||||
			_stream = new BufferedStream (client.GetStream());
 | 
					        // the data. It can also mean that the connection has been
 | 
				
			||||||
			_controlTime = DateTime.UtcNow;
 | 
					        // closed in the server. In both cases, the connection cannot
 | 
				
			||||||
			_buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
 | 
					        // be reused.
 | 
				
			||||||
		}
 | 
					        !this.Client.Poll(0, SelectMode.SelectRead);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Stream Stream
 | 
					  internal class UnixConnection
 | 
				
			||||||
		{
 | 
					  {
 | 
				
			||||||
			get { return _stream; }
 | 
					    DateTime _controlTime;
 | 
				
			||||||
		}
 | 
					    Stream _stream;
 | 
				
			||||||
 | 
					    ReusableUnixClient _client;
 | 
				
			||||||
 | 
					    HostConnectionPool _pool;
 | 
				
			||||||
 | 
					    Byte[] _buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public DateTime ControlTime
 | 
					    public UnixConnection (HostConnectionPool pool, ReusableUnixClient client)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			get { return _controlTime; }
 | 
					      this._pool = pool;
 | 
				
			||||||
			set { _controlTime = value; }
 | 
					      this._client = client;
 | 
				
			||||||
		}
 | 
					      this._stream = new BufferedStream (client.GetStream());
 | 
				
			||||||
 | 
					      this._controlTime = DateTime.UtcNow;
 | 
				
			||||||
 | 
					      this._buffer = new Byte[UnixMessageIO.DefaultStreamBufferSize];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool IsAlive
 | 
					    public Stream Stream => this._stream;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			get { return _client.IsAlive; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// This is a "thread safe" buffer that can be used by 
 | 
					    public DateTime ControlTime {
 | 
				
			||||||
		// UnixClientTransportSink to read or send data to the stream.
 | 
					      get => this._controlTime;
 | 
				
			||||||
		// The buffer is "thread safe" since only one thread can
 | 
					      set => this._controlTime = value;
 | 
				
			||||||
		// use a connection at a given time.
 | 
					    }
 | 
				
			||||||
		public byte[] Buffer
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			get { return _buffer; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Returns the connection to the pool
 | 
					    public Boolean IsAlive => this._client.IsAlive;
 | 
				
			||||||
		public void Release()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_pool.ReleaseConnection (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Close()
 | 
					    // This is a "thread safe" buffer that can be used by 
 | 
				
			||||||
		{
 | 
					    // UnixClientTransportSink to read or send data to the stream.
 | 
				
			||||||
			_client.Close();
 | 
					    // The buffer is "thread safe" since only one thread can
 | 
				
			||||||
		}
 | 
					    // use a connection at a given time.
 | 
				
			||||||
	}
 | 
					    public Byte[] Buffer => this._buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class HostConnectionPool
 | 
					    // Returns the connection to the pool
 | 
				
			||||||
	{
 | 
					    public void Release() => this._pool.ReleaseConnection(this);
 | 
				
			||||||
		ArrayList _pool = new ArrayList();
 | 
					 | 
				
			||||||
		int _activeConnections = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		string _path;
 | 
					    public void Close() => this._client.Close();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public HostConnectionPool (string path)
 | 
					  internal class HostConnectionPool
 | 
				
			||||||
		{
 | 
					  {
 | 
				
			||||||
			_path = path;
 | 
					    ArrayList _pool = new ArrayList();
 | 
				
			||||||
		}
 | 
					    Int32 _activeConnections = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixConnection GetConnection ()
 | 
					    String _path;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UnixConnection connection = null;
 | 
					 | 
				
			||||||
			lock (_pool)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				do
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					if (_pool.Count > 0) 
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						// There are available connections
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
						connection = (UnixConnection)_pool[_pool.Count - 1];
 | 
					    public HostConnectionPool(String path) => this._path = path;
 | 
				
			||||||
						_pool.RemoveAt(_pool.Count - 1);
 | 
					 | 
				
			||||||
						if (!connection.IsAlive) {
 | 
					 | 
				
			||||||
							CancelConnection (connection);
 | 
					 | 
				
			||||||
							connection = null;
 | 
					 | 
				
			||||||
							continue;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (connection == null && _activeConnections < UnixConnectionPool.MaxOpenConnections)
 | 
					    public UnixConnection GetConnection ()
 | 
				
			||||||
					{
 | 
					    {
 | 
				
			||||||
						// No connections available, but the max connections
 | 
					      UnixConnection connection = null;
 | 
				
			||||||
						// has not been reached yet, so a new one can be created
 | 
					      lock (this._pool)
 | 
				
			||||||
						// Create the connection outside the lock
 | 
					      {
 | 
				
			||||||
						break;
 | 
					        do
 | 
				
			||||||
					}
 | 
					        {
 | 
				
			||||||
 | 
					          if (this._pool.Count > 0) 
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            // There are available connections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// No available connections in the pool
 | 
					            connection = (UnixConnection)this._pool[this._pool.Count - 1];
 | 
				
			||||||
					// Wait for somewone to release one.
 | 
					            this._pool.RemoveAt(this._pool.Count - 1);
 | 
				
			||||||
 | 
					            if (!connection.IsAlive) {
 | 
				
			||||||
 | 
					              this.CancelConnection (connection);
 | 
				
			||||||
 | 
					              connection = null;
 | 
				
			||||||
 | 
					              continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (connection == null)
 | 
					          if (connection == null && this._activeConnections < UnixConnectionPool.MaxOpenConnections)
 | 
				
			||||||
					{
 | 
					          {
 | 
				
			||||||
						Monitor.Wait(_pool);
 | 
					            // No connections available, but the max connections
 | 
				
			||||||
					}
 | 
					            // has not been reached yet, so a new one can be created
 | 
				
			||||||
				} 
 | 
					            // Create the connection outside the lock
 | 
				
			||||||
				while (connection == null);
 | 
					            break;
 | 
				
			||||||
			}
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (connection == null)
 | 
					          // No available connections in the pool
 | 
				
			||||||
				return CreateConnection ();
 | 
					          // Wait for somewone to release one.
 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				return connection;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private UnixConnection CreateConnection()
 | 
					          if (connection == null)
 | 
				
			||||||
		{
 | 
					          {
 | 
				
			||||||
			try
 | 
					            _ = Monitor.Wait(this._pool);
 | 
				
			||||||
			{
 | 
					          }
 | 
				
			||||||
				ReusableUnixClient client = new ReusableUnixClient (_path);
 | 
					        } 
 | 
				
			||||||
				UnixConnection entry = new UnixConnection(this, client);
 | 
					        while (connection == null);
 | 
				
			||||||
				_activeConnections++;
 | 
					      }
 | 
				
			||||||
				return entry;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch (Exception ex)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				throw new RemotingException (ex.Message);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void ReleaseConnection (UnixConnection entry)
 | 
					      if (connection == null) {
 | 
				
			||||||
		{
 | 
					        return this.CreateConnection ();
 | 
				
			||||||
			lock (_pool)
 | 
					      } else {
 | 
				
			||||||
			{
 | 
					        return connection;
 | 
				
			||||||
				entry.ControlTime = DateTime.UtcNow;	// Initialize timeout
 | 
					      }
 | 
				
			||||||
				_pool.Add (entry);
 | 
					    }
 | 
				
			||||||
				Monitor.Pulse (_pool);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void CancelConnection(UnixConnection entry)
 | 
					    private UnixConnection CreateConnection()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			try
 | 
					      try
 | 
				
			||||||
			{
 | 
					      {
 | 
				
			||||||
				entry.Stream.Close();
 | 
					        ReusableUnixClient client = new ReusableUnixClient (this._path);
 | 
				
			||||||
				_activeConnections--;
 | 
					        UnixConnection entry = new UnixConnection(this, client);
 | 
				
			||||||
			}
 | 
					        this._activeConnections++;
 | 
				
			||||||
			catch
 | 
					        return entry;
 | 
				
			||||||
			{
 | 
					      }
 | 
				
			||||||
			}
 | 
					      catch (Exception ex)
 | 
				
			||||||
		}
 | 
					      {
 | 
				
			||||||
 | 
					        throw new RemotingException (ex.Message);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void PurgeConnections()
 | 
					    public void ReleaseConnection (UnixConnection entry)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			lock (_pool)
 | 
					      lock (this._pool)
 | 
				
			||||||
			{
 | 
					      {
 | 
				
			||||||
				for (int n=0; n < _pool.Count; n++)
 | 
					        entry.ControlTime = DateTime.UtcNow;  // Initialize timeout
 | 
				
			||||||
				{
 | 
					        _ = this._pool.Add(entry);
 | 
				
			||||||
					UnixConnection entry = (UnixConnection)_pool[n];
 | 
					        Monitor.Pulse (this._pool);
 | 
				
			||||||
					if ( (DateTime.UtcNow - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)
 | 
					      }
 | 
				
			||||||
					{
 | 
					    }
 | 
				
			||||||
						CancelConnection (entry);
 | 
					 | 
				
			||||||
						_pool.RemoveAt(n);
 | 
					 | 
				
			||||||
						n--;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
					    private void CancelConnection(UnixConnection entry)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      try
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        entry.Stream.Close();
 | 
				
			||||||
 | 
					        this._activeConnections--;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      catch
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void PurgeConnections()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      lock (this._pool)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        for (Int32 n =0; n < this._pool.Count; n++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          UnixConnection entry = (UnixConnection)this._pool[n];
 | 
				
			||||||
 | 
					          if ( (DateTime.UtcNow - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            this.CancelConnection (entry);
 | 
				
			||||||
 | 
					            this._pool.RemoveAt(n);
 | 
				
			||||||
 | 
					            n--;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -38,246 +38,265 @@ using System.Runtime.Remoting;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix 
 | 
					namespace Mono.Remoting.Channels.Unix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	enum MessageStatus { MethodMessage = 0, CancelSignal = 1, Unknown = 10}
 | 
					  enum MessageStatus { MethodMessage = 0, CancelSignal = 1, Unknown = 10}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	internal class UnixMessageIO
 | 
					  internal class UnixMessageIO
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		static byte[][] _msgHeaders = 
 | 
					    static Byte[][] _msgHeaders = 
 | 
				
			||||||
			  {
 | 
					        {
 | 
				
			||||||
				  new byte[] { (byte)'.', (byte)'N', (byte)'E', (byte)'T', 1, 0 },
 | 
					          new Byte[] { (Byte)'.', (Byte)'N', (Byte)'E', (Byte)'T', 1, 0 },
 | 
				
			||||||
				  new byte[] { 255, 255, 255, 255, 255, 255 }
 | 
					          new Byte[] { 255, 255, 255, 255, 255, 255 }
 | 
				
			||||||
			  };
 | 
					        };
 | 
				
			||||||
							
 | 
					              
 | 
				
			||||||
		public static int DefaultStreamBufferSize = 1000;
 | 
					    public static Int32 DefaultStreamBufferSize = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Identifies an incoming message
 | 
					    // Identifies an incoming message
 | 
				
			||||||
		public static MessageStatus ReceiveMessageStatus (Stream networkStream, byte[] buffer)
 | 
					    public static MessageStatus ReceiveMessageStatus (Stream networkStream, Byte[] buffer)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			try {
 | 
					      try {
 | 
				
			||||||
				StreamRead (networkStream, buffer, 6);
 | 
					        _ = StreamRead(networkStream, buffer, 6);
 | 
				
			||||||
			} catch (Exception ex) {
 | 
					      } catch (Exception ex) {
 | 
				
			||||||
				throw new RemotingException ("Unix transport error.", ex);
 | 
					        throw new RemotingException ("Unix transport error.", ex);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
					      try
 | 
				
			||||||
			{
 | 
					      {
 | 
				
			||||||
				bool[] isOnTrack = new bool[_msgHeaders.Length];
 | 
					        Boolean[] isOnTrack = new Boolean[_msgHeaders.Length];
 | 
				
			||||||
				bool atLeastOneOnTrack = true;
 | 
					        Boolean atLeastOneOnTrack = true;
 | 
				
			||||||
				int i = 0;
 | 
					        Int32 i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				while (atLeastOneOnTrack)
 | 
					        while (atLeastOneOnTrack)
 | 
				
			||||||
				{
 | 
					        {
 | 
				
			||||||
					atLeastOneOnTrack = false;
 | 
					          atLeastOneOnTrack = false;
 | 
				
			||||||
					byte c = buffer [i];
 | 
					          Byte c = buffer [i];
 | 
				
			||||||
					for (int n = 0; n<_msgHeaders.Length; n++)
 | 
					          for (Int32 n = 0; n<_msgHeaders.Length; n++)
 | 
				
			||||||
					{
 | 
					          {
 | 
				
			||||||
						if (i > 0 && !isOnTrack[n]) continue;
 | 
					            if (i > 0 && !isOnTrack[n]) {
 | 
				
			||||||
 | 
					              continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            isOnTrack[n] = c == _msgHeaders[n][i];
 | 
				
			||||||
 | 
					            if (isOnTrack[n] && i == _msgHeaders[n].Length-1) {
 | 
				
			||||||
 | 
					              return (MessageStatus) n;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            atLeastOneOnTrack = atLeastOneOnTrack || isOnTrack[n];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          i++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return MessageStatus.Unknown;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      catch (Exception ex) {
 | 
				
			||||||
 | 
					        throw new RemotingException ("Unix transport error.", ex);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    static Boolean StreamRead (Stream networkStream, Byte[] buffer, Int32 count)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Int32 nr = 0;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        Int32 pr = networkStream.Read (buffer, nr, count - nr);
 | 
				
			||||||
 | 
					        if (pr == 0) {
 | 
				
			||||||
 | 
					          throw new RemotingException ("Connection closed");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nr += pr;
 | 
				
			||||||
 | 
					      } while (nr < count);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						isOnTrack[n] = (c == _msgHeaders[n][i]);
 | 
					    public static void SendMessageStream (Stream networkStream, Stream data, ITransportHeaders requestHeaders, Byte[] buffer)
 | 
				
			||||||
						if (isOnTrack[n] && (i == _msgHeaders[n].Length-1)) return (MessageStatus) n;
 | 
					    {
 | 
				
			||||||
						atLeastOneOnTrack = atLeastOneOnTrack || isOnTrack[n];
 | 
					      if (buffer == null) {
 | 
				
			||||||
					}
 | 
					        buffer = new Byte[DefaultStreamBufferSize];
 | 
				
			||||||
					i++;
 | 
					      }
 | 
				
			||||||
				}
 | 
					
 | 
				
			||||||
				return MessageStatus.Unknown;
 | 
					      // Writes the message start header
 | 
				
			||||||
			}
 | 
					      Byte[] dotnetHeader = _msgHeaders[(Int32) MessageStatus.MethodMessage];
 | 
				
			||||||
			catch (Exception ex) {
 | 
					      networkStream.Write(dotnetHeader, 0, dotnetHeader.Length);
 | 
				
			||||||
				throw new RemotingException ("Unix transport error.", ex);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		static bool StreamRead (Stream networkStream, byte[] buffer, int count)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int nr = 0;
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				int pr = networkStream.Read (buffer, nr, count - nr);
 | 
					 | 
				
			||||||
				if (pr == 0)
 | 
					 | 
				
			||||||
					throw new RemotingException ("Connection closed");
 | 
					 | 
				
			||||||
				nr += pr;
 | 
					 | 
				
			||||||
			} while (nr < count);
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void SendMessageStream (Stream networkStream, Stream data, ITransportHeaders requestHeaders, byte[] buffer)
 | 
					      // Writes header tag (0x0000 if request stream, 0x0002 if response stream)
 | 
				
			||||||
		{
 | 
					      if(requestHeaders["__RequestUri"]!=null) {
 | 
				
			||||||
			if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
 | 
					        buffer [0] = (Byte) 0;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        buffer[0] = (Byte) 2;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      buffer [1] = (Byte) 0 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes the message start header
 | 
					      // Writes ID
 | 
				
			||||||
			byte[] dotnetHeader = _msgHeaders[(int) MessageStatus.MethodMessage];
 | 
					      buffer [2] = (Byte) 0;
 | 
				
			||||||
			networkStream.Write(dotnetHeader, 0, dotnetHeader.Length);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes header tag (0x0000 if request stream, 0x0002 if response stream)
 | 
					      // Writes assemblyID????
 | 
				
			||||||
			if(requestHeaders["__RequestUri"]!=null) buffer [0] = (byte) 0;
 | 
					      buffer [3] = (Byte) 0;
 | 
				
			||||||
			else buffer[0] = (byte) 2;
 | 
					
 | 
				
			||||||
			buffer [1] = (byte) 0 ;
 | 
					      // Writes the length of the stream being sent (not including the headers)
 | 
				
			||||||
 | 
					      Int32 num = (Int32)data.Length;
 | 
				
			||||||
 | 
					      buffer [4] = (Byte) num;
 | 
				
			||||||
 | 
					      buffer [5] = (Byte) (num >> 8);
 | 
				
			||||||
 | 
					      buffer [6] = (Byte) (num >> 16);
 | 
				
			||||||
 | 
					      buffer [7] = (Byte) (num >> 24);
 | 
				
			||||||
 | 
					      networkStream.Write(buffer, 0, 8);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      // Writes the message headers
 | 
				
			||||||
 | 
					      SendHeaders (networkStream, requestHeaders, buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes ID
 | 
					      // Writes the stream
 | 
				
			||||||
			buffer [2] = (byte) 0;
 | 
					      if (data is MemoryStream)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        // The copy of the stream can be optimized. The internal
 | 
				
			||||||
 | 
					        // buffer of MemoryStream can be used.
 | 
				
			||||||
 | 
					        MemoryStream memStream = (MemoryStream)data;
 | 
				
			||||||
 | 
					        networkStream.Write (memStream.GetBuffer(), 0, (Int32)memStream.Length);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        Int32 nread = data.Read (buffer, 0, buffer.Length);
 | 
				
			||||||
 | 
					        while (nread > 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          networkStream.Write (buffer, 0, nread);
 | 
				
			||||||
 | 
					          nread = data.Read (buffer, 0, buffer.Length);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    static Byte[] msgUriTransportKey = new Byte[] { 4, 0, 1, 1 };
 | 
				
			||||||
 | 
					    static Byte[] msgContentTypeTransportKey = new Byte[] { 6, 0, 1, 1 };
 | 
				
			||||||
 | 
					    static Byte[] msgDefaultTransportKey = new Byte[] { 1, 0, 1 };
 | 
				
			||||||
 | 
					    static Byte[] msgHeaderTerminator = new Byte[] { 0, 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes assemblyID????
 | 
					    private static void SendHeaders(Stream networkStream, ITransportHeaders requestHeaders, Byte[] buffer)
 | 
				
			||||||
			buffer [3] = (byte) 0;
 | 
					    {
 | 
				
			||||||
 | 
					      // Writes the headers as a sequence of strings
 | 
				
			||||||
 | 
					      if (networkStream != null)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        IEnumerator e = requestHeaders.GetEnumerator();
 | 
				
			||||||
 | 
					        while (e.MoveNext())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          DictionaryEntry hdr = (DictionaryEntry)e.Current;
 | 
				
			||||||
 | 
					          switch (hdr.Key.ToString())
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            case "__RequestUri": 
 | 
				
			||||||
 | 
					              networkStream.Write (msgUriTransportKey, 0, 4);
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					            case "Content-Type": 
 | 
				
			||||||
 | 
					              networkStream.Write (msgContentTypeTransportKey, 0, 4);
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					              networkStream.Write (msgDefaultTransportKey, 0, 3);
 | 
				
			||||||
 | 
					              SendString (networkStream, hdr.Key.ToString(), buffer);
 | 
				
			||||||
 | 
					              networkStream.WriteByte (1);
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          SendString (networkStream, hdr.Value.ToString(), buffer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      networkStream.Write (msgHeaderTerminator, 0, 2);	// End of headers
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public static ITransportHeaders ReceiveHeaders (Stream networkStream, Byte[] buffer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      _ = StreamRead(networkStream, buffer, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Byte headerType = buffer [0];
 | 
				
			||||||
 | 
					      TransportHeaders headers = new TransportHeaders ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes the length of the stream being sent (not including the headers)
 | 
					      while (headerType != 0)
 | 
				
			||||||
			int num = (int)data.Length;
 | 
					      {
 | 
				
			||||||
			buffer [4] = (byte) num;
 | 
					        String key;
 | 
				
			||||||
			buffer [5] = (byte) (num >> 8);
 | 
					        _ = StreamRead(networkStream, buffer, 1);	// byte 1
 | 
				
			||||||
			buffer [6] = (byte) (num >> 16);
 | 
					        switch (headerType)
 | 
				
			||||||
			buffer [7] = (byte) (num >> 24);
 | 
					        {
 | 
				
			||||||
			networkStream.Write(buffer, 0, 8);
 | 
					          case 4: key = "__RequestUri"; break;
 | 
				
			||||||
	
 | 
					          case 6: key = "Content-Type"; break;
 | 
				
			||||||
			// Writes the message headers
 | 
					          case 1: key = ReceiveString (networkStream, buffer); break;
 | 
				
			||||||
			SendHeaders (networkStream, requestHeaders, buffer);
 | 
					          default: throw new NotSupportedException ("Unknown header code: " + headerType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _ = StreamRead(networkStream, buffer, 1);	// byte 1
 | 
				
			||||||
 | 
					        headers[key] = ReceiveString (networkStream, buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = StreamRead(networkStream, buffer, 2);
 | 
				
			||||||
 | 
					        headerType = buffer [0];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Writes the stream
 | 
					      return headers;
 | 
				
			||||||
			if (data is MemoryStream)
 | 
					    }
 | 
				
			||||||
			{
 | 
					    
 | 
				
			||||||
				// The copy of the stream can be optimized. The internal
 | 
					    public static Stream ReceiveMessageStream (Stream networkStream, out ITransportHeaders headers, Byte[] buffer)
 | 
				
			||||||
				// buffer of MemoryStream can be used.
 | 
					    {
 | 
				
			||||||
				MemoryStream memStream = (MemoryStream)data;
 | 
					      headers = null;
 | 
				
			||||||
				networkStream.Write (memStream.GetBuffer(), 0, (int)memStream.Length);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				int nread = data.Read (buffer, 0, buffer.Length);
 | 
					 | 
				
			||||||
				while (nread > 0)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					networkStream.Write (buffer, 0, nread);
 | 
					 | 
				
			||||||
					nread = data.Read (buffer, 0, buffer.Length);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		static byte[] msgUriTransportKey = new byte[] { 4, 0, 1, 1 };
 | 
					 | 
				
			||||||
		static byte[] msgContentTypeTransportKey = new byte[] { 6, 0, 1, 1 };
 | 
					 | 
				
			||||||
		static byte[] msgDefaultTransportKey = new byte[] { 1, 0, 1 };
 | 
					 | 
				
			||||||
		static byte[] msgHeaderTerminator = new byte[] { 0, 0 };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void SendHeaders(Stream networkStream, ITransportHeaders requestHeaders, byte[] buffer)
 | 
					      if (buffer == null) {
 | 
				
			||||||
		{
 | 
					        buffer = new Byte[DefaultStreamBufferSize];
 | 
				
			||||||
			// Writes the headers as a sequence of strings
 | 
					      }
 | 
				
			||||||
			if (networkStream != null)
 | 
					
 | 
				
			||||||
			{
 | 
					      // Reads header tag:  0 -> Stream with headers or 2 -> Response Stream
 | 
				
			||||||
				IEnumerator e = requestHeaders.GetEnumerator();
 | 
					      // +
 | 
				
			||||||
				while (e.MoveNext())
 | 
					      // Gets the length of the data stream
 | 
				
			||||||
				{
 | 
					      _ = StreamRead(networkStream, buffer, 8);
 | 
				
			||||||
					DictionaryEntry hdr = (DictionaryEntry)e.Current;
 | 
					
 | 
				
			||||||
					switch (hdr.Key.ToString())
 | 
					      Int32 byteCount = buffer [4] | (buffer [5] << 8) |
 | 
				
			||||||
					{
 | 
					        (buffer [6] << 16) | (buffer [7] << 24);
 | 
				
			||||||
						case "__RequestUri": 
 | 
					 | 
				
			||||||
							networkStream.Write (msgUriTransportKey, 0, 4);
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						case "Content-Type": 
 | 
					 | 
				
			||||||
							networkStream.Write (msgContentTypeTransportKey, 0, 4);
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						default: 
 | 
					 | 
				
			||||||
							networkStream.Write (msgDefaultTransportKey, 0, 3);
 | 
					 | 
				
			||||||
							SendString (networkStream, hdr.Key.ToString(), buffer);
 | 
					 | 
				
			||||||
							networkStream.WriteByte (1);
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					SendString (networkStream, hdr.Value.ToString(), buffer);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			networkStream.Write (msgHeaderTerminator, 0, 2);	// End of headers
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public static ITransportHeaders ReceiveHeaders (Stream networkStream, byte[] buffer)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			StreamRead (networkStream, buffer, 2);
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			byte headerType = buffer [0];
 | 
					 | 
				
			||||||
			TransportHeaders headers = new TransportHeaders ();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			while (headerType != 0)
 | 
					      // Reads the headers
 | 
				
			||||||
			{
 | 
					      headers = ReceiveHeaders (networkStream, buffer);
 | 
				
			||||||
				string key;
 | 
					
 | 
				
			||||||
				StreamRead (networkStream, buffer, 1);	// byte 1
 | 
					      Byte[] resultBuffer = new Byte[byteCount];
 | 
				
			||||||
				switch (headerType)
 | 
					      _ = StreamRead(networkStream, resultBuffer, byteCount);
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					case 4: key = "__RequestUri"; break;
 | 
					 | 
				
			||||||
					case 6: key = "Content-Type"; break;
 | 
					 | 
				
			||||||
					case 1: key = ReceiveString (networkStream, buffer); break;
 | 
					 | 
				
			||||||
					default: throw new NotSupportedException ("Unknown header code: " + headerType);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				StreamRead (networkStream, buffer, 1);	// byte 1
 | 
					 | 
				
			||||||
				headers[key] = ReceiveString (networkStream, buffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				StreamRead (networkStream, buffer, 2);
 | 
					      return new MemoryStream (resultBuffer);
 | 
				
			||||||
				headerType = buffer [0];
 | 
					    }		
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return headers;
 | 
					    private static void SendString (Stream networkStream, String str, Byte[] buffer)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
		
 | 
					      // Allocates a buffer. Use the internal buffer if it is 
 | 
				
			||||||
		public static Stream ReceiveMessageStream (Stream networkStream, out ITransportHeaders headers, byte[] buffer)
 | 
					      // big enough. If not, create a new one.
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			headers = null;
 | 
					      Int32 maxBytes = Encoding.UTF8.GetMaxByteCount(str.Length)+4;	//+4 bytes for storing the string length
 | 
				
			||||||
 | 
					      if (maxBytes > buffer.Length) {
 | 
				
			||||||
 | 
					        buffer = new Byte[maxBytes];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 num = Encoding.UTF8.GetBytes (str, 0, str.Length, buffer, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
 | 
					      // store number of bytes (not number of chars!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Reads header tag:  0 -> Stream with headers or 2 -> Response Stream
 | 
					      buffer [0] = (Byte) num;
 | 
				
			||||||
			// +
 | 
					      buffer [1] = (Byte) (num >> 8);
 | 
				
			||||||
			// Gets the length of the data stream
 | 
					      buffer [2] = (Byte) (num >> 16);
 | 
				
			||||||
			StreamRead (networkStream, buffer, 8);
 | 
					      buffer [3] = (Byte) (num >> 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int byteCount = (buffer [4] | (buffer [5] << 8) |
 | 
					      // Write the string bytes
 | 
				
			||||||
				(buffer [6] << 16) | (buffer [7] << 24));
 | 
					      networkStream.Write (buffer, 0, num + 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Reads the headers
 | 
					    private static String ReceiveString (Stream networkStream, Byte[] buffer)
 | 
				
			||||||
			headers = ReceiveHeaders (networkStream, buffer);
 | 
					    {
 | 
				
			||||||
 | 
					      _ = StreamRead(networkStream, buffer, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Reads the number of bytes (not chars!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 byteCount = buffer [0] | (buffer [1] << 8) |
 | 
				
			||||||
 | 
					        (buffer [2] << 16) | (buffer [3] << 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			byte[] resultBuffer = new byte[byteCount];
 | 
					      if (byteCount == 0) {
 | 
				
			||||||
			StreamRead (networkStream, resultBuffer, byteCount);
 | 
					        return String.Empty;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
			return new MemoryStream (resultBuffer);
 | 
					
 | 
				
			||||||
		}		
 | 
					      // Allocates a buffer of the correct size. Use the
 | 
				
			||||||
 | 
					      // internal buffer if it is big enough
 | 
				
			||||||
		private static void SendString (Stream networkStream, string str, byte[] buffer)
 | 
					
 | 
				
			||||||
		{
 | 
					      if (byteCount > buffer.Length) {
 | 
				
			||||||
			// Allocates a buffer. Use the internal buffer if it is 
 | 
					        buffer = new Byte[byteCount];
 | 
				
			||||||
			// big enough. If not, create a new one.
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int maxBytes = Encoding.UTF8.GetMaxByteCount(str.Length)+4;	//+4 bytes for storing the string length
 | 
					      // Reads the string
 | 
				
			||||||
			if (maxBytes > buffer.Length)
 | 
					
 | 
				
			||||||
				buffer = new byte[maxBytes];
 | 
					      _ = StreamRead(networkStream, buffer, byteCount);
 | 
				
			||||||
 | 
					      Char[] chars = Encoding.UTF8.GetChars (buffer, 0, byteCount);
 | 
				
			||||||
			int num = Encoding.UTF8.GetBytes (str, 0, str.Length, buffer, 4);
 | 
					  
 | 
				
			||||||
 | 
					      return new String(chars);
 | 
				
			||||||
			// store number of bytes (not number of chars!)
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
			buffer [0] = (byte) num;
 | 
					  }
 | 
				
			||||||
			buffer [1] = (byte) (num >> 8);
 | 
					 | 
				
			||||||
			buffer [2] = (byte) (num >> 16);
 | 
					 | 
				
			||||||
			buffer [3] = (byte) (num >> 24);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Write the string bytes
 | 
					 | 
				
			||||||
			networkStream.Write (buffer, 0, num + 4);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private static string ReceiveString (Stream networkStream, byte[] buffer)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			StreamRead (networkStream, buffer, 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Reads the number of bytes (not chars!)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			int byteCount = (buffer [0] | (buffer [1] << 8) |
 | 
					 | 
				
			||||||
				(buffer [2] << 16) | (buffer [3] << 24));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (byteCount == 0) return string.Empty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Allocates a buffer of the correct size. Use the
 | 
					 | 
				
			||||||
			// internal buffer if it is big enough
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (byteCount > buffer.Length)
 | 
					 | 
				
			||||||
				buffer = new byte[byteCount];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Reads the string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			StreamRead (networkStream, buffer, byteCount);
 | 
					 | 
				
			||||||
			char[] chars = Encoding.UTF8.GetChars (buffer, 0, byteCount);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			return new string (chars);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -42,18 +42,18 @@ using Mono.Unix;
 | 
				
			|||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class UnixServerChannel : IChannelReceiver, IChannel
 | 
					    public class UnixServerChannel : IChannelReceiver, IChannel
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        string path = null;
 | 
					    String path = null;
 | 
				
			||||||
        string name = "unix";
 | 
					    String name = "unix";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int priority = 1;
 | 
					    Int32 priority = 1;
 | 
				
			||||||
        bool supressChannelData = false;
 | 
					    Boolean supressChannelData = false;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Thread server_thread = null;
 | 
					        Thread server_thread = null;
 | 
				
			||||||
        UnixListener listener;
 | 
					        UnixListener listener;
 | 
				
			||||||
        UnixServerTransportSink sink;
 | 
					        UnixServerTransportSink sink;
 | 
				
			||||||
        ChannelDataStore channel_data;
 | 
					        ChannelDataStore channel_data;
 | 
				
			||||||
        int _maxConcurrentConnections = 100;
 | 
					    Int32 _maxConcurrentConnections = 100;
 | 
				
			||||||
        ArrayList _activeConnections = new ArrayList();
 | 
					        ArrayList _activeConnections = new ArrayList();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -62,30 +62,30 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
            if (serverSinkProvider == null) 
 | 
					            if (serverSinkProvider == null) 
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                serverSinkProvider = new UnixBinaryServerFormatterSinkProvider ();
 | 
					                serverSinkProvider = new UnixBinaryServerFormatterSinkProvider ();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            // Gets channel data from the chain of channel providers
 | 
					      // Gets channel data from the chain of channel providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            channel_data = new ChannelDataStore (null);
 | 
					      this.channel_data = new ChannelDataStore (null);
 | 
				
			||||||
            IServerChannelSinkProvider provider = serverSinkProvider;
 | 
					            IServerChannelSinkProvider provider = serverSinkProvider;
 | 
				
			||||||
            while (provider != null)
 | 
					            while (provider != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                provider.GetChannelData(channel_data);
 | 
					                provider.GetChannelData(this.channel_data);
 | 
				
			||||||
                provider = provider.Next;
 | 
					                provider = provider.Next;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Creates the sink chain that will process all incoming messages
 | 
					            // Creates the sink chain that will process all incoming messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
 | 
					            IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
 | 
				
			||||||
            sink = new UnixServerTransportSink (next_sink);
 | 
					      this.sink = new UnixServerTransportSink (next_sink);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            StartListening (null);
 | 
					      this.StartListening (null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public UnixServerChannel (string path)
 | 
					        public UnixServerChannel (String path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.path = path;
 | 
					            this.path = path;
 | 
				
			||||||
            Init (null);
 | 
					      this.Init (null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnixServerChannel (IDictionary properties,
 | 
					        public UnixServerChannel (IDictionary properties,
 | 
				
			||||||
@ -93,90 +93,80 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            foreach(DictionaryEntry property in properties)
 | 
					            foreach(DictionaryEntry property in properties)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch((string)property.Key)
 | 
					                switch((String)property.Key)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                case "path":
 | 
					                case "path":
 | 
				
			||||||
                    path = property.Value as string;
 | 
					            this.path = property.Value as String;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case "priority":
 | 
					                case "priority":
 | 
				
			||||||
                    priority = Convert.ToInt32(property.Value);
 | 
					            this.priority = Convert.ToInt32(property.Value);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case "supressChannelData":
 | 
					                case "supressChannelData":
 | 
				
			||||||
                    supressChannelData = Convert.ToBoolean (property.Value);
 | 
					            this.supressChannelData = Convert.ToBoolean (property.Value);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }            
 | 
					            }
 | 
				
			||||||
            Init (serverSinkProvider);
 | 
					      this.Init (serverSinkProvider);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnixServerChannel (string name, string path,
 | 
					        public UnixServerChannel (String name, String path,
 | 
				
			||||||
                                  IServerChannelSinkProvider serverSinkProvider)
 | 
					                                  IServerChannelSinkProvider serverSinkProvider)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.name = name;
 | 
					            this.name = name;
 | 
				
			||||||
            this.path = path;
 | 
					            this.path = path;
 | 
				
			||||||
            Init (serverSinkProvider);
 | 
					      this.Init (serverSinkProvider);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public UnixServerChannel (string name, string path)
 | 
					        public UnixServerChannel (String name, String path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.name = name;
 | 
					            this.name = name;
 | 
				
			||||||
            this.path = path;
 | 
					            this.path = path;
 | 
				
			||||||
            Init (null);
 | 
					      this.Init (null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public object ChannelData
 | 
					        public Object ChannelData
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (supressChannelData) return null;
 | 
					                if (this.supressChannelData) {
 | 
				
			||||||
                else return channel_data;
 | 
					          return null;
 | 
				
			||||||
            }
 | 
					        } else {
 | 
				
			||||||
        }
 | 
					          return this.channel_data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        public string ChannelName
 | 
					      }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String ChannelName => this.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int32 ChannelPriority => this.priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String GetChannelUri() => "unix://" + this.path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String[] GetUrlsForUri (String uri)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get {
 | 
					            if (!uri.StartsWith ("/")) {
 | 
				
			||||||
                return name;
 | 
					        uri = "/" + uri;
 | 
				
			||||||
            }
 | 
					      }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					      String[] chnl_uris = this.channel_data.ChannelUris;
 | 
				
			||||||
 | 
					      String[] result = new String [chnl_uris.Length];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int ChannelPriority
 | 
					            for (Int32 i = 0; i < chnl_uris.Length; i++) {
 | 
				
			||||||
        {
 | 
					        result [i] = chnl_uris [i] + "?" + uri;
 | 
				
			||||||
            get {
 | 
					      }
 | 
				
			||||||
                return priority;
 | 
					
 | 
				
			||||||
            }
 | 
					      return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string GetChannelUri ()
 | 
					    public String Parse(String url, out String objectURI) => UnixChannel.ParseUnixURL(url, out objectURI);
 | 
				
			||||||
        {
 | 
					
 | 
				
			||||||
            return "unix://" + path;
 | 
					    void WaitForConnections ()
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        public string[] GetUrlsForUri (string uri)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (!uri.StartsWith ("/")) uri = "/" + uri;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            string [] chnl_uris = channel_data.ChannelUris;
 | 
					 | 
				
			||||||
            string [] result = new String [chnl_uris.Length];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (int i = 0; i < chnl_uris.Length; i++) 
 | 
					 | 
				
			||||||
                result [i] = chnl_uris [i] + "?" + uri;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            return result;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public string Parse (string url, out string objectURI)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return UnixChannel.ParseUnixURL (url, out objectURI);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void WaitForConnections ()
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                while (true) 
 | 
					                while (true) 
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Socket client = listener.AcceptSocket ();
 | 
					                    Socket client = this.listener.AcceptSocket ();
 | 
				
			||||||
                    CreateListenerConnection (client);
 | 
					          this.CreateListenerConnection (client);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch
 | 
					            catch
 | 
				
			||||||
@ -185,71 +175,77 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        internal void CreateListenerConnection (Socket client)
 | 
					        internal void CreateListenerConnection (Socket client)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            lock (_activeConnections)
 | 
					            lock (this._activeConnections)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (_activeConnections.Count >= _maxConcurrentConnections)
 | 
					                    if (this._activeConnections.Count >= this._maxConcurrentConnections) {
 | 
				
			||||||
                        Monitor.Wait (_activeConnections);
 | 
					          _ = Monitor.Wait(this._activeConnections);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
                    if (server_thread == null) return;    // Server was stopped while waiting
 | 
					
 | 
				
			||||||
 | 
					        if (this.server_thread == null) {
 | 
				
			||||||
                    ClientConnection reader = new ClientConnection (this, client, sink);
 | 
					          return;    // Server was stopped while waiting
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ClientConnection reader = new ClientConnection (this, client, this.sink);
 | 
				
			||||||
                    Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
 | 
					                    Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
 | 
				
			||||||
                    thread.Start();
 | 
					                    thread.Start();
 | 
				
			||||||
                    thread.IsBackground = true;
 | 
					                    thread.IsBackground = true;
 | 
				
			||||||
                    _activeConnections.Add (thread);
 | 
					        _ = this._activeConnections.Add(thread);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal void ReleaseConnection (Thread thread)
 | 
					        internal void ReleaseConnection (Thread thread)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            lock (_activeConnections)
 | 
					            lock (this._activeConnections)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _activeConnections.Remove (thread);
 | 
					        this._activeConnections.Remove (thread);
 | 
				
			||||||
                    Monitor.Pulse (_activeConnections);
 | 
					                    Monitor.Pulse (this._activeConnections);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public void StartListening (object data)
 | 
					        public void StartListening (Object data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            listener = new UnixListener (path);
 | 
					      this.listener = new UnixListener (this.path);
 | 
				
			||||||
            Mono.Unix.Native.Syscall.chmod (path,
 | 
					      _ = Mono.Unix.Native.Syscall.chmod(this.path,
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IRUSR |
 | 
					                               Mono.Unix.Native.FilePermissions.S_IRUSR |
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IWUSR |
 | 
					                               Mono.Unix.Native.FilePermissions.S_IWUSR |
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IRGRP |
 | 
					                               Mono.Unix.Native.FilePermissions.S_IRGRP |
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IWGRP |
 | 
					                               Mono.Unix.Native.FilePermissions.S_IWGRP |
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IROTH |
 | 
					                               Mono.Unix.Native.FilePermissions.S_IROTH |
 | 
				
			||||||
                                     Mono.Unix.Native.FilePermissions.S_IWOTH);
 | 
					                               Mono.Unix.Native.FilePermissions.S_IWOTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (server_thread == null) 
 | 
					            if (this.server_thread == null) 
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                listener.Start ();
 | 
					        this.listener.Start ();
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                string[] uris = new String [1];
 | 
					        String[] uris = new String [1];
 | 
				
			||||||
                uris = new String [1];
 | 
					                uris = new String [1];
 | 
				
			||||||
                uris [0] = GetChannelUri ();
 | 
					                uris [0] = this.GetChannelUri ();
 | 
				
			||||||
                channel_data.ChannelUris = uris;
 | 
					        this.channel_data.ChannelUris = uris;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                server_thread = new Thread (new ThreadStart (WaitForConnections));
 | 
					        this.server_thread = new Thread (new ThreadStart (this.WaitForConnections));
 | 
				
			||||||
                server_thread.IsBackground = true;
 | 
					        this.server_thread.IsBackground = true;
 | 
				
			||||||
                server_thread.Start ();
 | 
					        this.server_thread.Start ();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void StopListening (object data)
 | 
					        public void StopListening (Object data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (server_thread == null) return;
 | 
					            if (this.server_thread == null) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      lock (this._activeConnections)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					        this.server_thread.Abort ();
 | 
				
			||||||
 | 
					        this.server_thread = null;
 | 
				
			||||||
 | 
					        this.listener.Stop ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lock (_activeConnections)
 | 
					                    foreach (Thread thread in this._activeConnections) {
 | 
				
			||||||
                {
 | 
					          thread.Abort();
 | 
				
			||||||
                    server_thread.Abort ();
 | 
					        }
 | 
				
			||||||
                    server_thread = null;
 | 
					
 | 
				
			||||||
                    listener.Stop ();
 | 
					        this._activeConnections.Clear();
 | 
				
			||||||
 | 
					                    Monitor.PulseAll (this._activeConnections);
 | 
				
			||||||
                    foreach (Thread thread in _activeConnections)
 | 
					 | 
				
			||||||
                        thread.Abort();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    _activeConnections.Clear();
 | 
					 | 
				
			||||||
                    Monitor.PulseAll (_activeConnections);
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -259,48 +255,43 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
        Socket _client;
 | 
					        Socket _client;
 | 
				
			||||||
        UnixServerTransportSink _sink;
 | 
					        UnixServerTransportSink _sink;
 | 
				
			||||||
        Stream _stream;
 | 
					        Stream _stream;
 | 
				
			||||||
        UnixServerChannel _serverChannel;
 | 
					        UnixServerChannel _serverChannel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byte[] _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
 | 
					    Byte[] _buffer = new Byte[UnixMessageIO.DefaultStreamBufferSize];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ClientConnection (UnixServerChannel serverChannel, Socket client, UnixServerTransportSink sink)
 | 
					        public ClientConnection (UnixServerChannel serverChannel, Socket client, UnixServerTransportSink sink)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _serverChannel = serverChannel;
 | 
					      this._serverChannel = serverChannel;
 | 
				
			||||||
            _client = client;
 | 
					      this._client = client;
 | 
				
			||||||
            _sink = sink;
 | 
					      this._sink = sink;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Socket Client {
 | 
					    public Socket Client => this._client;
 | 
				
			||||||
            get { return _client; }
 | 
					
 | 
				
			||||||
        }
 | 
					    public Byte[] Buffer => this._buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public byte[] Buffer
 | 
					    public void ProcessMessages()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return _buffer; }
 | 
					      Byte[] buffer = new Byte[256];
 | 
				
			||||||
        }
 | 
					      this._stream = new BufferedStream (new NetworkStream (this._client));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        public void ProcessMessages()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
			byte[] buffer = new byte[256];
 | 
					 | 
				
			||||||
            _stream = new BufferedStream (new NetworkStream (_client));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                bool end = false;
 | 
					        Boolean end = false;
 | 
				
			||||||
                while (!end)
 | 
					                while (!end)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    MessageStatus type = UnixMessageIO.ReceiveMessageStatus (_stream, buffer);
 | 
					                    MessageStatus type = UnixMessageIO.ReceiveMessageStatus (this._stream, buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    switch (type)
 | 
					                    switch (type)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
						case MessageStatus.MethodMessage:
 | 
					            case MessageStatus.MethodMessage:
 | 
				
			||||||
							_sink.InternalProcessMessage (this, _stream);
 | 
					              this._sink.InternalProcessMessage (this, this._stream);
 | 
				
			||||||
							break;
 | 
					              break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						case MessageStatus.Unknown:
 | 
					            case MessageStatus.Unknown:
 | 
				
			||||||
						case MessageStatus.CancelSignal:
 | 
					            case MessageStatus.CancelSignal:
 | 
				
			||||||
							end = true;
 | 
					              end = true;
 | 
				
			||||||
							break;
 | 
					              break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -310,21 +301,15 @@ namespace Mono.Remoting.Channels.Unix
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
				try {
 | 
					        try {
 | 
				
			||||||
	                _serverChannel.ReleaseConnection (Thread.CurrentThread);
 | 
					          this._serverChannel.ReleaseConnection (Thread.CurrentThread);
 | 
				
			||||||
	                _stream.Close();
 | 
					          this._stream.Close();
 | 
				
			||||||
					_client.Close ();
 | 
					          this._client.Close ();
 | 
				
			||||||
				} catch {
 | 
					        } catch {
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        public bool IsLocal
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return true;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
 | 
					    public Boolean IsLocal => true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -35,102 +35,80 @@ using System.Runtime.Remoting.Messaging;
 | 
				
			|||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Runtime.Remoting.Channels;
 | 
					using System.Runtime.Remoting.Channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Remoting.Channels.Unix
 | 
					namespace Mono.Remoting.Channels.Unix {
 | 
				
			||||||
{
 | 
					  internal class UnixServerTransportSink : IServerChannelSink, IChannelSinkBase {
 | 
				
			||||||
    internal class UnixServerTransportSink : IServerChannelSink, IChannelSinkBase
 | 
					    IServerChannelSink next_sink;
 | 
				
			||||||
    {
 | 
					
 | 
				
			||||||
        IServerChannelSink next_sink;
 | 
					    public UnixServerTransportSink(IServerChannelSink next) => this.next_sink = next;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        public UnixServerTransportSink (IServerChannelSink next)
 | 
					    public IServerChannelSink NextChannelSink => this.next_sink;
 | 
				
			||||||
        {
 | 
					
 | 
				
			||||||
            next_sink = next;
 | 
					    public IDictionary Properties {
 | 
				
			||||||
        }
 | 
					      get {
 | 
				
			||||||
        
 | 
					        if(this.next_sink != null) {
 | 
				
			||||||
        public IServerChannelSink NextChannelSink 
 | 
					          return this.next_sink.Properties;
 | 
				
			||||||
        {
 | 
					        } else {
 | 
				
			||||||
            get 
 | 
					          return null;
 | 
				
			||||||
            {
 | 
					        }
 | 
				
			||||||
                return next_sink;
 | 
					      }
 | 
				
			||||||
            }
 | 
					    }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					    public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state,
 | 
				
			||||||
        public IDictionary Properties 
 | 
					                                      IMessage msg, ITransportHeaders headers, Stream responseStream) {
 | 
				
			||||||
        {
 | 
					      ClientConnection connection = (ClientConnection)state;
 | 
				
			||||||
            get 
 | 
					      NetworkStream stream = new NetworkStream(connection.Client);
 | 
				
			||||||
            {
 | 
					      UnixMessageIO.SendMessageStream(stream, responseStream, headers, connection.Buffer);
 | 
				
			||||||
                if (next_sink != null) return next_sink.Properties;
 | 
					      stream.Flush();
 | 
				
			||||||
                else return null;
 | 
					      stream.Close();
 | 
				
			||||||
            }
 | 
					    }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					    public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state,
 | 
				
			||||||
        public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
 | 
					                                     IMessage msg, ITransportHeaders headers) => null;
 | 
				
			||||||
                                          IMessage msg, ITransportHeaders headers, Stream responseStream)
 | 
					
 | 
				
			||||||
        {
 | 
					    public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
 | 
				
			||||||
            ClientConnection connection = (ClientConnection)state;
 | 
					                                            IMessage requestMsg,
 | 
				
			||||||
            NetworkStream stream = new NetworkStream (connection.Client);
 | 
					                                            ITransportHeaders requestHeaders,
 | 
				
			||||||
            UnixMessageIO.SendMessageStream (stream, responseStream, headers, connection.Buffer);
 | 
					                                            Stream requestStream,
 | 
				
			||||||
            stream.Flush ();
 | 
					                                            out IMessage responseMsg,
 | 
				
			||||||
            stream.Close ();
 | 
					                                            out ITransportHeaders responseHeaders,
 | 
				
			||||||
        }
 | 
					                                            out Stream responseStream) =>
 | 
				
			||||||
 | 
					        // this is the first sink, and UnixServerChannel does not call it.
 | 
				
			||||||
        public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
 | 
					        throw new NotSupportedException();
 | 
				
			||||||
                                         IMessage msg, ITransportHeaders headers)
 | 
					
 | 
				
			||||||
        {
 | 
					    internal void InternalProcessMessage(ClientConnection connection, Stream stream) {
 | 
				
			||||||
            return null;
 | 
					      // Reads the headers and the request stream
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
        
 | 
					      Stream requestStream;
 | 
				
			||||||
        public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
 | 
					
 | 
				
			||||||
                                                IMessage requestMsg,
 | 
					      requestStream = UnixMessageIO.ReceiveMessageStream(stream, out ITransportHeaders requestHeaders, connection.Buffer);
 | 
				
			||||||
                                                ITransportHeaders requestHeaders,
 | 
					
 | 
				
			||||||
                                                Stream requestStream,
 | 
					      /*            try {
 | 
				
			||||||
                                                out IMessage responseMsg,
 | 
					                      PeerCred cred = connection.Client.PeerCredential;
 | 
				
			||||||
                                                out ITransportHeaders responseHeaders,
 | 
					                      requestHeaders["__uid"] = cred.UserID;
 | 
				
			||||||
                                                out Stream responseStream)
 | 
					                  } catch (Exception e) {
 | 
				
			||||||
        {
 | 
					                      Console.WriteLine ("Couldn't get the peer cred: " + e);
 | 
				
			||||||
            // this is the first sink, and UnixServerChannel does not call it.
 | 
					                  }
 | 
				
			||||||
            throw new NotSupportedException ();
 | 
					      */
 | 
				
			||||||
        }
 | 
					      // Pushes the connection object together with the sink. This information
 | 
				
			||||||
 | 
					      // will be used for sending the response in an async call.
 | 
				
			||||||
        internal void InternalProcessMessage (ClientConnection connection, Stream stream)
 | 
					
 | 
				
			||||||
        {
 | 
					      ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
 | 
				
			||||||
            // Reads the headers and the request stream
 | 
					      sinkStack.Push(this, connection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Stream requestStream;
 | 
					
 | 
				
			||||||
            ITransportHeaders requestHeaders;
 | 
					      ServerProcessing proc = this.next_sink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            requestStream = UnixMessageIO.ReceiveMessageStream (stream, out requestHeaders, connection.Buffer);
 | 
					      switch(proc) {
 | 
				
			||||||
 | 
					        case ServerProcessing.Complete:
 | 
				
			||||||
/*            try {
 | 
					          UnixMessageIO.SendMessageStream(stream, responseStream, responseHeaders, connection.Buffer);
 | 
				
			||||||
                PeerCred cred = connection.Client.PeerCredential;
 | 
					          stream.Flush();
 | 
				
			||||||
                requestHeaders["__uid"] = cred.UserID;
 | 
					          break;
 | 
				
			||||||
            } catch (Exception e) {
 | 
					
 | 
				
			||||||
                Console.WriteLine ("Couldn't get the peer cred: " + e);
 | 
					        case ServerProcessing.Async:
 | 
				
			||||||
            }
 | 
					        case ServerProcessing.OneWay:
 | 
				
			||||||
*/
 | 
					          break;
 | 
				
			||||||
            // Pushes the connection object together with the sink. This information
 | 
					      }
 | 
				
			||||||
            // will be used for sending the response in an async call.
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
            ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
 | 
					 | 
				
			||||||
            sinkStack.Push(this, connection);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ITransportHeaders responseHeaders;
 | 
					 | 
				
			||||||
            Stream responseStream;
 | 
					 | 
				
			||||||
            IMessage responseMsg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ServerProcessing proc = next_sink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            switch (proc)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            case ServerProcessing.Complete:
 | 
					 | 
				
			||||||
                UnixMessageIO.SendMessageStream (stream, responseStream, responseHeaders, connection.Buffer);
 | 
					 | 
				
			||||||
                stream.Flush ();
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case ServerProcessing.Async:
 | 
					 | 
				
			||||||
            case ServerProcessing.OneWay:
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -35,154 +35,158 @@ using System.Text;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix.Native {
 | 
					namespace Mono.Unix.Native {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This class represents a single unmanaged function with "cdecl" calling
 | 
					  // This class represents a single unmanaged function with "cdecl" calling
 | 
				
			||||||
	// convention -- that is, it can accept a variable number of arguments which
 | 
					  // convention -- that is, it can accept a variable number of arguments which
 | 
				
			||||||
	// are passed on the runtime stack.
 | 
					  // are passed on the runtime stack.
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// To use, create an instance:
 | 
					  // To use, create an instance:
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	//    CdeclFunction printf = new CdeclFunction ("the library", 
 | 
					  //    CdeclFunction printf = new CdeclFunction ("the library", 
 | 
				
			||||||
	//        "the function name", /* optional */ typeof (ReturnType));
 | 
					  //        "the function name", /* optional */ typeof (ReturnType));
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// Then call the Invoke method with the appropriate number of arguments:
 | 
					  // Then call the Invoke method with the appropriate number of arguments:
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	//    printf.Invoke (new object[]{"hello, %s\n", "world!"});
 | 
					  //    printf.Invoke (new object[]{"hello, %s\n", "world!"});
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// In the background a P/Invoke definition for the method with the
 | 
					  // In the background a P/Invoke definition for the method with the
 | 
				
			||||||
	// requested argument types will be generated and invoked, invoking the
 | 
					  // requested argument types will be generated and invoked, invoking the
 | 
				
			||||||
	// unmanaged function.  The generated methods are cached, so that subsequent
 | 
					  // unmanaged function.  The generated methods are cached, so that subsequent
 | 
				
			||||||
	// calls with the same argument list do not generate new code, speeding up
 | 
					  // calls with the same argument list do not generate new code, speeding up
 | 
				
			||||||
	// the call sequence.
 | 
					  // the call sequence.
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// Invoking Cdecl functions is not guaranteed to be portable across all 
 | 
					  // Invoking Cdecl functions is not guaranteed to be portable across all 
 | 
				
			||||||
	// platforms.  For example, AMD64 requires that the caller set EAX to the 
 | 
					  // platforms.  For example, AMD64 requires that the caller set EAX to the 
 | 
				
			||||||
	// number of floating point arguments passed in the SSE registers.  This 
 | 
					  // number of floating point arguments passed in the SSE registers.  This 
 | 
				
			||||||
	// is only required for variable argument/cdecl functions; consequently, 
 | 
					  // is only required for variable argument/cdecl functions; consequently, 
 | 
				
			||||||
	// the overload technique used by this class wouldn't normally work.  
 | 
					  // the overload technique used by this class wouldn't normally work.  
 | 
				
			||||||
	// Mono's AMD64 JIT works around this by always setting EAX on P/Invoke
 | 
					  // Mono's AMD64 JIT works around this by always setting EAX on P/Invoke
 | 
				
			||||||
	// invocations, allowing CdeclFunction to work properly, but it will not
 | 
					  // invocations, allowing CdeclFunction to work properly, but it will not
 | 
				
			||||||
	// necessarily always work.  See also: 
 | 
					  // necessarily always work.  See also: 
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	//     http://lwn.net/Articles/5201/?format=printable
 | 
					  //     http://lwn.net/Articles/5201/?format=printable
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// Due to potential portability issues, cdecl functions should be avoided 
 | 
					  // Due to potential portability issues, cdecl functions should be avoided 
 | 
				
			||||||
	// on most platforms.
 | 
					  // on most platforms.
 | 
				
			||||||
	//
 | 
					  //
 | 
				
			||||||
	// This class is intended to be thread-safe.
 | 
					  // This class is intended to be thread-safe.
 | 
				
			||||||
	public sealed class CdeclFunction
 | 
					  public sealed class CdeclFunction
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		// The readonly fields (1) shouldn't be modified, and (2) should only be
 | 
					    // The readonly fields (1) shouldn't be modified, and (2) should only be
 | 
				
			||||||
		// used when `overloads' is locked.
 | 
					    // used when `overloads' is locked.
 | 
				
			||||||
		private readonly string library;
 | 
					    private readonly String library;
 | 
				
			||||||
		private readonly string method;
 | 
					    private readonly String method;
 | 
				
			||||||
		private readonly Type returnType;
 | 
					    private readonly Type returnType;
 | 
				
			||||||
		private readonly AssemblyName assemblyName;
 | 
					    private readonly AssemblyName assemblyName;
 | 
				
			||||||
		private readonly AssemblyBuilder assemblyBuilder;
 | 
					    private readonly AssemblyBuilder assemblyBuilder;
 | 
				
			||||||
		private readonly ModuleBuilder moduleBuilder;
 | 
					    private readonly ModuleBuilder moduleBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private Hashtable overloads;
 | 
					    private readonly Hashtable overloads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public CdeclFunction (string library, string method)
 | 
					    public CdeclFunction (String library, String method)
 | 
				
			||||||
			: this (library, method, typeof(void))
 | 
					      : this (library, method, typeof(void))
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public CdeclFunction (string library, string method, Type returnType)
 | 
					    public CdeclFunction (String library, String method, Type returnType)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.library = library;
 | 
					      this.library = library;
 | 
				
			||||||
			this.method = method;
 | 
					      this.method = method;
 | 
				
			||||||
			this.returnType = returnType;
 | 
					      this.returnType = returnType;
 | 
				
			||||||
			this.overloads = new Hashtable ();
 | 
					      this.overloads = new Hashtable ();
 | 
				
			||||||
			this.assemblyName = new AssemblyName ();
 | 
					      this.assemblyName = new AssemblyName {
 | 
				
			||||||
			this.assemblyName.Name = "Mono.Posix.Imports." + library;
 | 
					        Name = "Mono.Posix.Imports." + library
 | 
				
			||||||
			this.assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
 | 
					      };
 | 
				
			||||||
					assemblyName, AssemblyBuilderAccess.Run);
 | 
					      this.assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
 | 
				
			||||||
			this.moduleBuilder = assemblyBuilder.DefineDynamicModule (assemblyName.Name);
 | 
					          this.assemblyName, AssemblyBuilderAccess.Run);
 | 
				
			||||||
		}
 | 
					      this.moduleBuilder = this.assemblyBuilder.DefineDynamicModule (this.assemblyName.Name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public object Invoke (object[] parameters)
 | 
					    public Object Invoke (Object[] parameters)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Type[] parameterTypes = GetParameterTypes (parameters);
 | 
					      Type[] parameterTypes = GetParameterTypes (parameters);
 | 
				
			||||||
			MethodInfo m = CreateMethod (parameterTypes);
 | 
					      MethodInfo m = this.CreateMethod (parameterTypes);
 | 
				
			||||||
			return m.Invoke (null, parameters);
 | 
					      return m.Invoke (null, parameters);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private MethodInfo CreateMethod (Type[] parameterTypes)
 | 
					    private MethodInfo CreateMethod (Type[] parameterTypes)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			string typeName = GetTypeName (parameterTypes);
 | 
					      String typeName = this.GetTypeName (parameterTypes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			lock (overloads) {
 | 
					      lock (this.overloads) {
 | 
				
			||||||
				MethodInfo mi = (MethodInfo) overloads [typeName];
 | 
					        MethodInfo mi = (MethodInfo)this.overloads [typeName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (mi != null) {
 | 
					        if (mi != null) {
 | 
				
			||||||
					return mi;
 | 
					          return mi;
 | 
				
			||||||
				}
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				TypeBuilder tb = CreateType (typeName);
 | 
					        TypeBuilder tb = this.CreateType (typeName);
 | 
				
			||||||
				/* MethodBuilder mb = */ tb.DefinePInvokeMethod (
 | 
					        /* MethodBuilder mb = */
 | 
				
			||||||
						method, 
 | 
					        _ = tb.DefinePInvokeMethod(
 | 
				
			||||||
						library, 
 | 
					          this.method,
 | 
				
			||||||
						MethodAttributes.PinvokeImpl | MethodAttributes.Static | MethodAttributes.Public,
 | 
					          this.library,
 | 
				
			||||||
						CallingConventions.Standard, 
 | 
					          MethodAttributes.PinvokeImpl | MethodAttributes.Static | MethodAttributes.Public,
 | 
				
			||||||
						returnType, 
 | 
					          CallingConventions.Standard,
 | 
				
			||||||
						parameterTypes, 
 | 
					          this.returnType,
 | 
				
			||||||
						CallingConvention.Cdecl,
 | 
					          parameterTypes,
 | 
				
			||||||
						CharSet.Ansi);
 | 
					          CallingConvention.Cdecl,
 | 
				
			||||||
				mi = tb.CreateType ().GetMethod (method);
 | 
					          CharSet.Ansi);
 | 
				
			||||||
				overloads.Add (typeName, mi);
 | 
					        mi = tb.CreateType ().GetMethod (this.method);
 | 
				
			||||||
				return mi;
 | 
					        this.overloads.Add (typeName, mi);
 | 
				
			||||||
			}
 | 
					        return mi;
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private TypeBuilder CreateType(String typeName) => this.moduleBuilder.DefineType(typeName, TypeAttributes.Public);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Type GetMarshalType (Type t)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      switch (Type.GetTypeCode (t)) {
 | 
				
			||||||
 | 
					        // types < sizeof(int) are marshaled as ints
 | 
				
			||||||
 | 
					        case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: 
 | 
				
			||||||
 | 
					        case TypeCode.Int16: case TypeCode.Int32: 
 | 
				
			||||||
 | 
					          return typeof(Int32);
 | 
				
			||||||
 | 
					        case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32:
 | 
				
			||||||
 | 
					          return typeof(UInt32);
 | 
				
			||||||
 | 
					        case TypeCode.Int64:
 | 
				
			||||||
 | 
					          return typeof(Int64);
 | 
				
			||||||
 | 
					        case TypeCode.UInt64:
 | 
				
			||||||
 | 
					          return typeof(UInt64);
 | 
				
			||||||
 | 
					        case TypeCode.Single: case TypeCode.Double:
 | 
				
			||||||
 | 
					          return typeof(Double);
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          return t;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private TypeBuilder CreateType (string typeName)
 | 
					    private String GetTypeName (Type[] parameterTypes)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			return moduleBuilder.DefineType (typeName, TypeAttributes.Public);
 | 
					      StringBuilder sb = new StringBuilder ();
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      _ = sb.Append("[").Append(this.library).Append("] ").Append(this.method);
 | 
				
			||||||
 | 
					      _ = sb.Append("(");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static Type GetMarshalType (Type t)
 | 
					      if (parameterTypes.Length > 0) {
 | 
				
			||||||
		{
 | 
					        _ = sb.Append(parameterTypes[0]);
 | 
				
			||||||
			switch (Type.GetTypeCode (t)) {
 | 
					      }
 | 
				
			||||||
				// types < sizeof(int) are marshaled as ints
 | 
					
 | 
				
			||||||
				case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: 
 | 
					      for (Int32 i = 1; i < parameterTypes.Length; ++i) {
 | 
				
			||||||
				case TypeCode.Int16: case TypeCode.Int32: 
 | 
					        _ = sb.Append(",").Append(parameterTypes[i]);
 | 
				
			||||||
					return typeof(int);
 | 
					      }
 | 
				
			||||||
				case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32:
 | 
					
 | 
				
			||||||
					return typeof(uint);
 | 
					      _ = sb.Append(") : ").Append(this.returnType.FullName);
 | 
				
			||||||
				case TypeCode.Int64:
 | 
					 | 
				
			||||||
					return typeof(long);
 | 
					 | 
				
			||||||
				case TypeCode.UInt64:
 | 
					 | 
				
			||||||
					return typeof(ulong);
 | 
					 | 
				
			||||||
				case TypeCode.Single: case TypeCode.Double:
 | 
					 | 
				
			||||||
					return typeof(double);
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					return t;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private string GetTypeName (Type[] parameterTypes)
 | 
					      return sb.ToString ();
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
			StringBuilder sb = new StringBuilder ();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sb.Append ("[").Append (library).Append ("] ").Append (method);
 | 
					    private static Type[] GetParameterTypes (Object[] parameters)
 | 
				
			||||||
			sb.Append ("(");
 | 
					    {
 | 
				
			||||||
 | 
					      Type[] parameterTypes = new Type [parameters.Length];
 | 
				
			||||||
			if (parameterTypes.Length > 0)
 | 
					      for (Int32 i = 0; i < parameters.Length; ++i) {
 | 
				
			||||||
				sb.Append (parameterTypes [0]);
 | 
					        parameterTypes [i] = GetMarshalType (parameters [i].GetType ());
 | 
				
			||||||
			for (int i = 1; i < parameterTypes.Length; ++i)
 | 
					      }
 | 
				
			||||||
				sb.Append (",").Append (parameterTypes [i]);
 | 
					
 | 
				
			||||||
 | 
					      return parameterTypes;
 | 
				
			||||||
			sb.Append (") : ").Append (returnType.FullName);
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
			return sb.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private static Type[] GetParameterTypes (object[] parameters)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Type[] parameterTypes = new Type [parameters.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i < parameters.Length; ++i)
 | 
					 | 
				
			||||||
				parameterTypes [i] = GetMarshalType (parameters [i].GetType ());
 | 
					 | 
				
			||||||
			return parameterTypes;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -32,48 +32,42 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix.Native {
 | 
					namespace Mono.Unix.Native {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class FileNameMarshaler : ICustomMarshaler {
 | 
					  class FileNameMarshaler : ICustomMarshaler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static FileNameMarshaler Instance = new FileNameMarshaler ();
 | 
					    private static readonly FileNameMarshaler Instance = new FileNameMarshaler ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE0060:Nicht verwendete Parameter entfernen", Justification = "<Ausstehend>")]
 | 
				
			||||||
 | 
					    public static ICustomMarshaler GetInstance(String s) => Instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void CleanUpManagedData (Object o)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void CleanUpNativeData(IntPtr pNativeData) =>
 | 
				
			||||||
 | 
					      // Console.WriteLine ("# FileNameMarshaler.CleanUpManagedData ({0:x})", pNativeData);
 | 
				
			||||||
 | 
					      UnixMarshal.FreeHeap(pNativeData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int32 GetNativeDataSize() => IntPtr.Size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IntPtr MarshalManagedToNative (Object obj)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if(!(obj is String s)) {
 | 
				
			||||||
 | 
					        return IntPtr.Zero;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      IntPtr p = UnixMarshal.StringToHeap (s, UnixEncoding.Instance);
 | 
				
			||||||
 | 
					      // Console.WriteLine ("# FileNameMarshaler.MarshalNativeToManaged for `{0}'={1:x}", s, p);
 | 
				
			||||||
 | 
					      return p;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static ICustomMarshaler GetInstance (string s)
 | 
					    public Object MarshalNativeToManaged (IntPtr pNativeData)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			return Instance;
 | 
					      String s = UnixMarshal.PtrToString (pNativeData, UnixEncoding.Instance);
 | 
				
			||||||
		}
 | 
					      // Console.WriteLine ("# FileNameMarshaler.MarshalNativeToManaged ({0:x})=`{1}'",
 | 
				
			||||||
 | 
					      // 		pNativeData, s);
 | 
				
			||||||
		public void CleanUpManagedData (object o)
 | 
					      return s;
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
		}
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void CleanUpNativeData (IntPtr pNativeData)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Console.WriteLine ("# FileNameMarshaler.CleanUpManagedData ({0:x})", pNativeData);
 | 
					 | 
				
			||||||
			UnixMarshal.FreeHeap (pNativeData);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public int GetNativeDataSize ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return IntPtr.Size;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public IntPtr MarshalManagedToNative (object obj)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			string s = obj as string;
 | 
					 | 
				
			||||||
			if (s == null)
 | 
					 | 
				
			||||||
				return IntPtr.Zero;
 | 
					 | 
				
			||||||
			IntPtr p = UnixMarshal.StringToHeap (s, UnixEncoding.Instance);
 | 
					 | 
				
			||||||
			// Console.WriteLine ("# FileNameMarshaler.MarshalNativeToManaged for `{0}'={1:x}", s, p);
 | 
					 | 
				
			||||||
			return p;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public object MarshalNativeToManaged (IntPtr pNativeData)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			string s = UnixMarshal.PtrToString (pNativeData, UnixEncoding.Instance);
 | 
					 | 
				
			||||||
			// Console.WriteLine ("# FileNameMarshaler.MarshalNativeToManaged ({0:x})=`{1}'",
 | 
					 | 
				
			||||||
			// 		pNativeData, s);
 | 
					 | 
				
			||||||
			return s;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -30,31 +30,23 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[AttributeUsage (
 | 
					[AttributeUsage (
 | 
				
			||||||
		AttributeTargets.Class    |
 | 
					    AttributeTargets.Class    |
 | 
				
			||||||
		AttributeTargets.Delegate |
 | 
					    AttributeTargets.Delegate |
 | 
				
			||||||
		AttributeTargets.Enum     |
 | 
					    AttributeTargets.Enum     |
 | 
				
			||||||
		AttributeTargets.Field    |
 | 
					    AttributeTargets.Field    |
 | 
				
			||||||
		AttributeTargets.Struct)]
 | 
					    AttributeTargets.Struct)]
 | 
				
			||||||
internal class MapAttribute : Attribute {
 | 
					internal class MapAttribute : Attribute {
 | 
				
			||||||
	private string nativeType;
 | 
					  public MapAttribute ()
 | 
				
			||||||
	private string suppressFlags;
 | 
					  {
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public MapAttribute ()
 | 
					  public MapAttribute(String nativeType) => this.NativeType = nativeType;
 | 
				
			||||||
	{
 | 
					
 | 
				
			||||||
	}
 | 
					  public String NativeType {
 | 
				
			||||||
 | 
					    get;
 | 
				
			||||||
	public MapAttribute (string nativeType)
 | 
					  }
 | 
				
			||||||
	{
 | 
					
 | 
				
			||||||
		this.nativeType = nativeType;
 | 
					  public String SuppressFlags { get;
 | 
				
			||||||
	}
 | 
					    set; }
 | 
				
			||||||
 | 
					 | 
				
			||||||
	public string NativeType {
 | 
					 | 
				
			||||||
		get {return nativeType;}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public string SuppressFlags {
 | 
					 | 
				
			||||||
		get {return suppressFlags;}
 | 
					 | 
				
			||||||
		set {suppressFlags = value;}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,470 +14,458 @@ using Mono.Unix.Android;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix.Native {
 | 
					namespace Mono.Unix.Native {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[CLSCompliant (false)]
 | 
					  //[CLSCompliant (false)]
 | 
				
			||||||
	public sealed /* static */ partial class NativeConvert
 | 
					  public sealed /* static */ partial class NativeConvert
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		//
 | 
					    //
 | 
				
			||||||
		// Non-generated exports
 | 
					    // Non-generated exports
 | 
				
			||||||
		//
 | 
					    //
 | 
				
			||||||
#if MONODROID
 | 
					#if MONODROID
 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
 | 
				
			||||||
		static extern int HelperFromRealTimeSignum (Int32 offset, out Int32 rval);
 | 
					    static extern int HelperFromRealTimeSignum (Int32 offset, out Int32 rval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static int FromRealTimeSignum (Int32 offset, out Int32 rval)
 | 
					    static int FromRealTimeSignum (Int32 offset, out Int32 rval)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (!AndroidUtils.AreRealTimeSignalsSafe ())
 | 
					      if (!AndroidUtils.AreRealTimeSignalsSafe ())
 | 
				
			||||||
				throw new PlatformNotSupportedException ("Real-time signals are not supported on this Android architecture");
 | 
					        throw new PlatformNotSupportedException ("Real-time signals are not supported on this Android architecture");
 | 
				
			||||||
			return HelperFromRealTimeSignum (offset, out rval);
 | 
					      return HelperFromRealTimeSignum (offset, out rval);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
 | 
				
			||||||
		private static extern int FromRealTimeSignum (Int32 offset, out Int32 rval);
 | 
					    private static extern Int32 FromRealTimeSignum (Int32 offset, out Int32 rval);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		// convert a realtime signal to os signal
 | 
					    // convert a realtime signal to os signal
 | 
				
			||||||
		public static int FromRealTimeSignum (RealTimeSignum sig)
 | 
					    public static Int32 FromRealTimeSignum (RealTimeSignum sig)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int sigNum;
 | 
					      if(FromRealTimeSignum(sig.Offset, out Int32 sigNum) == -1) {
 | 
				
			||||||
			if (FromRealTimeSignum (sig.Offset, out sigNum) == -1)
 | 
					        ThrowArgumentException(sig.Offset);
 | 
				
			||||||
				ThrowArgumentException (sig.Offset);
 | 
					      }
 | 
				
			||||||
			return sigNum;
 | 
					
 | 
				
			||||||
		}
 | 
					      return sigNum;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // convert an offset to an rt signum
 | 
				
			||||||
 | 
					    public static RealTimeSignum ToRealTimeSignum(Int32 offset) => new RealTimeSignum(offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // convert from octal representation.
 | 
				
			||||||
 | 
					    public static FilePermissions FromOctalPermissionString (String value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      UInt32 n = Convert.ToUInt32 (value, 8);
 | 
				
			||||||
 | 
					      return ToFilePermissions (n);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// convert an offset to an rt signum
 | 
					    public static String ToOctalPermissionString (FilePermissions value)
 | 
				
			||||||
		public static RealTimeSignum ToRealTimeSignum (int offset)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      String s = Convert.ToString ((Int32) (value & ~FilePermissions.S_IFMT), 8);
 | 
				
			||||||
			return new RealTimeSignum (offset);
 | 
					      return new String('0', 4-s.Length) + s;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// convert from octal representation.
 | 
					    public static FilePermissions FromUnixPermissionString (String value)
 | 
				
			||||||
		public static FilePermissions FromOctalPermissionString (string value)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      if (value == null) {
 | 
				
			||||||
			uint n = Convert.ToUInt32 (value, 8);
 | 
					        throw new ArgumentNullException ("value");
 | 
				
			||||||
			return ToFilePermissions (n);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      if (value.Length != 9 && value.Length != 10) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("value", "must contain 9 or 10 characters");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 i = 0;
 | 
				
			||||||
 | 
					      FilePermissions perms = new FilePermissions ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string ToOctalPermissionString (FilePermissions value)
 | 
					      if (value.Length == 10) {
 | 
				
			||||||
		{
 | 
					        perms |= GetUnixPermissionDevice (value [i]);
 | 
				
			||||||
			string s = Convert.ToString ((int) (value & ~FilePermissions.S_IFMT), 8);
 | 
					        ++i;
 | 
				
			||||||
			return new string ('0', 4-s.Length) + s;
 | 
					      }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static FilePermissions FromUnixPermissionString (string value)
 | 
					      perms |= GetUnixPermissionGroup (
 | 
				
			||||||
		{
 | 
					        value [i++], FilePermissions.S_IRUSR,
 | 
				
			||||||
			if (value == null)
 | 
					        value [i++], FilePermissions.S_IWUSR,
 | 
				
			||||||
				throw new ArgumentNullException ("value");
 | 
					        value [i++], FilePermissions.S_IXUSR,
 | 
				
			||||||
			if (value.Length != 9 && value.Length != 10)
 | 
					        's', 'S', FilePermissions.S_ISUID);
 | 
				
			||||||
				throw new ArgumentException ("value", "must contain 9 or 10 characters");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int i = 0;
 | 
					      perms |= GetUnixPermissionGroup (
 | 
				
			||||||
			FilePermissions perms = new FilePermissions ();
 | 
					        value [i++], FilePermissions.S_IRGRP,
 | 
				
			||||||
 | 
					        value [i++], FilePermissions.S_IWGRP,
 | 
				
			||||||
 | 
					        value [i++], FilePermissions.S_IXGRP,
 | 
				
			||||||
 | 
					        's', 'S', FilePermissions.S_ISGID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (value.Length == 10) {
 | 
					      perms |= GetUnixPermissionGroup (
 | 
				
			||||||
				perms |= GetUnixPermissionDevice (value [i]);
 | 
					        value [i++], FilePermissions.S_IROTH,
 | 
				
			||||||
				++i;
 | 
					        value [i++], FilePermissions.S_IWOTH,
 | 
				
			||||||
			}
 | 
					        value [i++], FilePermissions.S_IXOTH,
 | 
				
			||||||
 | 
					        't', 'T', FilePermissions.S_ISVTX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			perms |= GetUnixPermissionGroup (
 | 
					      return perms;
 | 
				
			||||||
				value [i++], FilePermissions.S_IRUSR,
 | 
					    }
 | 
				
			||||||
				value [i++], FilePermissions.S_IWUSR,
 | 
					 | 
				
			||||||
				value [i++], FilePermissions.S_IXUSR,
 | 
					 | 
				
			||||||
				's', 'S', FilePermissions.S_ISUID);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			perms |= GetUnixPermissionGroup (
 | 
					    private static FilePermissions GetUnixPermissionDevice (Char value)
 | 
				
			||||||
				value [i++], FilePermissions.S_IRGRP,
 | 
					    {
 | 
				
			||||||
				value [i++], FilePermissions.S_IWGRP,
 | 
					      switch (value) {
 | 
				
			||||||
				value [i++], FilePermissions.S_IXGRP,
 | 
					      case 'd': return FilePermissions.S_IFDIR;
 | 
				
			||||||
				's', 'S', FilePermissions.S_ISGID);
 | 
					      case 'c': return FilePermissions.S_IFCHR;
 | 
				
			||||||
 | 
					      case 'b': return FilePermissions.S_IFBLK;
 | 
				
			||||||
 | 
					      case '-': return FilePermissions.S_IFREG;
 | 
				
			||||||
 | 
					      case 'p': return FilePermissions.S_IFIFO;
 | 
				
			||||||
 | 
					      case 'l': return FilePermissions.S_IFLNK;
 | 
				
			||||||
 | 
					      case 's': return FilePermissions.S_IFSOCK;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      throw new ArgumentException ("value", "invalid device specification: " + 
 | 
				
			||||||
 | 
					        value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			perms |= GetUnixPermissionGroup (
 | 
					    private static FilePermissions GetUnixPermissionGroup (
 | 
				
			||||||
				value [i++], FilePermissions.S_IROTH,
 | 
					      Char read, FilePermissions readb,
 | 
				
			||||||
				value [i++], FilePermissions.S_IWOTH,
 | 
					      Char write, FilePermissions writeb,
 | 
				
			||||||
				value [i++], FilePermissions.S_IXOTH,
 | 
					      Char exec, FilePermissions execb,
 | 
				
			||||||
				't', 'T', FilePermissions.S_ISVTX);
 | 
					      Char xboth, Char xbitonly, FilePermissions xbit)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      FilePermissions perms = new FilePermissions ();
 | 
				
			||||||
 | 
					      if (read == 'r') {
 | 
				
			||||||
 | 
					        perms |= readb;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (write == 'w') {
 | 
				
			||||||
 | 
					        perms |= writeb;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (exec == 'x') {
 | 
				
			||||||
 | 
					        perms |= execb;
 | 
				
			||||||
 | 
					      } else if (exec == xbitonly) {
 | 
				
			||||||
 | 
					        perms |= xbit;
 | 
				
			||||||
 | 
					      } else if (exec == xboth) {
 | 
				
			||||||
 | 
					        perms |= execb | xbit;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return perms;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return perms;
 | 
					    // Create ls(1) drwxrwxrwx permissions display
 | 
				
			||||||
		}
 | 
					    public static String ToUnixPermissionString (FilePermissions value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Char[] access = new Char[] {
 | 
				
			||||||
 | 
					        '-',            // device
 | 
				
			||||||
 | 
					        '-', '-', '-',  // owner
 | 
				
			||||||
 | 
					        '-', '-', '-',  // group
 | 
				
			||||||
 | 
					        '-', '-', '-',  // other
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      Boolean have_device = true;
 | 
				
			||||||
 | 
					      switch (value & FilePermissions.S_IFMT) {
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFDIR:   access [0] = 'd'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFCHR:   access [0] = 'c'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFBLK:   access [0] = 'b'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFREG:   access [0] = '-'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFIFO:   access [0] = 'p'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFLNK:   access [0] = 'l'; break;
 | 
				
			||||||
 | 
					        case FilePermissions.S_IFSOCK:  access [0] = 's'; break;
 | 
				
			||||||
 | 
					        default:                        have_device = false; break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      SetUnixPermissionGroup (value, access, 1, 
 | 
				
			||||||
 | 
					        FilePermissions.S_IRUSR, FilePermissions.S_IWUSR, FilePermissions.S_IXUSR,
 | 
				
			||||||
 | 
					        's', 'S', FilePermissions.S_ISUID);
 | 
				
			||||||
 | 
					      SetUnixPermissionGroup (value, access, 4, 
 | 
				
			||||||
 | 
					        FilePermissions.S_IRGRP, FilePermissions.S_IWGRP, FilePermissions.S_IXGRP,
 | 
				
			||||||
 | 
					        's', 'S', FilePermissions.S_ISGID);
 | 
				
			||||||
 | 
					      SetUnixPermissionGroup (value, access, 7, 
 | 
				
			||||||
 | 
					        FilePermissions.S_IROTH, FilePermissions.S_IWOTH, FilePermissions.S_IXOTH,
 | 
				
			||||||
 | 
					        't', 'T', FilePermissions.S_ISVTX);
 | 
				
			||||||
 | 
					      return have_device 
 | 
				
			||||||
 | 
					        ? new String(access)
 | 
				
			||||||
 | 
					        : new String(access, 1, 9);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static FilePermissions GetUnixPermissionDevice (char value)
 | 
					    private static void SetUnixPermissionGroup (FilePermissions value,
 | 
				
			||||||
		{
 | 
					      Char[] access, Int32 index,
 | 
				
			||||||
			switch (value) {
 | 
					      FilePermissions read, FilePermissions write, FilePermissions exec,
 | 
				
			||||||
			case 'd': return FilePermissions.S_IFDIR;
 | 
					      Char both, Char setonly, FilePermissions setxbit)
 | 
				
			||||||
			case 'c': return FilePermissions.S_IFCHR;
 | 
					    {
 | 
				
			||||||
			case 'b': return FilePermissions.S_IFBLK;
 | 
					      if (UnixFileSystemInfo.IsSet (value, read)) {
 | 
				
			||||||
			case '-': return FilePermissions.S_IFREG;
 | 
					        access [index] = 'r';
 | 
				
			||||||
			case 'p': return FilePermissions.S_IFIFO;
 | 
					      }
 | 
				
			||||||
			case 'l': return FilePermissions.S_IFLNK;
 | 
					
 | 
				
			||||||
			case 's': return FilePermissions.S_IFSOCK;
 | 
					      if (UnixFileSystemInfo.IsSet (value, write)) {
 | 
				
			||||||
			}
 | 
					        access [index+1] = 'w';
 | 
				
			||||||
			throw new ArgumentException ("value", "invalid device specification: " + 
 | 
					      }
 | 
				
			||||||
				value);
 | 
					
 | 
				
			||||||
		}
 | 
					      access [index+2] = GetSymbolicMode (value, exec, both, setonly, setxbit);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static FilePermissions GetUnixPermissionGroup (
 | 
					    // Implement the GNU ls(1) permissions spec; see `info coreutils ls`,
 | 
				
			||||||
			char read, FilePermissions readb, 
 | 
					    // section 10.1.2, the `-l' argument information.
 | 
				
			||||||
			char write, FilePermissions writeb, 
 | 
					    private static Char GetSymbolicMode (FilePermissions value, 
 | 
				
			||||||
			char exec, FilePermissions execb,
 | 
					      FilePermissions xbit, Char both, Char setonly, FilePermissions setxbit)
 | 
				
			||||||
			char xboth, char xbitonly, FilePermissions xbit)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Boolean is_x  = UnixFileSystemInfo.IsSet (value, xbit);
 | 
				
			||||||
			FilePermissions perms = new FilePermissions ();
 | 
					      Boolean is_sx = UnixFileSystemInfo.IsSet (value, setxbit);
 | 
				
			||||||
			if (read == 'r')
 | 
					
 | 
				
			||||||
				perms |= readb;
 | 
					      return is_x && is_sx ? both : is_sx ? setonly : is_x ? 'x' : '-';
 | 
				
			||||||
			if (write == 'w')
 | 
					    }
 | 
				
			||||||
				perms |= writeb;
 | 
					
 | 
				
			||||||
			if (exec == 'x')
 | 
					    public static readonly DateTime UnixEpoch =
 | 
				
			||||||
				perms |= execb;
 | 
					      new DateTime (year:1970, month:1, day:1, hour:0, minute:0, second:0, kind:DateTimeKind.Utc);
 | 
				
			||||||
			else if (exec == xbitonly)
 | 
					    public static readonly DateTime LocalUnixEpoch = 
 | 
				
			||||||
				perms |= xbit;
 | 
					      new DateTime (1970, 1, 1);
 | 
				
			||||||
			else if (exec == xboth)
 | 
					    public static readonly TimeSpan LocalUtcOffset = 
 | 
				
			||||||
				perms |= (execb | xbit);
 | 
					      TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.UtcNow);
 | 
				
			||||||
			return perms;
 | 
					
 | 
				
			||||||
		}
 | 
					    public static DateTime ToDateTime(Int64 time) => FromTimeT(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static DateTime ToDateTime(Int64 time, Int64 nanoTime) => FromTimeT(time).AddMilliseconds(nanoTime / 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 FromDateTime(DateTime time) => ToTimeT(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static DateTime FromTimeT(Int64 time) => UnixEpoch.AddSeconds(time).ToLocalTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 ToTimeT (DateTime time)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (time.Kind == DateTimeKind.Unspecified) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("DateTimeKind.Unspecified is not supported. Use Local or Utc times.", "time");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (time.Kind == DateTimeKind.Local) {
 | 
				
			||||||
 | 
					        time = time.ToUniversalTime ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (Int64) (time - UnixEpoch).TotalSeconds;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Create ls(1) drwxrwxrwx permissions display
 | 
					    public static OpenFlags ToOpenFlags (FileMode mode, FileAccess access)
 | 
				
			||||||
		public static string ToUnixPermissionString (FilePermissions value)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      OpenFlags flags = 0;
 | 
				
			||||||
			char [] access = new char[] {
 | 
					      switch (mode) {
 | 
				
			||||||
				'-',            // device
 | 
					      case FileMode.CreateNew:
 | 
				
			||||||
				'-', '-', '-',  // owner
 | 
					        flags = OpenFlags.O_CREAT | OpenFlags.O_EXCL;
 | 
				
			||||||
				'-', '-', '-',  // group
 | 
					        break;
 | 
				
			||||||
				'-', '-', '-',  // other
 | 
					      case FileMode.Create:
 | 
				
			||||||
			};
 | 
					        flags = OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
 | 
				
			||||||
			bool have_device = true;
 | 
					        break;
 | 
				
			||||||
			switch (value & FilePermissions.S_IFMT) {
 | 
					      case FileMode.Open:
 | 
				
			||||||
				case FilePermissions.S_IFDIR:   access [0] = 'd'; break;
 | 
					        // do nothing
 | 
				
			||||||
				case FilePermissions.S_IFCHR:   access [0] = 'c'; break;
 | 
					        break;
 | 
				
			||||||
				case FilePermissions.S_IFBLK:   access [0] = 'b'; break;
 | 
					      case FileMode.OpenOrCreate:
 | 
				
			||||||
				case FilePermissions.S_IFREG:   access [0] = '-'; break;
 | 
					        flags = OpenFlags.O_CREAT;
 | 
				
			||||||
				case FilePermissions.S_IFIFO:   access [0] = 'p'; break;
 | 
					        break;
 | 
				
			||||||
				case FilePermissions.S_IFLNK:   access [0] = 'l'; break;
 | 
					      case FileMode.Truncate:
 | 
				
			||||||
				case FilePermissions.S_IFSOCK:  access [0] = 's'; break;
 | 
					        flags = OpenFlags.O_TRUNC;
 | 
				
			||||||
				default:                        have_device = false; break;
 | 
					        break;
 | 
				
			||||||
			}
 | 
					      case FileMode.Append:
 | 
				
			||||||
			SetUnixPermissionGroup (value, access, 1, 
 | 
					        flags = OpenFlags.O_APPEND;
 | 
				
			||||||
				FilePermissions.S_IRUSR, FilePermissions.S_IWUSR, FilePermissions.S_IXUSR,
 | 
					        break;
 | 
				
			||||||
				's', 'S', FilePermissions.S_ISUID);
 | 
					      default:
 | 
				
			||||||
			SetUnixPermissionGroup (value, access, 4, 
 | 
					        throw new ArgumentException (Locale.GetText ("Unsupported mode value"), "mode");
 | 
				
			||||||
				FilePermissions.S_IRGRP, FilePermissions.S_IWGRP, FilePermissions.S_IXGRP,
 | 
					      }
 | 
				
			||||||
				's', 'S', FilePermissions.S_ISGID);
 | 
					
 | 
				
			||||||
			SetUnixPermissionGroup (value, access, 7, 
 | 
					      // Is O_LARGEFILE supported?
 | 
				
			||||||
				FilePermissions.S_IROTH, FilePermissions.S_IWOTH, FilePermissions.S_IXOTH,
 | 
					      if(TryFromOpenFlags(OpenFlags.O_LARGEFILE, out _)) {
 | 
				
			||||||
				't', 'T', FilePermissions.S_ISVTX);
 | 
					        flags |= OpenFlags.O_LARGEFILE;
 | 
				
			||||||
			return have_device 
 | 
					      }
 | 
				
			||||||
				? new string (access)
 | 
					
 | 
				
			||||||
				: new string (access, 1, 9);
 | 
					      switch (access) {
 | 
				
			||||||
		}
 | 
					      case FileAccess.Read:
 | 
				
			||||||
 | 
					        flags |= OpenFlags.O_RDONLY;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case FileAccess.Write:
 | 
				
			||||||
 | 
					        flags |= OpenFlags.O_WRONLY;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case FileAccess.ReadWrite:
 | 
				
			||||||
 | 
					        flags |= OpenFlags.O_RDWR;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException (Locale.GetText ("Unsupported access value"), "access");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void SetUnixPermissionGroup (FilePermissions value,
 | 
					      return flags;
 | 
				
			||||||
			char[] access, int index,
 | 
					    }
 | 
				
			||||||
			FilePermissions read, FilePermissions write, FilePermissions exec,
 | 
					 | 
				
			||||||
			char both, char setonly, FilePermissions setxbit)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (UnixFileSystemInfo.IsSet (value, read))
 | 
					 | 
				
			||||||
				access [index] = 'r';
 | 
					 | 
				
			||||||
			if (UnixFileSystemInfo.IsSet (value, write))
 | 
					 | 
				
			||||||
				access [index+1] = 'w';
 | 
					 | 
				
			||||||
			access [index+2] = GetSymbolicMode (value, exec, both, setonly, setxbit);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Implement the GNU ls(1) permissions spec; see `info coreutils ls`,
 | 
					    public static String ToFopenMode (FileAccess access)
 | 
				
			||||||
		// section 10.1.2, the `-l' argument information.
 | 
					    {
 | 
				
			||||||
		private static char GetSymbolicMode (FilePermissions value, 
 | 
					      switch (access) {
 | 
				
			||||||
			FilePermissions xbit, char both, char setonly, FilePermissions setxbit)
 | 
					        case FileAccess.Read:       return "rb";
 | 
				
			||||||
		{
 | 
					        case FileAccess.Write:      return "wb";
 | 
				
			||||||
			bool is_x  = UnixFileSystemInfo.IsSet (value, xbit);
 | 
					        case FileAccess.ReadWrite:  return "r+b";
 | 
				
			||||||
			bool is_sx = UnixFileSystemInfo.IsSet (value, setxbit);
 | 
					        default:                    throw new ArgumentOutOfRangeException ("access");
 | 
				
			||||||
			
 | 
					      }
 | 
				
			||||||
			if (is_x && is_sx)
 | 
					    }
 | 
				
			||||||
				return both;
 | 
					 | 
				
			||||||
			if (is_sx)
 | 
					 | 
				
			||||||
				return setonly;
 | 
					 | 
				
			||||||
			if (is_x)
 | 
					 | 
				
			||||||
				return 'x';
 | 
					 | 
				
			||||||
			return '-';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static readonly DateTime UnixEpoch =
 | 
					    public static String ToFopenMode (FileMode mode)
 | 
				
			||||||
			new DateTime (year:1970, month:1, day:1, hour:0, minute:0, second:0, kind:DateTimeKind.Utc);
 | 
					    {
 | 
				
			||||||
		public static readonly DateTime LocalUnixEpoch = 
 | 
					      switch (mode) {
 | 
				
			||||||
			new DateTime (1970, 1, 1);
 | 
					        case FileMode.CreateNew: case FileMode.Create:        return "w+b";
 | 
				
			||||||
		public static readonly TimeSpan LocalUtcOffset = 
 | 
					        case FileMode.Open:      case FileMode.OpenOrCreate:  return "r+b";
 | 
				
			||||||
			TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.UtcNow);
 | 
					        case FileMode.Truncate: return "w+b";
 | 
				
			||||||
 | 
					        case FileMode.Append:   return "a+b";
 | 
				
			||||||
 | 
					        default:                throw new ArgumentOutOfRangeException ("mode");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static DateTime ToDateTime (long time)
 | 
					    private static readonly String[][] fopen_modes = new String[][]{
 | 
				
			||||||
		{
 | 
					      //                                         Read                       Write ReadWrite
 | 
				
			||||||
			return FromTimeT (time);
 | 
					      /*    FileMode.CreateNew: */  new String[]{"Can't Read+Create",       "wb", "w+b"},
 | 
				
			||||||
		}
 | 
					      /*       FileMode.Create: */  new String[]{"Can't Read+Create",       "wb", "w+b"},
 | 
				
			||||||
 | 
					      /*         FileMode.Open: */  new String[]{"rb",                      "wb", "r+b"},
 | 
				
			||||||
 | 
					      /* FileMode.OpenOrCreate: */  new String[]{"rb",                      "wb", "r+b"},
 | 
				
			||||||
 | 
					      /*     FileMode.Truncate: */  new String[]{"Cannot Truncate and Read","wb", "w+b"},
 | 
				
			||||||
 | 
					      /*       FileMode.Append: */  new String[]{"Cannot Append and Read",  "ab", "a+b"},
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static DateTime ToDateTime (long time, long nanoTime)
 | 
					    public static String ToFopenMode (FileMode mode, FileAccess access)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			return FromTimeT (time).AddMilliseconds (nanoTime / 1000);
 | 
					      Int32 fm = -1, fa = -1;
 | 
				
			||||||
		}
 | 
					      switch (mode) {
 | 
				
			||||||
 | 
					        case FileMode.CreateNew:    fm = 0; break;
 | 
				
			||||||
 | 
					        case FileMode.Create:       fm = 1; break;
 | 
				
			||||||
 | 
					        case FileMode.Open:         fm = 2; break;
 | 
				
			||||||
 | 
					        case FileMode.OpenOrCreate: fm = 3; break;
 | 
				
			||||||
 | 
					        case FileMode.Truncate:     fm = 4; break;
 | 
				
			||||||
 | 
					        case FileMode.Append:       fm = 5; break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      switch (access) {
 | 
				
			||||||
 | 
					        case FileAccess.Read:       fa = 0; break;
 | 
				
			||||||
 | 
					        case FileAccess.Write:      fa = 1; break;
 | 
				
			||||||
 | 
					        case FileAccess.ReadWrite:  fa = 2; break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long FromDateTime (DateTime time)
 | 
					      if (fm == -1) {
 | 
				
			||||||
		{
 | 
					        throw new ArgumentOutOfRangeException ("mode");
 | 
				
			||||||
			return ToTimeT (time);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      if (fa == -1) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("access");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      String fopen_mode = fopen_modes [fm][fa];
 | 
				
			||||||
 | 
					      if (fopen_mode [0] != 'r' && fopen_mode [0] != 'w' && fopen_mode [0] != 'a') {
 | 
				
			||||||
 | 
					        throw new ArgumentException (fopen_mode);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return fopen_mode;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static DateTime FromTimeT (long time)
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromStat")]
 | 
				
			||||||
		{
 | 
					    private static extern Int32 FromStat (ref Stat source, IntPtr destination);
 | 
				
			||||||
			return UnixEpoch.AddSeconds (time).ToLocalTime ();
 | 
					
 | 
				
			||||||
		}
 | 
					    public static Boolean TryCopy(ref Stat source, IntPtr destination) => FromStat(ref source, destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_ToStat")]
 | 
				
			||||||
 | 
					    private static extern Int32 ToStat (IntPtr source, out Stat destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(IntPtr source, out Stat destination) => ToStat(source, out destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromStatvfs")]
 | 
				
			||||||
 | 
					    private static extern Int32 FromStatvfs (ref Statvfs source, IntPtr destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(ref Statvfs source, IntPtr destination) => FromStatvfs(ref source, destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_ToStatvfs")]
 | 
				
			||||||
 | 
					    private static extern Int32 ToStatvfs (IntPtr source, out Statvfs destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(IntPtr source, out Statvfs destination) => ToStatvfs(source, out destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromInAddr")]
 | 
				
			||||||
 | 
					    private static extern Int32 FromInAddr (ref InAddr source, IntPtr destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(ref InAddr source, IntPtr destination) => FromInAddr(ref source, destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_ToInAddr")]
 | 
				
			||||||
 | 
					    private static extern Int32 ToInAddr (IntPtr source, out InAddr destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(IntPtr source, out InAddr destination) => ToInAddr(source, out destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromIn6Addr")]
 | 
				
			||||||
 | 
					    private static extern Int32 FromIn6Addr (ref In6Addr source, IntPtr destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(ref In6Addr source, IntPtr destination) => FromIn6Addr(ref source, destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_ToIn6Addr")]
 | 
				
			||||||
 | 
					    private static extern Int32 ToIn6Addr (IntPtr source, out In6Addr destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Boolean TryCopy(IntPtr source, out In6Addr destination) => ToIn6Addr(source, out destination) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static InAddr ToInAddr (System.Net.IPAddress address)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (address == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("address");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("address", "address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new InAddr (address.GetAddressBytes ());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long ToTimeT (DateTime time)
 | 
					    public static System.Net.IPAddress ToIPAddress (InAddr address)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (time.Kind == DateTimeKind.Unspecified)
 | 
					      Byte[] bytes = new Byte[4];
 | 
				
			||||||
				throw new ArgumentException ("DateTimeKind.Unspecified is not supported. Use Local or Utc times.", "time");
 | 
					      address.CopyTo (bytes, 0);
 | 
				
			||||||
 | 
					      return new System.Net.IPAddress (bytes);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (time.Kind == DateTimeKind.Local)
 | 
					    public static In6Addr ToIn6Addr (System.Net.IPAddress address)
 | 
				
			||||||
				time = time.ToUniversalTime ();
 | 
					    {
 | 
				
			||||||
 | 
					      if (address == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("address");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("address", "address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new In6Addr (address.GetAddressBytes ());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return (long) (time - UnixEpoch).TotalSeconds;
 | 
					    public static System.Net.IPAddress ToIPAddress (In6Addr address)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      Byte[] bytes = new Byte[16];
 | 
				
			||||||
 | 
					      address.CopyTo (bytes, 0);
 | 
				
			||||||
 | 
					      return new System.Net.IPAddress (bytes);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static OpenFlags ToOpenFlags (FileMode mode, FileAccess access)
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_FromSockaddr")]
 | 
				
			||||||
		{
 | 
					    private static extern unsafe Int32 FromSockaddr (_SockaddrHeader* source, IntPtr destination);
 | 
				
			||||||
			OpenFlags flags = 0;
 | 
					 | 
				
			||||||
			switch (mode) {
 | 
					 | 
				
			||||||
			case FileMode.CreateNew:
 | 
					 | 
				
			||||||
				flags = OpenFlags.O_CREAT | OpenFlags.O_EXCL;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileMode.Create:
 | 
					 | 
				
			||||||
				flags = OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileMode.Open:
 | 
					 | 
				
			||||||
				// do nothing
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileMode.OpenOrCreate:
 | 
					 | 
				
			||||||
				flags = OpenFlags.O_CREAT;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileMode.Truncate:
 | 
					 | 
				
			||||||
				flags = OpenFlags.O_TRUNC;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileMode.Append:
 | 
					 | 
				
			||||||
				flags = OpenFlags.O_APPEND;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("Unsupported mode value"), "mode");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Is O_LARGEFILE supported?
 | 
					    public static unsafe Boolean TryCopy (Sockaddr source, IntPtr destination)
 | 
				
			||||||
			int _v;
 | 
					    {
 | 
				
			||||||
			if (TryFromOpenFlags (OpenFlags.O_LARGEFILE, out _v))
 | 
					      if (source == null) {
 | 
				
			||||||
				flags |= OpenFlags.O_LARGEFILE;
 | 
					        throw new ArgumentNullException ("source");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Byte[] array = Sockaddr.GetDynamicData (source);
 | 
				
			||||||
 | 
					      // SockaddrStorage has to be handled extra because the native code assumes that SockaddrStorage input is used in-place
 | 
				
			||||||
 | 
					      if (source.type == (SockaddrType.SockaddrStorage | SockaddrType.MustBeWrapped)) {
 | 
				
			||||||
 | 
					        Marshal.Copy (array, 0, destination, (Int32) source.GetDynamicLength ());
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      fixed (SockaddrType* addr = &Sockaddr.GetAddress (source).type)
 | 
				
			||||||
 | 
					      fixed (Byte* data = array) {
 | 
				
			||||||
 | 
					        _SockaddrDynamic dyn = new _SockaddrDynamic (source, data, useMaxLength: false);
 | 
				
			||||||
 | 
					        return FromSockaddr (Sockaddr.GetNative (&dyn, addr), destination) == 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			switch (access) {
 | 
					    [DllImport (LIB, EntryPoint="Mono_Posix_ToSockaddr")]
 | 
				
			||||||
			case FileAccess.Read:
 | 
					    private static extern unsafe Int32 ToSockaddr (IntPtr source, Int64 size, _SockaddrHeader* destination);
 | 
				
			||||||
				flags |= OpenFlags.O_RDONLY;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileAccess.Write:
 | 
					 | 
				
			||||||
				flags |= OpenFlags.O_WRONLY;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case FileAccess.ReadWrite:
 | 
					 | 
				
			||||||
				flags |= OpenFlags.O_RDWR;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException (Locale.GetText ("Unsupported access value"), "access");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return flags;
 | 
					    public static unsafe Boolean TryCopy (IntPtr source, Int64 size, Sockaddr destination)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      if (destination == null) {
 | 
				
			||||||
		public static string ToFopenMode (FileAccess access)
 | 
					        throw new ArgumentNullException ("destination");
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			switch (access) {
 | 
					
 | 
				
			||||||
				case FileAccess.Read:       return "rb";
 | 
					      Byte[] array = Sockaddr.GetDynamicData (destination);
 | 
				
			||||||
				case FileAccess.Write:      return "wb";
 | 
					      fixed (SockaddrType* addr = &Sockaddr.GetAddress (destination).type)
 | 
				
			||||||
				case FileAccess.ReadWrite:  return "r+b";
 | 
					      fixed (Byte* data = Sockaddr.GetDynamicData (destination)) {
 | 
				
			||||||
				default:                    throw new ArgumentOutOfRangeException ("access");
 | 
					        _SockaddrDynamic dyn = new _SockaddrDynamic (destination, data, useMaxLength: true);
 | 
				
			||||||
			}
 | 
					        Int32 r = ToSockaddr (source, size, Sockaddr.GetNative (&dyn, addr));
 | 
				
			||||||
		}
 | 
					        dyn.Update (destination);
 | 
				
			||||||
 | 
					        // SockaddrStorage has to be handled extra because the native code assumes that SockaddrStorage input is used in-place
 | 
				
			||||||
		public static string ToFopenMode (FileMode mode)
 | 
					        if (r == 0 && destination.type == (SockaddrType.SockaddrStorage | SockaddrType.MustBeWrapped)) {
 | 
				
			||||||
		{
 | 
					          Marshal.Copy (source, array, 0, (Int32) destination.GetDynamicLength ());
 | 
				
			||||||
			switch (mode) {
 | 
					        }
 | 
				
			||||||
				case FileMode.CreateNew: case FileMode.Create:        return "w+b";
 | 
					        return r == 0;
 | 
				
			||||||
				case FileMode.Open:      case FileMode.OpenOrCreate:  return "r+b";
 | 
					      }
 | 
				
			||||||
				case FileMode.Truncate: return "w+b";
 | 
					    }
 | 
				
			||||||
				case FileMode.Append:   return "a+b";
 | 
					  }
 | 
				
			||||||
				default:                throw new ArgumentOutOfRangeException ("mode");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private static readonly string[][] fopen_modes = new string[][]{
 | 
					 | 
				
			||||||
			//                                         Read                       Write ReadWrite
 | 
					 | 
				
			||||||
			/*    FileMode.CreateNew: */  new string[]{"Can't Read+Create",       "wb", "w+b"},
 | 
					 | 
				
			||||||
			/*       FileMode.Create: */  new string[]{"Can't Read+Create",       "wb", "w+b"},
 | 
					 | 
				
			||||||
			/*         FileMode.Open: */  new string[]{"rb",                      "wb", "r+b"},
 | 
					 | 
				
			||||||
			/* FileMode.OpenOrCreate: */  new string[]{"rb",                      "wb", "r+b"},
 | 
					 | 
				
			||||||
			/*     FileMode.Truncate: */  new string[]{"Cannot Truncate and Read","wb", "w+b"},
 | 
					 | 
				
			||||||
			/*       FileMode.Append: */  new string[]{"Cannot Append and Read",  "ab", "a+b"},
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string ToFopenMode (FileMode mode, FileAccess access)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int fm = -1, fa = -1;
 | 
					 | 
				
			||||||
			switch (mode) {
 | 
					 | 
				
			||||||
				case FileMode.CreateNew:    fm = 0; break;
 | 
					 | 
				
			||||||
				case FileMode.Create:       fm = 1; break;
 | 
					 | 
				
			||||||
				case FileMode.Open:         fm = 2; break;
 | 
					 | 
				
			||||||
				case FileMode.OpenOrCreate: fm = 3; break;
 | 
					 | 
				
			||||||
				case FileMode.Truncate:     fm = 4; break;
 | 
					 | 
				
			||||||
				case FileMode.Append:       fm = 5; break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			switch (access) {
 | 
					 | 
				
			||||||
				case FileAccess.Read:       fa = 0; break;
 | 
					 | 
				
			||||||
				case FileAccess.Write:      fa = 1; break;
 | 
					 | 
				
			||||||
				case FileAccess.ReadWrite:  fa = 2; break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (fm == -1)
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("mode");
 | 
					 | 
				
			||||||
			if (fa == -1)
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("access");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			string fopen_mode = fopen_modes [fm][fa];
 | 
					 | 
				
			||||||
			if (fopen_mode [0] != 'r' && fopen_mode [0] != 'w' && fopen_mode [0] != 'a')
 | 
					 | 
				
			||||||
				throw new ArgumentException (fopen_mode);
 | 
					 | 
				
			||||||
			return fopen_mode;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromStat")]
 | 
					 | 
				
			||||||
		private static extern int FromStat (ref Stat source, IntPtr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (ref Stat source, IntPtr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return FromStat (ref source, destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_ToStat")]
 | 
					 | 
				
			||||||
		private static extern int ToStat (IntPtr source, out Stat destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (IntPtr source, out Stat destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return ToStat (source, out destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromStatvfs")]
 | 
					 | 
				
			||||||
		private static extern int FromStatvfs (ref Statvfs source, IntPtr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (ref Statvfs source, IntPtr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return FromStatvfs (ref source, destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_ToStatvfs")]
 | 
					 | 
				
			||||||
		private static extern int ToStatvfs (IntPtr source, out Statvfs destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (IntPtr source, out Statvfs destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return ToStatvfs (source, out destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromInAddr")]
 | 
					 | 
				
			||||||
		private static extern int FromInAddr (ref InAddr source, IntPtr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (ref InAddr source, IntPtr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return FromInAddr (ref source, destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_ToInAddr")]
 | 
					 | 
				
			||||||
		private static extern int ToInAddr (IntPtr source, out InAddr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (IntPtr source, out InAddr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return ToInAddr (source, out destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromIn6Addr")]
 | 
					 | 
				
			||||||
		private static extern int FromIn6Addr (ref In6Addr source, IntPtr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (ref In6Addr source, IntPtr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return FromIn6Addr (ref source, destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_ToIn6Addr")]
 | 
					 | 
				
			||||||
		private static extern int ToIn6Addr (IntPtr source, out In6Addr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool TryCopy (IntPtr source, out In6Addr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return ToIn6Addr (source, out destination) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static InAddr ToInAddr (System.Net.IPAddress address)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (address == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("address");
 | 
					 | 
				
			||||||
			if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
 | 
					 | 
				
			||||||
				throw new ArgumentException ("address", "address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork");
 | 
					 | 
				
			||||||
			return new InAddr (address.GetAddressBytes ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static System.Net.IPAddress ToIPAddress (InAddr address)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			var bytes = new byte[4];
 | 
					 | 
				
			||||||
			address.CopyTo (bytes, 0);
 | 
					 | 
				
			||||||
			return new System.Net.IPAddress (bytes);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static In6Addr ToIn6Addr (System.Net.IPAddress address)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (address == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("address");
 | 
					 | 
				
			||||||
			if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6)
 | 
					 | 
				
			||||||
				throw new ArgumentException ("address", "address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6");
 | 
					 | 
				
			||||||
			return new In6Addr (address.GetAddressBytes ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static System.Net.IPAddress ToIPAddress (In6Addr address)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			var bytes = new byte[16];
 | 
					 | 
				
			||||||
			address.CopyTo (bytes, 0);
 | 
					 | 
				
			||||||
			return new System.Net.IPAddress (bytes);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_FromSockaddr")]
 | 
					 | 
				
			||||||
		private static extern unsafe int FromSockaddr (_SockaddrHeader* source, IntPtr destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static unsafe bool TryCopy (Sockaddr source, IntPtr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (source == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("source");
 | 
					 | 
				
			||||||
			byte[] array = Sockaddr.GetDynamicData (source);
 | 
					 | 
				
			||||||
			// SockaddrStorage has to be handled extra because the native code assumes that SockaddrStorage input is used in-place
 | 
					 | 
				
			||||||
			if (source.type == (SockaddrType.SockaddrStorage | SockaddrType.MustBeWrapped)) {
 | 
					 | 
				
			||||||
				Marshal.Copy (array, 0, destination, (int) source.GetDynamicLength ());
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			fixed (SockaddrType* addr = &Sockaddr.GetAddress (source).type)
 | 
					 | 
				
			||||||
			fixed (byte* data = array) {
 | 
					 | 
				
			||||||
				var dyn = new _SockaddrDynamic (source, data, useMaxLength: false);
 | 
					 | 
				
			||||||
				return FromSockaddr (Sockaddr.GetNative (&dyn, addr), destination) == 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[DllImport (LIB, EntryPoint="Mono_Posix_ToSockaddr")]
 | 
					 | 
				
			||||||
		private static extern unsafe int ToSockaddr (IntPtr source, long size, _SockaddrHeader* destination);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static unsafe bool TryCopy (IntPtr source, long size, Sockaddr destination)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (destination == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("destination");
 | 
					 | 
				
			||||||
			byte[] array = Sockaddr.GetDynamicData (destination);
 | 
					 | 
				
			||||||
			fixed (SockaddrType* addr = &Sockaddr.GetAddress (destination).type)
 | 
					 | 
				
			||||||
			fixed (byte* data = Sockaddr.GetDynamicData (destination)) {
 | 
					 | 
				
			||||||
				var dyn = new _SockaddrDynamic (destination, data, useMaxLength: true);
 | 
					 | 
				
			||||||
				var r = ToSockaddr (source, size, Sockaddr.GetNative (&dyn, addr));
 | 
					 | 
				
			||||||
				dyn.Update (destination);
 | 
					 | 
				
			||||||
				// SockaddrStorage has to be handled extra because the native code assumes that SockaddrStorage input is used in-place
 | 
					 | 
				
			||||||
				if (r == 0 && destination.type == (SockaddrType.SockaddrStorage | SockaddrType.MustBeWrapped)) {
 | 
					 | 
				
			||||||
					Marshal.Copy (source, array, 0, (int) destination.GetDynamicLength ());
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return r == 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -25,57 +25,39 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					 | 
				
			||||||
using System.Threading;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix.Native {
 | 
					namespace Mono.Unix.Native {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public struct RealTimeSignum
 | 
					  public struct RealTimeSignum
 | 
				
			||||||
		: IEquatable <RealTimeSignum>
 | 
					    : IEquatable <RealTimeSignum>
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private int rt_offset;
 | 
					    private static readonly Int32 MaxOffset = UnixSignal.GetSIGRTMAX () - UnixSignal.GetSIGRTMIN () - 1;
 | 
				
			||||||
		private static readonly int MaxOffset = UnixSignal.GetSIGRTMAX () - UnixSignal.GetSIGRTMIN () - 1;
 | 
					    public static readonly RealTimeSignum MinValue = new RealTimeSignum (0);
 | 
				
			||||||
		public static readonly RealTimeSignum MinValue = new RealTimeSignum (0);
 | 
					    public static readonly RealTimeSignum MaxValue = new RealTimeSignum (MaxOffset);
 | 
				
			||||||
		public static readonly RealTimeSignum MaxValue = new RealTimeSignum (MaxOffset);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public RealTimeSignum (int offset)
 | 
					    public RealTimeSignum (Int32 offset)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (offset < 0)
 | 
					      if (offset < 0) {
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("Offset cannot be negative");
 | 
					        throw new ArgumentOutOfRangeException ("Offset cannot be negative");
 | 
				
			||||||
			if (offset > MaxOffset)
 | 
					      }
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("Offset greater than maximum supported SIGRT");
 | 
					
 | 
				
			||||||
			rt_offset = offset;
 | 
					      if (offset > MaxOffset) {
 | 
				
			||||||
 		}
 | 
					        throw new ArgumentOutOfRangeException ("Offset greater than maximum supported SIGRT");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.Offset = offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int Offset {
 | 
					    public Int32 Offset { get; }
 | 
				
			||||||
			get { return rt_offset; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override int GetHashCode ()
 | 
					    public override Int32 GetHashCode() => this.Offset.GetHashCode();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return rt_offset.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool Equals (object obj)
 | 
					    public override Boolean Equals(Object obj) => obj == null || obj.GetType() != this.GetType() ? false : this.Equals((RealTimeSignum)obj);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if ((obj == null) || (obj.GetType () != GetType ()))
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			return Equals ((RealTimeSignum)obj);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool Equals (RealTimeSignum value)
 | 
					    public Boolean Equals(RealTimeSignum value) => this.Offset == value.Offset;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Offset == value.Offset;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static bool operator== (RealTimeSignum lhs, RealTimeSignum rhs)
 | 
					    public static Boolean operator ==(RealTimeSignum lhs, RealTimeSignum rhs) => lhs.Equals(rhs);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return lhs.Equals (rhs);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static bool operator!= (RealTimeSignum lhs, RealTimeSignum rhs)
 | 
					    public static Boolean operator !=(RealTimeSignum lhs, RealTimeSignum rhs) => !lhs.Equals(rhs);
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			return !lhs.Equals (rhs);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,138 +1,152 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// TypeAttributes.cs
 | 
					// TypeAttributes.cs
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Author:
 | 
					// Author:
 | 
				
			||||||
//   Jonathan Pryor (jonpryor@vt.edu)
 | 
					//   Jonathan Pryor (jonpryor@vt.edu)
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// (C) 2006 Jonathan Pryor
 | 
					// (C) 2006 Jonathan Pryor
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Permission is hereby granted, free of charge, to any person obtaining
 | 
					// Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
// a copy of this software and associated documentation files (the
 | 
					// a copy of this software and associated documentation files (the
 | 
				
			||||||
// "Software"), to deal in the Software without restriction, including
 | 
					// "Software"), to deal in the Software without restriction, including
 | 
				
			||||||
// without limitation the rights to use, copy, modify, merge, publish,
 | 
					// without limitation the rights to use, copy, modify, merge, publish,
 | 
				
			||||||
// distribute, sublicense, and/or sell copies of the Software, and to
 | 
					// distribute, sublicense, and/or sell copies of the Software, and to
 | 
				
			||||||
// permit persons to whom the Software is furnished to do so, subject to
 | 
					// permit persons to whom the Software is furnished to do so, subject to
 | 
				
			||||||
// the following conditions:
 | 
					// the following conditions:
 | 
				
			||||||
// 
 | 
					// 
 | 
				
			||||||
// The above copyright notice and this permission notice shall be
 | 
					// The above copyright notice and this permission notice shall be
 | 
				
			||||||
// included in all copies or substantial portions of the Software.
 | 
					// included in all copies or substantial portions of the Software.
 | 
				
			||||||
// 
 | 
					// 
 | 
				
			||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
					// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
					// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
					// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
				
			||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
					// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
				
			||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
					// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
				
			||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
					// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
namespace Mono.Unix.Native {
 | 
					
 | 
				
			||||||
 | 
					namespace Mono.Unix.Native {
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					
 | 
				
			||||||
	internal class blkcnt_tAttribute : MapAttribute {
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		public blkcnt_tAttribute () : base ("blkcnt_t")
 | 
					  internal class blkcnt_tAttribute : MapAttribute {
 | 
				
			||||||
		{
 | 
					    
 | 
				
			||||||
		}
 | 
					    public blkcnt_tAttribute () : base ("blkcnt_t")
 | 
				
			||||||
	}
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					  }
 | 
				
			||||||
	internal class blksize_tAttribute : MapAttribute {
 | 
					
 | 
				
			||||||
		
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		public blksize_tAttribute () : base ("blksize_t")
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		{
 | 
					  internal class blksize_tAttribute : MapAttribute {
 | 
				
			||||||
		}
 | 
					    
 | 
				
			||||||
	}
 | 
					    public blksize_tAttribute () : base ("blksize_t")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    }
 | 
				
			||||||
	internal class dev_tAttribute : MapAttribute {
 | 
					  }
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public dev_tAttribute () : base ("dev_t")
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		{
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		}
 | 
					  internal class dev_tAttribute : MapAttribute {
 | 
				
			||||||
	}
 | 
					    
 | 
				
			||||||
 | 
					    public dev_tAttribute () : base ("dev_t")
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    {
 | 
				
			||||||
	internal class gid_tAttribute : MapAttribute {
 | 
					    }
 | 
				
			||||||
		
 | 
					  }
 | 
				
			||||||
		public gid_tAttribute () : base ("gid_t")
 | 
					
 | 
				
			||||||
		{
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		}
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
	}
 | 
					  internal class gid_tAttribute : MapAttribute {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    public gid_tAttribute () : base ("gid_t")
 | 
				
			||||||
	internal class fsblkcnt_tAttribute : MapAttribute {
 | 
					    {
 | 
				
			||||||
		
 | 
					    }
 | 
				
			||||||
		public fsblkcnt_tAttribute () : base ("fsblkcnt_t")
 | 
					  }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
		}
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
	}
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
 | 
					  internal class fsblkcnt_tAttribute : MapAttribute {
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    
 | 
				
			||||||
	internal class fsfilcnt_tAttribute : MapAttribute {
 | 
					    public fsblkcnt_tAttribute () : base ("fsblkcnt_t")
 | 
				
			||||||
		
 | 
					    {
 | 
				
			||||||
		public fsfilcnt_tAttribute () : base ("fsfilcnt_t")
 | 
					    }
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
	}
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					  internal class fsfilcnt_tAttribute : MapAttribute {
 | 
				
			||||||
	internal class ino_tAttribute : MapAttribute {
 | 
					    
 | 
				
			||||||
		
 | 
					    public fsfilcnt_tAttribute () : base ("fsfilcnt_t")
 | 
				
			||||||
		public ino_tAttribute () : base ("ino_t")
 | 
					    {
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
		}
 | 
					  }
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
	internal class nlink_tAttribute : MapAttribute {
 | 
					  internal class ino_tAttribute : MapAttribute {
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public nlink_tAttribute () : base ("nlink_t")
 | 
					    public ino_tAttribute () : base ("ino_t")
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
	internal class off_tAttribute : MapAttribute {
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		
 | 
					  internal class nlink_tAttribute : MapAttribute {
 | 
				
			||||||
		public off_tAttribute () : base ("off_t")
 | 
					    
 | 
				
			||||||
		{
 | 
					    public nlink_tAttribute () : base ("nlink_t")
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					
 | 
				
			||||||
	internal class pid_tAttribute : MapAttribute {
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		public pid_tAttribute () : base ("pid_t")
 | 
					  internal class off_tAttribute : MapAttribute {
 | 
				
			||||||
		{
 | 
					    
 | 
				
			||||||
		}
 | 
					    public off_tAttribute () : base ("off_t")
 | 
				
			||||||
	}
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					  }
 | 
				
			||||||
	internal class suseconds_tAttribute : MapAttribute {
 | 
					
 | 
				
			||||||
		
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		public suseconds_tAttribute () : base ("suseconds_t")
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		{
 | 
					  internal class pid_tAttribute : MapAttribute {
 | 
				
			||||||
		}
 | 
					    
 | 
				
			||||||
	}
 | 
					    public pid_tAttribute () : base ("pid_t")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    }
 | 
				
			||||||
	internal class uid_tAttribute : MapAttribute {
 | 
					  }
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public uid_tAttribute () : base ("uid_t")
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		{
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		}
 | 
					  internal class suseconds_tAttribute : MapAttribute {
 | 
				
			||||||
	}
 | 
					    
 | 
				
			||||||
 | 
					    public suseconds_tAttribute () : base ("suseconds_t")
 | 
				
			||||||
	[AttributeUsage (AttributeTargets.Field)]
 | 
					    {
 | 
				
			||||||
	internal class time_tAttribute : MapAttribute {
 | 
					    }
 | 
				
			||||||
		
 | 
					  }
 | 
				
			||||||
		public time_tAttribute () : base ("time_t")
 | 
					
 | 
				
			||||||
		{
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
		}
 | 
					  [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
	}
 | 
					  internal class uid_tAttribute : MapAttribute {
 | 
				
			||||||
}
 | 
					    
 | 
				
			||||||
 | 
					    public uid_tAttribute () : base ("uid_t")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [AttributeUsage (AttributeTargets.Field)]
 | 
				
			||||||
 | 
					  [SuppressMessage("Microsoft.Design","IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
 | 
					  internal class time_tAttribute : MapAttribute {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public time_tAttribute () : base ("time_t")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,88 +36,82 @@ using System.Text;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix
 | 
					namespace Mono.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	[Serializable]
 | 
					  [Serializable]
 | 
				
			||||||
	public class AbstractUnixEndPoint : EndPoint
 | 
					  public class AbstractUnixEndPoint : EndPoint
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		string path;
 | 
					    String path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public AbstractUnixEndPoint (string path)
 | 
					    public AbstractUnixEndPoint (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (path == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (path == "") {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("Cannot be empty.", "path");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.path = path;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (path == "")
 | 
					    public String Path {
 | 
				
			||||||
				throw new ArgumentException ("Cannot be empty.", "path");
 | 
					      get => this.path;
 | 
				
			||||||
			this.path = path;
 | 
					      set => this.path = value;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override AddressFamily AddressFamily => AddressFamily.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override EndPoint Create (SocketAddress socketAddress)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /*
 | 
				
			||||||
 | 
					       * Should also check this
 | 
				
			||||||
 | 
					       *
 | 
				
			||||||
 | 
					      int addr = (int) AddressFamily.Unix;
 | 
				
			||||||
 | 
					      if (socketAddress [0] != (addr & 0xFF))
 | 
				
			||||||
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string Path {
 | 
					      if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
				
			||||||
			get {
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
				return(path);
 | 
					       */
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			set {
 | 
					      Byte[] bytes = new Byte[socketAddress.Size - 2 - 1];
 | 
				
			||||||
				path=value;
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
			}
 | 
					        bytes [i] = socketAddress [2 + 1 + i];
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      String name = Encoding.Default.GetString (bytes);
 | 
				
			||||||
 | 
					      return new AbstractUnixEndPoint (name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override AddressFamily AddressFamily {
 | 
					    public override SocketAddress Serialize ()
 | 
				
			||||||
			get { return AddressFamily.Unix; }
 | 
					    {
 | 
				
			||||||
		}
 | 
					      Byte[] bytes = Encoding.Default.GetBytes (this.path);
 | 
				
			||||||
 | 
					      SocketAddress sa = new SocketAddress (this.AddressFamily, 2 + 1 + bytes.Length);
 | 
				
			||||||
 | 
					      //NULL prefix denotes the abstract namespace, see unix(7)
 | 
				
			||||||
 | 
					      //in this case, there is no NULL suffix
 | 
				
			||||||
 | 
					      sa [2] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override EndPoint Create (SocketAddress socketAddress)
 | 
					      // sa [0] -> family low byte, sa [1] -> family high byte
 | 
				
			||||||
		{
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
			/*
 | 
					        sa [i + 2 + 1] = bytes [i];
 | 
				
			||||||
			 * Should also check this
 | 
					      }
 | 
				
			||||||
			 *
 | 
					
 | 
				
			||||||
			int addr = (int) AddressFamily.Unix;
 | 
					      return sa;
 | 
				
			||||||
			if (socketAddress [0] != (addr & 0xFF))
 | 
					    }
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					
 | 
				
			||||||
 | 
					    public override String ToString() => this.path;
 | 
				
			||||||
			if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
					
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					    public override Int32 GetHashCode() => this.path.GetHashCode();
 | 
				
			||||||
			 */
 | 
					
 | 
				
			||||||
 | 
					    public override Boolean Equals (Object o)
 | 
				
			||||||
			byte [] bytes = new byte [socketAddress.Size - 2 - 1];
 | 
					    {
 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++) {
 | 
					      AbstractUnixEndPoint other = o as AbstractUnixEndPoint;
 | 
				
			||||||
				bytes [i] = socketAddress [2 + 1 + i];
 | 
					      if (other == null) {
 | 
				
			||||||
			}
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
			string name = Encoding.Default.GetString (bytes);
 | 
					
 | 
				
			||||||
			return new AbstractUnixEndPoint (name);
 | 
					      return other.path == this.path;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public override SocketAddress Serialize ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			byte [] bytes = Encoding.Default.GetBytes (path);
 | 
					 | 
				
			||||||
			SocketAddress sa = new SocketAddress (AddressFamily, 2 + 1 + bytes.Length);
 | 
					 | 
				
			||||||
			//NULL prefix denotes the abstract namespace, see unix(7)
 | 
					 | 
				
			||||||
			//in this case, there is no NULL suffix
 | 
					 | 
				
			||||||
			sa [2] = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// sa [0] -> family low byte, sa [1] -> family high byte
 | 
					 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++)
 | 
					 | 
				
			||||||
				sa [i + 2 + 1] = bytes [i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return sa;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override string ToString() {
 | 
					 | 
				
			||||||
			return(path);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override int GetHashCode ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return path.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override bool Equals (object o)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AbstractUnixEndPoint other = o as AbstractUnixEndPoint;
 | 
					 | 
				
			||||||
			if (other == null)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (other.path == path);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -33,104 +33,112 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class Catalog {
 | 
					  public class Catalog {
 | 
				
			||||||
		private Catalog () {}
 | 
					    private Catalog () {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
					    [DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
				
			||||||
		static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
					    static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
 | 
				
			||||||
		static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
 | 
					    [DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
				
			||||||
			IntPtr codeset);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
					    static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
 | 
				
			||||||
		static extern IntPtr textdomain (IntPtr domainname);
 | 
					      IntPtr codeset);
 | 
				
			||||||
		
 | 
					    [DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
				
			||||||
		public static void Init (String package, String localedir)
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		{
 | 
					    static extern IntPtr textdomain (IntPtr domainname);
 | 
				
			||||||
			IntPtr ipackage, ilocaledir, iutf8;
 | 
					    
 | 
				
			||||||
			MarshalStrings (package, out ipackage, localedir, out ilocaledir, 
 | 
					    public static void Init (String package, String localedir)
 | 
				
			||||||
					"UTF-8", out iutf8);
 | 
					    {
 | 
				
			||||||
			try {
 | 
					      MarshalStrings(package, out IntPtr ipackage, localedir, out IntPtr ilocaledir,
 | 
				
			||||||
				if (bindtextdomain (ipackage, ilocaledir) == IntPtr.Zero)
 | 
					          "UTF-8", out IntPtr iutf8);
 | 
				
			||||||
					throw new UnixIOException (Native.Errno.ENOMEM);
 | 
					      try {
 | 
				
			||||||
				if (bind_textdomain_codeset (ipackage, iutf8) == IntPtr.Zero)
 | 
					        if (bindtextdomain (ipackage, ilocaledir) == IntPtr.Zero) {
 | 
				
			||||||
					throw new UnixIOException (Native.Errno.ENOMEM);
 | 
					          throw new UnixIOException (Native.Errno.ENOMEM);
 | 
				
			||||||
				if (textdomain (ipackage) == IntPtr.Zero)
 | 
					        }
 | 
				
			||||||
					throw new UnixIOException (Native.Errno.ENOMEM);
 | 
					
 | 
				
			||||||
			}
 | 
					        if (bind_textdomain_codeset (ipackage, iutf8) == IntPtr.Zero) {
 | 
				
			||||||
			finally {
 | 
					          throw new UnixIOException (Native.Errno.ENOMEM);
 | 
				
			||||||
				UnixMarshal.FreeHeap (ipackage);
 | 
					        }
 | 
				
			||||||
				UnixMarshal.FreeHeap (ilocaledir);
 | 
					
 | 
				
			||||||
				UnixMarshal.FreeHeap (iutf8);
 | 
					        if (textdomain (ipackage) == IntPtr.Zero) {
 | 
				
			||||||
			}
 | 
					          throw new UnixIOException (Native.Errno.ENOMEM);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      finally {
 | 
				
			||||||
 | 
					        UnixMarshal.FreeHeap (ipackage);
 | 
				
			||||||
 | 
					        UnixMarshal.FreeHeap (ilocaledir);
 | 
				
			||||||
 | 
					        UnixMarshal.FreeHeap (iutf8);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void MarshalStrings (string s1, out IntPtr p1, 
 | 
					    private static void MarshalStrings (String s1, out IntPtr p1,
 | 
				
			||||||
				string s2, out IntPtr p2, string s3, out IntPtr p3)
 | 
					        String s2, out IntPtr p2, String s3, out IntPtr p3)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			p1 = p2 = p3 = IntPtr.Zero;
 | 
					      p1 = p2 = p3 = IntPtr.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Boolean cleanup = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool cleanup = true;
 | 
					      try {
 | 
				
			||||||
 | 
					        p1 = UnixMarshal.StringToHeap (s1);
 | 
				
			||||||
			try {
 | 
					        p2 = UnixMarshal.StringToHeap (s2);
 | 
				
			||||||
				p1 = UnixMarshal.StringToHeap (s1);
 | 
					        if (s3 != null) {
 | 
				
			||||||
				p2 = UnixMarshal.StringToHeap (s2);
 | 
					          p3 = UnixMarshal.StringToHeap (s3);
 | 
				
			||||||
				if (s3 != null)
 | 
					        }
 | 
				
			||||||
					p3 = UnixMarshal.StringToHeap (s3);
 | 
					
 | 
				
			||||||
				cleanup = false;
 | 
					        cleanup = false;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			finally {
 | 
					      finally {
 | 
				
			||||||
				if (cleanup) {
 | 
					        if (cleanup) {
 | 
				
			||||||
					UnixMarshal.FreeHeap (p1);
 | 
					          UnixMarshal.FreeHeap (p1);
 | 
				
			||||||
					UnixMarshal.FreeHeap (p2);
 | 
					          UnixMarshal.FreeHeap (p2);
 | 
				
			||||||
					UnixMarshal.FreeHeap (p3);
 | 
					          UnixMarshal.FreeHeap (p3);
 | 
				
			||||||
				}
 | 
					        }
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
	
 | 
					  
 | 
				
			||||||
		[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
					    [DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
				
			||||||
		static extern IntPtr gettext (IntPtr instring);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		
 | 
					    static extern IntPtr gettext (IntPtr instring);
 | 
				
			||||||
		public static String GetString (String s)
 | 
					    
 | 
				
			||||||
		{
 | 
					    public static String GetString (String s)
 | 
				
			||||||
			IntPtr ints = UnixMarshal.StringToHeap (s);
 | 
					    {
 | 
				
			||||||
			try {
 | 
					      IntPtr ints = UnixMarshal.StringToHeap (s);
 | 
				
			||||||
				// gettext(3) returns the input pointer if no translation is found
 | 
					      try {
 | 
				
			||||||
				IntPtr r = gettext (ints);
 | 
					        // gettext(3) returns the input pointer if no translation is found
 | 
				
			||||||
				if (r != ints)
 | 
					        IntPtr r = gettext (ints);
 | 
				
			||||||
					return UnixMarshal.PtrToStringUnix (r);
 | 
					        if (r != ints) {
 | 
				
			||||||
				return s;
 | 
					          return UnixMarshal.PtrToStringUnix (r);
 | 
				
			||||||
			}
 | 
					        }
 | 
				
			||||||
			finally {
 | 
					
 | 
				
			||||||
				UnixMarshal.FreeHeap (ints);
 | 
					        return s;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					      finally {
 | 
				
			||||||
	
 | 
					        UnixMarshal.FreeHeap (ints);
 | 
				
			||||||
		[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
					      }
 | 
				
			||||||
		static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
 | 
					    }
 | 
				
			||||||
		
 | 
					  
 | 
				
			||||||
		public static String GetPluralString (String s, String p, Int32 n)
 | 
					    [DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
 | 
				
			||||||
		{
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
			IntPtr ints, intp, _ignore;
 | 
					    static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
 | 
				
			||||||
			MarshalStrings (s, out ints, p, out intp, null, out _ignore);
 | 
					    
 | 
				
			||||||
 | 
					    public static String GetPluralString (String s, String p, Int32 n)
 | 
				
			||||||
			try {
 | 
					    {
 | 
				
			||||||
				// ngettext(3) returns an input pointer if no translation is found
 | 
					      MarshalStrings(s, out IntPtr ints, p, out IntPtr intp, null, out IntPtr _ignore);
 | 
				
			||||||
				IntPtr r = ngettext (ints, intp, n);
 | 
					
 | 
				
			||||||
				if (r == ints)
 | 
					      try {
 | 
				
			||||||
					return s;
 | 
					        // ngettext(3) returns an input pointer if no translation is found
 | 
				
			||||||
				if (r == intp)
 | 
					        IntPtr r = ngettext (ints, intp, n);
 | 
				
			||||||
					return p;
 | 
					        return r == ints ? s : r == intp ? p : UnixMarshal.PtrToStringUnix (r);
 | 
				
			||||||
				return UnixMarshal.PtrToStringUnix (r); 
 | 
					      } finally {
 | 
				
			||||||
			}
 | 
					        UnixMarshal.FreeHeap (ints);
 | 
				
			||||||
			finally {
 | 
					        UnixMarshal.FreeHeap (intp);
 | 
				
			||||||
				UnixMarshal.FreeHeap (ints);
 | 
					      }
 | 
				
			||||||
				UnixMarshal.FreeHeap (intp);
 | 
					    }
 | 
				
			||||||
			}
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,13 +31,13 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public enum FileAccessPattern {
 | 
					  public enum FileAccessPattern {
 | 
				
			||||||
		Normal     = Native.PosixFadviseAdvice.POSIX_FADV_NORMAL,
 | 
					    Normal     = Native.PosixFadviseAdvice.POSIX_FADV_NORMAL,
 | 
				
			||||||
		Sequential = Native.PosixFadviseAdvice.POSIX_FADV_SEQUENTIAL,
 | 
					    Sequential = Native.PosixFadviseAdvice.POSIX_FADV_SEQUENTIAL,
 | 
				
			||||||
		Random     = Native.PosixFadviseAdvice.POSIX_FADV_RANDOM,
 | 
					    Random     = Native.PosixFadviseAdvice.POSIX_FADV_RANDOM,
 | 
				
			||||||
		NoReuse    = Native.PosixFadviseAdvice.POSIX_FADV_NOREUSE,
 | 
					    NoReuse    = Native.PosixFadviseAdvice.POSIX_FADV_NOREUSE,
 | 
				
			||||||
		PreLoad    = Native.PosixFadviseAdvice.POSIX_FADV_WILLNEED,
 | 
					    PreLoad    = Native.PosixFadviseAdvice.POSIX_FADV_WILLNEED,
 | 
				
			||||||
		FlushCache = Native.PosixFadviseAdvice.POSIX_FADV_DONTNEED,
 | 
					    FlushCache = Native.PosixFadviseAdvice.POSIX_FADV_DONTNEED,
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,23 +31,23 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[Flags]
 | 
					  [Flags]
 | 
				
			||||||
	public enum FileAccessPermissions {
 | 
					  public enum FileAccessPermissions {
 | 
				
			||||||
		UserReadWriteExecute  = (int) Native.FilePermissions.S_IRWXU,
 | 
					    UserReadWriteExecute  = (Int32) Native.FilePermissions.S_IRWXU,
 | 
				
			||||||
		UserRead              = (int) Native.FilePermissions.S_IRUSR,
 | 
					    UserRead              = (Int32) Native.FilePermissions.S_IRUSR,
 | 
				
			||||||
		UserWrite             = (int) Native.FilePermissions.S_IWUSR,
 | 
					    UserWrite             = (Int32) Native.FilePermissions.S_IWUSR,
 | 
				
			||||||
		UserExecute           = (int) Native.FilePermissions.S_IXUSR,
 | 
					    UserExecute           = (Int32) Native.FilePermissions.S_IXUSR,
 | 
				
			||||||
		GroupReadWriteExecute = (int) Native.FilePermissions.S_IRWXG,
 | 
					    GroupReadWriteExecute = (Int32) Native.FilePermissions.S_IRWXG,
 | 
				
			||||||
		GroupRead             = (int) Native.FilePermissions.S_IRGRP,
 | 
					    GroupRead             = (Int32) Native.FilePermissions.S_IRGRP,
 | 
				
			||||||
		GroupWrite            = (int) Native.FilePermissions.S_IWGRP,
 | 
					    GroupWrite            = (Int32) Native.FilePermissions.S_IWGRP,
 | 
				
			||||||
		GroupExecute          = (int) Native.FilePermissions.S_IXGRP,
 | 
					    GroupExecute          = (Int32) Native.FilePermissions.S_IXGRP,
 | 
				
			||||||
		OtherReadWriteExecute = (int) Native.FilePermissions.S_IRWXO,
 | 
					    OtherReadWriteExecute = (Int32) Native.FilePermissions.S_IRWXO,
 | 
				
			||||||
		OtherRead             = (int) Native.FilePermissions.S_IROTH,
 | 
					    OtherRead             = (Int32) Native.FilePermissions.S_IROTH,
 | 
				
			||||||
		OtherWrite            = (int) Native.FilePermissions.S_IWOTH,
 | 
					    OtherWrite            = (Int32) Native.FilePermissions.S_IWOTH,
 | 
				
			||||||
		OtherExecute          = (int) Native.FilePermissions.S_IXOTH,
 | 
					    OtherExecute          = (Int32) Native.FilePermissions.S_IXOTH,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DefaultPermissions    = (int) Native.FilePermissions.DEFFILEMODE,
 | 
					    DefaultPermissions    = (Int32) Native.FilePermissions.DEFFILEMODE,
 | 
				
			||||||
		AllPermissions        = (int) Native.FilePermissions.ACCESSPERMS,
 | 
					    AllPermissions        = (Int32) Native.FilePermissions.ACCESSPERMS,
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,56 +27,53 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using Mono.Unix;
 | 
					using Mono.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed /* static */ class FileHandleOperations
 | 
					  public sealed /* static */ class FileHandleOperations
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private FileHandleOperations () {}
 | 
					    private FileHandleOperations () {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void AdviseFileAccessPattern (int fd, FileAccessPattern pattern, long offset, long len)
 | 
					    public static void AdviseFileAccessPattern (Int32 fd, FileAccessPattern pattern, Int64 offset, Int64 len)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.posix_fadvise (fd, offset, len,
 | 
					      Int32 r = Native.Syscall.posix_fadvise (fd, offset, len,
 | 
				
			||||||
				(Native.PosixFadviseAdvice) pattern);
 | 
					        (Native.PosixFadviseAdvice) pattern);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void AdviseFileAccessPattern (int fd, FileAccessPattern pattern)
 | 
					    public static void AdviseFileAccessPattern(Int32 fd, FileAccessPattern pattern) => AdviseFileAccessPattern(fd, pattern, 0, 0);
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			AdviseFileAccessPattern (fd, pattern, 0, 0);
 | 
					    [SuppressMessage("Microsoft.Design", "CS0618", Justification = "Someone do shit")]
 | 
				
			||||||
		}
 | 
					    public static void AdviseFileAccessPattern (FileStream file, FileAccessPattern pattern, Int64 offset, Int64 len)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
		public static void AdviseFileAccessPattern (FileStream file, FileAccessPattern pattern, long offset, long len)
 | 
					      if (file == null) {
 | 
				
			||||||
		{
 | 
					        throw new ArgumentNullException ("file");
 | 
				
			||||||
			if (file == null)
 | 
					      }
 | 
				
			||||||
				throw new ArgumentNullException ("file");
 | 
					
 | 
				
			||||||
			int r = Native.Syscall.posix_fadvise (file.Handle.ToInt32(), offset, len,
 | 
					      Int32 r = Native.Syscall.posix_fadvise (file.Handle.ToInt32(), offset, len,
 | 
				
			||||||
				(Native.PosixFadviseAdvice) pattern);
 | 
					        (Native.PosixFadviseAdvice) pattern);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void AdviseFileAccessPattern (FileStream file, FileAccessPattern pattern)
 | 
					    public static void AdviseFileAccessPattern(FileStream file, FileAccessPattern pattern) => AdviseFileAccessPattern(file, pattern, 0, 0);
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			AdviseFileAccessPattern (file, pattern, 0, 0);
 | 
					    public static void AdviseFileAccessPattern (UnixStream stream, FileAccessPattern pattern, Int64 offset, Int64 len)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      if (stream == null) {
 | 
				
			||||||
		public static void AdviseFileAccessPattern (UnixStream stream, FileAccessPattern pattern, long offset, long len)
 | 
					        throw new ArgumentNullException ("stream");
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			if (stream == null)
 | 
					
 | 
				
			||||||
				throw new ArgumentNullException ("stream");
 | 
					      Int32 r = Native.Syscall.posix_fadvise (stream.Handle, offset, len,
 | 
				
			||||||
			int r = Native.Syscall.posix_fadvise (stream.Handle, offset, len,
 | 
					        (Native.PosixFadviseAdvice) pattern);
 | 
				
			||||||
				(Native.PosixFadviseAdvice) pattern);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public static void AdviseFileAccessPattern(UnixStream stream, FileAccessPattern pattern) => AdviseFileAccessPattern(stream, pattern, 0, 0);
 | 
				
			||||||
		public static void AdviseFileAccessPattern (UnixStream stream, FileAccessPattern pattern)
 | 
					  }
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AdviseFileAccessPattern (stream, pattern, 0, 0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -31,11 +31,11 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[Flags]
 | 
					  [Flags]
 | 
				
			||||||
	public enum FileSpecialAttributes {
 | 
					  public enum FileSpecialAttributes {
 | 
				
			||||||
		SetUserId   = (int) Native.FilePermissions.S_ISUID,
 | 
					    SetUserId   = (Int32) Native.FilePermissions.S_ISUID,
 | 
				
			||||||
		SetGroupId  = (int) Native.FilePermissions.S_ISGID,
 | 
					    SetGroupId  = (Int32) Native.FilePermissions.S_ISGID,
 | 
				
			||||||
		Sticky      = (int) Native.FilePermissions.S_ISVTX,
 | 
					    Sticky      = (Int32) Native.FilePermissions.S_ISVTX,
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,14 +31,15 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public enum FileTypes {
 | 
					  public enum FileTypes {
 | 
				
			||||||
		Directory         = (int) Native.FilePermissions.S_IFDIR,
 | 
					    Directory         = (Int32) Native.FilePermissions.S_IFDIR,
 | 
				
			||||||
		CharacterDevice   = (int) Native.FilePermissions.S_IFCHR,
 | 
					    CharacterDevice   = (Int32) Native.FilePermissions.S_IFCHR,
 | 
				
			||||||
		BlockDevice       = (int) Native.FilePermissions.S_IFBLK,
 | 
					    BlockDevice       = (Int32) Native.FilePermissions.S_IFBLK,
 | 
				
			||||||
		RegularFile       = (int) Native.FilePermissions.S_IFREG,
 | 
					    RegularFile       = (Int32) Native.FilePermissions.S_IFREG,
 | 
				
			||||||
		Fifo              = (int) Native.FilePermissions.S_IFIFO,
 | 
					    Fifo              = (Int32) Native.FilePermissions.S_IFIFO,
 | 
				
			||||||
		SymbolicLink      = (int) Native.FilePermissions.S_IFLNK,
 | 
					    SymbolicLink      = (Int32) Native.FilePermissions.S_IFLNK,
 | 
				
			||||||
		Socket            = (int) Native.FilePermissions.S_IFSOCK,
 | 
					    Socket            = (Int32) Native.FilePermissions.S_IFSOCK,
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
}
 | 
					} 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -34,48 +34,36 @@ using System.Net.Sockets;
 | 
				
			|||||||
namespace Mono.Unix
 | 
					namespace Mono.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#pragma warning disable 649
 | 
					#pragma warning disable 649
 | 
				
			||||||
	internal struct PeerCredData {
 | 
					  internal struct PeerCredData {
 | 
				
			||||||
		public int pid;
 | 
					    public Int32 pid;
 | 
				
			||||||
		public int uid;
 | 
					    public Int32 uid;
 | 
				
			||||||
		public int gid;
 | 
					    public Int32 gid;
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
#pragma warning restore 649
 | 
					#pragma warning restore 649
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class PeerCred
 | 
					  public class PeerCred
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		/* Make sure this doesn't clash with anything in
 | 
					    /* Make sure this doesn't clash with anything in
 | 
				
			||||||
		 * SocketOptionName, and keep it synchronised with the
 | 
					     * SocketOptionName, and keep it synchronised with the
 | 
				
			||||||
		 * runtime
 | 
					     * runtime
 | 
				
			||||||
		 */
 | 
					     */
 | 
				
			||||||
		private const int so_peercred=10001;
 | 
					    private const Int32 so_peercred =10001;
 | 
				
			||||||
		private PeerCredData data;
 | 
					    private PeerCredData data;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public PeerCred (Socket sock) {
 | 
					    public PeerCred (Socket sock) {
 | 
				
			||||||
			if (sock.AddressFamily != AddressFamily.Unix) {
 | 
					      if (sock.AddressFamily != AddressFamily.Unix) {
 | 
				
			||||||
				throw new ArgumentException ("Only Unix sockets are supported", "sock");
 | 
					        throw new ArgumentException ("Only Unix sockets are supported", "sock");
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			data = (PeerCredData)
 | 
					      this.data = (PeerCredData)
 | 
				
			||||||
				sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
 | 
					        sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public int ProcessID {
 | 
					    public Int32 ProcessID => this.data.pid;
 | 
				
			||||||
			get {
 | 
					
 | 
				
			||||||
				return(data.pid);
 | 
					    public Int32 UserID => this.data.uid;
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Int32 GroupID => this.data.gid;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		public int UserID {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return(data.uid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public int GroupID {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return(data.gid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -34,373 +34,424 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class StdioFileStream : Stream
 | 
					  public class StdioFileStream : Stream
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		public static readonly IntPtr InvalidFileStream  = IntPtr.Zero;
 | 
					    public static readonly IntPtr InvalidFileStream  = IntPtr.Zero;
 | 
				
			||||||
		public static readonly IntPtr StandardInput  = Native.Stdlib.stdin;
 | 
					    public static readonly IntPtr StandardInput  = Native.Stdlib.stdin;
 | 
				
			||||||
		public static readonly IntPtr StandardOutput = Native.Stdlib.stdout;
 | 
					    public static readonly IntPtr StandardOutput = Native.Stdlib.stdout;
 | 
				
			||||||
		public static readonly IntPtr StandardError  = Native.Stdlib.stderr;
 | 
					    public static readonly IntPtr StandardError  = Native.Stdlib.stderr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (IntPtr fileStream)
 | 
					    public StdioFileStream (IntPtr fileStream)
 | 
				
			||||||
			: this (fileStream, true) {}
 | 
					      : this (fileStream, true) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public StdioFileStream(IntPtr fileStream, Boolean ownsHandle) => this.InitStream(fileStream, ownsHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public StdioFileStream (IntPtr fileStream, FileAccess access)
 | 
				
			||||||
 | 
					      : this (fileStream, access, true) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (IntPtr fileStream, bool ownsHandle)
 | 
					    public StdioFileStream (IntPtr fileStream, FileAccess access, Boolean ownsHandle)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			InitStream (fileStream, ownsHandle);
 | 
					      this.InitStream (fileStream, ownsHandle);
 | 
				
			||||||
		}
 | 
					      this.InitCanReadWrite (access);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (IntPtr fileStream, FileAccess access)
 | 
					    public StdioFileStream (String path)
 | 
				
			||||||
			: this (fileStream, access, true) {}
 | 
					    {
 | 
				
			||||||
 | 
					      if (path == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.InitStream (Fopen (path, "rb"), true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (IntPtr fileStream, FileAccess access, bool ownsHandle)
 | 
					    public StdioFileStream (String path, String mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			InitStream (fileStream, ownsHandle);
 | 
					      if (path == null) {
 | 
				
			||||||
			InitCanReadWrite (access);
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.InitStream (Fopen (path, mode), true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (string path)
 | 
					    public StdioFileStream (String path, FileMode mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (path == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
			InitStream (Fopen (path, "rb"), true);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      this.InitStream (Fopen (path, ToFopenMode (path, mode)), true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (string path, string mode)
 | 
					    public StdioFileStream (String path, FileAccess access)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (path == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
			InitStream (Fopen (path, mode), true);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      this.InitStream (Fopen (path, ToFopenMode (path, access)), true);
 | 
				
			||||||
 | 
					      this.InitCanReadWrite (access);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (string path, FileMode mode)
 | 
					    public StdioFileStream (String path, FileMode mode, FileAccess access)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (path == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
			InitStream (Fopen (path, ToFopenMode (path, mode)), true);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      this.InitStream (Fopen (path, ToFopenMode (path, mode, access)), true);
 | 
				
			||||||
 | 
					      this.InitCanReadWrite (access);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (string path, FileAccess access)
 | 
					    private static IntPtr Fopen (String path, String mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (path.Length == 0) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentException ("path");
 | 
				
			||||||
			InitStream (Fopen (path, ToFopenMode (path, access)), true);
 | 
					      }
 | 
				
			||||||
			InitCanReadWrite (access);
 | 
					
 | 
				
			||||||
		}
 | 
					      if (mode == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("mode");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      IntPtr f = Native.Stdlib.fopen (path, mode);
 | 
				
			||||||
 | 
					      if (f == IntPtr.Zero) {
 | 
				
			||||||
 | 
					        throw new DirectoryNotFoundException ("path", 
 | 
				
			||||||
 | 
					            UnixMarshal.CreateExceptionForLastError ());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public StdioFileStream (string path, FileMode mode, FileAccess access)
 | 
					    private void InitStream (IntPtr fileStream, Boolean ownsHandle)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (InvalidFileStream == fileStream) {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
 | 
				
			||||||
			InitStream (Fopen (path, ToFopenMode (path, mode, access)), true);
 | 
					      }
 | 
				
			||||||
			InitCanReadWrite (access);
 | 
					
 | 
				
			||||||
		}
 | 
					      this.file = fileStream;
 | 
				
			||||||
 | 
					      this.owner = ownsHandle;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        Int64 offset = Native.Stdlib.fseek (this.file, 0, Native.SeekFlags.SEEK_CUR);
 | 
				
			||||||
 | 
					        if (offset != -1) {
 | 
				
			||||||
 | 
					          this.canSeek = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = Native.Stdlib.fread(IntPtr.Zero, 0, 0, this.file);
 | 
				
			||||||
 | 
					        if (Native.Stdlib.ferror (this.file) == 0) {
 | 
				
			||||||
 | 
					          this.canRead = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = Native.Stdlib.fwrite(IntPtr.Zero, 0, 0, this.file);
 | 
				
			||||||
 | 
					        if (Native.Stdlib.ferror (this.file) == 0) {
 | 
				
			||||||
 | 
					          this.canWrite = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = Native.Stdlib.clearerr(this.file);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      catch (Exception) {
 | 
				
			||||||
 | 
					        throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static IntPtr Fopen (string path, string mode)
 | 
					    private void InitCanReadWrite (FileAccess access)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path.Length == 0)
 | 
					      this.canRead = this.canRead && 
 | 
				
			||||||
				throw new ArgumentException ("path");
 | 
					        (access == FileAccess.Read || access == FileAccess.ReadWrite);
 | 
				
			||||||
			if (mode == null)
 | 
					      this.canWrite = this.canWrite &&
 | 
				
			||||||
				throw new ArgumentNullException ("mode");
 | 
					        (access == FileAccess.Write || access == FileAccess.ReadWrite);
 | 
				
			||||||
			IntPtr f = Native.Stdlib.fopen (path, mode);
 | 
					    }
 | 
				
			||||||
			if (f == IntPtr.Zero)
 | 
					 | 
				
			||||||
				throw new DirectoryNotFoundException ("path", 
 | 
					 | 
				
			||||||
						UnixMarshal.CreateExceptionForLastError ());
 | 
					 | 
				
			||||||
			return f;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void InitStream (IntPtr fileStream, bool ownsHandle)
 | 
					    private static String ToFopenMode (String file, FileMode mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (InvalidFileStream == fileStream)
 | 
					      String cmode = Native.NativeConvert.ToFopenMode (mode);
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
 | 
					      _ = AssertFileMode(file, mode);
 | 
				
			||||||
			
 | 
					      return cmode;
 | 
				
			||||||
			this.file = fileStream;
 | 
					    }
 | 
				
			||||||
			this.owner = ownsHandle;
 | 
					
 | 
				
			||||||
			
 | 
					    private static String ToFopenMode(String file, FileAccess access) => Native.NativeConvert.ToFopenMode(access);
 | 
				
			||||||
			try {
 | 
					
 | 
				
			||||||
				long offset = Native.Stdlib.fseek (file, 0, Native.SeekFlags.SEEK_CUR);
 | 
					    private static String ToFopenMode (String file, FileMode mode, FileAccess access)
 | 
				
			||||||
				if (offset != -1)
 | 
					    {
 | 
				
			||||||
					canSeek = true;
 | 
					      String cmode = Native.NativeConvert.ToFopenMode (mode, access);
 | 
				
			||||||
				Native.Stdlib.fread (IntPtr.Zero, 0, 0, file);
 | 
					      Boolean exists = AssertFileMode (file, mode);
 | 
				
			||||||
				if (Native.Stdlib.ferror (file) == 0)
 | 
					      // HACK: for open-or-create & read, mode is "rb", which doesn't create
 | 
				
			||||||
					canRead = true;
 | 
					      // files.  If the file doesn't exist, we need to use "w+b" to ensure
 | 
				
			||||||
				Native.Stdlib.fwrite (IntPtr.Zero, 0, 0, file);
 | 
					      // file creation.
 | 
				
			||||||
				if (Native.Stdlib.ferror (file) == 0)
 | 
					      if (mode == FileMode.OpenOrCreate && access == FileAccess.Read && !exists) {
 | 
				
			||||||
					canWrite = true;  
 | 
					        cmode = "w+b";
 | 
				
			||||||
				Native.Stdlib.clearerr (file);
 | 
					      }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			catch (Exception) {
 | 
					      return cmode;
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
 | 
					    }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void InitCanReadWrite (FileAccess access)
 | 
					    private static Boolean AssertFileMode (String file, FileMode mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			canRead = canRead && 
 | 
					      Boolean exists = FileExists (file);
 | 
				
			||||||
				(access == FileAccess.Read || access == FileAccess.ReadWrite);
 | 
					      if (mode == FileMode.CreateNew && exists) {
 | 
				
			||||||
			canWrite = canWrite &&
 | 
					        throw new IOException ("File exists and FileMode.CreateNew specified");
 | 
				
			||||||
				(access == FileAccess.Write || access == FileAccess.ReadWrite);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      if ((mode == FileMode.Open || mode == FileMode.Truncate) && !exists) {
 | 
				
			||||||
 | 
					        throw new FileNotFoundException ("File doesn't exist and FileMode.Open specified", file);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return exists;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static string ToFopenMode (string file, FileMode mode)
 | 
					    private static Boolean FileExists (String file)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			string cmode = Native.NativeConvert.ToFopenMode (mode);
 | 
					      Boolean found = false;
 | 
				
			||||||
			AssertFileMode (file, mode);
 | 
					      IntPtr f = Native.Stdlib.fopen (file, "r");
 | 
				
			||||||
			return cmode;
 | 
					      found = f != IntPtr.Zero;
 | 
				
			||||||
		}
 | 
					      if (f != IntPtr.Zero) {
 | 
				
			||||||
 | 
					        _ = Native.Stdlib.fclose(f);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return found;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static string ToFopenMode (string file, FileAccess access)
 | 
					    private void AssertNotDisposed ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			return Native.NativeConvert.ToFopenMode (access);
 | 
					      if (this.file == InvalidFileStream) {
 | 
				
			||||||
		}
 | 
					        throw new ObjectDisposedException ("Invalid File Stream");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static string ToFopenMode (string file, FileMode mode, FileAccess access)
 | 
					    public IntPtr Handle {
 | 
				
			||||||
		{
 | 
					      get {
 | 
				
			||||||
			string cmode = Native.NativeConvert.ToFopenMode (mode, access);
 | 
					        this.AssertNotDisposed (); 
 | 
				
			||||||
			bool exists = AssertFileMode (file, mode);
 | 
					        GC.KeepAlive (this);
 | 
				
			||||||
			// HACK: for open-or-create & read, mode is "rb", which doesn't create
 | 
					        return this.file;
 | 
				
			||||||
			// files.  If the file doesn't exist, we need to use "w+b" to ensure
 | 
					      }
 | 
				
			||||||
			// file creation.
 | 
					    }
 | 
				
			||||||
			if (mode == FileMode.OpenOrCreate && access == FileAccess.Read && !exists)
 | 
					
 | 
				
			||||||
				cmode = "w+b";
 | 
					    public override Boolean CanRead => this.canRead;
 | 
				
			||||||
			return cmode;
 | 
					
 | 
				
			||||||
		}
 | 
					    public override Boolean CanSeek => this.canSeek;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override Boolean CanWrite => this.canWrite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override Int64 Length {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					        if (!this.CanSeek) {
 | 
				
			||||||
 | 
					          throw new NotSupportedException ("File Stream doesn't support seeking");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Int64 curPos = Native.Stdlib.ftell (this.file);
 | 
				
			||||||
 | 
					        if (curPos == -1) {
 | 
				
			||||||
 | 
					          throw new NotSupportedException ("Unable to obtain current file position");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Int32 r = Native.Stdlib.fseek (this.file, 0, Native.SeekFlags.SEEK_END);
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Int64 endPos = Native.Stdlib.ftell (this.file);
 | 
				
			||||||
 | 
					        if (endPos == -1) {
 | 
				
			||||||
 | 
					          UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r = Native.Stdlib.fseek (this.file, curPos, Native.SeekFlags.SEEK_SET);
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static bool AssertFileMode (string file, FileMode mode)
 | 
					        GC.KeepAlive (this);
 | 
				
			||||||
		{
 | 
					        return endPos;
 | 
				
			||||||
			bool exists = FileExists (file);
 | 
					      }
 | 
				
			||||||
			if (mode == FileMode.CreateNew && exists)
 | 
					    }
 | 
				
			||||||
				throw new IOException ("File exists and FileMode.CreateNew specified");
 | 
					 | 
				
			||||||
			if ((mode == FileMode.Open || mode == FileMode.Truncate) && !exists)
 | 
					 | 
				
			||||||
				throw new FileNotFoundException ("File doesn't exist and FileMode.Open specified", file);
 | 
					 | 
				
			||||||
			return exists;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static bool FileExists (string file)
 | 
					    public override Int64 Position {
 | 
				
			||||||
		{
 | 
					      get {
 | 
				
			||||||
			bool found = false;
 | 
					        this.AssertNotDisposed ();
 | 
				
			||||||
			IntPtr f = Native.Stdlib.fopen (file, "r");
 | 
					        if (!this.CanSeek) {
 | 
				
			||||||
			found = f != IntPtr.Zero;
 | 
					          throw new NotSupportedException ("The stream does not support seeking");
 | 
				
			||||||
			if (f != IntPtr.Zero)
 | 
					        }
 | 
				
			||||||
				Native.Stdlib.fclose (f);
 | 
					
 | 
				
			||||||
			return found;
 | 
					        Int64 pos = Native.Stdlib.ftell (this.file);
 | 
				
			||||||
		}
 | 
					        if (pos == -1) {
 | 
				
			||||||
 | 
					          UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GC.KeepAlive (this);
 | 
				
			||||||
 | 
					        return (Int64) pos;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      set {
 | 
				
			||||||
 | 
					        this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					        _ = this.Seek(value, SeekOrigin.Begin);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void AssertNotDisposed ()
 | 
					    public void SaveFilePosition (Native.FilePosition pos)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (file == InvalidFileStream)
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
				throw new ObjectDisposedException ("Invalid File Stream");
 | 
					      Int32 r = Native.Stdlib.fgetpos (this.file, pos);
 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IntPtr Handle {
 | 
					    public void RestoreFilePosition (Native.FilePosition pos)
 | 
				
			||||||
			get {
 | 
					    {
 | 
				
			||||||
				AssertNotDisposed (); 
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
				GC.KeepAlive (this);
 | 
					      if (pos == null) {
 | 
				
			||||||
				return file;
 | 
					        throw new ArgumentNullException ("value");
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      Int32 r = Native.Stdlib.fsetpos (this.file, pos);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanRead {
 | 
					    public override void Flush ()
 | 
				
			||||||
			get {return canRead;}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					      Int32 r = Native.Stdlib.fflush (this.file);
 | 
				
			||||||
 | 
					      if (r != 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanSeek {
 | 
					    public override unsafe Int32 Read ([In, Out] Byte[] buffer, Int32 offset, Int32 count)
 | 
				
			||||||
			get {return canSeek;}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					      this.AssertValidBuffer (buffer, offset, count);
 | 
				
			||||||
 | 
					      if (!this.CanRead) {
 | 
				
			||||||
 | 
					        throw new NotSupportedException ("Stream does not support reading");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      UInt64 r = 0;
 | 
				
			||||||
 | 
					      fixed (Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        r = Native.Stdlib.fread (buf, 1, (UInt64) count, this.file);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (r != (UInt64) count) {
 | 
				
			||||||
 | 
					        if (Native.Stdlib.ferror (this.file) != 0) {
 | 
				
			||||||
 | 
					          throw new IOException ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					      return (Int32) r;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanWrite {
 | 
					    private void AssertValidBuffer (Byte[] buffer, Int32 offset, Int32 count)
 | 
				
			||||||
			get {return canWrite;}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      if (buffer == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("buffer");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (offset < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("offset", "< 0");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (count < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("count", "< 0");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (offset > buffer.Length) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("destination offset is beyond array size");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (offset > buffer.Length - count) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("would overrun buffer");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override long Length {
 | 
					    public void Rewind ()
 | 
				
			||||||
			get {
 | 
					    {
 | 
				
			||||||
				AssertNotDisposed ();
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
				if (!CanSeek)
 | 
					      _ = Native.Stdlib.rewind(this.file);
 | 
				
			||||||
					throw new NotSupportedException ("File Stream doesn't support seeking");
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
				long curPos = Native.Stdlib.ftell (file);
 | 
					    }
 | 
				
			||||||
				if (curPos == -1)
 | 
					 | 
				
			||||||
					throw new NotSupportedException ("Unable to obtain current file position");
 | 
					 | 
				
			||||||
				int r = Native.Stdlib.fseek (file, 0, Native.SeekFlags.SEEK_END);
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				long endPos = Native.Stdlib.ftell (file);
 | 
					    public override Int64 Seek (Int64 offset, SeekOrigin origin)
 | 
				
			||||||
				if (endPos == -1)
 | 
					    {
 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					      if (!this.CanSeek) {
 | 
				
			||||||
 | 
					        throw new NotSupportedException ("The File Stream does not support seeking");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
 | 
				
			||||||
 | 
					      switch (origin) {
 | 
				
			||||||
 | 
					        case SeekOrigin.Begin:   sf = Native.SeekFlags.SEEK_SET; break;
 | 
				
			||||||
 | 
					        case SeekOrigin.Current: sf = Native.SeekFlags.SEEK_CUR; break;
 | 
				
			||||||
 | 
					        case SeekOrigin.End:     sf = Native.SeekFlags.SEEK_END; break;
 | 
				
			||||||
 | 
					        default: throw new ArgumentException ("origin");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 r = Native.Stdlib.fseek (this.file, offset, sf);
 | 
				
			||||||
 | 
					      if (r != 0) {
 | 
				
			||||||
 | 
					        throw new IOException ("Unable to seek",
 | 
				
			||||||
 | 
					            UnixMarshal.CreateExceptionForLastError ());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int64 pos = Native.Stdlib.ftell (this.file);
 | 
				
			||||||
 | 
					      if (pos == -1) {
 | 
				
			||||||
 | 
					        throw new IOException ("Unable to get current file position",
 | 
				
			||||||
 | 
					            UnixMarshal.CreateExceptionForLastError ());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					      return pos;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void SetLength(Int64 value) => throw new NotSupportedException("ANSI C doesn't provide a way to truncate a file");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override unsafe void Write (Byte[] buffer, Int32 offset, Int32 count)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      this.AssertNotDisposed ();
 | 
				
			||||||
 | 
					      this.AssertValidBuffer (buffer, offset, count);
 | 
				
			||||||
 | 
					      if (!this.CanWrite) {
 | 
				
			||||||
 | 
					        throw new NotSupportedException ("File Stream does not support writing");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      UInt64 r = 0;
 | 
				
			||||||
 | 
					      fixed (Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        r = Native.Stdlib.fwrite (buf, (UInt64) 1, (UInt64) count, this.file);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (r != (UInt64) count) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ~StdioFileStream ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      this.Close ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				r = Native.Stdlib.fseek (file, curPos, Native.SeekFlags.SEEK_SET);
 | 
					    public override void Close ()
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    {
 | 
				
			||||||
 | 
					      if (this.file == InvalidFileStream) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (this.owner) {
 | 
				
			||||||
 | 
					        Int32 r = Native.Stdlib.fclose (this.file);
 | 
				
			||||||
 | 
					        if (r != 0) {
 | 
				
			||||||
 | 
					          UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        this.Flush ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.file = InvalidFileStream;
 | 
				
			||||||
 | 
					      this.canRead = false;
 | 
				
			||||||
 | 
					      this.canSeek = false;
 | 
				
			||||||
 | 
					      this.canWrite = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				GC.KeepAlive (this);
 | 
					      GC.SuppressFinalize (this);
 | 
				
			||||||
				return endPos;
 | 
					      GC.KeepAlive (this);
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
		}
 | 
					    
 | 
				
			||||||
 | 
					    private Boolean canSeek  = false;
 | 
				
			||||||
		public override long Position {
 | 
					    private Boolean canRead  = false;
 | 
				
			||||||
			get {
 | 
					    private Boolean canWrite = false;
 | 
				
			||||||
				AssertNotDisposed ();
 | 
					    private Boolean owner    = true;
 | 
				
			||||||
				if (!CanSeek)
 | 
					    private IntPtr file   = InvalidFileStream;
 | 
				
			||||||
					throw new NotSupportedException ("The stream does not support seeking");
 | 
					  }
 | 
				
			||||||
				long pos = Native.Stdlib.ftell (file);
 | 
					 | 
				
			||||||
				if (pos == -1)
 | 
					 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
				GC.KeepAlive (this);
 | 
					 | 
				
			||||||
				return (long) pos;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			set {
 | 
					 | 
				
			||||||
				AssertNotDisposed ();
 | 
					 | 
				
			||||||
				Seek (value, SeekOrigin.Begin);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void SaveFilePosition (Native.FilePosition pos)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			int r = Native.Stdlib.fgetpos (file, pos);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void RestoreFilePosition (Native.FilePosition pos)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			if (pos == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("value");
 | 
					 | 
				
			||||||
			int r = Native.Stdlib.fsetpos (file, pos);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override void Flush ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			int r = Native.Stdlib.fflush (file);
 | 
					 | 
				
			||||||
			if (r != 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override unsafe int Read ([In, Out] byte[] buffer, int offset, int count)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					 | 
				
			||||||
			if (!CanRead)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("Stream does not support reading");
 | 
					 | 
				
			||||||
				 
 | 
					 | 
				
			||||||
			ulong r = 0;
 | 
					 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					 | 
				
			||||||
				r = Native.Stdlib.fread (buf, 1, (ulong) count, file);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (r != (ulong) count) {
 | 
					 | 
				
			||||||
				if (Native.Stdlib.ferror (file) != 0)
 | 
					 | 
				
			||||||
					throw new IOException ();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
			return (int) r;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void AssertValidBuffer (byte[] buffer, int offset, int count)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (buffer == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("buffer");
 | 
					 | 
				
			||||||
			if (offset < 0)
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("offset", "< 0");
 | 
					 | 
				
			||||||
			if (count < 0)
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("count", "< 0");
 | 
					 | 
				
			||||||
			if (offset > buffer.Length)
 | 
					 | 
				
			||||||
				throw new ArgumentException ("destination offset is beyond array size");
 | 
					 | 
				
			||||||
			if (offset > (buffer.Length - count))
 | 
					 | 
				
			||||||
				throw new ArgumentException ("would overrun buffer");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void Rewind ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			Native.Stdlib.rewind (file);
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override long Seek (long offset, SeekOrigin origin)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			if (!CanSeek)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("The File Stream does not support seeking");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
 | 
					 | 
				
			||||||
			switch (origin) {
 | 
					 | 
				
			||||||
				case SeekOrigin.Begin:   sf = Native.SeekFlags.SEEK_SET; break;
 | 
					 | 
				
			||||||
				case SeekOrigin.Current: sf = Native.SeekFlags.SEEK_CUR; break;
 | 
					 | 
				
			||||||
				case SeekOrigin.End:     sf = Native.SeekFlags.SEEK_END; break;
 | 
					 | 
				
			||||||
				default: throw new ArgumentException ("origin");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			int r = Native.Stdlib.fseek (file, offset, sf);
 | 
					 | 
				
			||||||
			if (r != 0)
 | 
					 | 
				
			||||||
				throw new IOException ("Unable to seek",
 | 
					 | 
				
			||||||
						UnixMarshal.CreateExceptionForLastError ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			long pos = Native.Stdlib.ftell (file);
 | 
					 | 
				
			||||||
			if (pos == -1)
 | 
					 | 
				
			||||||
				throw new IOException ("Unable to get current file position",
 | 
					 | 
				
			||||||
						UnixMarshal.CreateExceptionForLastError ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
			return pos;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override void SetLength (long value)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw new NotSupportedException ("ANSI C doesn't provide a way to truncate a file");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override unsafe void Write (byte[] buffer, int offset, int count)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					 | 
				
			||||||
			if (!CanWrite)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("File Stream does not support writing");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			ulong r = 0;
 | 
					 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					 | 
				
			||||||
				r = Native.Stdlib.fwrite (buf, (ulong) 1, (ulong) count, file);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (r != (ulong) count)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		~StdioFileStream ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Close ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override void Close ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (file == InvalidFileStream)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (owner) {
 | 
					 | 
				
			||||||
				int r = Native.Stdlib.fclose (file);
 | 
					 | 
				
			||||||
				if (r != 0)
 | 
					 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			} else
 | 
					 | 
				
			||||||
				Flush ();
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
			file = InvalidFileStream;
 | 
					 | 
				
			||||||
			canRead = false;
 | 
					 | 
				
			||||||
			canSeek = false;
 | 
					 | 
				
			||||||
			canWrite = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			GC.SuppressFinalize (this);
 | 
					 | 
				
			||||||
			GC.KeepAlive (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		private bool canSeek  = false;
 | 
					 | 
				
			||||||
		private bool canRead  = false;
 | 
					 | 
				
			||||||
		private bool canWrite = false;
 | 
					 | 
				
			||||||
		private bool owner    = true;
 | 
					 | 
				
			||||||
		private IntPtr file   = InvalidFileStream;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -35,196 +35,198 @@ using System.Runtime.InteropServices;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class UnixClient : MarshalByRefObject, IDisposable {
 | 
					  public class UnixClient : MarshalByRefObject, IDisposable {
 | 
				
			||||||
		NetworkStream stream;
 | 
					    NetworkStream stream;
 | 
				
			||||||
		Socket client;
 | 
					    Socket client;
 | 
				
			||||||
		bool disposed;
 | 
					    Boolean disposed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixClient ()
 | 
					    public UnixClient ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (client != null) {
 | 
					      if (this.client != null) {
 | 
				
			||||||
				client.Close ();
 | 
					        this.client.Close ();
 | 
				
			||||||
				client = null;
 | 
					        this.client = null;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.client = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			client = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
					    public UnixClient (String path) : this ()
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      if (path == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("ep");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.Connect (path);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixClient (string path) : this ()
 | 
					    public UnixClient (UnixEndPoint ep) : this ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      if (ep == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("ep");
 | 
					        throw new ArgumentNullException ("ep");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
			Connect (path);
 | 
					
 | 
				
			||||||
		}
 | 
					      this.Connect (ep);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public UnixClient (UnixEndPoint ep) : this ()
 | 
					
 | 
				
			||||||
		{
 | 
					    // UnixListener uses this when accepting a connection.
 | 
				
			||||||
			if (ep == null)
 | 
					    internal UnixClient(Socket sock) => this.Client = sock;
 | 
				
			||||||
				throw new ArgumentNullException ("ep");
 | 
					
 | 
				
			||||||
 | 
					    public
 | 
				
			||||||
			Connect (ep);
 | 
					    Socket Client {
 | 
				
			||||||
		}
 | 
					      get => this.client;
 | 
				
			||||||
 | 
					      set {
 | 
				
			||||||
		// UnixListener uses this when accepting a connection.
 | 
					        this.client = value;
 | 
				
			||||||
		internal UnixClient (Socket sock)
 | 
					        this.stream = null;
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			Client = sock;
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public PeerCred PeerCredential {
 | 
				
			||||||
		public
 | 
					      get {
 | 
				
			||||||
		Socket Client {
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
			get { return client; }
 | 
					        return new PeerCred (this.client);
 | 
				
			||||||
			set {
 | 
					      }
 | 
				
			||||||
				client = value;
 | 
					    }
 | 
				
			||||||
				stream = null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public PeerCred PeerCredential {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				CheckDisposed ();
 | 
					 | 
				
			||||||
				return new PeerCred (client);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public LingerOption LingerState {
 | 
					    public LingerOption LingerState {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				return (LingerOption) client.GetSocketOption (SocketOptionLevel.Socket,
 | 
					        return (LingerOption)this.client.GetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
									      SocketOptionName.Linger);
 | 
					                        SocketOptionName.Linger);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				client.SetSocketOption (SocketOptionLevel.Socket,
 | 
					        this.client.SetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
							SocketOptionName.Linger, value);
 | 
					              SocketOptionName.Linger, value);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int ReceiveBufferSize {
 | 
					    public Int32 ReceiveBufferSize {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				return (int) client.GetSocketOption (SocketOptionLevel.Socket,
 | 
					        return (Int32)this.client.GetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
								     SocketOptionName.ReceiveBuffer);
 | 
					                     SocketOptionName.ReceiveBuffer);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				client.SetSocketOption (SocketOptionLevel.Socket,
 | 
					        this.client.SetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
							SocketOptionName.ReceiveBuffer, value);
 | 
					              SocketOptionName.ReceiveBuffer, value);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
		public int ReceiveTimeout {
 | 
					    public Int32 ReceiveTimeout {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				return (int) client.GetSocketOption (SocketOptionLevel.Socket,
 | 
					        return (Int32)this.client.GetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
								     SocketOptionName.ReceiveTimeout);
 | 
					                     SocketOptionName.ReceiveTimeout);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				client.SetSocketOption (SocketOptionLevel.Socket,
 | 
					        this.client.SetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
							SocketOptionName.ReceiveTimeout, value);
 | 
					              SocketOptionName.ReceiveTimeout, value);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public int SendBufferSize {
 | 
					    public Int32 SendBufferSize {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				return (int) client.GetSocketOption (SocketOptionLevel.Socket,
 | 
					        return (Int32)this.client.GetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
								     SocketOptionName.SendBuffer);
 | 
					                     SocketOptionName.SendBuffer);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				client.SetSocketOption (SocketOptionLevel.Socket,
 | 
					        this.client.SetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
							SocketOptionName.SendBuffer, value);
 | 
					              SocketOptionName.SendBuffer, value);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public int SendTimeout {
 | 
					    public Int32 SendTimeout {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				return (int) client.GetSocketOption (SocketOptionLevel.Socket,
 | 
					        return (Int32)this.client.GetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
								     SocketOptionName.SendTimeout);
 | 
					                     SocketOptionName.SendTimeout);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				CheckDisposed ();
 | 
					        this.CheckDisposed ();
 | 
				
			||||||
				client.SetSocketOption (SocketOptionLevel.Socket,
 | 
					        this.client.SetSocketOption (SocketOptionLevel.Socket,
 | 
				
			||||||
							SocketOptionName.SendTimeout, value);
 | 
					              SocketOptionName.SendTimeout, value);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public void Close ()
 | 
					    public void Close ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			CheckDisposed ();
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
			Dispose ();
 | 
					      this.Dispose ();
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public void Connect (UnixEndPoint remoteEndPoint)
 | 
					    public void Connect (UnixEndPoint remoteEndPoint)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			CheckDisposed ();
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
			client.Connect (remoteEndPoint);
 | 
					      this.client.Connect (remoteEndPoint);
 | 
				
			||||||
			stream = new NetworkStream (client, true);
 | 
					      this.stream = new NetworkStream (this.client, true);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public void Connect (string path)
 | 
					    public void Connect (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			CheckDisposed ();
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
			Connect (new UnixEndPoint (path));
 | 
					      this.Connect (new UnixEndPoint (path));
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public void Dispose ()
 | 
					    public void Dispose ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Dispose (true);
 | 
					      this.Dispose (true);
 | 
				
			||||||
			GC.SuppressFinalize (this);
 | 
					      GC.SuppressFinalize (this);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected virtual void Dispose (bool disposing)
 | 
					    protected virtual void Dispose (Boolean disposing)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (disposed)
 | 
					      if (this.disposed) {
 | 
				
			||||||
				return;
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (disposing) {
 | 
				
			||||||
 | 
					        // release managed resources
 | 
				
			||||||
 | 
					        NetworkStream s = this.stream;
 | 
				
			||||||
 | 
					        this.stream = null;
 | 
				
			||||||
 | 
					        if (s != null) {
 | 
				
			||||||
 | 
					          // This closes the socket as well, as the NetworkStream
 | 
				
			||||||
 | 
					          // owns the socket.
 | 
				
			||||||
 | 
					          s.Close();
 | 
				
			||||||
 | 
					          s = null;
 | 
				
			||||||
 | 
					        } else if (this.client != null){
 | 
				
			||||||
 | 
					          this.client.Close ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.client = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.disposed = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (disposing) {
 | 
					    public NetworkStream GetStream ()
 | 
				
			||||||
				// release managed resources
 | 
					    {
 | 
				
			||||||
				NetworkStream s = stream;
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
				stream = null;
 | 
					      if (this.stream == null) {
 | 
				
			||||||
				if (s != null) {
 | 
					        this.stream = new NetworkStream (this.client, true);
 | 
				
			||||||
					// This closes the socket as well, as the NetworkStream
 | 
					      }
 | 
				
			||||||
					// owns the socket.
 | 
					
 | 
				
			||||||
					s.Close();
 | 
					      return this.stream;
 | 
				
			||||||
					s = null;
 | 
					    }
 | 
				
			||||||
				} else if (client != null){
 | 
					 | 
				
			||||||
					client.Close ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				client = null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			disposed = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public NetworkStream GetStream ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			CheckDisposed ();
 | 
					 | 
				
			||||||
			if (stream == null)
 | 
					 | 
				
			||||||
				stream = new NetworkStream (client, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return stream;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		void CheckDisposed ()
 | 
					    void CheckDisposed ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (disposed)
 | 
					      if (this.disposed) {
 | 
				
			||||||
				throw new ObjectDisposedException (GetType().FullName);
 | 
					        throw new ObjectDisposedException (this.GetType().FullName);
 | 
				
			||||||
		}        
 | 
					      }
 | 
				
			||||||
 | 
					    }        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~UnixClient ()
 | 
					    ~UnixClient ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Dispose (false);
 | 
					      this.Dispose (false);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -35,216 +35,223 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixDirectoryInfo : UnixFileSystemInfo
 | 
					  public sealed class UnixDirectoryInfo : UnixFileSystemInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		public UnixDirectoryInfo (string path)
 | 
					    public UnixDirectoryInfo (String path)
 | 
				
			||||||
			: base (path)
 | 
					      : base (path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixDirectoryInfo (string path, Native.Stat stat)
 | 
					    internal UnixDirectoryInfo (String path, Native.Stat stat)
 | 
				
			||||||
			: base (path, stat)
 | 
					      : base (path, stat)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override string Name {
 | 
					    public override String Name {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				string r = UnixPath.GetFileName (FullPath);
 | 
					        String r = UnixPath.GetFileName (this.FullPath);
 | 
				
			||||||
				if (r == null || r.Length == 0)
 | 
					        return r == null || r.Length == 0 ? this.FullPath : r;
 | 
				
			||||||
					return FullPath;
 | 
					      }
 | 
				
			||||||
				return r;
 | 
					    }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixDirectoryInfo Parent {
 | 
					    public UnixDirectoryInfo Parent {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (FullPath == "/")
 | 
					        if (this.FullPath == "/") {
 | 
				
			||||||
					return this;
 | 
					          return this;
 | 
				
			||||||
				string dirname = UnixPath.GetDirectoryName (FullPath);
 | 
					        }
 | 
				
			||||||
				if (dirname == "")
 | 
					
 | 
				
			||||||
					throw new InvalidOperationException ("Do not know parent directory for path `" + FullPath + "'");
 | 
					        String dirname = UnixPath.GetDirectoryName (this.FullPath);
 | 
				
			||||||
				return new UnixDirectoryInfo (dirname);
 | 
					        if (dirname == "") {
 | 
				
			||||||
			}
 | 
					          throw new InvalidOperationException ("Do not know parent directory for path `" + this.FullPath + "'");
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new UnixDirectoryInfo (dirname);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixDirectoryInfo Root {
 | 
					    public UnixDirectoryInfo Root {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				string root = UnixPath.GetPathRoot (FullPath);
 | 
					        String root = UnixPath.GetPathRoot (this.FullPath);
 | 
				
			||||||
				if (root == null)
 | 
					        return root == null ? null : new UnixDirectoryInfo (root);
 | 
				
			||||||
					return null;
 | 
					      }
 | 
				
			||||||
				return new UnixDirectoryInfo (root);
 | 
					    }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
		public void Create (Mono.Unix.Native.FilePermissions mode)
 | 
					    public void Create (Mono.Unix.Native.FilePermissions mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Mono.Unix.Native.Syscall.mkdir (FullPath, mode);
 | 
					      Int32 r = Mono.Unix.Native.Syscall.mkdir (this.FullPath, mode);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			base.Refresh ();
 | 
					      base.Refresh ();
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Create(FileAccessPermissions mode) => this.Create((Native.FilePermissions)mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Create ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Mono.Unix.Native.FilePermissions mode = 
 | 
				
			||||||
 | 
					        Mono.Unix.Native.FilePermissions.ACCESSPERMS;
 | 
				
			||||||
 | 
					      this.Create (mode);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void Delete() => this.Delete(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Delete (Boolean recursive)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (recursive) {
 | 
				
			||||||
 | 
					        foreach (UnixFileSystemInfo e in this.GetFileSystemEntries ()) {
 | 
				
			||||||
 | 
					          UnixDirectoryInfo d = e as UnixDirectoryInfo;
 | 
				
			||||||
 | 
					          if (d != null) {
 | 
				
			||||||
 | 
					            d.Delete (true);
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            e.Delete ();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Int32 r = Native.Syscall.rmdir (this.FullPath);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      base.Refresh ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Create (FileAccessPermissions mode)
 | 
					    public Native.Dirent[] GetEntries ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Create ((Native.FilePermissions) mode);
 | 
					      IntPtr dirp = Native.Syscall.opendir (this.FullPath);
 | 
				
			||||||
		}
 | 
					      if (dirp == IntPtr.Zero) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Boolean complete = false;
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        Native.Dirent[] entries = GetEntries (dirp);
 | 
				
			||||||
 | 
					        complete = true;
 | 
				
			||||||
 | 
					        return entries;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      finally {
 | 
				
			||||||
 | 
					        Int32 r = Native.Syscall.closedir (dirp);
 | 
				
			||||||
 | 
					        // don't throw an exception if an exception is in progress
 | 
				
			||||||
 | 
					        if (complete) {
 | 
				
			||||||
 | 
					          UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Create ()
 | 
					    private static Native.Dirent[] GetEntries (IntPtr dirp)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Mono.Unix.Native.FilePermissions mode = 
 | 
					      ArrayList entries = new ArrayList ();
 | 
				
			||||||
				Mono.Unix.Native.FilePermissions.ACCESSPERMS;
 | 
					
 | 
				
			||||||
			Create (mode);
 | 
					      Int32 r;
 | 
				
			||||||
		}
 | 
					      IntPtr result;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        Native.Dirent d = new Native.Dirent ();
 | 
				
			||||||
 | 
					        r = Native.Syscall.readdir_r (dirp, d, out result);
 | 
				
			||||||
 | 
					        if (r == 0 && result != IntPtr.Zero) {
 | 
				
			||||||
 | 
					          // don't include current & parent dirs
 | 
				
			||||||
 | 
					          if (d.d_name != "." && d.d_name != "..") {
 | 
				
			||||||
 | 
					            _ = entries.Add(d);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } while  (r == 0 && result != IntPtr.Zero);
 | 
				
			||||||
 | 
					      if (r != 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void Delete ()
 | 
					    public Native.Dirent[] GetEntries (Regex regex)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Delete (false);
 | 
					      IntPtr dirp = Native.Syscall.opendir (this.FullPath);
 | 
				
			||||||
		}
 | 
					      if (dirp == IntPtr.Zero) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        return GetEntries (dirp, regex);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      finally {
 | 
				
			||||||
 | 
					        Int32 r = Native.Syscall.closedir (dirp);
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Delete (bool recursive)
 | 
					    private static Native.Dirent[] GetEntries (IntPtr dirp, Regex regex)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (recursive) {
 | 
					      ArrayList entries = new ArrayList ();
 | 
				
			||||||
				foreach (UnixFileSystemInfo e in GetFileSystemEntries ()) {
 | 
					
 | 
				
			||||||
					UnixDirectoryInfo d = e as UnixDirectoryInfo;
 | 
					      Int32 r;
 | 
				
			||||||
					if (d != null)
 | 
					      IntPtr result;
 | 
				
			||||||
						d.Delete (true);
 | 
					      do {
 | 
				
			||||||
					else
 | 
					        Native.Dirent d = new Native.Dirent ();
 | 
				
			||||||
						e.Delete ();
 | 
					        r = Native.Syscall.readdir_r (dirp, d, out result);
 | 
				
			||||||
				}
 | 
					        if (r == 0 && result != IntPtr.Zero && regex.Match (d.d_name).Success) {
 | 
				
			||||||
			}
 | 
					          // don't include current & parent dirs
 | 
				
			||||||
			int r = Native.Syscall.rmdir (FullPath);
 | 
					          if (d.d_name != "." && d.d_name != "..") {
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					            _ = entries.Add(d);
 | 
				
			||||||
			base.Refresh ();
 | 
					          }
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					      } while  (r == 0 && result != IntPtr.Zero);
 | 
				
			||||||
 | 
					      if (r != 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Native.Dirent[] GetEntries ()
 | 
					    public Native.Dirent[] GetEntries (String regex)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			IntPtr dirp = Native.Syscall.opendir (FullPath);
 | 
					      Regex re = new Regex (regex);
 | 
				
			||||||
			if (dirp == IntPtr.Zero)
 | 
					      return this.GetEntries (re);
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool complete = false;
 | 
					    public UnixFileSystemInfo[] GetFileSystemEntries ()
 | 
				
			||||||
			try {
 | 
					    {
 | 
				
			||||||
				Native.Dirent[] entries = GetEntries (dirp);
 | 
					      Native.Dirent[] dentries = this.GetEntries ();
 | 
				
			||||||
				complete = true;
 | 
					      return this.GetFileSystemEntries (dentries);
 | 
				
			||||||
				return entries;
 | 
					    }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			finally {
 | 
					 | 
				
			||||||
				int r = Native.Syscall.closedir (dirp);
 | 
					 | 
				
			||||||
				// don't throw an exception if an exception is in progress
 | 
					 | 
				
			||||||
				if (complete)
 | 
					 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static Native.Dirent[] GetEntries (IntPtr dirp)
 | 
					    private UnixFileSystemInfo[] GetFileSystemEntries (Native.Dirent[] dentries)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			ArrayList entries = new ArrayList ();
 | 
					      UnixFileSystemInfo[] entries = new UnixFileSystemInfo[dentries.Length];
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i != entries.Length; ++i) {
 | 
				
			||||||
 | 
					        entries [i] = UnixFileSystemInfo.GetFileSystemEntry (
 | 
				
			||||||
 | 
					            UnixPath.Combine (this.FullPath, dentries[i].d_name));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return entries;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int r;
 | 
					    public UnixFileSystemInfo[] GetFileSystemEntries (Regex regex)
 | 
				
			||||||
			IntPtr result;
 | 
					    {
 | 
				
			||||||
			do {
 | 
					      Native.Dirent[] dentries = this.GetEntries (regex);
 | 
				
			||||||
				Native.Dirent d = new Native.Dirent ();
 | 
					      return this.GetFileSystemEntries (dentries);
 | 
				
			||||||
				r = Native.Syscall.readdir_r (dirp, d, out result);
 | 
					    }
 | 
				
			||||||
				if (r == 0 && result != IntPtr.Zero)
 | 
					 | 
				
			||||||
					// don't include current & parent dirs
 | 
					 | 
				
			||||||
					if (d.d_name != "." && d.d_name != "..")
 | 
					 | 
				
			||||||
						entries.Add (d);
 | 
					 | 
				
			||||||
			} while  (r == 0 && result != IntPtr.Zero);
 | 
					 | 
				
			||||||
			if (r != 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
 | 
					    public UnixFileSystemInfo[] GetFileSystemEntries (String regex)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      Regex re = new Regex (regex);
 | 
				
			||||||
 | 
					      return this.GetFileSystemEntries (re);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Native.Dirent[] GetEntries (Regex regex)
 | 
					    public static String GetCurrentDirectory ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			IntPtr dirp = Native.Syscall.opendir (FullPath);
 | 
					      StringBuilder buf = new StringBuilder (16);
 | 
				
			||||||
			if (dirp == IntPtr.Zero)
 | 
					      IntPtr r = IntPtr.Zero;
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      do {
 | 
				
			||||||
 | 
					        buf.Capacity *= 2;
 | 
				
			||||||
 | 
					        r = Native.Syscall.getcwd (buf, (UInt64) buf.Capacity);
 | 
				
			||||||
 | 
					      } while (r == IntPtr.Zero && Native.Syscall.GetLastError() == Native.Errno.ERANGE);
 | 
				
			||||||
 | 
					      if (r == IntPtr.Zero) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return buf.ToString ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try {
 | 
					    public static void SetCurrentDirectory (String path)
 | 
				
			||||||
				return GetEntries (dirp, regex);
 | 
					    {
 | 
				
			||||||
			}
 | 
					      Int32 r = Native.Syscall.chdir (path);
 | 
				
			||||||
			finally {
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
				int r = Native.Syscall.closedir (dirp);
 | 
					    }
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					  }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private static Native.Dirent[] GetEntries (IntPtr dirp, Regex regex)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ArrayList entries = new ArrayList ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			int r;
 | 
					 | 
				
			||||||
			IntPtr result;
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				Native.Dirent d = new Native.Dirent ();
 | 
					 | 
				
			||||||
				r = Native.Syscall.readdir_r (dirp, d, out result);
 | 
					 | 
				
			||||||
				if (r == 0 && result != IntPtr.Zero && regex.Match (d.d_name).Success) {
 | 
					 | 
				
			||||||
					// don't include current & parent dirs
 | 
					 | 
				
			||||||
					if (d.d_name != "." && d.d_name != "..")
 | 
					 | 
				
			||||||
						entries.Add (d);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} while  (r == 0 && result != IntPtr.Zero);
 | 
					 | 
				
			||||||
			if (r != 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Native.Dirent[] GetEntries (string regex)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Regex re = new Regex (regex);
 | 
					 | 
				
			||||||
			return GetEntries (re);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixFileSystemInfo[] GetFileSystemEntries ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Native.Dirent[] dentries = GetEntries ();
 | 
					 | 
				
			||||||
			return GetFileSystemEntries (dentries);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private UnixFileSystemInfo[] GetFileSystemEntries (Native.Dirent[] dentries)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UnixFileSystemInfo[] entries = new UnixFileSystemInfo[dentries.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i != entries.Length; ++i)
 | 
					 | 
				
			||||||
				entries [i] = UnixFileSystemInfo.GetFileSystemEntry (
 | 
					 | 
				
			||||||
						UnixPath.Combine (FullPath, dentries[i].d_name));
 | 
					 | 
				
			||||||
			return entries;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixFileSystemInfo[] GetFileSystemEntries (Regex regex)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Native.Dirent[] dentries = GetEntries (regex);
 | 
					 | 
				
			||||||
			return GetFileSystemEntries (dentries);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixFileSystemInfo[] GetFileSystemEntries (string regex)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Regex re = new Regex (regex);
 | 
					 | 
				
			||||||
			return GetFileSystemEntries (re);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string GetCurrentDirectory ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			StringBuilder buf = new StringBuilder (16);
 | 
					 | 
				
			||||||
			IntPtr r = IntPtr.Zero;
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				buf.Capacity *= 2;
 | 
					 | 
				
			||||||
				r = Native.Syscall.getcwd (buf, (ulong) buf.Capacity);
 | 
					 | 
				
			||||||
			} while (r == IntPtr.Zero && Native.Syscall.GetLastError() == Native.Errno.ERANGE);
 | 
					 | 
				
			||||||
			if (r == IntPtr.Zero)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return buf.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void SetCurrentDirectory (string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int r = Native.Syscall.chdir (path);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -33,163 +33,157 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public enum UnixDriveType {
 | 
					  public enum UnixDriveType {
 | 
				
			||||||
		Unknown,
 | 
					    Unknown,
 | 
				
			||||||
		NoRootDirectory,
 | 
					    NoRootDirectory,
 | 
				
			||||||
		Removable,
 | 
					    Removable,
 | 
				
			||||||
		Fixed,
 | 
					    Fixed,
 | 
				
			||||||
		Network,
 | 
					    Network,
 | 
				
			||||||
		CDRom,
 | 
					    CDRom,
 | 
				
			||||||
		Ram
 | 
					    Ram
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// All methods & properties can throw IOException
 | 
					  // All methods & properties can throw IOException
 | 
				
			||||||
	public sealed class UnixDriveInfo
 | 
					  public sealed class UnixDriveInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private Native.Statvfs stat;
 | 
					    private Native.Statvfs stat;
 | 
				
			||||||
		private string fstype, mount_point, block_device;
 | 
					    private String fstype, mount_point, block_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixDriveInfo (string mountPoint)
 | 
					    public UnixDriveInfo (String mountPoint)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (mountPoint == null)
 | 
					      if (mountPoint == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("mountPoint");
 | 
					        throw new ArgumentNullException ("mountPoint");
 | 
				
			||||||
			Native.Fstab fstab = Native.Syscall.getfsfile (mountPoint);
 | 
					      }
 | 
				
			||||||
			if (fstab != null) {
 | 
					
 | 
				
			||||||
				FromFstab (fstab);
 | 
					      Native.Fstab fstab = Native.Syscall.getfsfile (mountPoint);
 | 
				
			||||||
			}
 | 
					      if (fstab != null) {
 | 
				
			||||||
			else {
 | 
					        this.FromFstab (fstab);
 | 
				
			||||||
				this.mount_point  = mountPoint;
 | 
					      }
 | 
				
			||||||
				this.block_device = "";
 | 
					      else {
 | 
				
			||||||
				this.fstype       = "Unknown";
 | 
					        this.mount_point  = mountPoint;
 | 
				
			||||||
			}
 | 
					        this.block_device = "";
 | 
				
			||||||
		}
 | 
					        this.fstype       = "Unknown";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void FromFstab (Native.Fstab fstab)
 | 
					    private void FromFstab (Native.Fstab fstab)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.fstype       = fstab.fs_vfstype;
 | 
					      this.fstype       = fstab.fs_vfstype;
 | 
				
			||||||
			this.mount_point  = fstab.fs_file;
 | 
					      this.mount_point  = fstab.fs_file;
 | 
				
			||||||
			this.block_device = fstab.fs_spec;
 | 
					      this.block_device = fstab.fs_spec;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixDriveInfo GetForSpecialFile (string specialFile)
 | 
					    public static UnixDriveInfo GetForSpecialFile (String specialFile)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (specialFile == null)
 | 
					      if (specialFile == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("specialFile");
 | 
					        throw new ArgumentNullException ("specialFile");
 | 
				
			||||||
			Native.Fstab f = Native.Syscall.getfsspec (specialFile);
 | 
					      }
 | 
				
			||||||
			if (f == null)
 | 
					
 | 
				
			||||||
				throw new ArgumentException ("specialFile isn't valid: " + specialFile);
 | 
					      Native.Fstab f = Native.Syscall.getfsspec (specialFile);
 | 
				
			||||||
			return new UnixDriveInfo (f);
 | 
					      if (f == null) {
 | 
				
			||||||
		}
 | 
					        throw new ArgumentException ("specialFile isn't valid: " + specialFile);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new UnixDriveInfo (f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private UnixDriveInfo(Native.Fstab fstab) => this.FromFstab(fstab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int64 AvailableFreeSpace {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.Refresh (); return Convert.ToInt64 (this.stat.f_bavail * this.stat.f_frsize);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String DriveFormat => this.fstype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixDriveType DriveType => UnixDriveType.Unknown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // this throws no exceptions
 | 
				
			||||||
 | 
					    public Boolean IsReady {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        Boolean ready = this.Refresh (false);
 | 
				
			||||||
 | 
					        if (this.mount_point == "/" || !ready) {
 | 
				
			||||||
 | 
					          return ready;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Int32 r = Native.Syscall.statvfs(this.RootDirectory.Parent.FullName,
 | 
				
			||||||
 | 
					            out Native.Statvfs parent);
 | 
				
			||||||
 | 
					        return r != 0 ? false : parent.f_fsid != this.stat.f_fsid;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String Name => this.mount_point;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixDirectoryInfo RootDirectory => new UnixDirectoryInfo(this.mount_point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int64 TotalFreeSpace {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.Refresh (); return (Int64) (this.stat.f_bfree * this.stat.f_frsize);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private UnixDriveInfo (Native.Fstab fstab)
 | 
					    public Int64 TotalSize {
 | 
				
			||||||
		{
 | 
					      get {
 | 
				
			||||||
			FromFstab (fstab);
 | 
					        this.Refresh (); return (Int64) (this.stat.f_frsize * this.stat.f_blocks);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // also throws SecurityException if caller lacks perms
 | 
				
			||||||
 | 
					    public String VolumeLabel => this.block_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int64 MaximumFilenameLength {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.Refresh (); return Convert.ToInt64 (this.stat.f_namemax);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public long AvailableFreeSpace {
 | 
					    public static UnixDriveInfo[] GetDrives ()
 | 
				
			||||||
			get {Refresh (); return Convert.ToInt64 (stat.f_bavail * stat.f_frsize);}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      // TODO: Return any drives mentioned by getmntent(3) once getmntent(3)
 | 
				
			||||||
 | 
					      // is exported by Syscall.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string DriveFormat {
 | 
					      // throws IOException, UnauthorizedAccessException (no permission)
 | 
				
			||||||
			get {return fstype;}
 | 
					      ArrayList entries = new ArrayList ();
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixDriveType DriveType {
 | 
					      lock (Native.Syscall.fstab_lock) {
 | 
				
			||||||
			get {return UnixDriveType.Unknown;}
 | 
					        Int32 r = Native.Syscall.setfsent ();
 | 
				
			||||||
		}
 | 
					        if (r != 1) {
 | 
				
			||||||
 | 
					          throw new IOException ("Error calling setfsent(3)", new UnixIOException ());
 | 
				
			||||||
		// this throws no exceptions
 | 
					        }
 | 
				
			||||||
		public bool IsReady {
 | 
					
 | 
				
			||||||
			get {
 | 
					        try {
 | 
				
			||||||
				bool ready = Refresh (false);
 | 
					          Native.Fstab fs;
 | 
				
			||||||
				if (mount_point == "/" || !ready)
 | 
					          while ((fs = Native.Syscall.getfsent()) != null) {
 | 
				
			||||||
					return ready;
 | 
					            // avoid virtual entries, such as "swap"
 | 
				
			||||||
				Native.Statvfs parent;
 | 
					            if (fs.fs_file != null && fs.fs_file.StartsWith ("/")) {
 | 
				
			||||||
				int r = Native.Syscall.statvfs (RootDirectory.Parent.FullName, 
 | 
					              _ = entries.Add(new UnixDriveInfo(fs));
 | 
				
			||||||
						out parent);
 | 
					            }
 | 
				
			||||||
				if (r != 0)
 | 
					          }
 | 
				
			||||||
					return false;
 | 
					        }
 | 
				
			||||||
				return parent.f_fsid != stat.f_fsid;
 | 
					        finally {
 | 
				
			||||||
			}
 | 
					          _ = Native.Syscall.endfsent();
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public string Name {
 | 
					      return (UnixDriveInfo[]) entries.ToArray (typeof(UnixDriveInfo));
 | 
				
			||||||
			get {return mount_point;}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public override String ToString() => this.VolumeLabel;
 | 
				
			||||||
		public UnixDirectoryInfo RootDirectory {
 | 
					
 | 
				
			||||||
			get {return new UnixDirectoryInfo (mount_point);}
 | 
					    private void Refresh() => this.Refresh(true);
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    private Boolean Refresh (Boolean throwException)
 | 
				
			||||||
		public long TotalFreeSpace {
 | 
					    {
 | 
				
			||||||
			get {Refresh (); return (long) (stat.f_bfree * stat.f_frsize);}
 | 
					      Int32 r = Native.Syscall.statvfs (this.mount_point, out this.stat);
 | 
				
			||||||
		}
 | 
					      if (r == -1 && throwException) {
 | 
				
			||||||
 | 
					        Native.Errno e = Native.Syscall.GetLastError ();
 | 
				
			||||||
		public long TotalSize {
 | 
					        throw new InvalidOperationException (
 | 
				
			||||||
			get {Refresh (); return (long) (stat.f_frsize * stat.f_blocks);}
 | 
					            UnixMarshal.GetErrorDescription (e),
 | 
				
			||||||
		}
 | 
					            new UnixIOException (e));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		// also throws SecurityException if caller lacks perms
 | 
					      else if (r == -1) {
 | 
				
			||||||
		public string VolumeLabel {
 | 
					        return false;
 | 
				
			||||||
			get {return block_device;}
 | 
					      }
 | 
				
			||||||
			// set {}
 | 
					
 | 
				
			||||||
		}
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public long MaximumFilenameLength {
 | 
					  }
 | 
				
			||||||
			get {Refresh (); return Convert.ToInt64 (stat.f_namemax);}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static UnixDriveInfo[] GetDrives ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// TODO: Return any drives mentioned by getmntent(3) once getmntent(3)
 | 
					 | 
				
			||||||
			// is exported by Syscall.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// throws IOException, UnauthorizedAccessException (no permission)
 | 
					 | 
				
			||||||
			ArrayList entries = new ArrayList ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			lock (Native.Syscall.fstab_lock) {
 | 
					 | 
				
			||||||
				int r = Native.Syscall.setfsent ();
 | 
					 | 
				
			||||||
				if (r != 1)
 | 
					 | 
				
			||||||
					throw new IOException ("Error calling setfsent(3)", new UnixIOException ());
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					Native.Fstab fs;
 | 
					 | 
				
			||||||
					while ((fs = Native.Syscall.getfsent()) != null) {
 | 
					 | 
				
			||||||
						// avoid virtual entries, such as "swap"
 | 
					 | 
				
			||||||
						if (fs.fs_file != null && fs.fs_file.StartsWith ("/"))
 | 
					 | 
				
			||||||
							entries.Add (new UnixDriveInfo (fs));
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				finally {
 | 
					 | 
				
			||||||
					Native.Syscall.endfsent ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return (UnixDriveInfo[]) entries.ToArray (typeof(UnixDriveInfo));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override string ToString ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return VolumeLabel;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void Refresh ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Refresh (true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private bool Refresh (bool throwException)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int r = Native.Syscall.statvfs (mount_point, out stat);
 | 
					 | 
				
			||||||
			if (r == -1 && throwException) {
 | 
					 | 
				
			||||||
				Native.Errno e = Native.Syscall.GetLastError ();
 | 
					 | 
				
			||||||
				throw new InvalidOperationException (
 | 
					 | 
				
			||||||
						UnixMarshal.GetErrorDescription (e),
 | 
					 | 
				
			||||||
						new UnixIOException (e));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if (r == -1)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -34,100 +34,95 @@ using System.Text;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix
 | 
					namespace Mono.Unix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	[Serializable]
 | 
					  [Serializable]
 | 
				
			||||||
	public class UnixEndPoint : EndPoint
 | 
					  public class UnixEndPoint : EndPoint
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		string filename;
 | 
					    String filename;
 | 
				
			||||||
		
 | 
					    
 | 
				
			||||||
		public UnixEndPoint (string filename)
 | 
					    public UnixEndPoint (String filename)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (filename == null)
 | 
					      if (filename == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("filename");
 | 
					        throw new ArgumentNullException ("filename");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (filename == "") {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("Cannot be empty.", "filename");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.filename = filename;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public String Filename {
 | 
				
			||||||
 | 
					      get => this.filename;
 | 
				
			||||||
 | 
					      set => this.filename = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override AddressFamily AddressFamily => AddressFamily.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override EndPoint Create (SocketAddress socketAddress)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /*
 | 
				
			||||||
 | 
					       * Should also check this
 | 
				
			||||||
 | 
					       *
 | 
				
			||||||
 | 
					      int addr = (int) AddressFamily.Unix;
 | 
				
			||||||
 | 
					      if (socketAddress [0] != (addr & 0xFF))
 | 
				
			||||||
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (filename == "")
 | 
					      if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
				
			||||||
				throw new ArgumentException ("Cannot be empty.", "filename");
 | 
					        throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
				
			||||||
			this.filename = filename;
 | 
					       */
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public string Filename {
 | 
					 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return(filename);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			set {
 | 
					 | 
				
			||||||
				filename=value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override AddressFamily AddressFamily {
 | 
					      if (socketAddress.Size == 2) {
 | 
				
			||||||
			get { return AddressFamily.Unix; }
 | 
					        // Empty filename.
 | 
				
			||||||
		}
 | 
					        // Probably from RemoteEndPoint which on linux does not return the file name.
 | 
				
			||||||
 | 
					        UnixEndPoint uep = new UnixEndPoint("a") {
 | 
				
			||||||
 | 
					          filename = ""
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        return uep;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Int32 size = socketAddress.Size - 2;
 | 
				
			||||||
 | 
					      Byte[] bytes = new Byte[size];
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
 | 
					        bytes [i] = socketAddress [i + 2];
 | 
				
			||||||
 | 
					        // There may be junk after the null terminator, so ignore it all.
 | 
				
			||||||
 | 
					        if (bytes [i] == 0) {
 | 
				
			||||||
 | 
					          size = i;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      String name = Encoding.Default.GetString (bytes, 0, size);
 | 
				
			||||||
 | 
					      return new UnixEndPoint (name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override EndPoint Create (SocketAddress socketAddress)
 | 
					    public override SocketAddress Serialize ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			/*
 | 
					      Byte[] bytes = Encoding.Default.GetBytes (this.filename);
 | 
				
			||||||
			 * Should also check this
 | 
					      SocketAddress sa = new SocketAddress (this.AddressFamily, 2 + bytes.Length + 1);
 | 
				
			||||||
			 *
 | 
					      // sa [0] -> family low byte, sa [1] -> family high byte
 | 
				
			||||||
			int addr = (int) AddressFamily.Unix;
 | 
					      for (Int32 i = 0; i < bytes.Length; i++) {
 | 
				
			||||||
			if (socketAddress [0] != (addr & 0xFF))
 | 
					        sa [2 + i] = bytes [i];
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //NULL suffix for non-abstract path
 | 
				
			||||||
 | 
					      sa[2 + bytes.Length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (socketAddress [1] != ((addr & 0xFF00) >> 8))
 | 
					      return sa;
 | 
				
			||||||
				throw new ArgumentException ("socketAddress is not a unix socket address.");
 | 
					    }
 | 
				
			||||||
			 */
 | 
					
 | 
				
			||||||
 | 
					    public override String ToString() => this.filename;
 | 
				
			||||||
			if (socketAddress.Size == 2) {
 | 
					
 | 
				
			||||||
				// Empty filename.
 | 
					    public override Int32 GetHashCode() => this.filename.GetHashCode();
 | 
				
			||||||
				// Probably from RemoteEndPoint which on linux does not return the file name.
 | 
					
 | 
				
			||||||
				UnixEndPoint uep = new UnixEndPoint ("a");
 | 
					    public override Boolean Equals (Object o)
 | 
				
			||||||
				uep.filename = "";
 | 
					    {
 | 
				
			||||||
				return uep;
 | 
					      UnixEndPoint other = o as UnixEndPoint;
 | 
				
			||||||
			}
 | 
					      if (other == null) {
 | 
				
			||||||
			int size = socketAddress.Size - 2;
 | 
					        return false;
 | 
				
			||||||
			byte [] bytes = new byte [size];
 | 
					      }
 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++) {
 | 
					
 | 
				
			||||||
				bytes [i] = socketAddress [i + 2];
 | 
					      return other.filename == this.filename;
 | 
				
			||||||
				// There may be junk after the null terminator, so ignore it all.
 | 
					    }
 | 
				
			||||||
				if (bytes [i] == 0) {
 | 
					  }
 | 
				
			||||||
					size = i;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			string name = Encoding.Default.GetString (bytes, 0, size);
 | 
					 | 
				
			||||||
			return new UnixEndPoint (name);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override SocketAddress Serialize ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			byte [] bytes = Encoding.Default.GetBytes (filename);
 | 
					 | 
				
			||||||
			SocketAddress sa = new SocketAddress (AddressFamily, 2 + bytes.Length + 1);
 | 
					 | 
				
			||||||
			// sa [0] -> family low byte, sa [1] -> family high byte
 | 
					 | 
				
			||||||
			for (int i = 0; i < bytes.Length; i++)
 | 
					 | 
				
			||||||
				sa [2 + i] = bytes [i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//NULL suffix for non-abstract path
 | 
					 | 
				
			||||||
			sa[2 + bytes.Length] = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return sa;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override string ToString() {
 | 
					 | 
				
			||||||
			return(filename);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override int GetHashCode ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return filename.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override bool Equals (object o)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UnixEndPoint other = o as UnixEndPoint;
 | 
					 | 
				
			||||||
			if (other == null)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (other.filename == filename);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,211 +28,204 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections;
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using Mono.Unix;
 | 
					using Mono.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed /* static */ class UnixEnvironment
 | 
					  public sealed /* static */ class UnixEnvironment
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private UnixEnvironment () {}
 | 
					    private UnixEnvironment () {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string CurrentDirectory {
 | 
					    public static String CurrentDirectory {
 | 
				
			||||||
			get {
 | 
					      get => UnixDirectoryInfo.GetCurrentDirectory();
 | 
				
			||||||
				return UnixDirectoryInfo.GetCurrentDirectory ();
 | 
					      set => UnixDirectoryInfo.SetCurrentDirectory(value);
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
			set {
 | 
					
 | 
				
			||||||
				UnixDirectoryInfo.SetCurrentDirectory (value);
 | 
					    public static String MachineName {
 | 
				
			||||||
			}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        if(Native.Syscall.uname(out Native.Utsname buf) != 0) {
 | 
				
			||||||
 | 
					          throw UnixMarshal.CreateExceptionForLastError();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return buf.nodename;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      set {
 | 
				
			||||||
 | 
					        Int32 r = Native.Syscall.sethostname (value);
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String UserName => UnixUserInfo.GetRealUser().UserName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixGroupInfo RealGroup => new UnixGroupInfo(RealGroupId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 RealGroupId => Native.Syscall.getgid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixUserInfo RealUser => new UnixUserInfo(RealUserId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 RealUserId => Native.Syscall.getuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixGroupInfo EffectiveGroup {
 | 
				
			||||||
 | 
					      get => new UnixGroupInfo(EffectiveGroupId);
 | 
				
			||||||
 | 
					      set => EffectiveGroupId = value.GroupId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 EffectiveGroupId {
 | 
				
			||||||
 | 
					      get => Native.Syscall.getegid();
 | 
				
			||||||
 | 
					      set => _ = Native.Syscall.setegid(Convert.ToUInt32(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixUserInfo EffectiveUser {
 | 
				
			||||||
 | 
					      get => new UnixUserInfo(EffectiveUserId);
 | 
				
			||||||
 | 
					      set => EffectiveUserId = value.UserId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int64 EffectiveUserId {
 | 
				
			||||||
 | 
					      get => Native.Syscall.geteuid();
 | 
				
			||||||
 | 
					      set => _ = Native.Syscall.seteuid(Convert.ToUInt32(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String Login => UnixUserInfo.GetRealUser().UserName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
 | 
					    public static Int64 GetConfigurationValue (Native.SysconfName name)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Int64 r = Native.Syscall.sysconf (name);
 | 
				
			||||||
 | 
					      if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return r;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string MachineName {
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
			get {
 | 
					    public static String GetConfigurationString (Native.ConfstrName name)
 | 
				
			||||||
				Native.Utsname buf;
 | 
					    {
 | 
				
			||||||
				if (Native.Syscall.uname (out buf) != 0)
 | 
					      UInt64 len = Native.Syscall.confstr (name, null, 0);
 | 
				
			||||||
					throw UnixMarshal.CreateExceptionForLastError ();
 | 
					      if (len == unchecked ((UInt64) (-1))) {
 | 
				
			||||||
				return buf.nodename;
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			set {
 | 
					
 | 
				
			||||||
				int r = Native.Syscall.sethostname (value);
 | 
					      if (len == 0) {
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					        return "";
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      StringBuilder buf = new StringBuilder ((Int32) len+1);
 | 
				
			||||||
 | 
					      len = Native.Syscall.confstr (name, buf, len);
 | 
				
			||||||
 | 
					      if (len == unchecked ((UInt64) (-1))) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return buf.ToString ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string UserName {
 | 
					    public static void SetNiceValue (Int32 inc)
 | 
				
			||||||
			get {return UnixUserInfo.GetRealUser ().UserName;}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      Int32 r = Native.Syscall.nice (inc);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixGroupInfo RealGroup {
 | 
					    public static Int32 CreateSession ()
 | 
				
			||||||
			get {return new UnixGroupInfo (RealGroupId);}
 | 
					    {
 | 
				
			||||||
			// set can't be done as setgid(2) modifies effective gid as well
 | 
					      Int32 s = Native.Syscall.setsid ();
 | 
				
			||||||
		}
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (s);
 | 
				
			||||||
 | 
					      return s;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long RealGroupId {
 | 
					    public static void SetProcessGroup ()
 | 
				
			||||||
			get {return Native.Syscall.getgid ();}
 | 
					    {
 | 
				
			||||||
			// set can't be done as setgid(2) modifies effective gid as well
 | 
					      Int32 r = Native.Syscall.setpgrp ();
 | 
				
			||||||
		}
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int32 GetProcessGroup() => Native.Syscall.getpgrp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixGroupInfo[] GetSupplementaryGroups ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      UInt32[] ids = _GetSupplementaryGroupIds ();
 | 
				
			||||||
 | 
					      UnixGroupInfo[] groups = new UnixGroupInfo [ids.Length];
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i < groups.Length; ++i) {
 | 
				
			||||||
 | 
					        groups [i] = new UnixGroupInfo (ids [i]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return groups;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixUserInfo RealUser {
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
			get {return new UnixUserInfo (RealUserId);}
 | 
					    private static UInt32[] _GetSupplementaryGroupIds ()
 | 
				
			||||||
			// set can't be done as setuid(2) modifies effective uid as well
 | 
					    {
 | 
				
			||||||
		}
 | 
					      Int32 ngroups = Native.Syscall.getgroups (0, new UInt32[]{});
 | 
				
			||||||
 | 
					      if (ngroups == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      UInt32[] groups = new UInt32[ngroups];
 | 
				
			||||||
 | 
					      Int32 r = Native.Syscall.getgroups (groups);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      return groups;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long RealUserId {
 | 
					    public static void SetSupplementaryGroups (UnixGroupInfo[] groups)
 | 
				
			||||||
			get {return Native.Syscall.getuid ();}
 | 
					    {
 | 
				
			||||||
			// set can't be done as setuid(2) modifies effective uid as well
 | 
					      UInt32[] list = new UInt32[groups.Length];
 | 
				
			||||||
		}
 | 
					      for (Int32 i = 0; i < list.Length; ++i) {
 | 
				
			||||||
 | 
					        list [i] = Convert.ToUInt32 (groups [i].GroupId);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Int32 r = Native.Syscall.setgroups (list);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixGroupInfo EffectiveGroup {
 | 
					    public static Int64[] GetSupplementaryGroupIds ()
 | 
				
			||||||
			get {return new UnixGroupInfo (EffectiveGroupId);}
 | 
					    {
 | 
				
			||||||
			set {EffectiveGroupId = value.GroupId;}
 | 
					      UInt32[] _groups = _GetSupplementaryGroupIds ();
 | 
				
			||||||
		}
 | 
					      Int64[] groups = new Int64[_groups.Length];
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i < groups.Length; ++i) {
 | 
				
			||||||
 | 
					        groups [i] = _groups [i];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return groups;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long EffectiveGroupId {
 | 
					    public static void SetSupplementaryGroupIds (Int64[] list)
 | 
				
			||||||
			get {return Native.Syscall.getegid ();}
 | 
					    {
 | 
				
			||||||
			set {Native.Syscall.setegid (Convert.ToUInt32 (value));}
 | 
					      UInt32[] _list = new UInt32[list.Length];
 | 
				
			||||||
		}
 | 
					      for (Int32 i = 0; i < _list.Length; ++i) {
 | 
				
			||||||
 | 
					        _list [i] = Convert.ToUInt32 (list [i]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 r = Native.Syscall.setgroups (_list);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Int32 GetParentProcessId() => Native.Syscall.getppid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static UnixProcess GetParentProcess() => new UnixProcess(GetParentProcessId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String[] GetUserShells ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ArrayList shells = new ArrayList ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixUserInfo EffectiveUser {
 | 
					      lock (Native.Syscall.usershell_lock) {
 | 
				
			||||||
			get {return new UnixUserInfo (EffectiveUserId);}
 | 
					        try {
 | 
				
			||||||
			set {EffectiveUserId = value.UserId;}
 | 
					          if (Native.Syscall.setusershell () != 0) {
 | 
				
			||||||
		}
 | 
					            UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          String shell;
 | 
				
			||||||
 | 
					          while ((shell = Native.Syscall.getusershell ()) != null) {
 | 
				
			||||||
 | 
					            _ = shells.Add(shell);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        finally {
 | 
				
			||||||
 | 
					          _ = Native.Syscall.endusershell();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long EffectiveUserId {
 | 
					      return (String[]) shells.ToArray (typeof(String));
 | 
				
			||||||
			get {return Native.Syscall.geteuid ();}
 | 
					    }
 | 
				
			||||||
			set {Native.Syscall.seteuid (Convert.ToUInt32 (value));}
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string Login {
 | 
					 | 
				
			||||||
			get {return UnixUserInfo.GetRealUser ().UserName;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public static long GetConfigurationValue (Native.SysconfName name)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			long r = Native.Syscall.sysconf (name);
 | 
					 | 
				
			||||||
			if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return r;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public static string GetConfigurationString (Native.ConfstrName name)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ulong len = Native.Syscall.confstr (name, null, 0);
 | 
					 | 
				
			||||||
			if (len == unchecked ((ulong) (-1)))
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			if (len == 0)
 | 
					 | 
				
			||||||
				return "";
 | 
					 | 
				
			||||||
			StringBuilder buf = new StringBuilder ((int) len+1);
 | 
					 | 
				
			||||||
			len = Native.Syscall.confstr (name, buf, len);
 | 
					 | 
				
			||||||
			if (len == unchecked ((ulong) (-1)))
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return buf.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void SetNiceValue (int inc)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int r = Native.Syscall.nice (inc);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static int CreateSession ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int s = Native.Syscall.setsid ();
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (s);
 | 
					 | 
				
			||||||
			return s;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void SetProcessGroup ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int r = Native.Syscall.setpgrp ();
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static int GetProcessGroup ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Native.Syscall.getpgrp ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static UnixGroupInfo[] GetSupplementaryGroups ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			uint[] ids = _GetSupplementaryGroupIds ();
 | 
					 | 
				
			||||||
			UnixGroupInfo[] groups = new UnixGroupInfo [ids.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i < groups.Length; ++i)
 | 
					 | 
				
			||||||
				groups [i] = new UnixGroupInfo (ids [i]);
 | 
					 | 
				
			||||||
			return groups;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private static uint[] _GetSupplementaryGroupIds ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int ngroups = Native.Syscall.getgroups (0, new uint[]{});
 | 
					 | 
				
			||||||
			if (ngroups == -1)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			uint[] groups = new uint[ngroups];
 | 
					 | 
				
			||||||
			int r = Native.Syscall.getgroups (groups);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
			return groups;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void SetSupplementaryGroups (UnixGroupInfo[] groups)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			uint[] list = new uint [groups.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i < list.Length; ++i) {
 | 
					 | 
				
			||||||
				list [i] = Convert.ToUInt32 (groups [i].GroupId);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			int r = Native.Syscall.setgroups (list);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static long[] GetSupplementaryGroupIds ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			uint[] _groups = _GetSupplementaryGroupIds ();
 | 
					 | 
				
			||||||
			long[] groups = new long [_groups.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i < groups.Length; ++i)
 | 
					 | 
				
			||||||
				groups [i] = _groups [i];
 | 
					 | 
				
			||||||
			return groups;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void SetSupplementaryGroupIds (long[] list)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			uint[] _list = new uint [list.Length];
 | 
					 | 
				
			||||||
			for (int i = 0; i < _list.Length; ++i)
 | 
					 | 
				
			||||||
				_list [i] = Convert.ToUInt32 (list [i]);
 | 
					 | 
				
			||||||
			int r = Native.Syscall.setgroups (_list);
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static int GetParentProcessId ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Native.Syscall.getppid ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public static UnixProcess GetParentProcess ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return new UnixProcess (GetParentProcessId ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string[] GetUserShells ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ArrayList shells = new ArrayList ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			lock (Native.Syscall.usershell_lock) {
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					if (Native.Syscall.setusershell () != 0)
 | 
					 | 
				
			||||||
						UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
					string shell;
 | 
					 | 
				
			||||||
					while ((shell = Native.Syscall.getusershell ()) != null)
 | 
					 | 
				
			||||||
						shells.Add (shell);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				finally {
 | 
					 | 
				
			||||||
					Native.Syscall.endusershell ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (string[]) shells.ToArray (typeof(string));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -33,115 +33,110 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixFileInfo : UnixFileSystemInfo
 | 
					  public sealed class UnixFileInfo : UnixFileSystemInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		public UnixFileInfo (string path)
 | 
					    public UnixFileInfo (String path)
 | 
				
			||||||
			: base (path)
 | 
					      : base (path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixFileInfo (string path, Native.Stat stat)
 | 
					    internal UnixFileInfo (String path, Native.Stat stat)
 | 
				
			||||||
			: base (path, stat)
 | 
					      : base (path, stat)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override String Name => UnixPath.GetFileName(this.FullPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String DirectoryName => UnixPath.GetDirectoryName(this.FullPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixDirectoryInfo Directory => new UnixDirectoryInfo(this.DirectoryName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void Delete ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Int32 r = Native.Syscall.unlink (this.FullPath);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      base.Refresh ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override string Name {
 | 
					    public UnixStream Create ()
 | 
				
			||||||
			get {return UnixPath.GetFileName (FullPath);}
 | 
					    {
 | 
				
			||||||
		}
 | 
					      Native.FilePermissions mode = // 0644
 | 
				
			||||||
 | 
					        Native.FilePermissions.S_IRUSR | Native.FilePermissions.S_IWUSR |
 | 
				
			||||||
 | 
					        Native.FilePermissions.S_IRGRP | Native.FilePermissions.S_IROTH; 
 | 
				
			||||||
 | 
					      return this.Create (mode);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string DirectoryName {
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
			get {return UnixPath.GetDirectoryName (FullPath);}
 | 
					    public UnixStream Create (Native.FilePermissions mode)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      Int32 fd = Native.Syscall.creat (this.FullPath, mode);
 | 
				
			||||||
 | 
					      if (fd < 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      base.Refresh ();
 | 
				
			||||||
 | 
					      return new UnixStream (fd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UnixStream Create(FileAccessPermissions mode) => this.Create((Native.FilePermissions)mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
 | 
					    public UnixStream Open (Native.OpenFlags flags)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ((flags & Native.OpenFlags.O_CREAT) != 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentException (
 | 
				
			||||||
 | 
					            "Cannot specify OpenFlags.O_CREAT without providing " + 
 | 
				
			||||||
 | 
					            "FilePermissions.  Use the Open(OpenFlags, FilePermissions) " +
 | 
				
			||||||
 | 
					            "method instead");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 fd = Native.Syscall.open (this.FullPath, flags);
 | 
				
			||||||
 | 
					      if (fd < 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new UnixStream (fd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixDirectoryInfo Directory {
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
			get {return new UnixDirectoryInfo (DirectoryName);}
 | 
					    public UnixStream Open (Native.OpenFlags flags, Native.FilePermissions mode)
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      Int32 fd = Native.Syscall.open (this.FullPath, flags, mode);
 | 
				
			||||||
 | 
					      if (fd < 0) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new UnixStream (fd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void Delete ()
 | 
					    public UnixStream Open (FileMode mode)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.unlink (FullPath);
 | 
					      Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, FileAccess.ReadWrite);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      return this.Open (flags);
 | 
				
			||||||
			base.Refresh ();
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixStream Create ()
 | 
					    public UnixStream Open (FileMode mode, FileAccess access)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Native.FilePermissions mode = // 0644
 | 
					      Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, access);
 | 
				
			||||||
				Native.FilePermissions.S_IRUSR | Native.FilePermissions.S_IWUSR |
 | 
					      return this.Open (flags);
 | 
				
			||||||
				Native.FilePermissions.S_IRGRP | Native.FilePermissions.S_IROTH; 
 | 
					    }
 | 
				
			||||||
			return Create (mode);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
		public UnixStream Create (Native.FilePermissions mode)
 | 
					    public UnixStream Open (FileMode mode, FileAccess access, Native.FilePermissions perms)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int fd = Native.Syscall.creat (FullPath, mode);
 | 
					      Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, access);
 | 
				
			||||||
			if (fd < 0)
 | 
					      Int32 fd = Native.Syscall.open (this.FullPath, flags, perms);
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      if (fd < 0) {
 | 
				
			||||||
			base.Refresh ();
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			return new UnixStream (fd);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return new UnixStream (fd);
 | 
				
			||||||
		public UnixStream Create (FileAccessPermissions mode)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			return Create ((Native.FilePermissions) mode);
 | 
					    public UnixStream OpenRead() => this.Open(FileMode.Open, FileAccess.Read);
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public UnixStream OpenWrite() => this.Open(FileMode.OpenOrCreate, FileAccess.Write);
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					  }
 | 
				
			||||||
		public UnixStream Open (Native.OpenFlags flags)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if ((flags & Native.OpenFlags.O_CREAT) != 0)
 | 
					 | 
				
			||||||
				throw new ArgumentException (
 | 
					 | 
				
			||||||
						"Cannot specify OpenFlags.O_CREAT without providing " + 
 | 
					 | 
				
			||||||
						"FilePermissions.  Use the Open(OpenFlags, FilePermissions) " +
 | 
					 | 
				
			||||||
						"method instead");
 | 
					 | 
				
			||||||
			int fd = Native.Syscall.open (FullPath, flags);
 | 
					 | 
				
			||||||
			if (fd < 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return new UnixStream (fd);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public UnixStream Open (Native.OpenFlags flags, Native.FilePermissions mode)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int fd = Native.Syscall.open (FullPath, flags, mode);
 | 
					 | 
				
			||||||
			if (fd < 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return new UnixStream (fd);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixStream Open (FileMode mode)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, FileAccess.ReadWrite);
 | 
					 | 
				
			||||||
			return Open (flags);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixStream Open (FileMode mode, FileAccess access)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, access);
 | 
					 | 
				
			||||||
			return Open (flags);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public UnixStream Open (FileMode mode, FileAccess access, Native.FilePermissions perms)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Native.OpenFlags flags = Native.NativeConvert.ToOpenFlags (mode, access);
 | 
					 | 
				
			||||||
			int fd = Native.Syscall.open (FullPath, flags, perms);
 | 
					 | 
				
			||||||
			if (fd < 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return new UnixStream (fd);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixStream OpenRead ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Open (FileMode.Open, FileAccess.Read);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public UnixStream OpenWrite ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Open (FileMode.OpenOrCreate, FileAccess.Write);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -33,396 +33,409 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public abstract class UnixFileSystemInfo
 | 
					  public abstract class UnixFileSystemInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private Native.Stat stat;
 | 
					    private Native.Stat stat;
 | 
				
			||||||
		private string fullPath;
 | 
					    private String fullPath;
 | 
				
			||||||
		private string originalPath;
 | 
					    private String originalPath;
 | 
				
			||||||
		private bool valid = false;
 | 
					    private Boolean valid = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal const FileSpecialAttributes AllSpecialAttributes = 
 | 
					    internal const FileSpecialAttributes AllSpecialAttributes = 
 | 
				
			||||||
			FileSpecialAttributes.SetUserId | FileSpecialAttributes.SetGroupId |
 | 
					      FileSpecialAttributes.SetUserId | FileSpecialAttributes.SetGroupId |
 | 
				
			||||||
			FileSpecialAttributes.Sticky;
 | 
					      FileSpecialAttributes.Sticky;
 | 
				
			||||||
		internal const FileTypes AllFileTypes = 
 | 
					    internal const FileTypes AllFileTypes = 
 | 
				
			||||||
			FileTypes.Directory | FileTypes.CharacterDevice | FileTypes.BlockDevice |
 | 
					      FileTypes.Directory | FileTypes.CharacterDevice | FileTypes.BlockDevice |
 | 
				
			||||||
			FileTypes.RegularFile | FileTypes.Fifo | FileTypes.SymbolicLink | 
 | 
					      FileTypes.RegularFile | FileTypes.Fifo | FileTypes.SymbolicLink | 
 | 
				
			||||||
			FileTypes.Socket;
 | 
					      FileTypes.Socket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected UnixFileSystemInfo (string path)
 | 
					    protected UnixFileSystemInfo (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			UnixPath.CheckPath (path);
 | 
					      UnixPath.CheckPath (path);
 | 
				
			||||||
			this.originalPath = path;
 | 
					      this.originalPath = path;
 | 
				
			||||||
			this.fullPath = UnixPath.GetFullPath (path);
 | 
					      this.fullPath = UnixPath.GetFullPath (path);
 | 
				
			||||||
			Refresh (true);
 | 
					      this.Refresh (true);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixFileSystemInfo (String path, Native.Stat stat)
 | 
					    internal UnixFileSystemInfo (String path, Native.Stat stat)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.originalPath = path;
 | 
					      this.originalPath = path;
 | 
				
			||||||
			this.fullPath = UnixPath.GetFullPath (path);
 | 
					      this.fullPath = UnixPath.GetFullPath (path);
 | 
				
			||||||
			this.stat = stat;
 | 
					      this.stat = stat;
 | 
				
			||||||
			this.valid = true;
 | 
					      this.valid = true;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected string FullPath {
 | 
					    protected String FullPath {
 | 
				
			||||||
			get {return fullPath;}
 | 
					      get => this.fullPath;
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				if (fullPath != value) {
 | 
					        if(this.fullPath != value) {
 | 
				
			||||||
					UnixPath.CheckPath (value);
 | 
					          UnixPath.CheckPath(value);
 | 
				
			||||||
					valid = false;
 | 
					          this.valid = false;
 | 
				
			||||||
					fullPath = value;
 | 
					          this.fullPath = value;
 | 
				
			||||||
				}
 | 
					        }
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected string OriginalPath {
 | 
					    protected String OriginalPath {
 | 
				
			||||||
			get {return originalPath;}
 | 
					      get => this.originalPath;
 | 
				
			||||||
			set {originalPath = value;}
 | 
					      set => this.originalPath = value;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void AssertValid ()
 | 
					    private void AssertValid ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Refresh (false);
 | 
					      this.Refresh (false);
 | 
				
			||||||
			if (!valid)
 | 
					      if (!this.valid) {
 | 
				
			||||||
				throw new InvalidOperationException ("Path doesn't exist!");
 | 
					        throw new InvalidOperationException ("Path doesn't exist!");
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public virtual string FullName {
 | 
					
 | 
				
			||||||
			get {return FullPath;}
 | 
					    public virtual String FullName => this.FullPath;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public abstract String Name {get;}
 | 
				
			||||||
		public abstract string Name {get;}
 | 
					
 | 
				
			||||||
 | 
					    public Boolean Exists {
 | 
				
			||||||
		public bool Exists {
 | 
					      get {
 | 
				
			||||||
			get {
 | 
					        this.Refresh (true);
 | 
				
			||||||
				Refresh (true);
 | 
					        return this.valid;
 | 
				
			||||||
				return valid;
 | 
					      }
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public Int64 Device {
 | 
				
			||||||
		public long Device {
 | 
					      get {
 | 
				
			||||||
			get {AssertValid (); return Convert.ToInt64 (stat.st_dev);}
 | 
					        this.AssertValid (); return Convert.ToInt64 (this.stat.st_dev);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public long Inode {
 | 
					    public Int64 Inode {
 | 
				
			||||||
			get {AssertValid (); return Convert.ToInt64 (stat.st_ino);}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return Convert.ToInt64 (this.stat.st_ino);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					
 | 
				
			||||||
		public Native.FilePermissions Protection {
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
			get {AssertValid (); return (Native.FilePermissions) stat.st_mode;}
 | 
					    public Native.FilePermissions Protection {
 | 
				
			||||||
			set {
 | 
					      get {
 | 
				
			||||||
				int r = Native.Syscall.chmod (FullPath, value);
 | 
					        this.AssertValid (); return (Native.FilePermissions)this.stat.st_mode;}
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      set {
 | 
				
			||||||
			}
 | 
					        Int32 r = Native.Syscall.chmod (this.FullPath, value);
 | 
				
			||||||
		}
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public FileTypes FileType {
 | 
					    }
 | 
				
			||||||
			get {
 | 
					
 | 
				
			||||||
				AssertValid ();
 | 
					    public FileTypes FileType {
 | 
				
			||||||
				return (FileTypes) (stat.st_mode & Native.FilePermissions.S_IFMT);
 | 
					      get {
 | 
				
			||||||
			}
 | 
					        this.AssertValid ();
 | 
				
			||||||
			// no set as chmod(2) won't accept changing the file type.
 | 
					        return (FileTypes) (this.stat.st_mode & Native.FilePermissions.S_IFMT);
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					      // no set as chmod(2) won't accept changing the file type.
 | 
				
			||||||
		public FileAccessPermissions FileAccessPermissions {
 | 
					    }
 | 
				
			||||||
			get {
 | 
					
 | 
				
			||||||
				AssertValid (); 
 | 
					    public FileAccessPermissions FileAccessPermissions {
 | 
				
			||||||
				int perms = (int) stat.st_mode;
 | 
					      get {
 | 
				
			||||||
				return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
 | 
					        this.AssertValid ();
 | 
				
			||||||
			}
 | 
					        Int32 perms = (Int32)this.stat.st_mode;
 | 
				
			||||||
			set {
 | 
					        return (FileAccessPermissions) (perms & (Int32) FileAccessPermissions.AllPermissions);
 | 
				
			||||||
				AssertValid ();
 | 
					      }
 | 
				
			||||||
				int perms = (int) stat.st_mode;
 | 
					      set {
 | 
				
			||||||
				perms &= (int) ~FileAccessPermissions.AllPermissions;
 | 
					        this.AssertValid ();
 | 
				
			||||||
				perms |= (int) value;
 | 
					        Int32 perms = (Int32)this.stat.st_mode;
 | 
				
			||||||
				Protection = (Native.FilePermissions) perms;
 | 
					        perms &= (Int32) ~FileAccessPermissions.AllPermissions;
 | 
				
			||||||
			}
 | 
					        perms |= (Int32) value;
 | 
				
			||||||
		}
 | 
					        this.Protection = (Native.FilePermissions) perms;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public FileSpecialAttributes FileSpecialAttributes {
 | 
					    }
 | 
				
			||||||
			get {
 | 
					
 | 
				
			||||||
				AssertValid ();
 | 
					    public FileSpecialAttributes FileSpecialAttributes {
 | 
				
			||||||
				int attrs = (int) stat.st_mode;
 | 
					      get {
 | 
				
			||||||
				return (FileSpecialAttributes) (attrs & (int) AllSpecialAttributes);
 | 
					        this.AssertValid ();
 | 
				
			||||||
			}
 | 
					        Int32 attrs = (Int32)this.stat.st_mode;
 | 
				
			||||||
			set {
 | 
					        return (FileSpecialAttributes) (attrs & (Int32) AllSpecialAttributes);
 | 
				
			||||||
				AssertValid ();
 | 
					      }
 | 
				
			||||||
				int perms = (int) stat.st_mode;
 | 
					      set {
 | 
				
			||||||
				perms &= (int) ~AllSpecialAttributes;
 | 
					        this.AssertValid ();
 | 
				
			||||||
				perms |= (int) value;
 | 
					        Int32 perms = (Int32)this.stat.st_mode;
 | 
				
			||||||
				Protection = (Native.FilePermissions) perms;
 | 
					        perms &= (Int32) ~AllSpecialAttributes;
 | 
				
			||||||
			}
 | 
					        perms |= (Int32) value;
 | 
				
			||||||
		}
 | 
					        this.Protection = (Native.FilePermissions) perms;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public long LinkCount {
 | 
					    }
 | 
				
			||||||
			get {AssertValid (); return Convert.ToInt64 (stat.st_nlink);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Int64 LinkCount {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		public UnixUserInfo OwnerUser {
 | 
					        this.AssertValid (); return Convert.ToInt64 (this.stat.st_nlink);}
 | 
				
			||||||
			get {AssertValid (); return new UnixUserInfo (stat.st_uid);}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public UnixUserInfo OwnerUser {
 | 
				
			||||||
		public long OwnerUserId {
 | 
					      get {
 | 
				
			||||||
			get {AssertValid (); return stat.st_uid;}
 | 
					        this.AssertValid (); return new UnixUserInfo (this.stat.st_uid);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixGroupInfo OwnerGroup {
 | 
					    public Int64 OwnerUserId {
 | 
				
			||||||
			get {AssertValid (); return new UnixGroupInfo (stat.st_gid);}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return this.stat.st_uid;}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public long OwnerGroupId {
 | 
					
 | 
				
			||||||
			get {AssertValid (); return stat.st_gid;}
 | 
					    public UnixGroupInfo OwnerGroup {
 | 
				
			||||||
		}
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertValid (); return new UnixGroupInfo (this.stat.st_gid);}
 | 
				
			||||||
		public long DeviceType {
 | 
					    }
 | 
				
			||||||
			get {AssertValid (); return Convert.ToInt64 (stat.st_rdev);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Int64 OwnerGroupId {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		public long Length {
 | 
					        this.AssertValid (); return this.stat.st_gid;}
 | 
				
			||||||
			get {AssertValid (); return (long) stat.st_size;}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public Int64 DeviceType {
 | 
				
			||||||
		public long BlockSize {
 | 
					      get {
 | 
				
			||||||
			get {AssertValid (); return (long) stat.st_blksize;}
 | 
					        this.AssertValid (); return Convert.ToInt64 (this.stat.st_rdev);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public long BlocksAllocated {
 | 
					    public Int64 Length {
 | 
				
			||||||
			get {AssertValid (); return (long) stat.st_blocks;}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return (Int64)this.stat.st_size;}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public DateTime LastAccessTime {
 | 
					
 | 
				
			||||||
			get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime, stat.st_atime_nsec);}
 | 
					    public Int64 BlockSize {
 | 
				
			||||||
		}
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertValid (); return (Int64)this.stat.st_blksize;}
 | 
				
			||||||
		public DateTime LastAccessTimeUtc {
 | 
					    }
 | 
				
			||||||
			get {return LastAccessTime.ToUniversalTime ();}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Int64 BlocksAllocated {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		public DateTime LastWriteTime {
 | 
					        this.AssertValid (); return (Int64)this.stat.st_blocks;}
 | 
				
			||||||
			get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime, stat.st_mtime_nsec);}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public DateTime LastAccessTime {
 | 
				
			||||||
		public DateTime LastWriteTimeUtc {
 | 
					      get {
 | 
				
			||||||
			get {return LastWriteTime.ToUniversalTime ();}
 | 
					        this.AssertValid (); return Native.NativeConvert.ToDateTime (this.stat.st_atime, this.stat.st_atime_nsec);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public DateTime LastStatusChangeTime {
 | 
					    public DateTime LastAccessTimeUtc => this.LastAccessTime.ToUniversalTime();
 | 
				
			||||||
			get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime, stat.st_ctime_nsec);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public DateTime LastWriteTime {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		public DateTime LastStatusChangeTimeUtc {
 | 
					        this.AssertValid (); return Native.NativeConvert.ToDateTime (this.stat.st_mtime, this.stat.st_mtime_nsec);}
 | 
				
			||||||
			get {return LastStatusChangeTime.ToUniversalTime ();}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public DateTime LastWriteTimeUtc => this.LastWriteTime.ToUniversalTime();
 | 
				
			||||||
		public bool IsDirectory {
 | 
					
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR);}
 | 
					    public DateTime LastStatusChangeTime {
 | 
				
			||||||
		}
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertValid (); return Native.NativeConvert.ToDateTime (this.stat.st_ctime, this.stat.st_ctime_nsec);}
 | 
				
			||||||
		public bool IsCharacterDevice {
 | 
					    }
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFCHR);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public DateTime LastStatusChangeTimeUtc => this.LastStatusChangeTime.ToUniversalTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool IsBlockDevice {
 | 
					    public Boolean IsDirectory {
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFBLK);}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFDIR);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public bool IsRegularFile {
 | 
					
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFREG);}
 | 
					    public Boolean IsCharacterDevice {
 | 
				
			||||||
		}
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFCHR);}
 | 
				
			||||||
		public bool IsFifo {
 | 
					    }
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Boolean IsBlockDevice {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		public bool IsSymbolicLink {
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFBLK);}
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK);}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public Boolean IsRegularFile {
 | 
				
			||||||
		public bool IsSocket {
 | 
					      get {
 | 
				
			||||||
			get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFSOCK);}
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFREG);}
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool IsSetUser {
 | 
					    public Boolean IsFifo {
 | 
				
			||||||
			get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISUID);}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFIFO);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public bool IsSetGroup {
 | 
					
 | 
				
			||||||
			get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISGID);}
 | 
					    public Boolean IsSymbolicLink {
 | 
				
			||||||
		}
 | 
					      get {
 | 
				
			||||||
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFLNK);}
 | 
				
			||||||
		public bool IsSticky {
 | 
					    }
 | 
				
			||||||
			get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISVTX);}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Boolean IsSocket {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		internal static bool IsFileType (Native.FilePermissions mode, Native.FilePermissions type)
 | 
					        this.AssertValid (); return IsFileType (this.stat.st_mode, Native.FilePermissions.S_IFSOCK);}
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
			return (mode & Native.FilePermissions.S_IFMT) == type;
 | 
					
 | 
				
			||||||
		}
 | 
					    public Boolean IsSetUser {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		internal static bool IsSet (Native.FilePermissions mode, Native.FilePermissions type)
 | 
					        this.AssertValid (); return IsSet (this.stat.st_mode, Native.FilePermissions.S_ISUID);}
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
			return (mode & type) == type;
 | 
					
 | 
				
			||||||
		}
 | 
					    public Boolean IsSetGroup {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					        this.AssertValid (); return IsSet (this.stat.st_mode, Native.FilePermissions.S_ISGID);}
 | 
				
			||||||
		public bool CanAccess (Native.AccessModes mode)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			int r = Native.Syscall.access (FullPath, mode);
 | 
					    public Boolean IsSticky {
 | 
				
			||||||
			return r == 0;
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.AssertValid (); return IsSet (this.stat.st_mode, Native.FilePermissions.S_ISVTX);}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public UnixFileSystemInfo CreateLink (string path)
 | 
					
 | 
				
			||||||
		{
 | 
					    internal static Boolean IsFileType(Native.FilePermissions mode, Native.FilePermissions type) => (mode & Native.FilePermissions.S_IFMT) == type;
 | 
				
			||||||
			int r = Native.Syscall.link (FullName, path);
 | 
					
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    internal static Boolean IsSet(Native.FilePermissions mode, Native.FilePermissions type) => (mode & type) == type;
 | 
				
			||||||
			return GetFileSystemEntry (path);
 | 
					
 | 
				
			||||||
		}
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
 | 
					    public Boolean CanAccess (Native.AccessModes mode)
 | 
				
			||||||
		public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Int32 r = Native.Syscall.access (this.FullPath, mode);
 | 
				
			||||||
			int r = Native.Syscall.symlink (FullName, path);
 | 
					      return r == 0;
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
			return new UnixSymbolicLinkInfo (path);
 | 
					
 | 
				
			||||||
		}
 | 
					    public UnixFileSystemInfo CreateLink (String path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
		public abstract void Delete ();
 | 
					      Int32 r = Native.Syscall.link (this.FullName, path);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					      return GetFileSystemEntry (path);
 | 
				
			||||||
		public long GetConfigurationValue (Native.PathconfName name)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			long r = Native.Syscall.pathconf (FullPath, name);
 | 
					    public UnixSymbolicLinkInfo CreateSymbolicLink (String path)
 | 
				
			||||||
			if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0)
 | 
					    {
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      Int32 r = Native.Syscall.symlink (this.FullName, path);
 | 
				
			||||||
			return r;
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					      return new UnixSymbolicLinkInfo (path);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
		public void Refresh ()
 | 
					
 | 
				
			||||||
		{
 | 
					    public abstract void Delete ();
 | 
				
			||||||
			Refresh (true);
 | 
					
 | 
				
			||||||
		}
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
 | 
					    public Int64 GetConfigurationValue (Native.PathconfName name)
 | 
				
			||||||
		internal void Refresh (bool force)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Int64 r = Native.Syscall.pathconf (this.FullPath, name);
 | 
				
			||||||
			if (valid && !force)
 | 
					      if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0) {
 | 
				
			||||||
				return;
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			valid = GetFileStatus (FullPath, out this.stat);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return r;
 | 
				
			||||||
		protected virtual bool GetFileStatus (string path, out Native.Stat stat)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			return Native.Syscall.stat (path, out stat) == 0;
 | 
					    public void Refresh() => this.Refresh(true);
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    internal void Refresh (Boolean force)
 | 
				
			||||||
		public void SetLength (long length)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      if (this.valid && !force) {
 | 
				
			||||||
			int r;
 | 
					        return;
 | 
				
			||||||
			do {
 | 
					      }
 | 
				
			||||||
				r = Native.Syscall.truncate (FullPath, length);
 | 
					
 | 
				
			||||||
			}	while (UnixMarshal.ShouldRetrySyscall (r));
 | 
					      this.valid = this.GetFileStatus (this.FullPath, out this.stat);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    protected virtual Boolean GetFileStatus(String path, out Native.Stat stat) => Native.Syscall.stat(path, out stat) == 0;
 | 
				
			||||||
		public virtual void SetOwner (long owner, long group)
 | 
					
 | 
				
			||||||
		{
 | 
					    public void SetLength (Int64 length)
 | 
				
			||||||
			uint _owner = Convert.ToUInt32 (owner);
 | 
					    {
 | 
				
			||||||
			uint _group = Convert.ToUInt32 (group);
 | 
					      Int32 r;
 | 
				
			||||||
			int r = Native.Syscall.chown (FullPath, _owner, _group);
 | 
					      do {
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					        r = Native.Syscall.truncate (this.FullPath, length);
 | 
				
			||||||
		}
 | 
					      }	while (UnixMarshal.ShouldRetrySyscall (r));
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		public void SetOwner (string owner)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			Native.Passwd pw = Native.Syscall.getpwnam (owner);
 | 
					    public virtual void SetOwner (Int64 owner, Int64 group)
 | 
				
			||||||
			if (pw == null)
 | 
					    {
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
 | 
					      UInt32 _owner = Convert.ToUInt32 (owner);
 | 
				
			||||||
			uint uid = pw.pw_uid;
 | 
					      UInt32 _group = Convert.ToUInt32 (group);
 | 
				
			||||||
			uint gid = pw.pw_gid;
 | 
					      Int32 r = Native.Syscall.chown (this.FullPath, _owner, _group);
 | 
				
			||||||
			SetOwner ((long) uid, (long) gid);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SetOwner (string owner, string group)
 | 
					    public void SetOwner (String owner)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			long uid = -1;
 | 
					      Native.Passwd pw = Native.Syscall.getpwnam (owner);
 | 
				
			||||||
			if (owner != null)
 | 
					      if (pw == null) {
 | 
				
			||||||
				uid = new UnixUserInfo (owner).UserId;
 | 
					        throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
 | 
				
			||||||
			long gid = -1;
 | 
					      }
 | 
				
			||||||
			if (group != null)
 | 
					
 | 
				
			||||||
				gid = new UnixGroupInfo (group).GroupId;
 | 
					      UInt32 uid = pw.pw_uid;
 | 
				
			||||||
 | 
					      UInt32 gid = pw.pw_gid;
 | 
				
			||||||
			SetOwner (uid, gid);
 | 
					      this.SetOwner ((Int64) uid, (Int64) gid);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SetOwner (UnixUserInfo owner)
 | 
					    public void SetOwner (String owner, String group)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			long uid, gid;
 | 
					      Int64 uid = -1;
 | 
				
			||||||
			uid = gid = -1;
 | 
					      if (owner != null) {
 | 
				
			||||||
			if (owner != null) {
 | 
					        uid = new UnixUserInfo (owner).UserId;
 | 
				
			||||||
				uid = owner.UserId;
 | 
					      }
 | 
				
			||||||
				gid = owner.GroupId;
 | 
					
 | 
				
			||||||
			}
 | 
					      Int64 gid = -1;
 | 
				
			||||||
			SetOwner (uid, gid);
 | 
					      if (group != null) {
 | 
				
			||||||
		}
 | 
					        gid = new UnixGroupInfo (group).GroupId;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public void SetOwner (UnixUserInfo owner, UnixGroupInfo group)
 | 
					
 | 
				
			||||||
		{
 | 
					      this.SetOwner (uid, gid);
 | 
				
			||||||
			long uid, gid;
 | 
					    }
 | 
				
			||||||
			uid = gid = -1;
 | 
					
 | 
				
			||||||
			if (owner != null)
 | 
					    public void SetOwner (UnixUserInfo owner)
 | 
				
			||||||
				uid = owner.UserId;
 | 
					    {
 | 
				
			||||||
			if (group != null)
 | 
					      Int64 uid, gid;
 | 
				
			||||||
				gid = owner.GroupId;
 | 
					      uid = gid = -1;
 | 
				
			||||||
			SetOwner (uid, gid);
 | 
					      if (owner != null) {
 | 
				
			||||||
		}
 | 
					        uid = owner.UserId;
 | 
				
			||||||
 | 
					        gid = owner.GroupId;
 | 
				
			||||||
		public override string ToString ()
 | 
					      }
 | 
				
			||||||
		{
 | 
					      this.SetOwner (uid, gid);
 | 
				
			||||||
			return FullPath;
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public void SetOwner (UnixUserInfo owner, UnixGroupInfo group)
 | 
				
			||||||
		public Native.Stat ToStat ()
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Int64 uid, gid;
 | 
				
			||||||
			AssertValid ();
 | 
					      uid = gid = -1;
 | 
				
			||||||
			return stat;
 | 
					      if (owner != null) {
 | 
				
			||||||
		}
 | 
					        uid = owner.UserId;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public static UnixFileSystemInfo GetFileSystemEntry (string path)
 | 
					
 | 
				
			||||||
		{
 | 
					      if (group != null) {
 | 
				
			||||||
			UnixFileSystemInfo info;
 | 
					        gid = owner.GroupId;
 | 
				
			||||||
			if (TryGetFileSystemEntry (path, out info))
 | 
					      }
 | 
				
			||||||
				return info;
 | 
					
 | 
				
			||||||
 | 
					      this.SetOwner (uid, gid);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastError ();
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Throw DirectoryNotFoundException because lstat(2) probably failed
 | 
					    public override String ToString() => this.FullPath;
 | 
				
			||||||
			// because of ENOTDIR (e.g. "/path/to/file/wtf"), so
 | 
					
 | 
				
			||||||
			// DirectoryNotFoundException is what would have been thrown anyway.
 | 
					    public Native.Stat ToStat ()
 | 
				
			||||||
			throw new DirectoryNotFoundException ("UnixMarshal.ThrowExceptionForLastError didn't throw?!");
 | 
					    {
 | 
				
			||||||
		}
 | 
					      this.AssertValid ();
 | 
				
			||||||
 | 
					      return this.stat;
 | 
				
			||||||
		public static bool TryGetFileSystemEntry (string path, out UnixFileSystemInfo entry)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			Native.Stat stat;
 | 
					    public static UnixFileSystemInfo GetFileSystemEntry (String path)
 | 
				
			||||||
			int r = Native.Syscall.lstat (path, out stat);
 | 
					    {
 | 
				
			||||||
			if (r == -1) {
 | 
					      if(TryGetFileSystemEntry(path, out UnixFileSystemInfo info)) {
 | 
				
			||||||
				if (Native.Stdlib.GetLastError() == Native.Errno.ENOENT) {
 | 
					        return info;
 | 
				
			||||||
					entry = new UnixFileInfo (path);
 | 
					      }
 | 
				
			||||||
					return true;
 | 
					
 | 
				
			||||||
				}
 | 
					      UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
				entry = null;
 | 
					
 | 
				
			||||||
				return false;
 | 
					      // Throw DirectoryNotFoundException because lstat(2) probably failed
 | 
				
			||||||
			}
 | 
					      // because of ENOTDIR (e.g. "/path/to/file/wtf"), so
 | 
				
			||||||
 | 
					      // DirectoryNotFoundException is what would have been thrown anyway.
 | 
				
			||||||
			if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR))
 | 
					      throw new DirectoryNotFoundException ("UnixMarshal.ThrowExceptionForLastError didn't throw?!");
 | 
				
			||||||
				entry = new UnixDirectoryInfo (path, stat);
 | 
					    }
 | 
				
			||||||
			else if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK))
 | 
					
 | 
				
			||||||
				entry = new UnixSymbolicLinkInfo (path, stat);
 | 
					    public static Boolean TryGetFileSystemEntry (String path, out UnixFileSystemInfo entry)
 | 
				
			||||||
			else
 | 
					    {
 | 
				
			||||||
				entry = new UnixFileInfo (path, stat);
 | 
					      Int32 r = Native.Syscall.lstat(path, out Native.Stat stat);
 | 
				
			||||||
 | 
					      if (r == -1) {
 | 
				
			||||||
			return true;
 | 
					        if (Native.Stdlib.GetLastError() == Native.Errno.ENOENT) {
 | 
				
			||||||
		}
 | 
					          entry = new UnixFileInfo (path);
 | 
				
			||||||
	}
 | 
					          return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        entry = null;
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      entry = IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR)
 | 
				
			||||||
 | 
					        ? new UnixDirectoryInfo (path, stat)
 | 
				
			||||||
 | 
					        : IsFileType(stat.st_mode, Native.FilePermissions.S_IFLNK)
 | 
				
			||||||
 | 
					          ? new UnixSymbolicLinkInfo(path, stat)
 | 
				
			||||||
 | 
					          : (UnixFileSystemInfo)new UnixFileInfo(path, stat);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -33,117 +33,91 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixGroupInfo
 | 
					  public sealed class UnixGroupInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private Native.Group group;
 | 
					    private readonly Native.Group group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixGroupInfo (string group)
 | 
					    public UnixGroupInfo (String group)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.group = new Native.Group ();
 | 
					      this.group = new Native.Group ();
 | 
				
			||||||
			Native.Group gr;
 | 
					      Int32 r = Native.Syscall.getgrnam_r(group, this.group, out Native.Group gr);
 | 
				
			||||||
			int r = Native.Syscall.getgrnam_r (group, this.group, out gr);
 | 
					      if (r != 0 || gr == null) {
 | 
				
			||||||
			if (r != 0 || gr == null)
 | 
					        throw new ArgumentException (Locale.GetText ("invalid group name"), "group");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid group name"), "group");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixGroupInfo (long group)
 | 
					    public UnixGroupInfo (Int64 group)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.group = new Native.Group ();
 | 
					      this.group = new Native.Group ();
 | 
				
			||||||
			Native.Group gr;
 | 
					      Int32 r = Native.Syscall.getgrgid_r(Convert.ToUInt32(group), this.group, out Native.Group gr);
 | 
				
			||||||
			int r = Native.Syscall.getgrgid_r (Convert.ToUInt32 (group), this.group, out gr);
 | 
					      if (r != 0 || gr == null) {
 | 
				
			||||||
			if (r != 0 || gr == null)
 | 
					        throw new ArgumentException (Locale.GetText ("invalid group id"), "group");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid group id"), "group");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixGroupInfo (Native.Group group)
 | 
					    public UnixGroupInfo(Native.Group group) => this.group = CopyGroup(group);
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			this.group = CopyGroup (group);
 | 
					    private static Native.Group CopyGroup(Native.Group group) => new Native.Group {
 | 
				
			||||||
		}
 | 
					      gr_gid = group.gr_gid,
 | 
				
			||||||
 | 
					      gr_mem = group.gr_mem,
 | 
				
			||||||
		private static Native.Group CopyGroup (Native.Group group)
 | 
					      gr_name = group.gr_name,
 | 
				
			||||||
		{
 | 
					      gr_passwd = group.gr_passwd
 | 
				
			||||||
			Native.Group g = new Native.Group ();
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			g.gr_gid    = group.gr_gid;
 | 
					    public String GroupName => this.group.gr_name;
 | 
				
			||||||
			g.gr_mem    = group.gr_mem;
 | 
					
 | 
				
			||||||
			g.gr_name   = group.gr_name;
 | 
					    public String Password => this.group.gr_passwd;
 | 
				
			||||||
			g.gr_passwd = group.gr_passwd;
 | 
					
 | 
				
			||||||
 | 
					    public Int64 GroupId => this.group.gr_gid;
 | 
				
			||||||
			return g;
 | 
					
 | 
				
			||||||
		}
 | 
					    public UnixUserInfo[] GetMembers ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
		public string GroupName {
 | 
					      ArrayList members = new ArrayList (this.group.gr_mem.Length);
 | 
				
			||||||
			get {return group.gr_name;}
 | 
					      for (Int32 i = 0; i < this.group.gr_mem.Length; ++i) {
 | 
				
			||||||
		}
 | 
					        try {
 | 
				
			||||||
 | 
					          _ = members.Add(new UnixUserInfo(this.group.gr_mem[i]));
 | 
				
			||||||
		public string Password {
 | 
					        } catch (ArgumentException) {
 | 
				
			||||||
			get {return group.gr_passwd;}
 | 
					          // ignore invalid users
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public long GroupId {
 | 
					      return (UnixUserInfo[]) members.ToArray (typeof (UnixUserInfo));
 | 
				
			||||||
			get {return group.gr_gid;}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					    public String[] GetMemberNames() => (String[])this.group.gr_mem.Clone();
 | 
				
			||||||
		public UnixUserInfo[] GetMembers ()
 | 
					
 | 
				
			||||||
		{
 | 
					    public override Int32 GetHashCode() => this.group.GetHashCode();
 | 
				
			||||||
			ArrayList members = new ArrayList (group.gr_mem.Length);
 | 
					
 | 
				
			||||||
			for (int i = 0; i < group.gr_mem.Length; ++i) {
 | 
					    public override Boolean Equals(Object obj) => obj == null || this.GetType() != obj.GetType() ? false : this.group.Equals(((UnixGroupInfo)obj).group);
 | 
				
			||||||
				try {
 | 
					
 | 
				
			||||||
					members.Add (new UnixUserInfo (group.gr_mem [i]));
 | 
					    public override String ToString() => this.group.ToString();
 | 
				
			||||||
				} catch (ArgumentException) {
 | 
					
 | 
				
			||||||
					// ignore invalid users
 | 
					    public Native.Group ToGroup() => CopyGroup(this.group);
 | 
				
			||||||
				}
 | 
					
 | 
				
			||||||
			}
 | 
					    public static UnixGroupInfo[] GetLocalGroups ()
 | 
				
			||||||
			return (UnixUserInfo[]) members.ToArray (typeof (UnixUserInfo));
 | 
					    {
 | 
				
			||||||
		}
 | 
					      ArrayList entries = new ArrayList ();
 | 
				
			||||||
 | 
					      lock (Native.Syscall.grp_lock) {
 | 
				
			||||||
		public string[] GetMemberNames ()
 | 
					        if (Native.Syscall.setgrent () != 0) {
 | 
				
			||||||
		{
 | 
					          UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			return (string[]) group.gr_mem.Clone ();
 | 
					        }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
		public override int GetHashCode ()
 | 
					          Native.Group g;
 | 
				
			||||||
		{
 | 
					          while ((g = Native.Syscall.getgrent()) != null) {
 | 
				
			||||||
			return group.GetHashCode ();
 | 
					            _ = entries.Add(new UnixGroupInfo(g));
 | 
				
			||||||
		}
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool Equals (object obj)
 | 
					          if (Native.Syscall.GetLastError() != (Native.Errno) 0) {
 | 
				
			||||||
		{
 | 
					            UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			if (obj == null || GetType () != obj.GetType())
 | 
					          }
 | 
				
			||||||
				return false;
 | 
					        }
 | 
				
			||||||
			return group.Equals (((UnixGroupInfo) obj).group);
 | 
					        finally {
 | 
				
			||||||
		}
 | 
					          _ = Native.Syscall.endgrent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
		public override string ToString ()
 | 
					      }
 | 
				
			||||||
		{
 | 
					      return (UnixGroupInfo[]) entries.ToArray (typeof(UnixGroupInfo));
 | 
				
			||||||
			return group.ToString();
 | 
					    }
 | 
				
			||||||
		}
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
		public Native.Group ToGroup ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return CopyGroup (group);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static UnixGroupInfo[] GetLocalGroups ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ArrayList entries = new ArrayList ();
 | 
					 | 
				
			||||||
			lock (Native.Syscall.grp_lock) {
 | 
					 | 
				
			||||||
				if (Native.Syscall.setgrent () != 0)
 | 
					 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					Native.Group g;
 | 
					 | 
				
			||||||
					while ((g = Native.Syscall.getgrent()) != null)
 | 
					 | 
				
			||||||
						entries.Add (new UnixGroupInfo (g));
 | 
					 | 
				
			||||||
					if (Native.Syscall.GetLastError() != (Native.Errno) 0)
 | 
					 | 
				
			||||||
						UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				finally {
 | 
					 | 
				
			||||||
					Native.Syscall.endgrent ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return (UnixGroupInfo[]) entries.ToArray (typeof(UnixGroupInfo));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -30,75 +30,49 @@ using System;
 | 
				
			|||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
using System.Runtime.Serialization;
 | 
					using System.Runtime.Serialization;
 | 
				
			||||||
using Mono.Unix;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[Serializable]
 | 
					  [Serializable]
 | 
				
			||||||
	public class UnixIOException : IOException
 | 
					  public class UnixIOException : IOException
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private int errno;
 | 
					    private Int32 errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixIOException ()
 | 
					    public UnixIOException ()
 | 
				
			||||||
			: this (Marshal.GetLastWin32Error())
 | 
					      : this (Marshal.GetLastWin32Error())
 | 
				
			||||||
		{}
 | 
					    {}
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public UnixIOException (int errno)
 | 
					    public UnixIOException(Int32 errno)
 | 
				
			||||||
			: base (GetMessage (Native.NativeConvert.ToErrno (errno)))
 | 
					      : base(GetMessage(Native.NativeConvert.ToErrno(errno))) => this.errno = errno;
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			this.errno = errno;
 | 
					    public UnixIOException(Int32 errno, Exception inner)
 | 
				
			||||||
		}
 | 
					      : base(GetMessage(Native.NativeConvert.ToErrno(errno)), inner) => this.errno = errno;
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public UnixIOException (int errno, Exception inner)
 | 
					 | 
				
			||||||
			: base (GetMessage (Native.NativeConvert.ToErrno (errno)), inner)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.errno = errno;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixIOException (Native.Errno errno)
 | 
					    public UnixIOException(Native.Errno errno)
 | 
				
			||||||
			: base (GetMessage (errno))
 | 
					      : base(GetMessage(errno)) => this.errno = Native.NativeConvert.FromErrno(errno);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.errno = Native.NativeConvert.FromErrno (errno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixIOException (Native.Errno errno, Exception inner)
 | 
					    public UnixIOException(Native.Errno errno, Exception inner)
 | 
				
			||||||
			: base (GetMessage (errno), inner)
 | 
					      : base(GetMessage(errno), inner) => this.errno = Native.NativeConvert.FromErrno(errno);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.errno = Native.NativeConvert.FromErrno (errno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixIOException (string message)
 | 
					    public UnixIOException(String message)
 | 
				
			||||||
			: base (message)
 | 
					      : base(message) => this.errno = 0;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.errno = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixIOException (string message, Exception inner)
 | 
					    public UnixIOException(String message, Exception inner)
 | 
				
			||||||
			: base (message, inner)
 | 
					      : base(message, inner) => this.errno = 0;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.errno = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected UnixIOException (SerializationInfo info, StreamingContext context)
 | 
					    protected UnixIOException (SerializationInfo info, StreamingContext context)
 | 
				
			||||||
			: base (info, context)
 | 
					      : base (info, context)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public int NativeErrorCode {
 | 
					    public Int32 NativeErrorCode => this.errno;
 | 
				
			||||||
			get {return errno;}
 | 
					
 | 
				
			||||||
		}
 | 
					    public Native.Errno ErrorCode => Native.NativeConvert.ToErrno(this.errno);
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		public Native.Errno ErrorCode {
 | 
					    private static String GetMessage(Native.Errno errno) => String.Format("{0} [{1}].",
 | 
				
			||||||
			get {return Native.NativeConvert.ToErrno (errno);}
 | 
					          UnixMarshal.GetErrorDescription(errno),
 | 
				
			||||||
		}
 | 
					          errno);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
		private static string GetMessage (Native.Errno errno)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return string.Format ("{0} [{1}].",
 | 
					 | 
				
			||||||
					UnixMarshal.GetErrorDescription (errno),
 | 
					 | 
				
			||||||
					errno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -35,139 +35,141 @@ using System.IO;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class UnixListener : MarshalByRefObject, IDisposable {
 | 
					  public class UnixListener : MarshalByRefObject, IDisposable {
 | 
				
			||||||
		bool disposed;
 | 
					    Boolean disposed;
 | 
				
			||||||
		bool listening;
 | 
					    Boolean listening;
 | 
				
			||||||
		Socket server;
 | 
					    Socket server;
 | 
				
			||||||
		EndPoint savedEP;
 | 
					    EndPoint savedEP;
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
		void Init (UnixEndPoint ep)
 | 
					    void Init (UnixEndPoint ep)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			listening = false;
 | 
					      this.listening = false;
 | 
				
			||||||
			string filename = ep.Filename;
 | 
					      String filename = ep.Filename;
 | 
				
			||||||
			if (File.Exists (filename)) {
 | 
					      if (File.Exists (filename)) {
 | 
				
			||||||
				Socket conn = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
					        Socket conn = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
				
			||||||
				try {
 | 
					        try {
 | 
				
			||||||
					conn.Connect (ep);
 | 
					          conn.Connect (ep);
 | 
				
			||||||
					conn.Close ();
 | 
					          conn.Close ();
 | 
				
			||||||
					throw new InvalidOperationException ("There's already a server listening on " + filename);
 | 
					          throw new InvalidOperationException ("There's already a server listening on " + filename);
 | 
				
			||||||
				} catch (SocketException) {
 | 
					        } catch (SocketException) {
 | 
				
			||||||
				}
 | 
					        }
 | 
				
			||||||
				File.Delete (filename);
 | 
					        File.Delete (filename);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.server = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
				
			||||||
 | 
					      this.server.Bind (ep);
 | 
				
			||||||
 | 
					      this.savedEP = this.server.LocalEndPoint;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    public UnixListener (String path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (!Directory.Exists (Path.GetDirectoryName (path))) {
 | 
				
			||||||
 | 
					        _ = Directory.CreateDirectory(Path.GetDirectoryName(path));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.Init (new UnixEndPoint (path));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			server = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
 | 
					    public UnixListener (UnixEndPoint localEndPoint)
 | 
				
			||||||
			server.Bind (ep);
 | 
					    {
 | 
				
			||||||
			savedEP = server.LocalEndPoint;
 | 
					      if (localEndPoint == null) {
 | 
				
			||||||
		}
 | 
					        throw new ArgumentNullException ("localendPoint");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.Init (localEndPoint);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public EndPoint LocalEndpoint => this.savedEP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected Socket Server => this.server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Socket AcceptSocket ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
 | 
					      if (!this.listening) {
 | 
				
			||||||
 | 
					        throw new InvalidOperationException ("Socket is not listening");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return this.server.Accept ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public UnixListener (string path)
 | 
					    public UnixClient AcceptUnixClient ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (!Directory.Exists (Path.GetDirectoryName (path)))
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
				Directory.CreateDirectory (Path.GetDirectoryName (path));
 | 
					      if (!this.listening) {
 | 
				
			||||||
            
 | 
					        throw new InvalidOperationException ("Socket is not listening");
 | 
				
			||||||
			Init (new UnixEndPoint (path));
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return new UnixClient (this.AcceptSocket ());
 | 
				
			||||||
		public UnixListener (UnixEndPoint localEndPoint)
 | 
					    }
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (localEndPoint == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ("localendPoint");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Init (localEndPoint);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public EndPoint LocalEndpoint {
 | 
					    ~UnixListener ()
 | 
				
			||||||
			get { return savedEP; }
 | 
					    {
 | 
				
			||||||
		}
 | 
					      this.Dispose (false);
 | 
				
			||||||
        
 | 
					    }
 | 
				
			||||||
		protected Socket Server {
 | 
					 | 
				
			||||||
			get { return server; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
		public Socket AcceptSocket ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			CheckDisposed ();
 | 
					 | 
				
			||||||
			if (!listening)
 | 
					 | 
				
			||||||
				throw new InvalidOperationException ("Socket is not listening");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return server.Accept ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
		public UnixClient AcceptUnixClient ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			CheckDisposed ();
 | 
					 | 
				
			||||||
			if (!listening)
 | 
					 | 
				
			||||||
				throw new InvalidOperationException ("Socket is not listening");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return new UnixClient (AcceptSocket ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
		~UnixListener ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Dispose (false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
		public bool Pending ()
 | 
					    public Boolean Pending ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			CheckDisposed ();
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
			if (!listening)
 | 
					      if (!this.listening) {
 | 
				
			||||||
				throw new InvalidOperationException ("Socket is not listening");
 | 
					        throw new InvalidOperationException ("Socket is not listening");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return this.server.Poll (1000, SelectMode.SelectRead);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Start() => this.Start(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Start (Int32 backlog)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
 | 
					      if (this.listening) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.server.Listen (backlog);
 | 
				
			||||||
 | 
					      this.listening = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return server.Poll (1000, SelectMode.SelectRead);
 | 
					    public void Stop ()
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      this.CheckDisposed ();
 | 
				
			||||||
 | 
					      this.Dispose (true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Dispose ()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      this.Dispose (true);
 | 
				
			||||||
 | 
					      GC.SuppressFinalize (this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected void Dispose (Boolean disposing)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (this.disposed) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (disposing) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          File.Delete (((UnixEndPoint)this.savedEP).Filename);
 | 
				
			||||||
 | 
					        } catch {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.server != null) {
 | 
				
			||||||
 | 
					          this.server.Close ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.server = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.disposed = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		public void Start ()
 | 
					    void CheckDisposed ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Start (5);
 | 
					      if (this.disposed) {
 | 
				
			||||||
		}
 | 
					        throw new ObjectDisposedException (this.GetType().FullName);
 | 
				
			||||||
        
 | 
					      }
 | 
				
			||||||
		public void Start (int backlog)
 | 
					    }        
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			CheckDisposed ();
 | 
					 | 
				
			||||||
			if (listening)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			server.Listen (backlog);
 | 
					 | 
				
			||||||
			listening = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void Stop ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			CheckDisposed ();
 | 
					 | 
				
			||||||
			Dispose (true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void Dispose ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Dispose (true);
 | 
					 | 
				
			||||||
			GC.SuppressFinalize (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		protected void Dispose (bool disposing)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (disposed)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (disposing) {
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					File.Delete (((UnixEndPoint) savedEP).Filename);
 | 
					 | 
				
			||||||
				} catch {
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (server != null)
 | 
					 | 
				
			||||||
					server.Close ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				server = null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			disposed = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
		void CheckDisposed ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (disposed)
 | 
					 | 
				
			||||||
				throw new ObjectDisposedException (GetType().FullName);
 | 
					 | 
				
			||||||
		}        
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Net.Sockets;
 | 
					using System.Net.Sockets;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
@ -36,461 +37,434 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Scenario:  We want to be able to translate an Error to a string.
 | 
					  // Scenario:  We want to be able to translate an Error to a string.
 | 
				
			||||||
	//  Problem:  Thread-safety.  Strerror(3) isn't thread safe (unless
 | 
					  //  Problem:  Thread-safety.  Strerror(3) isn't thread safe (unless
 | 
				
			||||||
	//            thread-local-variables are used, which is probably only 
 | 
					  //            thread-local-variables are used, which is probably only 
 | 
				
			||||||
	//            true on Windows).
 | 
					  //            true on Windows).
 | 
				
			||||||
	// Solution:  Use strerror_r().
 | 
					  // Solution:  Use strerror_r().
 | 
				
			||||||
	//  Problem:  strerror_r() isn't portable. 
 | 
					  //  Problem:  strerror_r() isn't portable. 
 | 
				
			||||||
	//            (Apparently Solaris doesn't provide it.)
 | 
					  //            (Apparently Solaris doesn't provide it.)
 | 
				
			||||||
	// Solution:  Cry.  Then introduce an intermediary, ErrorMarshal.
 | 
					  // Solution:  Cry.  Then introduce an intermediary, ErrorMarshal.
 | 
				
			||||||
	//            ErrorMarshal exposes a single public delegate, Translator,
 | 
					  //            ErrorMarshal exposes a single public delegate, Translator,
 | 
				
			||||||
	//            which will convert an Error to a string.  It's static
 | 
					  //            which will convert an Error to a string.  It's static
 | 
				
			||||||
	//            constructor first tries using strerror_r().  If it works,
 | 
					  //            constructor first tries using strerror_r().  If it works,
 | 
				
			||||||
	//            great; use it in the future.  If it doesn't work, fallback to
 | 
					  //            great; use it in the future.  If it doesn't work, fallback to
 | 
				
			||||||
	//            using strerror(3).
 | 
					  //            using strerror(3).
 | 
				
			||||||
	//            This should be thread safe, since the check is done within the
 | 
					  //            This should be thread safe, since the check is done within the
 | 
				
			||||||
	//            class constructor lock.
 | 
					  //            class constructor lock.
 | 
				
			||||||
	//            Strerror(3) will be thread-safe from managed code, but won't
 | 
					  //            Strerror(3) will be thread-safe from managed code, but won't
 | 
				
			||||||
	//            be thread-safe between managed & unmanaged code.
 | 
					  //            be thread-safe between managed & unmanaged code.
 | 
				
			||||||
	internal class ErrorMarshal
 | 
					  internal class ErrorMarshal
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		internal delegate string ErrorTranslator (Native.Errno errno);
 | 
					    internal delegate String ErrorTranslator (Native.Errno errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal static readonly ErrorTranslator Translate;
 | 
					    internal static readonly ErrorTranslator Translate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static ErrorMarshal ()
 | 
					    static ErrorMarshal ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			try {
 | 
					      try {
 | 
				
			||||||
				Translate = new ErrorTranslator (strerror_r);
 | 
					        Translate = new ErrorTranslator (strerror_r);
 | 
				
			||||||
				Translate (Native.Errno.ERANGE);
 | 
					        _ = Translate(Native.Errno.ERANGE);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			catch (EntryPointNotFoundException) {
 | 
					      catch (EntryPointNotFoundException) {
 | 
				
			||||||
				Translate = new ErrorTranslator (strerror);
 | 
					        Translate = new ErrorTranslator (strerror);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static string strerror (Native.Errno errno)
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
		{
 | 
					    private static String strerror(Native.Errno errno) => Native.Stdlib.strerror(errno);
 | 
				
			||||||
			return Native.Stdlib.strerror (errno);
 | 
					
 | 
				
			||||||
		}
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
 | 
					    private static String strerror_r (Native.Errno errno)
 | 
				
			||||||
		private static string strerror_r (Native.Errno errno)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      StringBuilder buf = new StringBuilder (16);
 | 
				
			||||||
			StringBuilder buf = new StringBuilder (16);
 | 
					      Int32 r;
 | 
				
			||||||
			int r = 0;
 | 
					      do {
 | 
				
			||||||
			do {
 | 
					        buf.Capacity *= 2;
 | 
				
			||||||
				buf.Capacity *= 2;
 | 
					        r = Native.Syscall.strerror_r (errno, buf);
 | 
				
			||||||
				r = Native.Syscall.strerror_r (errno, buf);
 | 
					      } while (r == -1 && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
 | 
				
			||||||
			} while (r == -1 && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
 | 
					
 | 
				
			||||||
 | 
					      return r == -1 ? "** Unknown error code: " + (Int32) errno + "**" : buf.ToString();
 | 
				
			||||||
			if (r == -1)
 | 
					    }
 | 
				
			||||||
				return "** Unknown error code: " + ((int) errno) + "**";
 | 
					  }
 | 
				
			||||||
			return buf.ToString();
 | 
					
 | 
				
			||||||
		}
 | 
					  public sealed /* static */ class UnixMarshal
 | 
				
			||||||
	}
 | 
					  {
 | 
				
			||||||
 | 
					    private UnixMarshal () {}
 | 
				
			||||||
	public sealed /* static */ class UnixMarshal
 | 
					
 | 
				
			||||||
	{
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
		private UnixMarshal () {}
 | 
					    public static String GetErrorDescription(Native.Errno errno) => ErrorMarshal.Translate(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    public static IntPtr AllocHeap (Int64 size)
 | 
				
			||||||
		public static string GetErrorDescription (Native.Errno errno)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      if (size < 0) {
 | 
				
			||||||
			return ErrorMarshal.Translate (errno);
 | 
					        throw new ArgumentOutOfRangeException ("size", "< 0");
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static IntPtr AllocHeap (long size)
 | 
					      return Native.Stdlib.malloc ((UInt64) size);
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
			if (size < 0)
 | 
					
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("size", "< 0");
 | 
					    public static IntPtr ReAllocHeap (IntPtr ptr, Int64 size)
 | 
				
			||||||
			return Native.Stdlib.malloc ((ulong) size);
 | 
					    {
 | 
				
			||||||
		}
 | 
					      if (size < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("size", "< 0");
 | 
				
			||||||
		public static IntPtr ReAllocHeap (IntPtr ptr, long size)
 | 
					      }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			if (size < 0)
 | 
					      return Native.Stdlib.realloc (ptr, (UInt64) size);
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("size", "< 0");
 | 
					    }
 | 
				
			||||||
			return Native.Stdlib.realloc (ptr, (ulong) size);
 | 
					
 | 
				
			||||||
		}
 | 
					    public static void FreeHeap(IntPtr ptr) => Native.Stdlib.free(ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static void FreeHeap (IntPtr ptr)
 | 
					    public static unsafe String PtrToStringUnix (IntPtr p)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Native.Stdlib.free (ptr);
 | 
					      if (p == IntPtr.Zero) {
 | 
				
			||||||
		}
 | 
					        return null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public static unsafe string PtrToStringUnix (IntPtr p)
 | 
					
 | 
				
			||||||
		{
 | 
					      Int32 len = checked ((Int32) Native.Stdlib.strlen (p));
 | 
				
			||||||
			if (p == IntPtr.Zero)
 | 
					      return new String((SByte*) p, 0, len, UnixEncoding.Instance);
 | 
				
			||||||
				return null;
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int len = checked ((int) Native.Stdlib.strlen (p));
 | 
					    public static String PtrToString(IntPtr p) => p == IntPtr.Zero ? null : PtrToString(p, UnixEncoding.Instance);
 | 
				
			||||||
			return new string ((sbyte*) p, 0, len, UnixEncoding.Instance);
 | 
					
 | 
				
			||||||
		}
 | 
					    public static unsafe String PtrToString (IntPtr p, Encoding encoding)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
		public static string PtrToString (IntPtr p)
 | 
					      if (p == IntPtr.Zero) {
 | 
				
			||||||
		{
 | 
					        return null;
 | 
				
			||||||
			if (p == IntPtr.Zero)
 | 
					      }
 | 
				
			||||||
				return null;
 | 
					
 | 
				
			||||||
			return PtrToString (p, UnixEncoding.Instance);
 | 
					      if (encoding == null) {
 | 
				
			||||||
		}
 | 
					        throw new ArgumentNullException ("encoding");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public static unsafe string PtrToString (IntPtr p, Encoding encoding)
 | 
					
 | 
				
			||||||
		{
 | 
					      Int32 len = GetStringByteLength (p, encoding);
 | 
				
			||||||
			if (p == IntPtr.Zero)
 | 
					
 | 
				
			||||||
				return null;
 | 
					      // Due to variable-length encoding schemes, GetStringByteLength() may
 | 
				
			||||||
 | 
					      // have returned multiple "null" characters.  (For example, when
 | 
				
			||||||
			if (encoding == null)
 | 
					      // encoding a string into UTF-8 there will be 4 terminating nulls.)
 | 
				
			||||||
				throw new ArgumentNullException ("encoding");
 | 
					      // We don't want these null's to be in the returned string, so strip
 | 
				
			||||||
 | 
					      // them off.
 | 
				
			||||||
			int len = GetStringByteLength (p, encoding);
 | 
					      String s = new String((SByte*) p, 0, len, encoding);
 | 
				
			||||||
 | 
					      len = s.Length;
 | 
				
			||||||
			// Due to variable-length encoding schemes, GetStringByteLength() may
 | 
					      while (len > 0 && s [len-1] == 0) {
 | 
				
			||||||
			// have returned multiple "null" characters.  (For example, when
 | 
					        --len;
 | 
				
			||||||
			// encoding a string into UTF-8 there will be 4 terminating nulls.)
 | 
					      }
 | 
				
			||||||
			// We don't want these null's to be in the returned string, so strip
 | 
					
 | 
				
			||||||
			// them off.
 | 
					      return len == s.Length ? s : s.Substring (0, len);
 | 
				
			||||||
			string s = new string ((sbyte*) p, 0, len, encoding);
 | 
					    }
 | 
				
			||||||
			len = s.Length;
 | 
					
 | 
				
			||||||
			while (len > 0 && s [len-1] == 0)
 | 
					    private static Int32 GetStringByteLength (IntPtr p, Encoding encoding)
 | 
				
			||||||
				--len;
 | 
					    {
 | 
				
			||||||
			if (len == s.Length) 
 | 
					      Type encodingType = encoding.GetType ();
 | 
				
			||||||
				return s;
 | 
					
 | 
				
			||||||
			return s.Substring (0, len);
 | 
					      Int32 len = typeof(UTF8Encoding).IsAssignableFrom (encodingType) ||
 | 
				
			||||||
		}
 | 
					          typeof(UTF7Encoding).IsAssignableFrom (encodingType) ||
 | 
				
			||||||
 | 
					          typeof(UnixEncoding).IsAssignableFrom (encodingType) ||
 | 
				
			||||||
		private static int GetStringByteLength (IntPtr p, Encoding encoding)
 | 
					          typeof(ASCIIEncoding).IsAssignableFrom (encodingType)
 | 
				
			||||||
		{
 | 
					        ? (Int32) Native.Stdlib.strlen (p)
 | 
				
			||||||
			Type encodingType = encoding.GetType ();
 | 
					        : typeof(UnicodeEncoding).IsAssignableFrom(encodingType)
 | 
				
			||||||
 | 
					          ? GetInt16BufferLength(p)
 | 
				
			||||||
			int len = -1;
 | 
					          : typeof(UTF32Encoding).IsAssignableFrom(encodingType)
 | 
				
			||||||
 | 
					                  ? GetInt32BufferLength(p)
 | 
				
			||||||
			// Encodings that will always end with a single null byte
 | 
					                  : GetRandomBufferLength(p, encoding.GetMaxByteCount(1));
 | 
				
			||||||
			if (typeof(UTF8Encoding).IsAssignableFrom (encodingType) ||
 | 
					
 | 
				
			||||||
					typeof(UTF7Encoding).IsAssignableFrom (encodingType) ||
 | 
					      // Encodings that will always end with a single null byte
 | 
				
			||||||
					typeof(UnixEncoding).IsAssignableFrom (encodingType) ||
 | 
					
 | 
				
			||||||
					typeof(ASCIIEncoding).IsAssignableFrom (encodingType)) {
 | 
					      if(len == -1) {
 | 
				
			||||||
				len = checked ((int) Native.Stdlib.strlen (p));
 | 
					        throw new NotSupportedException ("Unable to determine native string buffer length");
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			// Encodings that will always end with a 0x0000 16-bit word
 | 
					
 | 
				
			||||||
			else if (typeof(UnicodeEncoding).IsAssignableFrom (encodingType)) {
 | 
					      return len;
 | 
				
			||||||
				len = GetInt16BufferLength (p);
 | 
					    }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			// Encodings that will always end with a 0x00000000 32-bit word
 | 
					    private static Int32 GetInt16BufferLength (IntPtr p)
 | 
				
			||||||
			else if (typeof(UTF32Encoding).IsAssignableFrom (encodingType)) {
 | 
					    {
 | 
				
			||||||
				len = GetInt32BufferLength (p);
 | 
					      Int32 len = 0;
 | 
				
			||||||
			}
 | 
					      while (Marshal.ReadInt16 (p, len*2) != 0) {
 | 
				
			||||||
			// Some non-public encoding, such as Latin1 or a DBCS charset.
 | 
					        checked {++len;}
 | 
				
			||||||
			// Look for a sequence of encoding.GetMaxByteCount() bytes that are all
 | 
					      }
 | 
				
			||||||
			// 0, which should be the terminating null.
 | 
					
 | 
				
			||||||
			// This is "iffy", since it may fail for variable-width encodings; for
 | 
					      return checked(len*2);
 | 
				
			||||||
			// example, UTF8Encoding.GetMaxByteCount(1) = 4, so this would read 3
 | 
					    }
 | 
				
			||||||
			// bytes past the end of the string, possibly into garbage memory
 | 
					
 | 
				
			||||||
			// (which is why we special case UTF above).
 | 
					    private static Int32 GetInt32BufferLength (IntPtr p)
 | 
				
			||||||
			else {
 | 
					    {
 | 
				
			||||||
				len = GetRandomBufferLength (p, encoding.GetMaxByteCount(1));
 | 
					      Int32 len = 0;
 | 
				
			||||||
			}
 | 
					      while (Marshal.ReadInt32 (p, len*4) != 0) {
 | 
				
			||||||
 | 
					        checked {++len;}
 | 
				
			||||||
			if (len == -1)
 | 
					      }
 | 
				
			||||||
				throw new NotSupportedException ("Unable to determine native string buffer length");
 | 
					
 | 
				
			||||||
			return len;
 | 
					      return checked(len*4);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static int GetInt16BufferLength (IntPtr p)
 | 
					    private static Int32 GetRandomBufferLength (IntPtr p, Int32 nullLength)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int len = 0;
 | 
					      switch (nullLength) {
 | 
				
			||||||
			while (Marshal.ReadInt16 (p, len*2) != 0)
 | 
					        case 1: return checked ((Int32) Native.Stdlib.strlen (p));
 | 
				
			||||||
				checked {++len;}
 | 
					        case 2: return GetInt16BufferLength (p);
 | 
				
			||||||
			return checked(len*2);
 | 
					        case 4: return GetInt32BufferLength (p);
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static int GetInt32BufferLength (IntPtr p)
 | 
					      Int32 len = 0;
 | 
				
			||||||
		{
 | 
					      Int32 num_null_seen = 0;
 | 
				
			||||||
			int len = 0;
 | 
					
 | 
				
			||||||
			while (Marshal.ReadInt32 (p, len*4) != 0)
 | 
					      do {
 | 
				
			||||||
				checked {++len;}
 | 
					        Byte b = Marshal.ReadByte (p, len++);
 | 
				
			||||||
			return checked(len*4);
 | 
					        if (b == 0) {
 | 
				
			||||||
		}
 | 
					          ++num_null_seen;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
		private static int GetRandomBufferLength (IntPtr p, int nullLength)
 | 
					          num_null_seen = 0;
 | 
				
			||||||
		{
 | 
					        }
 | 
				
			||||||
			switch (nullLength) {
 | 
					      } while (num_null_seen != nullLength);
 | 
				
			||||||
				case 1: return checked ((int) Native.Stdlib.strlen (p));
 | 
					
 | 
				
			||||||
				case 2: return GetInt16BufferLength (p);
 | 
					      return len;
 | 
				
			||||||
				case 4: return GetInt32BufferLength (p);
 | 
					    }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
			int len = 0;
 | 
					     * Marshal a C `char **'.  ANSI C `main' requirements are assumed:
 | 
				
			||||||
			int num_null_seen = 0;
 | 
					     *
 | 
				
			||||||
 | 
					     *   stringArray is an array of pointers to C strings
 | 
				
			||||||
			do {
 | 
					     *   stringArray has a terminating NULL string.
 | 
				
			||||||
				byte b = Marshal.ReadByte (p, len++);
 | 
					     *
 | 
				
			||||||
				if (b == 0)
 | 
					     * For example:
 | 
				
			||||||
					++num_null_seen;
 | 
					     *   stringArray[0] = "string 1";
 | 
				
			||||||
				else
 | 
					     *   stringArray[1] = "string 2";
 | 
				
			||||||
					num_null_seen = 0;
 | 
					     *   stringArray[2] = NULL
 | 
				
			||||||
			} while (num_null_seen != nullLength);
 | 
					     *
 | 
				
			||||||
 | 
					     * The terminating NULL is required so that we know when to stop looking
 | 
				
			||||||
			return len;
 | 
					     * for strings.
 | 
				
			||||||
		}
 | 
					     */
 | 
				
			||||||
 | 
					    public static String[] PtrToStringArray(IntPtr stringArray) => PtrToStringArray(stringArray, UnixEncoding.Instance);
 | 
				
			||||||
		/*
 | 
					
 | 
				
			||||||
		 * Marshal a C `char **'.  ANSI C `main' requirements are assumed:
 | 
					    public static String[] PtrToStringArray (IntPtr stringArray, Encoding encoding)
 | 
				
			||||||
		 *
 | 
					    {
 | 
				
			||||||
		 *   stringArray is an array of pointers to C strings
 | 
					      if (stringArray == IntPtr.Zero) {
 | 
				
			||||||
		 *   stringArray has a terminating NULL string.
 | 
					        return new String[]{};
 | 
				
			||||||
		 *
 | 
					      }
 | 
				
			||||||
		 * For example:
 | 
					
 | 
				
			||||||
		 *   stringArray[0] = "string 1";
 | 
					      Int32 argc = CountStrings (stringArray);
 | 
				
			||||||
		 *   stringArray[1] = "string 2";
 | 
					      return PtrToStringArray (argc, stringArray, encoding);
 | 
				
			||||||
		 *   stringArray[2] = NULL
 | 
					    }
 | 
				
			||||||
		 *
 | 
					
 | 
				
			||||||
		 * The terminating NULL is required so that we know when to stop looking
 | 
					    private static Int32 CountStrings (IntPtr stringArray)
 | 
				
			||||||
		 * for strings.
 | 
					    {
 | 
				
			||||||
		 */
 | 
					      Int32 count = 0;
 | 
				
			||||||
		public static string[] PtrToStringArray (IntPtr stringArray)
 | 
					      while (Marshal.ReadIntPtr (stringArray, count*IntPtr.Size) != IntPtr.Zero) {
 | 
				
			||||||
		{
 | 
					        ++count;
 | 
				
			||||||
			return PtrToStringArray (stringArray, UnixEncoding.Instance);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return count;
 | 
				
			||||||
		public static string[] PtrToStringArray (IntPtr stringArray, Encoding encoding)
 | 
					    }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			if (stringArray == IntPtr.Zero)
 | 
					    /*
 | 
				
			||||||
				return new string[]{};
 | 
					     * Like PtrToStringArray(IntPtr), but it allows the user to specify how
 | 
				
			||||||
 | 
					     * many strings to look for in the array.  As such, the requirement for a
 | 
				
			||||||
			int argc = CountStrings (stringArray);
 | 
					     * terminating NULL element is not required.
 | 
				
			||||||
			return PtrToStringArray (argc, stringArray, encoding);
 | 
					     *
 | 
				
			||||||
		}
 | 
					     * Usage is similar to ANSI C `main': count is argc, stringArray is argv.
 | 
				
			||||||
 | 
					     * stringArray[count] is NOT accessed (though ANSI C requires that 
 | 
				
			||||||
		private static int CountStrings (IntPtr stringArray)
 | 
					     * argv[argc] = NULL, which PtrToStringArray(IntPtr) requires).
 | 
				
			||||||
		{
 | 
					     */
 | 
				
			||||||
			int count = 0;
 | 
					    public static String[] PtrToStringArray(Int32 count, IntPtr stringArray) => PtrToStringArray(count, stringArray, UnixEncoding.Instance);
 | 
				
			||||||
			while (Marshal.ReadIntPtr (stringArray, count*IntPtr.Size) != IntPtr.Zero)
 | 
					
 | 
				
			||||||
				++count;
 | 
					    public static String[] PtrToStringArray (Int32 count, IntPtr stringArray, Encoding encoding)
 | 
				
			||||||
			return count;
 | 
					    {
 | 
				
			||||||
		}
 | 
					      if (count < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("count", "< 0");
 | 
				
			||||||
		/*
 | 
					      }
 | 
				
			||||||
		 * Like PtrToStringArray(IntPtr), but it allows the user to specify how
 | 
					
 | 
				
			||||||
		 * many strings to look for in the array.  As such, the requirement for a
 | 
					      if (encoding == null) {
 | 
				
			||||||
		 * terminating NULL element is not required.
 | 
					        throw new ArgumentNullException ("encoding");
 | 
				
			||||||
		 *
 | 
					      }
 | 
				
			||||||
		 * Usage is similar to ANSI C `main': count is argc, stringArray is argv.
 | 
					
 | 
				
			||||||
		 * stringArray[count] is NOT accessed (though ANSI C requires that 
 | 
					      if (stringArray == IntPtr.Zero) {
 | 
				
			||||||
		 * argv[argc] = NULL, which PtrToStringArray(IntPtr) requires).
 | 
					        return new String[count];
 | 
				
			||||||
		 */
 | 
					      }
 | 
				
			||||||
		public static string[] PtrToStringArray (int count, IntPtr stringArray)
 | 
					
 | 
				
			||||||
		{
 | 
					      String[] members = new String[count];
 | 
				
			||||||
			return PtrToStringArray (count, stringArray, UnixEncoding.Instance);
 | 
					      for (Int32 i = 0; i < count; ++i) {
 | 
				
			||||||
		}
 | 
					        IntPtr s = Marshal.ReadIntPtr (stringArray, i * IntPtr.Size);
 | 
				
			||||||
 | 
					        members[i] = PtrToString (s, encoding);
 | 
				
			||||||
		public static string[] PtrToStringArray (int count, IntPtr stringArray, Encoding encoding)
 | 
					      }
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			if (count < 0)
 | 
					      return members;
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("count", "< 0");
 | 
					    }
 | 
				
			||||||
			if (encoding == null)
 | 
					
 | 
				
			||||||
				throw new ArgumentNullException ("encoding");
 | 
					    public static IntPtr StringToHeap(String s) => StringToHeap(s, UnixEncoding.Instance);
 | 
				
			||||||
			if (stringArray == IntPtr.Zero)
 | 
					
 | 
				
			||||||
				return new string[count];
 | 
					    public static IntPtr StringToHeap(String s, Encoding encoding) => s == null ? IntPtr.Zero : StringToHeap(s, 0, s.Length, encoding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			string[] members = new string[count];
 | 
					    public static IntPtr StringToHeap(String s, Int32 index, Int32 count) => StringToHeap(s, index, count, UnixEncoding.Instance);
 | 
				
			||||||
			for (int i = 0; i < count; ++i) {
 | 
					
 | 
				
			||||||
				IntPtr s = Marshal.ReadIntPtr (stringArray, i * IntPtr.Size);
 | 
					    public static IntPtr StringToHeap (String s, Int32 index, Int32 count, Encoding encoding)
 | 
				
			||||||
				members[i] = PtrToString (s, encoding);
 | 
					    {
 | 
				
			||||||
			}
 | 
					      if (s == null) {
 | 
				
			||||||
 | 
					        return IntPtr.Zero;
 | 
				
			||||||
			return members;
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      if (encoding == null) {
 | 
				
			||||||
		public static IntPtr StringToHeap (string s)
 | 
					        throw new ArgumentNullException ("encoding");
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			return StringToHeap (s, UnixEncoding.Instance);
 | 
					
 | 
				
			||||||
		}
 | 
					      if (index < 0 || count < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException (index < 0 ? "index" : "count",
 | 
				
			||||||
		public static IntPtr StringToHeap (string s, Encoding encoding)
 | 
					           "Non - negative number required.");
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			if (s == null)
 | 
					
 | 
				
			||||||
				return IntPtr.Zero;
 | 
					      if (s.Length - index < count) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException ("s", "Index and count must refer to a location within the string.");
 | 
				
			||||||
			return StringToHeap (s, 0, s.Length, encoding);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      Int32 null_terminator_count = encoding.GetMaxByteCount (1);
 | 
				
			||||||
		public static IntPtr StringToHeap (string s, int index, int count)
 | 
					      Int32 length_without_null = encoding.GetByteCount (s);
 | 
				
			||||||
		{
 | 
					      Int32 marshalLength = checked (length_without_null + null_terminator_count);
 | 
				
			||||||
			return StringToHeap (s, index, count, UnixEncoding.Instance);
 | 
					
 | 
				
			||||||
		}
 | 
					      IntPtr mem = AllocHeap (marshalLength);
 | 
				
			||||||
 | 
					      if (mem == IntPtr.Zero) {
 | 
				
			||||||
		public static IntPtr StringToHeap (string s, int index, int count, Encoding encoding)
 | 
					        throw new UnixIOException (Native.Errno.ENOMEM);
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			if (s == null)
 | 
					
 | 
				
			||||||
				return IntPtr.Zero;
 | 
					      unsafe {
 | 
				
			||||||
 | 
					        fixed (Char* p = s) {
 | 
				
			||||||
			if (encoding == null)
 | 
					          Byte* marshal = (Byte*)mem;
 | 
				
			||||||
				throw new ArgumentNullException ("encoding");
 | 
					          Int32 bytes_copied;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (index < 0 || count < 0)
 | 
					          try {
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ((index < 0 ? "index" : "count"),
 | 
					            bytes_copied = encoding.GetBytes (p + index, count, marshal, marshalLength);
 | 
				
			||||||
					 "Non - negative number required.");
 | 
					          } catch {
 | 
				
			||||||
 | 
					            FreeHeap (mem);
 | 
				
			||||||
			if (s.Length - index < count)
 | 
					            throw;
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("s", "Index and count must refer to a location within the string.");
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int null_terminator_count = encoding.GetMaxByteCount (1);
 | 
					          if (bytes_copied != length_without_null) {
 | 
				
			||||||
			int length_without_null = encoding.GetByteCount (s);
 | 
					            FreeHeap (mem);
 | 
				
			||||||
			int marshalLength = checked (length_without_null + null_terminator_count);
 | 
					            throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
			IntPtr mem = AllocHeap (marshalLength);
 | 
					
 | 
				
			||||||
			if (mem == IntPtr.Zero)
 | 
					          marshal += length_without_null;
 | 
				
			||||||
				throw new UnixIOException (Native.Errno.ENOMEM);
 | 
					          for (Int32 i = 0; i < null_terminator_count; ++i) {
 | 
				
			||||||
 | 
					            marshal[i] = 0;
 | 
				
			||||||
			unsafe {
 | 
					          }
 | 
				
			||||||
				fixed (char* p = s) {
 | 
					        }
 | 
				
			||||||
					byte* marshal = (byte*)mem;
 | 
					      }
 | 
				
			||||||
					int bytes_copied;
 | 
					
 | 
				
			||||||
 | 
					      return mem;
 | 
				
			||||||
					try {
 | 
					    }
 | 
				
			||||||
						bytes_copied = encoding.GetBytes (p + index, count, marshal, marshalLength);
 | 
					
 | 
				
			||||||
					} catch {
 | 
					    public static Boolean ShouldRetrySyscall(Int32 r) => r == -1 && Native.Stdlib.GetLastError() == Native.Errno.EINTR;
 | 
				
			||||||
						FreeHeap (mem);
 | 
					
 | 
				
			||||||
						throw;
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
					}
 | 
					    public static Boolean ShouldRetrySyscall (Int32 r, out Native.Errno errno)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
					if (bytes_copied != length_without_null) {
 | 
					      errno = (Native.Errno) 0;
 | 
				
			||||||
						FreeHeap (mem);
 | 
					      return r == -1 && (errno = Native.Stdlib.GetLastError ()) == Native.Errno.EINTR;
 | 
				
			||||||
						throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
 | 
					    }
 | 
				
			||||||
					}
 | 
					
 | 
				
			||||||
 | 
					    // we can't permit any printf(3)-style formatting information, since that
 | 
				
			||||||
					marshal += length_without_null;
 | 
					    // would kill the stack.  However, replacing %% is silly, and some %* are
 | 
				
			||||||
					for (int i = 0; i < null_terminator_count; ++i)
 | 
					    // permitted (such as %m in syslog to print strerror(errno)).
 | 
				
			||||||
						marshal[i] = 0;
 | 
					    internal static String EscapeFormatString (String message,
 | 
				
			||||||
				}
 | 
					        Char[] permitted)
 | 
				
			||||||
			}
 | 
					    {
 | 
				
			||||||
 | 
					      if (message == null) {
 | 
				
			||||||
			return mem;
 | 
					        return "";
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static bool ShouldRetrySyscall (int r)
 | 
					      StringBuilder sb = new StringBuilder (message.Length);
 | 
				
			||||||
		{
 | 
					      for (Int32 i = 0; i < message.Length; ++i) {
 | 
				
			||||||
			if (r == -1 && Native.Stdlib.GetLastError () == Native.Errno.EINTR)
 | 
					        Char c = message [i];
 | 
				
			||||||
				return true;
 | 
					        _ = sb.Append(c);
 | 
				
			||||||
			return false;
 | 
					        if (c == '%' && i+1 < message.Length) {
 | 
				
			||||||
		}
 | 
					          Char n = message [i+1];
 | 
				
			||||||
 | 
					          _ = n == '%' || IsCharPresent (permitted, n) ? sb.Append(n) : sb.Append('%').Append(n);
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					
 | 
				
			||||||
		public static bool ShouldRetrySyscall (int r, out Native.Errno errno)
 | 
					          ++i;
 | 
				
			||||||
		{
 | 
					        }
 | 
				
			||||||
			errno = (Native.Errno) 0;
 | 
					        // invalid format string: % at EOS.
 | 
				
			||||||
			if (r == -1 && (errno = Native.Stdlib.GetLastError ()) == Native.Errno.EINTR)
 | 
					        else if (c == '%') {
 | 
				
			||||||
				return true;
 | 
					          _ = sb.Append('%');
 | 
				
			||||||
			return false;
 | 
					        }
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					      return sb.ToString ();
 | 
				
			||||||
		// we can't permit any printf(3)-style formatting information, since that
 | 
					    }
 | 
				
			||||||
		// would kill the stack.  However, replacing %% is silly, and some %* are
 | 
					
 | 
				
			||||||
		// permitted (such as %m in syslog to print strerror(errno)).
 | 
					    private static Boolean IsCharPresent (Char[] array, Char c)
 | 
				
			||||||
		internal static string EscapeFormatString (string message, 
 | 
					    {
 | 
				
			||||||
				char [] permitted)
 | 
					      if (array == null) {
 | 
				
			||||||
		{
 | 
					        return false;
 | 
				
			||||||
			if (message == null)
 | 
					      }
 | 
				
			||||||
				return "";
 | 
					
 | 
				
			||||||
			StringBuilder sb = new StringBuilder (message.Length);
 | 
					      for (Int32 i = 0; i < array.Length; ++i) {
 | 
				
			||||||
			for (int i = 0; i < message.Length; ++i) {
 | 
					        if (array [i] == c) {
 | 
				
			||||||
				char c = message [i];
 | 
					          return true;
 | 
				
			||||||
				sb.Append (c);
 | 
					        }
 | 
				
			||||||
				if (c == '%' && (i+1) < message.Length) {
 | 
					      }
 | 
				
			||||||
					char n = message [i+1];
 | 
					
 | 
				
			||||||
					if (n == '%' || IsCharPresent (permitted, n))
 | 
					      return false;
 | 
				
			||||||
						sb.Append (n);
 | 
					    }
 | 
				
			||||||
					else
 | 
					
 | 
				
			||||||
						sb.Append ('%').Append (n);
 | 
					    internal static Exception CreateExceptionForError (Native.Errno errno)
 | 
				
			||||||
					++i;
 | 
					    {
 | 
				
			||||||
				}
 | 
					      String message = GetErrorDescription (errno);
 | 
				
			||||||
				// invalid format string: % at EOS.
 | 
					      UnixIOException p = new UnixIOException (errno);
 | 
				
			||||||
				else if (c == '%')
 | 
					
 | 
				
			||||||
					sb.Append ('%');
 | 
					      // Ordering: Order alphabetically by exception first (right column),
 | 
				
			||||||
			}
 | 
					      // then order alphabetically by Errno value (left column) for the given
 | 
				
			||||||
			return sb.ToString ();
 | 
					      // exception.
 | 
				
			||||||
		}
 | 
					      switch (errno) {
 | 
				
			||||||
 | 
					        case Native.Errno.EBADF:
 | 
				
			||||||
		private static bool IsCharPresent (char[] array, char c)
 | 
					        case Native.Errno.EINVAL:        return new ArgumentException (message, p);
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			if (array == null)
 | 
					        case Native.Errno.ERANGE:        return new ArgumentOutOfRangeException (message);
 | 
				
			||||||
				return false;
 | 
					        case Native.Errno.ENOTDIR:       return new DirectoryNotFoundException (message, p);
 | 
				
			||||||
			for (int i = 0; i < array.Length; ++i)
 | 
					        case Native.Errno.ENOENT:        return new FileNotFoundException (message, p);
 | 
				
			||||||
				if (array [i] == c)
 | 
					
 | 
				
			||||||
					return true;
 | 
					        case Native.Errno.EOPNOTSUPP:
 | 
				
			||||||
			return false;
 | 
					        case Native.Errno.EPERM:         return new InvalidOperationException (message, p);
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					        case Native.Errno.ENOEXEC:       return new InvalidProgramException (message, p);
 | 
				
			||||||
		internal static Exception CreateExceptionForError (Native.Errno errno)
 | 
					
 | 
				
			||||||
		{
 | 
					        case Native.Errno.EIO:
 | 
				
			||||||
			string message = GetErrorDescription (errno);
 | 
					        case Native.Errno.ENOSPC:
 | 
				
			||||||
			UnixIOException p = new UnixIOException (errno);
 | 
					        case Native.Errno.ENOTEMPTY:
 | 
				
			||||||
 | 
					        case Native.Errno.ENXIO:
 | 
				
			||||||
			// Ordering: Order alphabetically by exception first (right column),
 | 
					        case Native.Errno.EROFS:
 | 
				
			||||||
			// then order alphabetically by Errno value (left column) for the given
 | 
					        case Native.Errno.ESPIPE:        return new IOException (message, p);
 | 
				
			||||||
			// exception.
 | 
					
 | 
				
			||||||
			switch (errno) {
 | 
					        case Native.Errno.EFAULT:        return new NullReferenceException (message, p);
 | 
				
			||||||
				case Native.Errno.EBADF:
 | 
					        case Native.Errno.EOVERFLOW:     return new OverflowException (message, p);
 | 
				
			||||||
				case Native.Errno.EINVAL:        return new ArgumentException (message, p);
 | 
					        case Native.Errno.ENAMETOOLONG:  return new PathTooLongException (message, p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				case Native.Errno.ERANGE:        return new ArgumentOutOfRangeException (message);
 | 
					        case Native.Errno.EACCES:
 | 
				
			||||||
				case Native.Errno.ENOTDIR:       return new DirectoryNotFoundException (message, p);
 | 
					        case Native.Errno.EISDIR:        return new UnauthorizedAccessException (message, p);
 | 
				
			||||||
				case Native.Errno.ENOENT:        return new FileNotFoundException (message, p);
 | 
					
 | 
				
			||||||
 | 
					        default: /* ignore */     break;
 | 
				
			||||||
				case Native.Errno.EOPNOTSUPP:
 | 
					      }
 | 
				
			||||||
				case Native.Errno.EPERM:         return new InvalidOperationException (message, p);
 | 
					      return p;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
				case Native.Errno.ENOEXEC:       return new InvalidProgramException (message, p);
 | 
					
 | 
				
			||||||
 | 
					    internal static Exception CreateExceptionForLastError() => CreateExceptionForError(Native.Stdlib.GetLastError());
 | 
				
			||||||
				case Native.Errno.EIO:
 | 
					
 | 
				
			||||||
				case Native.Errno.ENOSPC:
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
				case Native.Errno.ENOTEMPTY:
 | 
					    public static void ThrowExceptionForError(Native.Errno errno) => throw CreateExceptionForError(errno);
 | 
				
			||||||
				case Native.Errno.ENXIO:
 | 
					
 | 
				
			||||||
				case Native.Errno.EROFS:
 | 
					    public static void ThrowExceptionForLastError() => throw CreateExceptionForLastError();
 | 
				
			||||||
				case Native.Errno.ESPIPE:        return new IOException (message, p);
 | 
					
 | 
				
			||||||
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
				case Native.Errno.EFAULT:        return new NullReferenceException (message, p);
 | 
					    public static void ThrowExceptionForErrorIf (Int32 retval, Native.Errno errno)
 | 
				
			||||||
				case Native.Errno.EOVERFLOW:     return new OverflowException (message, p);
 | 
					    {
 | 
				
			||||||
				case Native.Errno.ENAMETOOLONG:  return new PathTooLongException (message, p);
 | 
					      if (retval == -1) {
 | 
				
			||||||
 | 
					        ThrowExceptionForError (errno);
 | 
				
			||||||
				case Native.Errno.EACCES:
 | 
					      }
 | 
				
			||||||
				case Native.Errno.EISDIR:        return new UnauthorizedAccessException (message, p);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				default: /* ignore */     break;
 | 
					    public static void ThrowExceptionForLastErrorIf (Int32 retval)
 | 
				
			||||||
			}
 | 
					    {
 | 
				
			||||||
			return p;
 | 
					      if (retval == -1) {
 | 
				
			||||||
		}
 | 
					        ThrowExceptionForLastError ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		internal static Exception CreateExceptionForLastError ()
 | 
					    }
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			return CreateExceptionForError (Native.Stdlib.GetLastError());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public static void ThrowExceptionForError (Native.Errno errno)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw CreateExceptionForError (errno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void ThrowExceptionForLastError ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			throw CreateExceptionForLastError ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public static void ThrowExceptionForErrorIf (int retval, Native.Errno errno)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (retval == -1)
 | 
					 | 
				
			||||||
				ThrowExceptionForError (errno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static void ThrowExceptionForLastErrorIf (int retval)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (retval == -1)
 | 
					 | 
				
			||||||
				ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -28,259 +28,272 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections;
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using Mono.Unix;
 | 
					using Mono.Unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixPath
 | 
					  public sealed class UnixPath
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private UnixPath () {}
 | 
					    private UnixPath () {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static readonly char DirectorySeparatorChar = '/';
 | 
					    public static readonly Char DirectorySeparatorChar = '/';
 | 
				
			||||||
		public static readonly char AltDirectorySeparatorChar = '/';
 | 
					    public static readonly Char AltDirectorySeparatorChar = '/';
 | 
				
			||||||
		public static readonly char PathSeparator = ':';
 | 
					    public static readonly Char PathSeparator = ':';
 | 
				
			||||||
		public static readonly char VolumeSeparatorChar = '/';
 | 
					    public static readonly Char VolumeSeparatorChar = '/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static readonly char[] _InvalidPathChars = new char[]{};
 | 
					    private static readonly Char[] _InvalidPathChars = new Char[]{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Char[] GetInvalidPathChars() => (Char[])_InvalidPathChars.Clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String Combine (String path1, params String[] paths)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (path1 == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("path1");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (paths == null) {
 | 
				
			||||||
 | 
					        throw new ArgumentNullException ("paths");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (path1.IndexOfAny (_InvalidPathChars) != -1) {
 | 
				
			||||||
 | 
					        throw new ArgumentException ("Illegal characters in path", "path1");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int32 len = path1.Length;
 | 
				
			||||||
 | 
					      Int32 start = -1;
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i < paths.Length; ++i) {
 | 
				
			||||||
 | 
					        if (paths [i] == null) {
 | 
				
			||||||
 | 
					          throw new ArgumentNullException ("paths[" + i + "]");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (paths [i].IndexOfAny (_InvalidPathChars) != -1) {
 | 
				
			||||||
 | 
					          throw new ArgumentException ("Illegal characters in path", "paths[" + i + "]");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (IsPathRooted (paths [i])) {
 | 
				
			||||||
 | 
					          len = 0;
 | 
				
			||||||
 | 
					          start = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        len += paths [i].Length + 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static char[] GetInvalidPathChars ()
 | 
					      StringBuilder sb = new StringBuilder (len);
 | 
				
			||||||
		{
 | 
					      if (start == -1) {
 | 
				
			||||||
			return (char[]) _InvalidPathChars.Clone ();
 | 
					        _ = sb.Append(path1);
 | 
				
			||||||
		}
 | 
					        start = 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      for (Int32 i = start; i < paths.Length; ++i) {
 | 
				
			||||||
 | 
					        Combine (sb, paths [i]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return sb.ToString ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string Combine (string path1, params string[] paths)
 | 
					    private static void Combine (StringBuilder path, String part)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path1 == null)
 | 
					      if (path.Length > 0 && part.Length > 0) {
 | 
				
			||||||
				throw new ArgumentNullException ("path1");
 | 
					        Char end = path [path.Length-1];
 | 
				
			||||||
			if (paths == null)
 | 
					        if (end != DirectorySeparatorChar && 
 | 
				
			||||||
				throw new ArgumentNullException ("paths");
 | 
					            end != AltDirectorySeparatorChar && 
 | 
				
			||||||
			if (path1.IndexOfAny (_InvalidPathChars) != -1)
 | 
					            end != VolumeSeparatorChar) {
 | 
				
			||||||
				throw new ArgumentException ("Illegal characters in path", "path1");
 | 
					          _ = path.Append(DirectorySeparatorChar);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      _ = path.Append(part);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int len = path1.Length;
 | 
					    public static String GetDirectoryName (String path)
 | 
				
			||||||
			int start = -1;
 | 
					    {
 | 
				
			||||||
			for (int i = 0; i < paths.Length; ++i) {
 | 
					      CheckPath (path);
 | 
				
			||||||
				if (paths [i] == null)
 | 
					 | 
				
			||||||
					throw new ArgumentNullException ("paths[" + i + "]");
 | 
					 | 
				
			||||||
				if (paths [i].IndexOfAny (_InvalidPathChars) != -1)
 | 
					 | 
				
			||||||
					throw new ArgumentException ("Illegal characters in path", "paths[" + i + "]");
 | 
					 | 
				
			||||||
				if (IsPathRooted (paths [i])) {
 | 
					 | 
				
			||||||
					len = 0;
 | 
					 | 
				
			||||||
					start = i;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				len += paths [i].Length + 1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StringBuilder sb = new StringBuilder (len);
 | 
					      Int32 lastDir = path.LastIndexOf (DirectorySeparatorChar);
 | 
				
			||||||
			if (start == -1) {
 | 
					      return lastDir > 0 ? path.Substring (0, lastDir) : lastDir == 0 ? "/" : "";
 | 
				
			||||||
				sb.Append (path1);
 | 
					    }
 | 
				
			||||||
				start = 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for (int i = start; i < paths.Length; ++i)
 | 
					 | 
				
			||||||
				Combine (sb, paths [i]);
 | 
					 | 
				
			||||||
			return sb.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void Combine (StringBuilder path, string part)
 | 
					    public static String GetFileName (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path.Length > 0 && part.Length > 0) {
 | 
					      if (path == null || path.Length == 0) {
 | 
				
			||||||
				char end = path [path.Length-1];
 | 
					        return path;
 | 
				
			||||||
				if (end != DirectorySeparatorChar && 
 | 
					      }
 | 
				
			||||||
						end != AltDirectorySeparatorChar && 
 | 
					
 | 
				
			||||||
						end != VolumeSeparatorChar)
 | 
					      Int32 lastDir = path.LastIndexOf (DirectorySeparatorChar);
 | 
				
			||||||
					path.Append (DirectorySeparatorChar);
 | 
					      return lastDir >= 0 ? path.Substring (lastDir+1) : path;
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
			path.Append (part);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetDirectoryName (string path)
 | 
					    public static String GetFullPath (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			CheckPath (path);
 | 
					      path = _GetFullPath (path);
 | 
				
			||||||
 | 
					      return GetCanonicalPath (path);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int lastDir = path.LastIndexOf (DirectorySeparatorChar);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
			if (lastDir > 0)
 | 
					    private static String _GetFullPath (String path)
 | 
				
			||||||
				return path.Substring (0, lastDir);
 | 
					    {
 | 
				
			||||||
			if (lastDir == 0)
 | 
					      if (path == null) {
 | 
				
			||||||
				return "/";
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
			return "";
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      if (!IsPathRooted (path)) {
 | 
				
			||||||
 | 
					        path = UnixDirectoryInfo.GetCurrentDirectory() + DirectorySeparatorChar + path;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return path;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetFileName (string path)
 | 
					    public static String GetCanonicalPath (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null || path.Length == 0)
 | 
					      GetPathComponents(path, out String[] dirs, out Int32 lastIndex);
 | 
				
			||||||
				return path;
 | 
					      String end = String.Join ("/", dirs, 0, lastIndex);
 | 
				
			||||||
 | 
					      return IsPathRooted (path) ? "/" + end : end;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int lastDir = path.LastIndexOf (DirectorySeparatorChar);
 | 
					    private static void GetPathComponents (String path, 
 | 
				
			||||||
			if (lastDir >= 0)
 | 
					      out String[] components, out Int32 lastIndex)
 | 
				
			||||||
				return path.Substring (lastDir+1);
 | 
					    {
 | 
				
			||||||
 | 
					      String[] dirs = path.Split (DirectorySeparatorChar);
 | 
				
			||||||
 | 
					      Int32 target = 0;
 | 
				
			||||||
 | 
					      for (Int32 i = 0; i < dirs.Length; ++i) {
 | 
				
			||||||
 | 
					        if (dirs [i] == "." || dirs [i] == String.Empty) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        } else if (dirs [i] == "..") {
 | 
				
			||||||
 | 
					          if (target != 0) {
 | 
				
			||||||
 | 
					            --target;
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            ++target;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					          dirs [target++] = dirs [i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      components = dirs;
 | 
				
			||||||
 | 
					      lastIndex = target;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return path;
 | 
					    public static String GetPathRoot(String path) => path == null ? null : !IsPathRooted(path) ? "" : "/";
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetFullPath (string path)
 | 
					    public static String GetCompleteRealPath (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			path = _GetFullPath (path);
 | 
					      if (path == null) {
 | 
				
			||||||
			return GetCanonicalPath (path);
 | 
					        throw new ArgumentNullException ("path");
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GetPathComponents(path, out String[] dirs, out Int32 lastIndex);
 | 
				
			||||||
 | 
					      StringBuilder realPath = new StringBuilder ();
 | 
				
			||||||
 | 
					      if (dirs.Length > 0) {
 | 
				
			||||||
 | 
					        String dir = IsPathRooted (path) ? "/" : "";
 | 
				
			||||||
 | 
					        dir += dirs [0];
 | 
				
			||||||
 | 
					        _ = realPath.Append(GetRealPath(dir));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      for (Int32 i = 1; i < lastIndex; ++i) {
 | 
				
			||||||
 | 
					        _ = realPath.Append("/").Append(dirs[i]);
 | 
				
			||||||
 | 
					        String p = GetRealPath (realPath.ToString());
 | 
				
			||||||
 | 
					        _ = realPath.Remove(0, realPath.Length);
 | 
				
			||||||
 | 
					        _ = realPath.Append(p);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return realPath.ToString ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static string _GetFullPath (string path)
 | 
					    public static String GetRealPath (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      do {
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					        String name = ReadSymbolicLink (path);
 | 
				
			||||||
			if (!IsPathRooted (path))
 | 
					        if (name == null) {
 | 
				
			||||||
				path = UnixDirectoryInfo.GetCurrentDirectory() + DirectorySeparatorChar + path;
 | 
					          return path;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (IsPathRooted (name)) {
 | 
				
			||||||
 | 
					          path = name;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          path = GetDirectoryName (path) + DirectorySeparatorChar + name;
 | 
				
			||||||
 | 
					          path = GetCanonicalPath (path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } while (true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return path;
 | 
					    // Read the specified symbolic link.  If the file isn't a symbolic link,
 | 
				
			||||||
		}
 | 
					    // return null; otherwise, return the contents of the symbolic link.
 | 
				
			||||||
 | 
					    internal static String ReadSymbolicLink (String path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      String target = TryReadLink (path);
 | 
				
			||||||
 | 
					      if (target == null) {
 | 
				
			||||||
 | 
					        Native.Errno errno = Native.Stdlib.GetLastError ();
 | 
				
			||||||
 | 
					        if (errno != Native.Errno.EINVAL) {
 | 
				
			||||||
 | 
					          UnixMarshal.ThrowExceptionForError (errno);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return target;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetCanonicalPath (string path)
 | 
					    public static String TryReadLink (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			string [] dirs;
 | 
					      Byte[] buf = new Byte[256];
 | 
				
			||||||
			int lastIndex;
 | 
					      do {
 | 
				
			||||||
			GetPathComponents (path, out dirs, out lastIndex);
 | 
					        Int64 r = Native.Syscall.readlink (path, buf);
 | 
				
			||||||
			string end = string.Join ("/", dirs, 0, lastIndex);
 | 
					        if (r < 0) {
 | 
				
			||||||
			return IsPathRooted (path) ? "/" + end : end;
 | 
					          return null;
 | 
				
			||||||
		}
 | 
					        } else if (r == buf.Length) {
 | 
				
			||||||
 | 
					          buf = new Byte[checked (buf.LongLength * 2)];
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return UnixEncoding.Instance.GetString (buf, 0, checked ((Int32) r));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } while (true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static void GetPathComponents (string path, 
 | 
					    public static String TryReadLinkAt (Int32 dirfd, String path)
 | 
				
			||||||
			out string[] components, out int lastIndex)
 | 
					    {
 | 
				
			||||||
		{
 | 
					      Byte[] buf = new Byte[256];
 | 
				
			||||||
			string [] dirs = path.Split (DirectorySeparatorChar);
 | 
					      do {
 | 
				
			||||||
			int target = 0;
 | 
					        Int64 r = Native.Syscall.readlinkat (dirfd, path, buf);
 | 
				
			||||||
			for (int i = 0; i < dirs.Length; ++i) {
 | 
					        if (r < 0) {
 | 
				
			||||||
				if (dirs [i] == "." || dirs [i] == string.Empty) continue;
 | 
					          return null;
 | 
				
			||||||
				else if (dirs [i] == "..") {
 | 
					        } else if (r == buf.Length) {
 | 
				
			||||||
					if (target != 0) --target;
 | 
					          buf = new Byte[checked (buf.LongLength * 2)];
 | 
				
			||||||
					else ++target;
 | 
					        } else {
 | 
				
			||||||
				}
 | 
					          return UnixEncoding.Instance.GetString (buf, 0, checked ((Int32) r));
 | 
				
			||||||
				else
 | 
					        }
 | 
				
			||||||
					dirs [target++] = dirs [i];
 | 
					      } while (true);
 | 
				
			||||||
			}
 | 
					    }
 | 
				
			||||||
			components = dirs;
 | 
					 | 
				
			||||||
			lastIndex = target;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetPathRoot (string path)
 | 
					    public static String ReadLink (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      String target = TryReadLink (path);
 | 
				
			||||||
				return null;
 | 
					      if (target == null) {
 | 
				
			||||||
			if (!IsPathRooted (path))
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
				return "";
 | 
					      }
 | 
				
			||||||
			return "/";
 | 
					
 | 
				
			||||||
		}
 | 
					      return target;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetCompleteRealPath (string path)
 | 
					    public static String ReadLinkAt (Int32 dirfd, String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (path == null)
 | 
					      String target = TryReadLinkAt (dirfd, path);
 | 
				
			||||||
				throw new ArgumentNullException ("path");
 | 
					      if (target == null) {
 | 
				
			||||||
			string [] dirs;
 | 
					        UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			int lastIndex;
 | 
					      }
 | 
				
			||||||
			GetPathComponents (path, out dirs, out lastIndex);
 | 
					
 | 
				
			||||||
			StringBuilder realPath = new StringBuilder ();
 | 
					      return target;
 | 
				
			||||||
			if (dirs.Length > 0) {
 | 
					    }
 | 
				
			||||||
				string dir = IsPathRooted (path) ? "/" : "";
 | 
					 | 
				
			||||||
				dir += dirs [0];
 | 
					 | 
				
			||||||
				realPath.Append (GetRealPath (dir));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for (int i = 1; i < lastIndex; ++i) {
 | 
					 | 
				
			||||||
				realPath.Append ("/").Append (dirs [i]);
 | 
					 | 
				
			||||||
				string p = GetRealPath (realPath.ToString());
 | 
					 | 
				
			||||||
				realPath.Remove (0, realPath.Length);
 | 
					 | 
				
			||||||
				realPath.Append (p);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return realPath.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static string GetRealPath (string path)
 | 
					    public static Boolean IsPathRooted(String path) => path == null || path.Length == 0 ? false : path[0] == DirectorySeparatorChar;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				string name = ReadSymbolicLink (path);
 | 
					 | 
				
			||||||
				if (name == null)
 | 
					 | 
				
			||||||
					return path;
 | 
					 | 
				
			||||||
				if (IsPathRooted (name))
 | 
					 | 
				
			||||||
					path = name;
 | 
					 | 
				
			||||||
				else {
 | 
					 | 
				
			||||||
					path = GetDirectoryName (path) + DirectorySeparatorChar + name;
 | 
					 | 
				
			||||||
					path = GetCanonicalPath (path);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} while (true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Read the specified symbolic link.  If the file isn't a symbolic link,
 | 
					    internal static void CheckPath (String path)
 | 
				
			||||||
		// return null; otherwise, return the contents of the symbolic link.
 | 
					    {
 | 
				
			||||||
		internal static string ReadSymbolicLink (string path)
 | 
					      if (path == null) {
 | 
				
			||||||
		{
 | 
					        throw new ArgumentNullException ();
 | 
				
			||||||
			string target = TryReadLink (path);
 | 
					      }
 | 
				
			||||||
			if (target == null) {
 | 
					
 | 
				
			||||||
				Native.Errno errno = Native.Stdlib.GetLastError ();
 | 
					      if (path.Length == 0) {
 | 
				
			||||||
				if (errno != Native.Errno.EINVAL)
 | 
					        throw new ArgumentException ("Path cannot contain a zero-length string", "path");
 | 
				
			||||||
					UnixMarshal.ThrowExceptionForError (errno);
 | 
					      }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			return target;
 | 
					      if (path.IndexOfAny (_InvalidPathChars) != -1) {
 | 
				
			||||||
		}
 | 
					        throw new ArgumentException ("Invalid characters in path.", "path");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
		public static string TryReadLink (string path)
 | 
					    }
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			byte[] buf = new byte[256];
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				long r = Native.Syscall.readlink (path, buf);
 | 
					 | 
				
			||||||
				if (r < 0)
 | 
					 | 
				
			||||||
					return null;
 | 
					 | 
				
			||||||
				else if (r == buf.Length)
 | 
					 | 
				
			||||||
					buf = new byte[checked (buf.LongLength * 2)];
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					return UnixEncoding.Instance.GetString (buf, 0, checked ((int) r));
 | 
					 | 
				
			||||||
			} while (true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string TryReadLinkAt (int dirfd, string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			byte[] buf = new byte[256];
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				long r = Native.Syscall.readlinkat (dirfd, path, buf);
 | 
					 | 
				
			||||||
				if (r < 0)
 | 
					 | 
				
			||||||
					return null;
 | 
					 | 
				
			||||||
				else if (r == buf.Length)
 | 
					 | 
				
			||||||
					buf = new byte[checked (buf.LongLength * 2)];
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					return UnixEncoding.Instance.GetString (buf, 0, checked ((int) r));
 | 
					 | 
				
			||||||
			} while (true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string ReadLink (string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			string target = TryReadLink (path);
 | 
					 | 
				
			||||||
			if (target == null)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError (); 
 | 
					 | 
				
			||||||
			return target;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static string ReadLinkAt (int dirfd, string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			string target = TryReadLinkAt (dirfd, path);
 | 
					 | 
				
			||||||
			if (target == null)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError (); 
 | 
					 | 
				
			||||||
			return target;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public static bool IsPathRooted (string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (path == null || path.Length == 0)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			return path [0] == DirectorySeparatorChar;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		internal static void CheckPath (string path)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (path == null)
 | 
					 | 
				
			||||||
				throw new ArgumentNullException ();
 | 
					 | 
				
			||||||
			if (path.Length == 0)
 | 
					 | 
				
			||||||
				throw new ArgumentException ("Path cannot contain a zero-length string", "path");
 | 
					 | 
				
			||||||
			if (path.IndexOfAny (_InvalidPathChars) != -1)
 | 
					 | 
				
			||||||
				throw new ArgumentException ("Invalid characters in path.", "path");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -33,56 +33,45 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public struct UnixPipes
 | 
					  public struct UnixPipes
 | 
				
			||||||
		: IEquatable <UnixPipes>
 | 
					    : IEquatable <UnixPipes>
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		public UnixPipes (UnixStream reading, UnixStream writing)
 | 
					    public UnixPipes (UnixStream reading, UnixStream writing)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			Reading = reading;
 | 
					      this.Reading = reading;
 | 
				
			||||||
			Writing = writing;
 | 
					      this.Writing = writing;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixStream Reading;
 | 
					    public UnixStream Reading;
 | 
				
			||||||
		public UnixStream Writing;
 | 
					    public UnixStream Writing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixPipes CreatePipes ()
 | 
					    public static UnixPipes CreatePipes ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int reading, writing;
 | 
					      Int32 r = Native.Syscall.pipe(out Int32 reading, out Int32 writing);
 | 
				
			||||||
			int r = Native.Syscall.pipe (out reading, out writing);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      return new UnixPipes (new UnixStream (reading), new UnixStream (writing));
 | 
				
			||||||
			return new UnixPipes (new UnixStream (reading), new UnixStream (writing));
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool Equals (object value)
 | 
					    public override Boolean Equals (Object value)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if ((value == null) || (value.GetType () != GetType ()))
 | 
					      if (value == null || value.GetType () != this.GetType ()) {
 | 
				
			||||||
				return false;
 | 
					        return false;
 | 
				
			||||||
			UnixPipes other = (UnixPipes) value;
 | 
					      }
 | 
				
			||||||
			return Reading.Handle == other.Reading.Handle &&
 | 
					
 | 
				
			||||||
				Writing.Handle == other.Writing.Handle;
 | 
					      UnixPipes other = (UnixPipes) value;
 | 
				
			||||||
		}
 | 
					      return this.Reading.Handle == other.Reading.Handle &&
 | 
				
			||||||
 | 
					        this.Writing.Handle == other.Writing.Handle;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool Equals (UnixPipes value)
 | 
					    public Boolean Equals(UnixPipes value) => this.Reading.Handle == value.Reading.Handle &&
 | 
				
			||||||
		{
 | 
					        this.Writing.Handle == value.Writing.Handle;
 | 
				
			||||||
			return Reading.Handle == value.Reading.Handle &&
 | 
					 | 
				
			||||||
				Writing.Handle == value.Writing.Handle;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override int GetHashCode ()
 | 
					    public override Int32 GetHashCode() => this.Reading.Handle.GetHashCode() ^ this.Writing.Handle.GetHashCode();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Reading.Handle.GetHashCode () ^ Writing.Handle.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static bool operator== (UnixPipes lhs, UnixPipes rhs)
 | 
					    public static Boolean operator ==(UnixPipes lhs, UnixPipes rhs) => lhs.Equals(rhs);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return lhs.Equals (rhs);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static bool operator!= (UnixPipes lhs, UnixPipes rhs)
 | 
					    public static Boolean operator !=(UnixPipes lhs, UnixPipes rhs) => !lhs.Equals(rhs);
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			return !lhs.Equals (rhs);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -31,127 +31,117 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixProcess
 | 
					  public sealed class UnixProcess
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private int pid;
 | 
					    private Int32 pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixProcess (int pid)
 | 
					    internal UnixProcess(Int32 pid) => this.pid = pid;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.pid = pid;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int Id {
 | 
					    public Int32 Id => this.pid;
 | 
				
			||||||
			get {return pid;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool HasExited {
 | 
					    public Boolean HasExited {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
				return Native.Syscall.WIFEXITED (status);
 | 
					        return Native.Syscall.WIFEXITED (status);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private int GetProcessStatus ()
 | 
					    private Int32 GetProcessStatus ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int status;
 | 
					      Int32 r = Native.Syscall.waitpid(this.pid, out Int32 status,
 | 
				
			||||||
			int r = Native.Syscall.waitpid (pid, out status, 
 | 
					          Native.WaitOptions.WNOHANG | Native.WaitOptions.WUNTRACED);
 | 
				
			||||||
					Native.WaitOptions.WNOHANG | Native.WaitOptions.WUNTRACED);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      return r;
 | 
				
			||||||
			return r;
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int ExitCode {
 | 
					    public Int32 ExitCode {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (!HasExited)
 | 
					        if (!this.HasExited) {
 | 
				
			||||||
					throw new InvalidOperationException (
 | 
					          throw new InvalidOperationException (
 | 
				
			||||||
							Locale.GetText ("Process hasn't exited"));
 | 
					              Locale.GetText ("Process hasn't exited"));
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        }
 | 
				
			||||||
				return Native.Syscall.WEXITSTATUS (status);
 | 
					
 | 
				
			||||||
			}
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
		}
 | 
					        return Native.Syscall.WEXITSTATUS (status);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool HasSignaled {
 | 
					    public Boolean HasSignaled {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
				return Native.Syscall.WIFSIGNALED (status);
 | 
					        return Native.Syscall.WIFSIGNALED (status);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Native.Signum TerminationSignal {
 | 
					    public Native.Signum TerminationSignal {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (!HasSignaled)
 | 
					        if (!this.HasSignaled) {
 | 
				
			||||||
					throw new InvalidOperationException (
 | 
					          throw new InvalidOperationException (
 | 
				
			||||||
							Locale.GetText ("Process wasn't terminated by a signal"));
 | 
					              Locale.GetText ("Process wasn't terminated by a signal"));
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        }
 | 
				
			||||||
				return Native.Syscall.WTERMSIG (status);
 | 
					
 | 
				
			||||||
			}
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
		}
 | 
					        return Native.Syscall.WTERMSIG (status);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool HasStopped {
 | 
					    public Boolean HasStopped {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
				return Native.Syscall.WIFSTOPPED (status);
 | 
					        return Native.Syscall.WIFSTOPPED (status);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Native.Signum StopSignal {
 | 
					    public Native.Signum StopSignal {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (!HasStopped)
 | 
					        if (!this.HasStopped) {
 | 
				
			||||||
					throw new InvalidOperationException (
 | 
					          throw new InvalidOperationException (
 | 
				
			||||||
							Locale.GetText ("Process isn't stopped"));
 | 
					              Locale.GetText ("Process isn't stopped"));
 | 
				
			||||||
				int status = GetProcessStatus ();
 | 
					        }
 | 
				
			||||||
				return Native.Syscall.WSTOPSIG (status);
 | 
					
 | 
				
			||||||
			}
 | 
					        Int32 status = this.GetProcessStatus ();
 | 
				
			||||||
		}
 | 
					        return Native.Syscall.WSTOPSIG (status);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int ProcessGroupId {
 | 
					    public Int32 ProcessGroupId {
 | 
				
			||||||
			get {return Native.Syscall.getpgid (pid);}
 | 
					      get => Native.Syscall.getpgid(this.pid);
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				int r = Native.Syscall.setpgid (pid, value);
 | 
					        Int32 r = Native.Syscall.setpgid(this.pid, value);
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int SessionId {
 | 
					    public Int32 SessionId {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int r = Native.Syscall.getsid (pid);
 | 
					        Int32 r = Native.Syscall.getsid (this.pid);
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
				return r;
 | 
					        return r;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixProcess GetCurrentProcess ()
 | 
					    public static UnixProcess GetCurrentProcess() => new UnixProcess(GetCurrentProcessId());
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return new UnixProcess (GetCurrentProcessId ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static int GetCurrentProcessId ()
 | 
					    public static Int32 GetCurrentProcessId() => Native.Syscall.getpid();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Native.Syscall.getpid ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Kill ()
 | 
					    public void Kill() => this.Signal(Native.Signum.SIGKILL);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Signal (Native.Signum.SIGKILL);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
		public void Signal (Native.Signum signal)
 | 
					    public void Signal (Native.Signum signal)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.kill (pid, signal);
 | 
					      Int32 r = Native.Syscall.kill (this.pid, signal);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void WaitForExit ()
 | 
					    public void WaitForExit ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int status;
 | 
					      Int32 r;
 | 
				
			||||||
			int r;
 | 
					      do {
 | 
				
			||||||
			do {
 | 
					        r = Native.Syscall.waitpid (this.pid, out Int32 status, (Native.WaitOptions) 0);
 | 
				
			||||||
				r = Native.Syscall.waitpid (pid, out status, (Native.WaitOptions) 0);
 | 
					      } while (UnixMarshal.ShouldRetrySyscall (r));
 | 
				
			||||||
			} while (UnixMarshal.ShouldRetrySyscall (r));
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
		}
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -35,193 +36,195 @@ using Mono.Unix.Native;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public class UnixSignal : WaitHandle {
 | 
					  public class UnixSignal : WaitHandle {
 | 
				
			||||||
		private int signum;
 | 
					    private readonly Int32 signum;
 | 
				
			||||||
		private IntPtr signal_info;
 | 
					    private IntPtr signal_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static UnixSignal ()
 | 
					    static UnixSignal() => Stdlib.VersionCheck();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Stdlib.VersionCheck ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixSignal (Signum signum)
 | 
					    public UnixSignal (Signum signum)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			this.signum = NativeConvert.FromSignum (signum);
 | 
					      this.signum = NativeConvert.FromSignum (signum);
 | 
				
			||||||
			this.signal_info = install (this.signum);
 | 
					      this.signal_info = install (this.signum);
 | 
				
			||||||
			if (this.signal_info == IntPtr.Zero) {
 | 
					      if (this.signal_info == IntPtr.Zero) {
 | 
				
			||||||
				throw new ArgumentException ("Unable to handle signal", "signum");
 | 
					        throw new ArgumentException ("Unable to handle signal", "signum");
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixSignal (Mono.Unix.Native.RealTimeSignum rtsig)
 | 
					    public UnixSignal (RealTimeSignum rtsig)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			signum = NativeConvert.FromRealTimeSignum (rtsig);
 | 
					      this.signum = NativeConvert.FromRealTimeSignum (rtsig);
 | 
				
			||||||
			this.signal_info = install (this.signum);
 | 
					      this.signal_info = install (this.signum);
 | 
				
			||||||
			Native.Errno err = Native.Stdlib.GetLastError ();
 | 
					      Native.Errno err = Native.Stdlib.GetLastError ();
 | 
				
			||||||
			if (this.signal_info == IntPtr.Zero) {
 | 
					      if (this.signal_info == IntPtr.Zero) {
 | 
				
			||||||
				if (err == Native.Errno.EADDRINUSE)
 | 
					        if (err == Native.Errno.EADDRINUSE) {
 | 
				
			||||||
					throw new ArgumentException ("Signal registered outside of Mono.Posix", "signum");
 | 
					          throw new ArgumentException ("Signal registered outside of Mono.Posix", "signum");
 | 
				
			||||||
				throw new ArgumentException ("Unable to handle signal", "signum");
 | 
					        }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					        throw new ArgumentException ("Unable to handle signal", "signum");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public Signum Signum {
 | 
					    public Signum Signum {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (IsRealTimeSignal)
 | 
					        if (this.IsRealTimeSignal) {
 | 
				
			||||||
					throw new InvalidOperationException ("This signal is a RealTimeSignum");
 | 
					          throw new InvalidOperationException ("This signal is a RealTimeSignum");
 | 
				
			||||||
				return NativeConvert.ToSignum (signum); 
 | 
					        }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					        return NativeConvert.ToSignum (this.signum); 
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public RealTimeSignum RealTimeSignum {
 | 
					    public RealTimeSignum RealTimeSignum {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				if (!IsRealTimeSignal)
 | 
					        if (!this.IsRealTimeSignal) {
 | 
				
			||||||
					throw new InvalidOperationException ("This signal is not a RealTimeSignum");
 | 
					          throw new InvalidOperationException ("This signal is not a RealTimeSignum");
 | 
				
			||||||
				return NativeConvert.ToRealTimeSignum (signum-GetSIGRTMIN ());
 | 
					        }
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
		}
 | 
					        return NativeConvert.ToRealTimeSignum (this.signum -GetSIGRTMIN ());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool IsRealTimeSignal {
 | 
					    public Boolean IsRealTimeSignal {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				AssertValid ();
 | 
					        this.AssertValid ();
 | 
				
			||||||
				int sigrtmin = GetSIGRTMIN ();
 | 
					        Int32 sigrtmin = GetSIGRTMIN ();
 | 
				
			||||||
				if (sigrtmin == -1)
 | 
					        return sigrtmin == -1 ? false : this.signum >= sigrtmin;
 | 
				
			||||||
					return false;
 | 
					      }
 | 
				
			||||||
				return signum >= sigrtmin;
 | 
					    }
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
					    [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
				
			||||||
				EntryPoint="Mono_Unix_UnixSignal_install", SetLastError=true)]
 | 
					        EntryPoint="Mono_Unix_UnixSignal_install", SetLastError=true)]
 | 
				
			||||||
		private static extern IntPtr install (int signum);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
 | 
					    private static extern IntPtr install (Int32 signum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
					    [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
				
			||||||
				EntryPoint="Mono_Unix_UnixSignal_uninstall")]
 | 
					        EntryPoint="Mono_Unix_UnixSignal_uninstall")]
 | 
				
			||||||
		private static extern int uninstall (IntPtr info);
 | 
					    [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")]
 | 
				
			||||||
 | 
					    private static extern Int32 uninstall (IntPtr info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
 | 
					    [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
 | 
				
			||||||
		delegate int Mono_Posix_RuntimeIsShuttingDown ();
 | 
					    delegate Int32 Mono_Posix_RuntimeIsShuttingDown ();
 | 
				
			||||||
		static Mono_Posix_RuntimeIsShuttingDown ShuttingDown = RuntimeShuttingDownCallback;
 | 
					    static Mono_Posix_RuntimeIsShuttingDown ShuttingDown = RuntimeShuttingDownCallback;
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		static int RuntimeShuttingDownCallback ()
 | 
					    static Int32 RuntimeShuttingDownCallback() => Environment.HasShutdownStarted ? 1 : 0;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Environment.HasShutdownStarted ? 1 : 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
					    [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
				
			||||||
				EntryPoint="Mono_Unix_UnixSignal_WaitAny")]
 | 
					        EntryPoint="Mono_Unix_UnixSignal_WaitAny")]
 | 
				
			||||||
		private static extern int WaitAny (IntPtr[] infos, int count, int timeout, Mono_Posix_RuntimeIsShuttingDown shutting_down);
 | 
					    private static extern Int32 WaitAny (IntPtr[] infos, Int32 count, Int32 timeout, Mono_Posix_RuntimeIsShuttingDown shutting_down);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
					    [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
				
			||||||
                                EntryPoint="Mono_Posix_SIGRTMIN")]
 | 
					                                EntryPoint="Mono_Posix_SIGRTMIN")]
 | 
				
			||||||
		internal static extern int GetSIGRTMIN ();
 | 
					    internal static extern Int32 GetSIGRTMIN ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
					    [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
 | 
				
			||||||
                                EntryPoint="Mono_Posix_SIGRTMAX")]
 | 
					                                EntryPoint="Mono_Posix_SIGRTMAX")]
 | 
				
			||||||
		internal static extern int GetSIGRTMAX ();
 | 
					    internal static extern Int32 GetSIGRTMAX ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void AssertValid ()
 | 
					    private void AssertValid ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (signal_info == IntPtr.Zero)
 | 
					      if (this.signal_info == IntPtr.Zero) {
 | 
				
			||||||
				throw new ObjectDisposedException (GetType().FullName);
 | 
					        throw new ObjectDisposedException (this.GetType().FullName);
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private unsafe SignalInfo* Info {
 | 
					    private unsafe SignalInfo* Info {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				AssertValid ();
 | 
					        this.AssertValid ();
 | 
				
			||||||
				return (SignalInfo*) signal_info;
 | 
					        return (SignalInfo*)this.signal_info;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool IsSet {
 | 
					    public Boolean IsSet => this.Count > 0;
 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return Count > 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public unsafe bool Reset ()
 | 
					    public unsafe Boolean Reset ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int n = Interlocked.Exchange (ref Info->count, 0);
 | 
					      Int32 n = Interlocked.Exchange (ref this.Info->count, 0);
 | 
				
			||||||
			return n != 0;
 | 
					      return n != 0;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public unsafe int Count {
 | 
					    public unsafe Int32 Count {
 | 
				
			||||||
			get {return Info->count;}
 | 
					      get => this.Info->count;
 | 
				
			||||||
			set {Interlocked.Exchange (ref Info->count, value);}
 | 
					      set => Interlocked.Exchange(ref this.Info->count, value);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// signum, count, write_fd, pipecnt, and pipelock are read from a signal handler thread
 | 
					    // signum, count, write_fd, pipecnt, and pipelock are read from a signal handler thread
 | 
				
			||||||
		// count and pipelock are both read and written from the signal handler thread
 | 
					    // count and pipelock are both read and written from the signal handler thread
 | 
				
			||||||
#pragma warning disable 649
 | 
					#pragma warning disable 649
 | 
				
			||||||
		[Map]
 | 
					    [Map]
 | 
				
			||||||
		struct SignalInfo {
 | 
					    struct SignalInfo {
 | 
				
			||||||
			public int signum, count, read_fd, write_fd, pipecnt, pipelock, have_handler;
 | 
					      public Int32 signum, count, read_fd, write_fd, pipecnt, pipelock, have_handler;
 | 
				
			||||||
			public IntPtr handler; // Backed-up handler to restore when signal unregistered
 | 
					      public IntPtr handler; // Backed-up handler to restore when signal unregistered
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
#pragma warning restore 649
 | 
					#pragma warning restore 649
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#region WaitHandle overrides
 | 
					    #region WaitHandle overrides
 | 
				
			||||||
		protected unsafe override void Dispose (bool disposing)
 | 
					    protected unsafe override void Dispose (Boolean disposing)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			base.Dispose (disposing);
 | 
					      base.Dispose (disposing);
 | 
				
			||||||
			if (signal_info == IntPtr.Zero)
 | 
					      if (this.signal_info == IntPtr.Zero) {
 | 
				
			||||||
				return;
 | 
					        return;
 | 
				
			||||||
			uninstall (signal_info);
 | 
					      }
 | 
				
			||||||
			signal_info = IntPtr.Zero;
 | 
					
 | 
				
			||||||
		}
 | 
					      _ = uninstall(this.signal_info);
 | 
				
			||||||
 | 
					      this.signal_info = IntPtr.Zero;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool WaitOne ()
 | 
					    public override Boolean WaitOne() => this.WaitOne(-1, false);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return WaitOne (-1, false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool WaitOne (TimeSpan timeout, bool exitContext)
 | 
					    public override Boolean WaitOne (TimeSpan timeout, Boolean exitContext)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			long ms = (long) timeout.TotalMilliseconds;
 | 
					      Int64 ms = (Int64) timeout.TotalMilliseconds;
 | 
				
			||||||
			if (ms < -1 || ms > Int32.MaxValue)
 | 
					      if (ms < -1 || ms > Int32.MaxValue) {
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("timeout");
 | 
					        throw new ArgumentOutOfRangeException ("timeout");
 | 
				
			||||||
			return WaitOne ((int) ms, exitContext);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return this.WaitOne ((Int32) ms, exitContext);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool WaitOne (int millisecondsTimeout, bool exitContext)
 | 
					    public override Boolean WaitOne (Int32 millisecondsTimeout, Boolean exitContext)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			AssertValid ();
 | 
					      this.AssertValid ();
 | 
				
			||||||
			if (exitContext)
 | 
					      if (exitContext) {
 | 
				
			||||||
				throw new InvalidOperationException ("exitContext is not supported");
 | 
					        throw new InvalidOperationException ("exitContext is not supported");
 | 
				
			||||||
			if (millisecondsTimeout == 0)
 | 
					      }
 | 
				
			||||||
				return IsSet;		
 | 
					
 | 
				
			||||||
			return WaitAny (new UnixSignal[]{this}, millisecondsTimeout) == 0;
 | 
					      return millisecondsTimeout == 0 ? this.IsSet : WaitAny (new UnixSignal[]{this}, millisecondsTimeout) == 0;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		#endregion
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static int WaitAny (UnixSignal[] signals)
 | 
					    public static Int32 WaitAny(UnixSignal[] signals) => WaitAny(signals, -1);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return WaitAny (signals, -1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static int WaitAny (UnixSignal[] signals, TimeSpan timeout)
 | 
					    public static Int32 WaitAny (UnixSignal[] signals, TimeSpan timeout)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			long ms = (long) timeout.TotalMilliseconds;
 | 
					      Int64 ms = (Int64) timeout.TotalMilliseconds;
 | 
				
			||||||
			if (ms < -1 || ms > Int32.MaxValue)
 | 
					      if (ms < -1 || ms > Int32.MaxValue) {
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("timeout");
 | 
					        throw new ArgumentOutOfRangeException ("timeout");
 | 
				
			||||||
			return WaitAny (signals, (int) ms);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      return WaitAny (signals, (Int32) ms);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			
 | 
					      
 | 
				
			||||||
		public static unsafe int WaitAny (UnixSignal[] signals, int millisecondsTimeout)
 | 
					    public static unsafe Int32 WaitAny (UnixSignal[] signals, Int32 millisecondsTimeout)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			if (signals == null)
 | 
					      if (signals == null) {
 | 
				
			||||||
				throw new ArgumentNullException ("signals");
 | 
					        throw new ArgumentNullException ("signals");
 | 
				
			||||||
			if (millisecondsTimeout < -1)
 | 
					      }
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("millisecondsTimeout");
 | 
					
 | 
				
			||||||
			IntPtr[] infos = new IntPtr [signals.Length];
 | 
					      if (millisecondsTimeout < -1) {
 | 
				
			||||||
			for (int i = 0; i < signals.Length; ++i) {
 | 
					        throw new ArgumentOutOfRangeException ("millisecondsTimeout");
 | 
				
			||||||
				infos [i] = signals [i].signal_info;
 | 
					      }
 | 
				
			||||||
				if (infos [i] == IntPtr.Zero)
 | 
					
 | 
				
			||||||
					throw new InvalidOperationException ("Disposed UnixSignal");
 | 
					      IntPtr[] infos = new IntPtr [signals.Length];
 | 
				
			||||||
			}
 | 
					      for (Int32 i = 0; i < signals.Length; ++i) {
 | 
				
			||||||
			return WaitAny (infos, infos.Length, millisecondsTimeout, ShuttingDown);
 | 
					        infos [i] = signals [i].signal_info;
 | 
				
			||||||
		}
 | 
					        if (infos [i] == IntPtr.Zero) {
 | 
				
			||||||
	}
 | 
					          throw new InvalidOperationException ("Disposed UnixSignal");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return WaitAny (infos, infos.Length, millisecondsTimeout, ShuttingDown);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,400 +36,427 @@ using Mono.Unix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixStream : Stream, IDisposable
 | 
					  public sealed class UnixStream : Stream, IDisposable {
 | 
				
			||||||
	{
 | 
					    public const Int32 InvalidFileDescriptor = -1;
 | 
				
			||||||
		public const int InvalidFileDescriptor = -1;
 | 
					    public const Int32 StandardInputFileDescriptor = 0;
 | 
				
			||||||
		public const int StandardInputFileDescriptor = 0;
 | 
					    public const Int32 StandardOutputFileDescriptor = 1;
 | 
				
			||||||
		public const int StandardOutputFileDescriptor = 1;
 | 
					    public const Int32 StandardErrorFileDescriptor = 2;
 | 
				
			||||||
		public const int StandardErrorFileDescriptor = 2;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixStream (int fileDescriptor)
 | 
					    public UnixStream(Int32 fileDescriptor)
 | 
				
			||||||
			: this (fileDescriptor, true) {}
 | 
					      : this(fileDescriptor, true) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixStream (int fileDescriptor, bool ownsHandle)
 | 
					    public UnixStream(Int32 fileDescriptor, Boolean ownsHandle) {
 | 
				
			||||||
		{
 | 
					      if(InvalidFileDescriptor == fileDescriptor) {
 | 
				
			||||||
			if (InvalidFileDescriptor == fileDescriptor)
 | 
					        throw new ArgumentException(Locale.GetText("Invalid file descriptor"), "fileDescriptor");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("Invalid file descriptor"), "fileDescriptor");
 | 
					      }
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
			this.fileDescriptor = fileDescriptor;
 | 
					      this.fileDescriptor = fileDescriptor;
 | 
				
			||||||
			this.owner = ownsHandle;
 | 
					      this.owner = ownsHandle;
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
			long offset = Native.Syscall.lseek (fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
 | 
					      Int64 offset = Native.Syscall.lseek(fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
 | 
				
			||||||
			if (offset != -1)
 | 
					      if(offset != -1) {
 | 
				
			||||||
				canSeek = true;
 | 
					        this.canSeek = true;
 | 
				
			||||||
			long read = Native.Syscall.read (fileDescriptor, IntPtr.Zero, 0);
 | 
					      }
 | 
				
			||||||
			if (read != -1)
 | 
					
 | 
				
			||||||
				canRead = true;
 | 
					      Int64 read = Native.Syscall.read(fileDescriptor, IntPtr.Zero, 0);
 | 
				
			||||||
			long write = Native.Syscall.write (fileDescriptor, IntPtr.Zero, 0);
 | 
					      if(read != -1) {
 | 
				
			||||||
			if (write != -1)
 | 
					        this.canRead = true;
 | 
				
			||||||
				canWrite = true;  
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      Int64 write = Native.Syscall.write(fileDescriptor, IntPtr.Zero, 0);
 | 
				
			||||||
 | 
					      if(write != -1) {
 | 
				
			||||||
 | 
					        this.canWrite = true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void AssertNotDisposed ()
 | 
					    private void AssertNotDisposed() {
 | 
				
			||||||
		{
 | 
					      if(this.fileDescriptor == InvalidFileDescriptor) {
 | 
				
			||||||
			if (fileDescriptor == InvalidFileDescriptor)
 | 
					        throw new ObjectDisposedException("Invalid File Descriptor");
 | 
				
			||||||
				throw new ObjectDisposedException ("Invalid File Descriptor");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int Handle {
 | 
					    public Int32 Handle => this.fileDescriptor;
 | 
				
			||||||
			get {return fileDescriptor;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanRead {
 | 
					    public override Boolean CanRead => this.canRead;
 | 
				
			||||||
			get {return canRead;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanSeek {
 | 
					    public override Boolean CanSeek => this.canSeek;
 | 
				
			||||||
			get {return canSeek;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool CanWrite {
 | 
					    public override Boolean CanWrite => this.canWrite;
 | 
				
			||||||
			get {return canWrite;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override long Length {
 | 
					    public override Int64 Length {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				AssertNotDisposed ();
 | 
					        this.AssertNotDisposed();
 | 
				
			||||||
				if (!CanSeek)
 | 
					        if(!this.CanSeek) {
 | 
				
			||||||
					throw new NotSupportedException ("File descriptor doesn't support seeking");
 | 
					          throw new NotSupportedException("File descriptor doesn't support seeking");
 | 
				
			||||||
				RefreshStat ();
 | 
					        }
 | 
				
			||||||
				return stat.st_size;
 | 
					
 | 
				
			||||||
			}
 | 
					        this.RefreshStat();
 | 
				
			||||||
		}
 | 
					        return this.stat.st_size;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override long Position {
 | 
					    public override Int64 Position {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				AssertNotDisposed ();
 | 
					        this.AssertNotDisposed();
 | 
				
			||||||
				if (!CanSeek)
 | 
					        if(!this.CanSeek) {
 | 
				
			||||||
					throw new NotSupportedException ("The stream does not support seeking");
 | 
					          throw new NotSupportedException("The stream does not support seeking");
 | 
				
			||||||
				long pos = Native.Syscall.lseek (fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
 | 
					        }
 | 
				
			||||||
				if (pos == -1)
 | 
					
 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					        Int64 pos = Native.Syscall.lseek(this.fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
 | 
				
			||||||
				return (long) pos;
 | 
					        if(pos == -1) {
 | 
				
			||||||
			}
 | 
					          UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
			set {
 | 
					        }
 | 
				
			||||||
				Seek (value, SeekOrigin.Begin);
 | 
					
 | 
				
			||||||
			}
 | 
					        return (Int64)pos;
 | 
				
			||||||
		}
 | 
					      }
 | 
				
			||||||
 | 
					      set => _ = this.Seek(value, SeekOrigin.Begin);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
		public Native.FilePermissions Protection {
 | 
					    public Native.FilePermissions Protection {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				RefreshStat ();
 | 
					        this.RefreshStat();
 | 
				
			||||||
				return stat.st_mode;
 | 
					        return this.stat.st_mode;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				// we can't change file type with fchmod, so clear out that portion
 | 
					        // we can't change file type with fchmod, so clear out that portion
 | 
				
			||||||
				value &= ~Native.FilePermissions.S_IFMT;
 | 
					        value &= ~Native.FilePermissions.S_IFMT;
 | 
				
			||||||
				int r = Native.Syscall.fchmod (fileDescriptor, value);
 | 
					        Int32 r = Native.Syscall.fchmod(this.fileDescriptor, value);
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					        UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public FileTypes FileType {
 | 
					    public FileTypes FileType {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int type = (int) Protection;
 | 
					        Int32 type = (Int32)this.Protection;
 | 
				
			||||||
				return (FileTypes) (type & (int) UnixFileSystemInfo.AllFileTypes);
 | 
					        return (FileTypes)(type & (Int32)UnixFileSystemInfo.AllFileTypes);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			// no set as fchmod(2) won't accept changing the file type.
 | 
					      // no set as fchmod(2) won't accept changing the file type.
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public FileAccessPermissions FileAccessPermissions {
 | 
					    public FileAccessPermissions FileAccessPermissions {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int perms = (int) Protection;
 | 
					        Int32 perms = (Int32)this.Protection;
 | 
				
			||||||
				return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
 | 
					        return (FileAccessPermissions)(perms & (Int32)FileAccessPermissions.AllPermissions);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				int perms = (int) Protection;
 | 
					        Int32 perms = (Int32)this.Protection;
 | 
				
			||||||
				perms &= (int) ~FileAccessPermissions.AllPermissions;
 | 
					        perms &= (Int32)~FileAccessPermissions.AllPermissions;
 | 
				
			||||||
				perms |= (int) value;
 | 
					        perms |= (Int32)value;
 | 
				
			||||||
				Protection = (Native.FilePermissions) perms;
 | 
					        this.Protection = (Native.FilePermissions)perms;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public FileSpecialAttributes FileSpecialAttributes {
 | 
					    public FileSpecialAttributes FileSpecialAttributes {
 | 
				
			||||||
			get {
 | 
					      get {
 | 
				
			||||||
				int attrs = (int) Protection;
 | 
					        Int32 attrs = (Int32)this.Protection;
 | 
				
			||||||
				return (FileSpecialAttributes) (attrs & (int) UnixFileSystemInfo.AllSpecialAttributes);
 | 
					        return (FileSpecialAttributes)(attrs & (Int32)UnixFileSystemInfo.AllSpecialAttributes);
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
			set {
 | 
					      set {
 | 
				
			||||||
				int perms = (int) Protection;
 | 
					        Int32 perms = (Int32)this.Protection;
 | 
				
			||||||
				perms &= (int) ~UnixFileSystemInfo.AllSpecialAttributes;
 | 
					        perms &= (Int32)~UnixFileSystemInfo.AllSpecialAttributes;
 | 
				
			||||||
				perms |= (int) value;
 | 
					        perms |= (Int32)value;
 | 
				
			||||||
				Protection = (Native.FilePermissions) perms;
 | 
					        this.Protection = (Native.FilePermissions)perms;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixUserInfo OwnerUser {
 | 
					    public UnixUserInfo OwnerUser {
 | 
				
			||||||
			get {RefreshStat (); return new UnixUserInfo (stat.st_uid);}
 | 
					      get {
 | 
				
			||||||
		}
 | 
					        this.RefreshStat();
 | 
				
			||||||
                                                                                                
 | 
					        return new UnixUserInfo(this.stat.st_uid);
 | 
				
			||||||
		public long OwnerUserId {
 | 
					      }
 | 
				
			||||||
			get {RefreshStat (); return stat.st_uid;}
 | 
					    }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
                                                                                                
 | 
					    public Int64 OwnerUserId {
 | 
				
			||||||
		public UnixGroupInfo OwnerGroup {
 | 
					      get {
 | 
				
			||||||
			get {RefreshStat (); return new UnixGroupInfo (stat.st_gid);}
 | 
					        this.RefreshStat();
 | 
				
			||||||
		}
 | 
					        return this.stat.st_uid;
 | 
				
			||||||
                                                                                                
 | 
					      }
 | 
				
			||||||
		public long OwnerGroupId {
 | 
					    }
 | 
				
			||||||
			get {RefreshStat (); return stat.st_gid;}
 | 
					
 | 
				
			||||||
		}
 | 
					    public UnixGroupInfo OwnerGroup {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.RefreshStat();
 | 
				
			||||||
 | 
					        return new UnixGroupInfo(this.stat.st_gid);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Int64 OwnerGroupId {
 | 
				
			||||||
 | 
					      get {
 | 
				
			||||||
 | 
					        this.RefreshStat();
 | 
				
			||||||
 | 
					        return this.stat.st_gid;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void RefreshStat ()
 | 
					    private void RefreshStat() {
 | 
				
			||||||
		{
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					      Int32 r = Native.Syscall.fstat(this.fileDescriptor, out this.stat);
 | 
				
			||||||
			int r = Native.Syscall.fstat (fileDescriptor, out stat);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void AdviseFileAccessPattern (FileAccessPattern pattern, long offset, long len)
 | 
					    public void AdviseFileAccessPattern(FileAccessPattern pattern, Int64 offset, Int64 len) => FileHandleOperations.AdviseFileAccessPattern(this.fileDescriptor, pattern, offset, len);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			FileHandleOperations.AdviseFileAccessPattern (fileDescriptor, pattern, offset, len);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void AdviseFileAccessPattern (FileAccessPattern pattern)
 | 
					    public void AdviseFileAccessPattern(FileAccessPattern pattern) => this.AdviseFileAccessPattern(pattern, 0, 0);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AdviseFileAccessPattern (pattern, 0, 0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void Flush ()
 | 
					    public override void Flush() {
 | 
				
			||||||
		{
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override unsafe int Read ([In, Out] byte[] buffer, int offset, int count)
 | 
					    public override unsafe Int32 Read([In, Out] Byte[] buffer, Int32 offset, Int32 count) {
 | 
				
			||||||
		{
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					      this.AssertValidBuffer(buffer, offset, count);
 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					      if(!this.CanRead) {
 | 
				
			||||||
			if (!CanRead)
 | 
					        throw new NotSupportedException("Stream does not support reading");
 | 
				
			||||||
				throw new NotSupportedException ("Stream does not support reading");
 | 
					      }
 | 
				
			||||||
				 
 | 
					
 | 
				
			||||||
			if (buffer.Length == 0)
 | 
					      if(buffer.Length == 0) {
 | 
				
			||||||
				return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int64 r = 0;
 | 
				
			||||||
 | 
					      fixed(Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					          r = Native.Syscall.read(this.fileDescriptor, buf, (UInt64)count);
 | 
				
			||||||
 | 
					        } while(UnixMarshal.ShouldRetrySyscall((Int32)r));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if(r == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (Int32)r;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long r = 0;
 | 
					    private void AssertValidBuffer(Byte[] buffer, Int32 offset, Int32 count) {
 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					      if(buffer == null) {
 | 
				
			||||||
				do {
 | 
					        throw new ArgumentNullException("buffer");
 | 
				
			||||||
					r = Native.Syscall.read (fileDescriptor, buf, (ulong) count);
 | 
					      }
 | 
				
			||||||
				} while (UnixMarshal.ShouldRetrySyscall ((int) r));
 | 
					
 | 
				
			||||||
			}
 | 
					      if(offset < 0) {
 | 
				
			||||||
			if (r == -1)
 | 
					        throw new ArgumentOutOfRangeException("offset", "< 0");
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      }
 | 
				
			||||||
			return (int) r;
 | 
					
 | 
				
			||||||
		}
 | 
					      if(count < 0) {
 | 
				
			||||||
 | 
					        throw new ArgumentOutOfRangeException("count", "< 0");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(offset > buffer.Length) {
 | 
				
			||||||
 | 
					        throw new ArgumentException("destination offset is beyond array size");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(offset > buffer.Length - count) {
 | 
				
			||||||
 | 
					        throw new ArgumentException("would overrun buffer");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void AssertValidBuffer (byte[] buffer, int offset, int count)
 | 
					    public unsafe Int32 ReadAtOffset([In, Out] Byte[] buffer,
 | 
				
			||||||
		{
 | 
					      Int32 offset, Int32 count, Int64 fileOffset) {
 | 
				
			||||||
			if (buffer == null)
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
				throw new ArgumentNullException ("buffer");
 | 
					      this.AssertValidBuffer(buffer, offset, count);
 | 
				
			||||||
			if (offset < 0)
 | 
					      if(!this.CanRead) {
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("offset", "< 0");
 | 
					        throw new NotSupportedException("Stream does not support reading");
 | 
				
			||||||
			if (count < 0)
 | 
					      }
 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("count", "< 0");
 | 
					
 | 
				
			||||||
			if (offset > buffer.Length)
 | 
					      if(buffer.Length == 0) {
 | 
				
			||||||
				throw new ArgumentException ("destination offset is beyond array size");
 | 
					        return 0;
 | 
				
			||||||
			if (offset > (buffer.Length - count))
 | 
					      }
 | 
				
			||||||
				throw new ArgumentException ("would overrun buffer");
 | 
					
 | 
				
			||||||
		}
 | 
					      Int64 r = 0;
 | 
				
			||||||
 | 
					      fixed(Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					          r = Native.Syscall.pread(this.fileDescriptor, buf, (UInt64)count, fileOffset);
 | 
				
			||||||
 | 
					        } while(UnixMarshal.ShouldRetrySyscall((Int32)r));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if(r == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (Int32)r;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public unsafe int ReadAtOffset ([In, Out] byte[] buffer, 
 | 
					    public override Int64 Seek(Int64 offset, SeekOrigin origin) {
 | 
				
			||||||
			int offset, int count, long fileOffset)
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
		{
 | 
					      if(!this.CanSeek) {
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					        throw new NotSupportedException("The File Descriptor does not support seeking");
 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					      }
 | 
				
			||||||
			if (!CanRead)
 | 
					
 | 
				
			||||||
				throw new NotSupportedException ("Stream does not support reading");
 | 
					      Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
 | 
				
			||||||
				 
 | 
					      switch(origin) {
 | 
				
			||||||
			if (buffer.Length == 0)
 | 
					        case SeekOrigin.Begin:
 | 
				
			||||||
				return 0;
 | 
					          sf = Native.SeekFlags.SEEK_SET;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case SeekOrigin.Current:
 | 
				
			||||||
 | 
					          sf = Native.SeekFlags.SEEK_CUR;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case SeekOrigin.End:
 | 
				
			||||||
 | 
					          sf = Native.SeekFlags.SEEK_END;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long r = 0;
 | 
					      Int64 pos = Native.Syscall.lseek(this.fileDescriptor, offset, sf);
 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					      if(pos == -1) {
 | 
				
			||||||
				do {
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
					r = Native.Syscall.pread (fileDescriptor, buf, (ulong) count, fileOffset);
 | 
					      }
 | 
				
			||||||
				} while (UnixMarshal.ShouldRetrySyscall ((int) r));
 | 
					
 | 
				
			||||||
			}
 | 
					      return (Int64)pos;
 | 
				
			||||||
			if (r == -1)
 | 
					    }
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return (int) r;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override long Seek (long offset, SeekOrigin origin)
 | 
					    public override void SetLength(Int64 value) {
 | 
				
			||||||
		{
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					      if(value < 0) {
 | 
				
			||||||
			if (!CanSeek)
 | 
					        throw new ArgumentOutOfRangeException("value", "< 0");
 | 
				
			||||||
				throw new NotSupportedException ("The File Descriptor does not support seeking");
 | 
					      }
 | 
				
			||||||
					
 | 
					
 | 
				
			||||||
			Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
 | 
					      if(!this.CanSeek && !this.CanWrite) {
 | 
				
			||||||
			switch (origin) {
 | 
					        throw new NotSupportedException("You can't truncating the current file descriptor");
 | 
				
			||||||
				case SeekOrigin.Begin:   sf = Native.SeekFlags.SEEK_SET; break;
 | 
					      }
 | 
				
			||||||
				case SeekOrigin.Current: sf = Native.SeekFlags.SEEK_CUR; break;
 | 
					
 | 
				
			||||||
				case SeekOrigin.End:     sf = Native.SeekFlags.SEEK_END; break;
 | 
					      Int32 r;
 | 
				
			||||||
			}
 | 
					      do {
 | 
				
			||||||
 | 
					        r = Native.Syscall.ftruncate(this.fileDescriptor, value);
 | 
				
			||||||
 | 
					      } while(UnixMarshal.ShouldRetrySyscall(r));
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long pos = Native.Syscall.lseek (fileDescriptor, offset, sf);
 | 
					    public override unsafe void Write(Byte[] buffer, Int32 offset, Int32 count) {
 | 
				
			||||||
			if (pos == -1)
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      this.AssertValidBuffer(buffer, offset, count);
 | 
				
			||||||
			return (long) pos;
 | 
					      if(!this.CanWrite) {
 | 
				
			||||||
		}
 | 
					        throw new NotSupportedException("File Descriptor does not support writing");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(buffer.Length == 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int64 r = 0;
 | 
				
			||||||
 | 
					      fixed(Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					          r = Native.Syscall.write(this.fileDescriptor, buf, (UInt64)count);
 | 
				
			||||||
 | 
					        } while(UnixMarshal.ShouldRetrySyscall((Int32)r));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if(r == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public unsafe void WriteAtOffset(Byte[] buffer,
 | 
				
			||||||
 | 
					      Int32 offset, Int32 count, Int64 fileOffset) {
 | 
				
			||||||
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
 | 
					      this.AssertValidBuffer(buffer, offset, count);
 | 
				
			||||||
 | 
					      if(!this.CanWrite) {
 | 
				
			||||||
 | 
					        throw new NotSupportedException("File Descriptor does not support writing");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(buffer.Length == 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int64 r = 0;
 | 
				
			||||||
 | 
					      fixed(Byte* buf = &buffer[offset]) {
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					          r = Native.Syscall.pwrite(this.fileDescriptor, buf, (UInt64)count, fileOffset);
 | 
				
			||||||
 | 
					        } while(UnixMarshal.ShouldRetrySyscall((Int32)r));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if(r == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void SetLength (long value)
 | 
					    public void SendTo(UnixStream output) => this.SendTo(output, (UInt64)output.Length);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			if (value < 0)
 | 
					 | 
				
			||||||
				throw new ArgumentOutOfRangeException ("value", "< 0");
 | 
					 | 
				
			||||||
			if (!CanSeek && !CanWrite)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("You can't truncating the current file descriptor");
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			int r;
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				r = Native.Syscall.ftruncate (fileDescriptor, value);
 | 
					 | 
				
			||||||
			} while (UnixMarshal.ShouldRetrySyscall (r));
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override unsafe void Write (byte[] buffer, int offset, int count)
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
		{
 | 
					    public void SendTo(UnixStream output, UInt64 count) => this.SendTo(output.Handle, count);
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					 | 
				
			||||||
			if (!CanWrite)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("File Descriptor does not support writing");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (buffer.Length == 0)
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
				return;
 | 
					    public void SendTo(Int32 out_fd, UInt64 count) {
 | 
				
			||||||
 | 
					      if(!this.CanWrite) {
 | 
				
			||||||
 | 
					        throw new NotSupportedException("Unable to write to the current file descriptor");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Int64 offset = this.Position;
 | 
				
			||||||
 | 
					      Int64 r = Native.Syscall.sendfile(out_fd, this.fileDescriptor, ref offset, count);
 | 
				
			||||||
 | 
					      if(r == -1) {
 | 
				
			||||||
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void SetOwner(Int64 user, Int64 group) {
 | 
				
			||||||
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long r = 0;
 | 
					      Int32 r = Native.Syscall.fchown(this.fileDescriptor,
 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					          Convert.ToUInt32(user), Convert.ToUInt32(group));
 | 
				
			||||||
				do {
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
					r = Native.Syscall.write (fileDescriptor, buf, (ulong) count);
 | 
					    }
 | 
				
			||||||
				} while (UnixMarshal.ShouldRetrySyscall ((int) r));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (r == -1)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public unsafe void WriteAtOffset (byte[] buffer, 
 | 
					 | 
				
			||||||
			int offset, int count, long fileOffset)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			AssertValidBuffer (buffer, offset, count);
 | 
					 | 
				
			||||||
			if (!CanWrite)
 | 
					 | 
				
			||||||
				throw new NotSupportedException ("File Descriptor does not support writing");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (buffer.Length == 0)
 | 
					    public void SetOwner(String user, String group) {
 | 
				
			||||||
				return;
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long r = 0;
 | 
					      Int64 uid = new UnixUserInfo(user).UserId;
 | 
				
			||||||
			fixed (byte* buf = &buffer[offset]) {
 | 
					      Int64 gid = new UnixGroupInfo(group).GroupId;
 | 
				
			||||||
				do {
 | 
					      this.SetOwner(uid, gid);
 | 
				
			||||||
					r = Native.Syscall.pwrite (fileDescriptor, buf, (ulong) count, fileOffset);
 | 
					    }
 | 
				
			||||||
				} while (UnixMarshal.ShouldRetrySyscall ((int) r));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (r == -1)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SendTo (UnixStream output)
 | 
					    public void SetOwner(String user) {
 | 
				
			||||||
		{
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
			SendTo (output, (ulong) output.Length);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					      Native.Passwd pw = Native.Syscall.getpwnam(user);
 | 
				
			||||||
		public void SendTo (UnixStream output, ulong count)
 | 
					      if(pw == null) {
 | 
				
			||||||
		{
 | 
					        throw new ArgumentException(Locale.GetText("invalid username"), "user");
 | 
				
			||||||
			SendTo (output.Handle, count);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      Int64 uid = pw.pw_uid;
 | 
				
			||||||
 | 
					      Int64 gid = pw.pw_gid;
 | 
				
			||||||
 | 
					      this.SetOwner(uid, gid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant(false)]
 | 
				
			||||||
		public void SendTo (int out_fd, ulong count)
 | 
					    public Int64 GetConfigurationValue(Native.PathconfName name) {
 | 
				
			||||||
		{
 | 
					      this.AssertNotDisposed();
 | 
				
			||||||
			if (!CanWrite)
 | 
					      Int64 r = Native.Syscall.fpathconf(this.fileDescriptor, name);
 | 
				
			||||||
				throw new NotSupportedException ("Unable to write to the current file descriptor");
 | 
					      if(r == -1 && Native.Syscall.GetLastError() != (Native.Errno)0) {
 | 
				
			||||||
			long offset = Position;
 | 
					        UnixMarshal.ThrowExceptionForLastError();
 | 
				
			||||||
			long r = Native.Syscall.sendfile (out_fd, fileDescriptor, ref offset, count);
 | 
					      }
 | 
				
			||||||
			if (r == -1)
 | 
					
 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					      return r;
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		public void SetOwner (long user, long group)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int r = Native.Syscall.fchown (fileDescriptor, 
 | 
					    ~UnixStream() {
 | 
				
			||||||
					Convert.ToUInt32 (user), Convert.ToUInt32 (group));
 | 
					      this.Close();
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					    }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SetOwner (string user, string group)
 | 
					    public override void Close() {
 | 
				
			||||||
		{
 | 
					      if(this.fileDescriptor == InvalidFileDescriptor) {
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.Flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			long uid = new UnixUserInfo (user).UserId;
 | 
					      if(!this.owner) {
 | 
				
			||||||
			long gid = new UnixGroupInfo (group).GroupId;
 | 
					        return;
 | 
				
			||||||
			SetOwner (uid, gid);
 | 
					      }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					      Int32 r;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        r = Native.Syscall.close(this.fileDescriptor);
 | 
				
			||||||
 | 
					      } while(UnixMarshal.ShouldRetrySyscall(r));
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf(r);
 | 
				
			||||||
 | 
					      this.fileDescriptor = InvalidFileDescriptor;
 | 
				
			||||||
 | 
					      GC.SuppressFinalize(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void IDisposable.Dispose() {
 | 
				
			||||||
 | 
					      if(this.fileDescriptor != InvalidFileDescriptor && this.owner) {
 | 
				
			||||||
 | 
					        this.Close();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      GC.SuppressFinalize(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SetOwner (string user)
 | 
					    private Boolean canSeek = false;
 | 
				
			||||||
		{
 | 
					    private Boolean canRead = false;
 | 
				
			||||||
			AssertNotDisposed ();
 | 
					    private Boolean canWrite = false;
 | 
				
			||||||
 | 
					    private Boolean owner = true;
 | 
				
			||||||
			Native.Passwd pw = Native.Syscall.getpwnam (user);
 | 
					    private Int32 fileDescriptor = InvalidFileDescriptor;
 | 
				
			||||||
			if (pw == null)
 | 
					    private Native.Stat stat;
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid username"), "user");
 | 
					  }
 | 
				
			||||||
			long uid = pw.pw_uid;
 | 
					 | 
				
			||||||
			long gid = pw.pw_gid;
 | 
					 | 
				
			||||||
			SetOwner (uid, gid);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					 | 
				
			||||||
		public long GetConfigurationValue (Native.PathconfName name)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			AssertNotDisposed ();
 | 
					 | 
				
			||||||
			long r = Native.Syscall.fpathconf (fileDescriptor, name);
 | 
					 | 
				
			||||||
			if (r == -1 && Native.Syscall.GetLastError() != (Native.Errno) 0)
 | 
					 | 
				
			||||||
				UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
			return r;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		~UnixStream ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Close ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public override void Close ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (fileDescriptor == InvalidFileDescriptor)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
			Flush ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (!owner)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			int r;
 | 
					 | 
				
			||||||
			do {
 | 
					 | 
				
			||||||
				r = Native.Syscall.close (fileDescriptor);
 | 
					 | 
				
			||||||
			} while (UnixMarshal.ShouldRetrySyscall (r));
 | 
					 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					 | 
				
			||||||
			fileDescriptor = InvalidFileDescriptor;
 | 
					 | 
				
			||||||
			GC.SuppressFinalize (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		void IDisposable.Dispose ()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (fileDescriptor != InvalidFileDescriptor && owner) {
 | 
					 | 
				
			||||||
				Close ();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			GC.SuppressFinalize (this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private bool canSeek = false;
 | 
					 | 
				
			||||||
		private bool canRead = false;
 | 
					 | 
				
			||||||
		private bool canWrite = false;
 | 
					 | 
				
			||||||
		private bool owner = true;
 | 
					 | 
				
			||||||
		private int fileDescriptor = InvalidFileDescriptor;
 | 
					 | 
				
			||||||
		private Native.Stat stat;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -27,82 +27,61 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.IO;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using Mono.Unix;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixSymbolicLinkInfo : UnixFileSystemInfo
 | 
					  public sealed class UnixSymbolicLinkInfo : UnixFileSystemInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		public UnixSymbolicLinkInfo (string path)
 | 
					    public UnixSymbolicLinkInfo (String path)
 | 
				
			||||||
			: base (path)
 | 
					      : base (path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal UnixSymbolicLinkInfo (string path, Native.Stat stat)
 | 
					    internal UnixSymbolicLinkInfo (String path, Native.Stat stat)
 | 
				
			||||||
			: base (path, stat)
 | 
					      : base (path, stat)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override string Name {
 | 
					    public override String Name => UnixPath.GetFileName(this.FullPath);
 | 
				
			||||||
			get {return UnixPath.GetFileName (FullPath);}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[Obsolete ("Use GetContents()")]
 | 
					    [Obsolete("Use GetContents()")]
 | 
				
			||||||
		public UnixFileSystemInfo Contents {
 | 
					    public UnixFileSystemInfo Contents => this.GetContents();
 | 
				
			||||||
			get {return GetContents ();}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string ContentsPath {
 | 
					    public String ContentsPath => UnixPath.ReadLink(this.FullPath);
 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return UnixPath.ReadLink (FullPath);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool HasContents {
 | 
					    public Boolean HasContents => UnixPath.TryReadLink(this.FullPath) != null;
 | 
				
			||||||
			get {
 | 
					 | 
				
			||||||
				return UnixPath.TryReadLink (FullPath) != null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixFileSystemInfo GetContents ()
 | 
					    public UnixFileSystemInfo GetContents() => UnixFileSystemInfo.GetFileSystemEntry(
 | 
				
			||||||
		{
 | 
					            UnixPath.Combine(UnixPath.GetDirectoryName(this.FullPath),
 | 
				
			||||||
			return UnixFileSystemInfo.GetFileSystemEntry (
 | 
					              this.ContentsPath));
 | 
				
			||||||
						UnixPath.Combine (UnixPath.GetDirectoryName (FullPath), 
 | 
					 | 
				
			||||||
							ContentsPath));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void CreateSymbolicLinkTo (string path)
 | 
					    public void CreateSymbolicLinkTo (String path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.symlink (path, FullName);
 | 
					      Int32 r = Native.Syscall.symlink (path, this.FullName);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void CreateSymbolicLinkTo (UnixFileSystemInfo path)
 | 
					    public void CreateSymbolicLinkTo (UnixFileSystemInfo path)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.symlink (path.FullName, FullName);
 | 
					      Int32 r = Native.Syscall.symlink (path.FullName, this.FullName);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void Delete ()
 | 
					    public override void Delete ()
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.unlink (FullPath);
 | 
					      Int32 r = Native.Syscall.unlink (this.FullPath);
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
			base.Refresh ();
 | 
					      this.Refresh();
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override void SetOwner (long owner, long group)
 | 
					    public override void SetOwner (Int64 owner, Int64 group)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			int r = Native.Syscall.lchown (FullPath, Convert.ToUInt32 (owner), Convert.ToUInt32 (group));
 | 
					      Int32 r = Native.Syscall.lchown (this.FullPath, Convert.ToUInt32 (owner), Convert.ToUInt32 (group));
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected override bool GetFileStatus (string path, out Native.Stat stat)
 | 
					    protected override Boolean GetFileStatus(String path, out Native.Stat stat) => Native.Syscall.lstat(path, out stat) == 0;
 | 
				
			||||||
		{
 | 
					  }
 | 
				
			||||||
			return Native.Syscall.lstat (path, out stat) == 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
@ -29,165 +29,121 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections;
 | 
					using System.Collections;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using Mono.Unix;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Mono.Unix {
 | 
					namespace Mono.Unix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public sealed class UnixUserInfo
 | 
					  public sealed class UnixUserInfo
 | 
				
			||||||
	{
 | 
					  {
 | 
				
			||||||
		private Native.Passwd passwd;
 | 
					    private readonly Native.Passwd passwd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixUserInfo (string user)
 | 
					    public UnixUserInfo (String user)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			passwd = new Native.Passwd ();
 | 
					      this.passwd = new Native.Passwd ();
 | 
				
			||||||
			Native.Passwd pw;
 | 
					      Int32 r = Native.Syscall.getpwnam_r(user, this.passwd, out Native.Passwd pw);
 | 
				
			||||||
			int r = Native.Syscall.getpwnam_r (user, passwd, out pw);
 | 
					      if (r != 0 || pw == null) {
 | 
				
			||||||
			if (r != 0 || pw == null)
 | 
					        throw new ArgumentException (Locale.GetText ("invalid username"), "user");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid username"), "user");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[CLSCompliant (false)]
 | 
					    //[CLSCompliant (false)]
 | 
				
			||||||
		public UnixUserInfo (uint user)
 | 
					    public UnixUserInfo (UInt32 user)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			passwd = new Native.Passwd ();
 | 
					      this.passwd = new Native.Passwd ();
 | 
				
			||||||
			Native.Passwd pw;
 | 
					      Int32 r = Native.Syscall.getpwuid_r(user, this.passwd, out Native.Passwd pw);
 | 
				
			||||||
			int r = Native.Syscall.getpwuid_r (user, passwd, out pw);
 | 
					      if (r != 0 || pw == null) {
 | 
				
			||||||
			if (r != 0 || pw == null)
 | 
					        throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixUserInfo (long user)
 | 
					    public UnixUserInfo (Int64 user)
 | 
				
			||||||
		{
 | 
					    {
 | 
				
			||||||
			passwd = new Native.Passwd ();
 | 
					      this.passwd = new Native.Passwd ();
 | 
				
			||||||
			Native.Passwd pw;
 | 
					      Int32 r = Native.Syscall.getpwuid_r(Convert.ToUInt32(user), this.passwd, out Native.Passwd pw);
 | 
				
			||||||
			int r = Native.Syscall.getpwuid_r (Convert.ToUInt32 (user), passwd, out pw);
 | 
					      if (r != 0 || pw == null) {
 | 
				
			||||||
			if (r != 0 || pw == null)
 | 
					        throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
 | 
				
			||||||
				throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
 | 
					      }
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixUserInfo (Native.Passwd passwd)
 | 
					    public UnixUserInfo(Native.Passwd passwd) => this.passwd = CopyPasswd(passwd);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.passwd = CopyPasswd (passwd);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static Native.Passwd CopyPasswd (Native.Passwd pw)
 | 
					    private static Native.Passwd CopyPasswd(Native.Passwd pw) => new Native.Passwd {
 | 
				
			||||||
		{
 | 
					      pw_name = pw.pw_name,
 | 
				
			||||||
			Native.Passwd p = new Native.Passwd ();
 | 
					      pw_passwd = pw.pw_passwd,
 | 
				
			||||||
 | 
					      pw_uid = pw.pw_uid,
 | 
				
			||||||
 | 
					      pw_gid = pw.pw_gid,
 | 
				
			||||||
 | 
					      pw_gecos = pw.pw_gecos,
 | 
				
			||||||
 | 
					      pw_dir = pw.pw_dir,
 | 
				
			||||||
 | 
					      pw_shell = pw.pw_shell
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			p.pw_name   = pw.pw_name;
 | 
					    public String UserName => this.passwd.pw_name;
 | 
				
			||||||
			p.pw_passwd = pw.pw_passwd;
 | 
					 | 
				
			||||||
			p.pw_uid    = pw.pw_uid;
 | 
					 | 
				
			||||||
			p.pw_gid    = pw.pw_gid;
 | 
					 | 
				
			||||||
			p.pw_gecos  = pw.pw_gecos;
 | 
					 | 
				
			||||||
			p.pw_dir    = pw.pw_dir;
 | 
					 | 
				
			||||||
			p.pw_shell  = pw.pw_shell;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return p;
 | 
					    public String Password => this.passwd.pw_passwd;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string UserName {
 | 
					    public Int64 UserId => this.passwd.pw_uid;
 | 
				
			||||||
			get {return passwd.pw_name;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string Password {
 | 
					    public UnixGroupInfo Group => new UnixGroupInfo(this.passwd.pw_gid);
 | 
				
			||||||
			get {return passwd.pw_passwd;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public long UserId {
 | 
					    public Int64 GroupId => this.passwd.pw_gid;
 | 
				
			||||||
			get {return passwd.pw_uid;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public UnixGroupInfo Group {
 | 
					    public String GroupName => this.Group.GroupName;
 | 
				
			||||||
			get {return new UnixGroupInfo (passwd.pw_gid);}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public long GroupId {
 | 
					    public String RealName => this.passwd.pw_gecos;
 | 
				
			||||||
			get {return passwd.pw_gid;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string GroupName {
 | 
					    public String HomeDirectory => this.passwd.pw_dir;
 | 
				
			||||||
			get {return Group.GroupName;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string RealName {
 | 
					    public String ShellProgram => this.passwd.pw_shell;
 | 
				
			||||||
			get {return passwd.pw_gecos;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string HomeDirectory {
 | 
					    public override Int32 GetHashCode() => this.passwd.GetHashCode();
 | 
				
			||||||
			get {return passwd.pw_dir;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string ShellProgram {
 | 
					    public override Boolean Equals(Object obj) => obj == null || this.GetType() != obj.GetType() ? false : this.passwd.Equals(((UnixUserInfo)obj).passwd);
 | 
				
			||||||
			get {return passwd.pw_shell;}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override int GetHashCode ()
 | 
					    public override String ToString() => this.passwd.ToString();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return passwd.GetHashCode ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override bool Equals (object obj)
 | 
					    public static UnixUserInfo GetRealUser() => new UnixUserInfo(GetRealUserId());
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (obj == null || GetType () != obj.GetType())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			return passwd.Equals (((UnixUserInfo) obj).passwd);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public override string ToString ()
 | 
					    public static Int64 GetRealUserId() => Native.Syscall.getuid();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return passwd.ToString ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static UnixUserInfo GetRealUser ()
 | 
					    // I would hope that this is the same as GetCurrentUserName, but it is a
 | 
				
			||||||
		{
 | 
					    // different syscall, so who knows.
 | 
				
			||||||
			return new UnixUserInfo (GetRealUserId ());
 | 
					    public static String GetLoginName ()
 | 
				
			||||||
		}
 | 
					    {
 | 
				
			||||||
 | 
					      StringBuilder buf = new StringBuilder (4);
 | 
				
			||||||
 | 
					      Int32 r;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        buf.Capacity *= 2;
 | 
				
			||||||
 | 
					        r = Native.Syscall.getlogin_r (buf, (UInt64) buf.Capacity);
 | 
				
			||||||
 | 
					      } while (r == -1 && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
 | 
				
			||||||
 | 
					      UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
				
			||||||
 | 
					      return buf.ToString ();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public static long GetRealUserId ()
 | 
					    public Native.Passwd ToPasswd() => CopyPasswd(this.passwd);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return Native.Syscall.getuid ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// I would hope that this is the same as GetCurrentUserName, but it is a
 | 
					    public static UnixUserInfo[] GetLocalUsers ()
 | 
				
			||||||
		// different syscall, so who knows.
 | 
					    {
 | 
				
			||||||
		public static string GetLoginName ()
 | 
					      ArrayList entries = new ArrayList ();
 | 
				
			||||||
		{
 | 
					      lock (Native.Syscall.pwd_lock) {
 | 
				
			||||||
			StringBuilder buf = new StringBuilder (4);
 | 
					        if (Native.Syscall.setpwent () != 0) {
 | 
				
			||||||
			int r;
 | 
					          UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
			do {
 | 
					        }
 | 
				
			||||||
				buf.Capacity *= 2;
 | 
					        try {
 | 
				
			||||||
				r = Native.Syscall.getlogin_r (buf, (ulong) buf.Capacity);
 | 
					          Native.Passwd p;
 | 
				
			||||||
			} while (r == (-1) && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
 | 
					          while ((p = Native.Syscall.getpwent()) != null) {
 | 
				
			||||||
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
 | 
					            _ = entries.Add(new UnixUserInfo(p));
 | 
				
			||||||
			return buf.ToString ();
 | 
					          }
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					          if (Native.Syscall.GetLastError () != (Native.Errno) 0) {
 | 
				
			||||||
		public Native.Passwd ToPasswd ()
 | 
					            UnixMarshal.ThrowExceptionForLastError ();
 | 
				
			||||||
		{
 | 
					          }
 | 
				
			||||||
			return CopyPasswd (passwd);
 | 
					        }
 | 
				
			||||||
		}
 | 
					        finally {
 | 
				
			||||||
 | 
					          _ = Native.Syscall.endpwent();
 | 
				
			||||||
		public static UnixUserInfo[] GetLocalUsers ()
 | 
					        }
 | 
				
			||||||
		{
 | 
					      }
 | 
				
			||||||
			ArrayList entries = new ArrayList ();
 | 
					      return (UnixUserInfo[]) entries.ToArray (typeof(UnixUserInfo));
 | 
				
			||||||
			lock (Native.Syscall.pwd_lock) {
 | 
					    }
 | 
				
			||||||
				if (Native.Syscall.setpwent () != 0) {
 | 
					  }
 | 
				
			||||||
					UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					Native.Passwd p;
 | 
					 | 
				
			||||||
					while ((p = Native.Syscall.getpwent()) != null)
 | 
					 | 
				
			||||||
						entries.Add (new UnixUserInfo (p));
 | 
					 | 
				
			||||||
					if (Native.Syscall.GetLastError () != (Native.Errno) 0)
 | 
					 | 
				
			||||||
						UnixMarshal.ThrowExceptionForLastError ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				finally {
 | 
					 | 
				
			||||||
					Native.Syscall.endpwent ();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return (UnixUserInfo[]) entries.ToArray (typeof(UnixUserInfo));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vim: noexpandtab
 | 
					// vim: noexpandtab
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user