Create Mono.Posix library
This commit is contained in:
commit
749da0d8db
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/.vs
|
||||
/Mono.Posix/obj
|
||||
/Mono.Posix/bin
|
25
Mono.Posix.sln
Normal file
25
Mono.Posix.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27703.2026
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Posix", "Mono.Posix\Mono.Posix.csproj", "{E2CA132E-E85C-40AD-BE94-B138AA68772B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {08A4AB48-4CF1-446D-9B29-6055D7993819}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
136
Mono.Posix/Consts.cs
Normal file
136
Mono.Posix/Consts.cs
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Consts.cs.in
|
||||
//
|
||||
// Author:
|
||||
// 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
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
static partial class Consts
|
||||
{
|
||||
public const string MonoCorlibVersion = "@MONO_CORLIB_VERSION@";
|
||||
}
|
||||
|
||||
#if !NETCORE
|
||||
|
||||
static partial class Consts
|
||||
{
|
||||
//
|
||||
// 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 MonoCopyright = "(c) Various Mono authors";
|
||||
|
||||
#if MOBILE
|
||||
// Versions of .NET Framework for Silverlight 4.0
|
||||
public const string FxVersion = "2.0.5.0";
|
||||
public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation
|
||||
public const string FxFileVersion = "4.0.50524.0";
|
||||
public const string EnvironmentVersion = FxFileVersion;
|
||||
|
||||
public const string VsFileVersion = "9.0.50727.42"; // unused, but needed for compilation
|
||||
#elif NET_4_6
|
||||
public const string FxVersion = "4.0.0.0";
|
||||
public const string FxFileVersion = "4.6.57.0";
|
||||
public const string EnvironmentVersion = "4.0.30319.42000";
|
||||
|
||||
public const string VsVersion = "0.0.0.0"; // Useless ?
|
||||
public const string VsFileVersion = "11.0.0.0"; // TODO:
|
||||
#elif NET_4_5
|
||||
public const string FxVersion = "4.0.0.0";
|
||||
public const string FxFileVersion = "4.0.30319.17020";
|
||||
public const string EnvironmentVersion = FxFileVersion;
|
||||
|
||||
public const string VsVersion = "0.0.0.0"; // Useless ?
|
||||
public const string VsFileVersion = "11.0.0.0"; // TODO:
|
||||
#elif NETCORE
|
||||
public const string FxVersion = "";
|
||||
public const string FxFileVersion = "";
|
||||
public const string EnvironmentVersion = FxFileVersion;
|
||||
|
||||
public const string VsVersion = "";
|
||||
public const string VsFileVersion = "";
|
||||
#elif NET_4_0
|
||||
#error Profile NET_4_0 is not supported.
|
||||
#elif NET_3_5
|
||||
#error Profile NET_3_5 is not supported.
|
||||
#elif NET_3_0
|
||||
#error Profile NET_3_0 is not supported.
|
||||
#elif NET_2_0
|
||||
#error Profile NET_2_0 is not supported.
|
||||
#elif NET_1_1
|
||||
#error Profile NET_1_1 is not supported.
|
||||
#elif NET_1_0
|
||||
#error Profile NET_1_0 is not supported.
|
||||
#else
|
||||
#error No profile symbols defined.
|
||||
#endif
|
||||
|
||||
#if MOBILE
|
||||
const string PublicKeyToken = "7cec85d7bea7798e";
|
||||
#else
|
||||
const string PublicKeyToken = "b77a5c561934e089";
|
||||
#endif
|
||||
|
||||
//
|
||||
// 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 AssemblyMicrosoft_VisualStudio_Web = "Microsoft.VisualStudio.Web, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblyMicrosoft_VSDesigner = "Microsoft.VSDesigner, Version=" + VsVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblyMono_Http = "Mono.Http, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
|
||||
public const string AssemblyMono_Posix = "Mono.Posix, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
|
||||
public const string AssemblyMono_Security = "Mono.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
|
||||
public const string AssemblyMono_Messaging_RabbitMQ = "Mono.Messaging.RabbitMQ, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=0738eb9f132ed756";
|
||||
public const string AssemblyCorlib = "mscorlib, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
|
||||
public const string AssemblySystem = "System, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
|
||||
public const string AssemblySystem_Data = "System.Data, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
|
||||
public const string AssemblySystem_Design = "System.Design, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblySystem_DirectoryServices = "System.DirectoryServices, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblySystem_Drawing = "System.Drawing, 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_Messaging = "System.Messaging, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblySystem_Security = "System.Security, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblySystem_ServiceProcess = "System.ServiceProcess, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
public const string AssemblySystem_Web = "System.Web, 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_2_0 = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
|
||||
public const string AssemblySystemCore_3_5 = "System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
|
||||
public const string AssemblySystem_Core = "System.Core, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=" + PublicKeyToken;
|
||||
public const string WindowsBase_3_0 = "WindowsBase, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35";
|
||||
public const string AssemblyWindowsBase = "WindowsBase, Version=4.0.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 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
|
51
Mono.Posix/Locale.cs
Normal file
51
Mono.Posix/Locale.cs
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Locale.cs
|
||||
//
|
||||
// Author:
|
||||
// Miguel de Icaza (miguel@ximian.com)
|
||||
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
|
||||
//
|
||||
// (C) 2001 - 2003 Ximian, Inc (http://www.ximian.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
internal sealed class Locale {
|
||||
|
||||
private Locale ()
|
||||
{
|
||||
}
|
||||
|
||||
public static string GetText (string msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static string GetText (string fmt, params object [] args)
|
||||
{
|
||||
return String.Format (fmt, args);
|
||||
}
|
||||
}
|
107
Mono.Posix/Mono.Posix.csproj
Normal file
107
Mono.Posix/Mono.Posix.csproj
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E2CA132E-E85C-40AD-BE94-B138AA68772B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Mono.Posix</RootNamespace>
|
||||
<AssemblyName>Mono.Posix</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;NET_4_6</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NET_4_6</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Consts.cs" />
|
||||
<Compile Include="Locale.cs" />
|
||||
<Compile Include="Mono.Posix\Catalog.cs" />
|
||||
<Compile Include="Mono.Posix\PeerCred.cs" />
|
||||
<Compile Include="Mono.Posix\Syscall.cs" />
|
||||
<Compile Include="Mono.Posix\UnixEndPoint.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixBinaryClientFormatterSink.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixBinaryClientFormatterSinkProvider.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixBinaryCore.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixBinaryServerFormatterSink.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixBinaryServerFormatterSinkProvider.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixChannel.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixClientChannel.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixClientTransportSink.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixClientTransportSinkProvider.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixConnectionPool.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixMessageIO.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixServerChannel.cs" />
|
||||
<Compile Include="Mono.Remoting.Channels.Unix\UnixServerTransportSink.cs" />
|
||||
<Compile Include="Mono.Unix.Native\CdeclFunction.cs" />
|
||||
<Compile Include="Mono.Unix.Native\FileNameMarshaler.cs" />
|
||||
<Compile Include="Mono.Unix.Native\MapAttribute.cs" />
|
||||
<Compile Include="Mono.Unix.Native\NativeConvert.cs" />
|
||||
<Compile Include="Mono.Unix.Native\NativeConvert.generated.cs" />
|
||||
<Compile Include="Mono.Unix.Native\RealTimeSignum.cs" />
|
||||
<Compile Include="Mono.Unix.Native\Stdlib.cs" />
|
||||
<Compile Include="Mono.Unix.Native\Syscall.cs" />
|
||||
<Compile Include="Mono.Unix.Native\TypeAttributes.cs" />
|
||||
<Compile Include="Mono.Unix\AbstractUnixEndPoint.cs" />
|
||||
<Compile Include="Mono.Unix\Catalog.cs" />
|
||||
<Compile Include="Mono.Unix\FileAccessPattern.cs" />
|
||||
<Compile Include="Mono.Unix\FileAccessPermissions.cs" />
|
||||
<Compile Include="Mono.Unix\FileHandleOperations.cs" />
|
||||
<Compile Include="Mono.Unix\FileSpecialAttributes.cs" />
|
||||
<Compile Include="Mono.Unix\FileTypes.cs" />
|
||||
<Compile Include="Mono.Unix\PeerCred.cs" />
|
||||
<Compile Include="Mono.Unix\StdioFileStream.cs" />
|
||||
<Compile Include="Mono.Unix\UnixClient.cs" />
|
||||
<Compile Include="Mono.Unix\UnixDirectoryInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixDriveInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixEncoding.cs" />
|
||||
<Compile Include="Mono.Unix\UnixEndPoint.cs" />
|
||||
<Compile Include="Mono.Unix\UnixEnvironment.cs" />
|
||||
<Compile Include="Mono.Unix\UnixFileInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixFileSystemInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixGroupInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixIOException.cs" />
|
||||
<Compile Include="Mono.Unix\UnixListener.cs" />
|
||||
<Compile Include="Mono.Unix\UnixMarshal.cs" />
|
||||
<Compile Include="Mono.Unix\UnixPath.cs" />
|
||||
<Compile Include="Mono.Unix\UnixPipes.cs" />
|
||||
<Compile Include="Mono.Unix\UnixProcess.cs" />
|
||||
<Compile Include="Mono.Unix\UnixSignal.cs" />
|
||||
<Compile Include="Mono.Unix\UnixStream.cs" />
|
||||
<Compile Include="Mono.Unix\UnixSymbolicLinkInfo.cs" />
|
||||
<Compile Include="Mono.Unix\UnixUserInfo.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Mono.Remoting.Channels.Unix\.gitattributes" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
86
Mono.Posix/Mono.Posix/Catalog.cs
Normal file
86
Mono.Posix/Mono.Posix/Catalog.cs
Normal file
@ -0,0 +1,86 @@
|
||||
//
|
||||
// Mono.Posix.Catalog.cs: Wrappers for the libintl library.
|
||||
//
|
||||
// Author:
|
||||
// Edd Dumbill (edd@usefulinc.com)
|
||||
//
|
||||
// (C) 2004 Edd Dumbill
|
||||
//
|
||||
// This file implements the low-level syscall interface to the POSIX
|
||||
// subsystem.
|
||||
//
|
||||
// This file tries to stay close to the low-level API as much as possible
|
||||
// using enumerations, structures and in a few cases, using existing .NET
|
||||
// data types.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// Since the values for the various constants on the API changes
|
||||
// from system to system (even Linux on different architectures will
|
||||
// have different values), we define our own set of values, and we
|
||||
// use a set of C helper routines to map from the constants we define
|
||||
// to the values of the native OS.
|
||||
//
|
||||
// Bitfields are flagged with the [Map] attribute, and a helper program
|
||||
// generates a set of map_XXXX routines that we can call to convert
|
||||
// from our value definitions to the value definitions expected by the
|
||||
// OS.
|
||||
//
|
||||
// Methods that require tuning are bound as `internal syscal_NAME' methods
|
||||
// and then a `NAME' method is exposed.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mono.Posix {
|
||||
|
||||
[Obsolete ("Use Mono.Unix.Catalog")]
|
||||
public class Catalog {
|
||||
[DllImport("intl")]
|
||||
static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
|
||||
[DllImport("intl")]
|
||||
static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
|
||||
IntPtr codeset);
|
||||
[DllImport("intl")]
|
||||
static extern IntPtr textdomain (IntPtr domainname);
|
||||
|
||||
public static void Init (String package, String localedir)
|
||||
{
|
||||
IntPtr ipackage = Marshal.StringToHGlobalAuto (package);
|
||||
IntPtr ilocaledir = Marshal.StringToHGlobalAuto (localedir);
|
||||
IntPtr iutf8 = Marshal.StringToHGlobalAuto ("UTF-8");
|
||||
bindtextdomain (ipackage, ilocaledir);
|
||||
bind_textdomain_codeset (ipackage, iutf8);
|
||||
textdomain (ipackage);
|
||||
Marshal.FreeHGlobal (ipackage);
|
||||
Marshal.FreeHGlobal (ilocaledir);
|
||||
Marshal.FreeHGlobal (iutf8);
|
||||
}
|
||||
|
||||
[DllImport("intl")]
|
||||
static extern IntPtr gettext (IntPtr instring);
|
||||
|
||||
public static String GetString (String s)
|
||||
{
|
||||
IntPtr ints = Marshal.StringToHGlobalAuto (s);
|
||||
String t = Marshal.PtrToStringAuto (gettext (ints));
|
||||
Marshal.FreeHGlobal (ints);
|
||||
return t;
|
||||
}
|
||||
|
||||
[DllImport("intl")]
|
||||
static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
|
||||
|
||||
public static String GetPluralString (String s, String p, Int32 n)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
81
Mono.Posix/Mono.Posix/PeerCred.cs
Normal file
81
Mono.Posix/Mono.Posix/PeerCred.cs
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Mono.Posix.PeerCred: Peer credentials class for AF_UNIX sockets
|
||||
//
|
||||
// Authors:
|
||||
// Dick Porter (dick@ximian.com)
|
||||
//
|
||||
// (C) 2004 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Mono.Posix
|
||||
{
|
||||
#pragma warning disable 649
|
||||
internal struct PeerCredData {
|
||||
public int pid;
|
||||
public int uid;
|
||||
public int gid;
|
||||
}
|
||||
#pragma warning restore 649
|
||||
|
||||
[Obsolete ("Use Mono.Unix.PeerCred")]
|
||||
public class PeerCred
|
||||
{
|
||||
/* Make sure this doesn't clash with anything in
|
||||
* SocketOptionName, and keep it synchronised with the
|
||||
* runtime
|
||||
*/
|
||||
private const int so_peercred=10001;
|
||||
private PeerCredData data;
|
||||
|
||||
public PeerCred (Socket sock) {
|
||||
if (sock.AddressFamily != AddressFamily.Unix) {
|
||||
throw new ArgumentException ("Only Unix sockets are supported", "sock");
|
||||
}
|
||||
|
||||
data = (PeerCredData)sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
|
||||
}
|
||||
|
||||
public int ProcessID {
|
||||
get {
|
||||
return(data.pid);
|
||||
}
|
||||
}
|
||||
|
||||
public int UserID {
|
||||
get {
|
||||
return(data.uid);
|
||||
}
|
||||
}
|
||||
|
||||
public int GroupID {
|
||||
get {
|
||||
return(data.gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
641
Mono.Posix/Mono.Posix/Syscall.cs
Normal file
641
Mono.Posix/Mono.Posix/Syscall.cs
Normal file
@ -0,0 +1,641 @@
|
||||
//
|
||||
// Mono.Posix.Syscall.cs: System calls to Posix subsystem features
|
||||
//
|
||||
// Author:
|
||||
// Miguel de Icaza (miguel@novell.com)
|
||||
//
|
||||
// (C) 2003 Novell, Inc.
|
||||
//
|
||||
// This file implements the low-level syscall interface to the POSIX
|
||||
// subsystem.
|
||||
//
|
||||
// This file tries to stay close to the low-level API as much as possible
|
||||
// using enumerations, structures and in a few cases, using existing .NET
|
||||
// data types.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// Since the values for the various constants on the API changes
|
||||
// from system to system (even Linux on different architectures will
|
||||
// have different values), we define our own set of values, and we
|
||||
// use a set of C helper routines to map from the constants we define
|
||||
// to the values of the native OS.
|
||||
//
|
||||
// Bitfields were flagged with the [Map] attribute, and a helper program
|
||||
// generates a set of map_XXXX routines that we can call to convert
|
||||
// from our value definitions to the value definitions expected by the
|
||||
// OS.
|
||||
//
|
||||
// Methods that require tuning are bound as `internal syscal_NAME' methods
|
||||
// and then a `NAME' method is exposed.
|
||||
//
|
||||
// Deprecated Warning:
|
||||
//
|
||||
// This class is deprecated, and exists only for backward compatibility.
|
||||
// Please use and maintain Mono.Unix.Native.Syscall.
|
||||
//
|
||||
// The [Map] attributes have been removed. The naming and methodology of
|
||||
// the mapping routines has changed. The old map functions still exist in
|
||||
// MonoPosixHelper, but they will not be updated any further.
|
||||
// Consequently, there is little point in maintaining the [Map] attributes
|
||||
// in this file, as they would only bloat MonoPosixHelper.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mono.Posix {
|
||||
|
||||
[Flags]
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.OpenFlags")]
|
||||
public enum OpenFlags {
|
||||
//
|
||||
// One of these
|
||||
//
|
||||
O_RDONLY = 0,
|
||||
O_WRONLY = 1,
|
||||
O_RDWR = 2,
|
||||
|
||||
//
|
||||
// Or-ed with zero or more of these
|
||||
//
|
||||
O_CREAT = 4,
|
||||
O_EXCL = 8,
|
||||
O_NOCTTY = 16,
|
||||
O_TRUNC = 32,
|
||||
O_APPEND = 64,
|
||||
O_NONBLOCK = 128,
|
||||
O_SYNC = 256,
|
||||
|
||||
//
|
||||
// These are non-Posix, think of a way of exposing
|
||||
// this for Linux users.
|
||||
//
|
||||
|
||||
// O_NOFOLLOW = 512,
|
||||
// O_DIRECTORY = 1024,
|
||||
// O_DIRECT = 2048,
|
||||
// O_ASYNC = 4096,
|
||||
// O_LARGEFILE = 8192
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions")]
|
||||
public enum FileMode {
|
||||
S_ISUID = 2048,
|
||||
S_ISGID = 1024,
|
||||
S_ISVTX = 512,
|
||||
S_IRUSR = 256,
|
||||
S_IWUSR = 128,
|
||||
S_IXUSR = 64,
|
||||
S_IRGRP = 32,
|
||||
S_IWGRP = 16,
|
||||
S_IXGRP = 8,
|
||||
S_IROTH = 4,
|
||||
S_IWOTH = 2,
|
||||
S_IXOTH = 1
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.WaitOptions")]
|
||||
public enum WaitOptions {
|
||||
WNOHANG,
|
||||
WUNTRACED
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.AccessModes")]
|
||||
public enum AccessMode {
|
||||
R_OK = 1,
|
||||
W_OK = 2,
|
||||
X_OK = 4,
|
||||
F_OK = 8
|
||||
}
|
||||
|
||||
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.Signum")]
|
||||
public enum Signals {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS,
|
||||
SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
|
||||
SIGALRM, SIGTERM, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
|
||||
SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
|
||||
SIGPROF, SIGWINCH, SIGIO,
|
||||
|
||||
// SIGPWR,
|
||||
SIGSYS,
|
||||
// SIGRTMIN
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
[Obsolete ("Use Mono.Unix.Native.Syscall.")]
|
||||
public class Syscall {
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int exit (int status);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int fork ();
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public unsafe static extern IntPtr read (int fileDescriptor, void *buf, IntPtr count);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public unsafe static extern IntPtr write (int fileDescriptor, void *buf, IntPtr count);
|
||||
|
||||
[DllImport ("libc", EntryPoint="open", SetLastError=true)]
|
||||
internal static extern int syscall_open (string pathname, int flags, int mode);
|
||||
|
||||
[DllImport ("MonoPosixHelper")]
|
||||
internal extern static int map_Mono_Posix_OpenFlags (OpenFlags flags);
|
||||
[DllImport ("MonoPosixHelper")]
|
||||
internal extern static int map_Mono_Posix_FileMode (FileMode mode);
|
||||
|
||||
public static int open (string pathname, OpenFlags flags)
|
||||
{
|
||||
if ((flags & OpenFlags.O_CREAT) != 0)
|
||||
throw new ArgumentException ("If you pass O_CREAT, you must call the method with the mode flag");
|
||||
|
||||
int posix_flags = map_Mono_Posix_OpenFlags (flags);
|
||||
return syscall_open (pathname, posix_flags, 0);
|
||||
}
|
||||
|
||||
public static int open (string pathname, OpenFlags flags, FileMode mode)
|
||||
{
|
||||
int posix_flags = map_Mono_Posix_OpenFlags (flags);
|
||||
int posix_mode = map_Mono_Posix_FileMode (mode);
|
||||
|
||||
return syscall_open (pathname, posix_flags, posix_mode);
|
||||
}
|
||||
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int close (int fileDescriptor);
|
||||
|
||||
[DllImport ("libc", EntryPoint="waitpid", SetLastError=true)]
|
||||
unsafe internal static extern int syscall_waitpid (int pid, int * status, int options);
|
||||
|
||||
[DllImport ("MonoPosixHelper")]
|
||||
internal extern static int map_Mono_Posix_WaitOptions (WaitOptions wait_options);
|
||||
|
||||
public static int waitpid (int pid, out int status, WaitOptions options)
|
||||
{
|
||||
unsafe {
|
||||
int s = 0;
|
||||
int r = syscall_waitpid (pid, &s, map_Mono_Posix_WaitOptions (options));
|
||||
status = s;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
public static int waitpid (int pid, WaitOptions options)
|
||||
{
|
||||
unsafe {
|
||||
return syscall_waitpid (pid, null, map_Mono_Posix_WaitOptions (options));
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wifexited")]
|
||||
public static extern int WIFEXITED (int status);
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wexitstatus")]
|
||||
public static extern int WEXITSTATUS (int status);
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wifsignaled")]
|
||||
public static extern int WIFSIGNALED (int status);
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wtermsig")]
|
||||
public static extern int WTERMSIG (int status);
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wifstopped")]
|
||||
public static extern int WIFSTOPPED (int status);
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="wstopsig")]
|
||||
public static extern int WSTOPSIG (int status);
|
||||
|
||||
[DllImport ("libc", EntryPoint="creat", SetLastError=true)]
|
||||
internal static extern int syscall_creat (string pathname, int flags);
|
||||
|
||||
public static int creat (string pathname, FileMode flags)
|
||||
{
|
||||
return syscall_creat (pathname, map_Mono_Posix_FileMode (flags));
|
||||
}
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int link (string oldPath, string newPath);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int unlink (string path);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int symlink (string oldpath, string newpath);
|
||||
|
||||
// TODO: execve
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int chdir (string path);
|
||||
|
||||
// TODO: time
|
||||
// TODO: mknod
|
||||
|
||||
|
||||
[DllImport ("libc", EntryPoint="chmod", SetLastError=true)]
|
||||
internal static extern int syscall_chmod (string path, int mode);
|
||||
|
||||
public static int chmod (string path, FileMode mode)
|
||||
{
|
||||
return syscall_chmod (path, map_Mono_Posix_FileMode (mode));
|
||||
}
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int chown (string path, int owner, int group);
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int lchown (string path, int owner, int group);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int lseek (int fileDescriptor, int offset, int whence);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getpid ();
|
||||
|
||||
// TODO: mount
|
||||
// TODO: umount
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setuid (int uid);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getuid ();
|
||||
|
||||
// TODO: stime
|
||||
// TODO: ptrace
|
||||
|
||||
[DllImport ("libc")]
|
||||
public static extern uint alarm (uint seconds);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int pause ();
|
||||
|
||||
// TODO: utime
|
||||
|
||||
[DllImport ("libc", EntryPoint="access", SetLastError=true)]
|
||||
internal extern static int syscall_access (string pathname, int mode);
|
||||
|
||||
[DllImport ("MonoPosixHelper")]
|
||||
internal extern static int map_Mono_Posix_AccessMode (AccessMode mode);
|
||||
|
||||
public static int access (string pathname, AccessMode mode)
|
||||
{
|
||||
return syscall_access (pathname, map_Mono_Posix_AccessMode (mode));
|
||||
}
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int nice (int increment);
|
||||
|
||||
// TODO: ftime
|
||||
|
||||
[DllImport ("libc")]
|
||||
public static extern void sync ();
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern void kill (int pid, int sig);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int rename (string oldPath, string newPath);
|
||||
|
||||
[DllImport ("libc", EntryPoint="mkdir", SetLastError=true)]
|
||||
internal extern static int syscall_mkdir (string pathname, int mode);
|
||||
|
||||
public static int mkdir (string pathname, FileMode mode)
|
||||
{
|
||||
return syscall_mkdir (pathname, map_Mono_Posix_FileMode (mode));
|
||||
}
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int rmdir (string path);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int dup (int fileDescriptor);
|
||||
|
||||
// TODO: pipe
|
||||
// TODO: times
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setgid (int gid);
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getgid ();
|
||||
|
||||
|
||||
public delegate void sighandler_t (int v);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int signal (int signum, sighandler_t handler);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int geteuid ();
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getegid ();
|
||||
|
||||
// TODO: fcntl
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setpgid (int pid, int pgid);
|
||||
|
||||
// TODO: ulimit
|
||||
|
||||
[DllImport ("libc")]
|
||||
public static extern int umask (int umask);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int chroot (string path);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int dup2 (int oldFileDescriptor, int newFileDescriptor);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getppid ();
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int getpgrp ();
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setsid ();
|
||||
|
||||
// TODO: sigaction
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setreuid (int ruid, int euid);
|
||||
|
||||
[DllImport ("libc", SetLastError=true)]
|
||||
public static extern int setregid (int rgid, int egid);
|
||||
|
||||
// these don't exactly match POSIX, but it's a nice way to get user/group names
|
||||
|
||||
[DllImport ("MonoPosixHelper", SetLastError=true)]
|
||||
private static extern string helper_Mono_Posix_GetUserName (int uid);
|
||||
|
||||
[DllImport ("MonoPosixHelper", SetLastError=true)]
|
||||
private static extern string helper_Mono_Posix_GetGroupName (int gid);
|
||||
|
||||
public static string getusername(int uid) { return helper_Mono_Posix_GetUserName(uid); }
|
||||
public static string getgroupname(int gid) { return helper_Mono_Posix_GetGroupName(gid); }
|
||||
|
||||
// TODO: sigsuspend
|
||||
// TODO: sigpending
|
||||
// TODO: setrlimit
|
||||
// TODO: getrlimit
|
||||
// TODO: getrusage
|
||||
// TODO: gettimeofday
|
||||
// TODO: settimeofday
|
||||
|
||||
[DllImport ("libc", EntryPoint="gethostname", SetLastError=true)]
|
||||
static extern int syscall_gethostname (byte[] p, int len);
|
||||
|
||||
public static string GetHostName ()
|
||||
{
|
||||
byte [] buf = new byte [256];
|
||||
int res = syscall_gethostname (buf, buf.Length);
|
||||
if (res == -1)
|
||||
return "localhost";
|
||||
for (res = 0; res < buf.Length; ++res) {
|
||||
if (buf [res] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString (buf, 0, res);
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public static string gethostname ()
|
||||
{
|
||||
return GetHostName ();
|
||||
}
|
||||
|
||||
|
||||
[DllImport ("libc", EntryPoint="isatty")]
|
||||
static extern int syscall_isatty (int desc);
|
||||
|
||||
public static bool isatty (int desc)
|
||||
{
|
||||
int res = syscall_isatty (desc);
|
||||
if (res == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
[DllImport ("MonoPosixHelper")]
|
||||
internal extern static int helper_Mono_Posix_Stat (string filename, bool dereference,
|
||||
out int device, out int inode, out int mode,
|
||||
out int nlinks, out int uid, out int gid,
|
||||
out int rdev, out long size, out long blksize, out long blocks,
|
||||
out long atime, out long mtime, out long ctime);
|
||||
|
||||
private static int stat2(string filename, bool dereference, out Stat stat) {
|
||||
int device, inode, mode;
|
||||
int nlinks, uid, gid, rdev;
|
||||
long size, blksize, blocks;
|
||||
long atime, mtime, ctime;
|
||||
|
||||
int ret = helper_Mono_Posix_Stat(filename, dereference,
|
||||
out device, out inode, out mode,
|
||||
out nlinks, out uid, out gid,
|
||||
out rdev, out size, out blksize, out blocks,
|
||||
out atime, out mtime, out ctime);
|
||||
|
||||
stat = new Stat(
|
||||
device, inode, mode,
|
||||
nlinks, uid, gid,
|
||||
rdev, size, blksize, blocks,
|
||||
atime, mtime, ctime);
|
||||
|
||||
if (ret != 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int stat(string filename, out Stat stat) {
|
||||
return stat2(filename, false, out stat);
|
||||
}
|
||||
|
||||
public static int lstat(string filename, out Stat stat) {
|
||||
return stat2(filename, true, out stat);
|
||||
}
|
||||
|
||||
[DllImport ("libc")]
|
||||
private static extern int readlink(string path, byte[] buffer, int buflen);
|
||||
|
||||
public static string readlink(string path) {
|
||||
byte[] buf = new byte[512];
|
||||
int ret = readlink(path, buf, buf.Length);
|
||||
if (ret == -1) return null;
|
||||
char[] cbuf = new char[512];
|
||||
int chars = System.Text.Encoding.Default.GetChars(buf, 0, ret, cbuf, 0);
|
||||
return new String(cbuf, 0, chars);
|
||||
}
|
||||
|
||||
[DllImport ("libc", EntryPoint="strerror")]
|
||||
static extern IntPtr _strerror(int errnum);
|
||||
|
||||
public static string strerror (int errnum)
|
||||
{
|
||||
return Marshal.PtrToStringAnsi (_strerror (errnum));
|
||||
}
|
||||
|
||||
[DllImport ("libc")]
|
||||
public static extern IntPtr opendir(string path);
|
||||
|
||||
[DllImport ("libc")]
|
||||
public static extern int closedir(IntPtr dir);
|
||||
|
||||
[DllImport ("MonoPosixHelper", EntryPoint="helper_Mono_Posix_readdir")]
|
||||
public static extern string readdir(IntPtr dir);
|
||||
|
||||
}
|
||||
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions")]
|
||||
public enum StatModeMasks {
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFMT")]
|
||||
TypeMask = 0xF000, // bitmask for the file type bitfields
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_RWXU")]
|
||||
OwnerMask = 0x1C0, // mask for file owner permissions
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_RWXG")]
|
||||
GroupMask = 0x38, // mask for group permissions
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_RWXO")]
|
||||
OthersMask = 0x7, // mask for permissions for others (not in group)
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions")]
|
||||
public enum StatMode {
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFSOCK")]
|
||||
Socket = 0xC000, // socket
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFLNK")]
|
||||
SymLink = 0xA000, // symbolic link
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFREG")]
|
||||
Regular = 0x8000, // regular file
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFBLK")]
|
||||
BlockDevice = 0x6000, // block device
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFDIR")]
|
||||
Directory = 0x4000, // directory
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFCHR")]
|
||||
CharDevice = 0x2000, // character device
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IFIFO")]
|
||||
FIFO = 0x1000, // fifo
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_ISUID")]
|
||||
SUid = 0x800, // set UID bit
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_ISGID")]
|
||||
SGid = 0x400, // set GID bit
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_ISVTX")]
|
||||
Sticky = 0x200, // sticky bit
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IRUSR")]
|
||||
OwnerRead = 0x100, // owner has read permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IWUSR")]
|
||||
OwnerWrite = 0x80, // owner has write permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IXUSR")]
|
||||
OwnerExecute = 0x40, // owner has execute permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IRGRP")]
|
||||
GroupRead = 0x20, // group has read permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IWGRP")]
|
||||
GroupWrite = 0x10, // group has write permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IXGRP")]
|
||||
GroupExecute = 0x8, // group has execute permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IROTH")]
|
||||
OthersRead = 0x4, // others have read permission
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IWOTH")]
|
||||
OthersWrite = 0x2, // others have write permisson
|
||||
[Obsolete ("Use Mono.Unix.Native.FilePermissions.S_IXOTH")]
|
||||
OthersExecute = 0x1, // others have execute permission
|
||||
}
|
||||
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat")]
|
||||
public struct Stat {
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_dev")]
|
||||
public readonly int Device;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_ino")]
|
||||
public readonly int INode;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_mode")]
|
||||
public readonly StatMode Mode;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_nlink")]
|
||||
public readonly int NLinks;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_uid")]
|
||||
public readonly int Uid;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_gid")]
|
||||
public readonly int Gid;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_rdev")]
|
||||
public readonly long DeviceType;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_size")]
|
||||
public readonly long Size;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_blksize")]
|
||||
public readonly long BlockSize;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_blocks")]
|
||||
public readonly long Blocks;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_atime")]
|
||||
public readonly DateTime ATime;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_mtime")]
|
||||
public readonly DateTime MTime;
|
||||
[Obsolete ("Use Mono.Unix.Native.Stat.st_ctime")]
|
||||
public readonly DateTime CTime;
|
||||
|
||||
[Obsolete ("Use Mono.Unix.Native.NativeConvert.LocalUnixEpoch")]
|
||||
public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1);
|
||||
|
||||
[Obsolete ("Use Mono.Unix.Native.NativeConvert.ToDateTime")]
|
||||
public static DateTime UnixToDateTime(long unix) {
|
||||
return UnixEpoch.Add(TimeSpan.FromSeconds(unix)).ToLocalTime();
|
||||
}
|
||||
|
||||
internal Stat(
|
||||
int device, int inode, int mode,
|
||||
int nlinks, int uid, int gid,
|
||||
int rdev, long size, long blksize, long blocks,
|
||||
long atime, long mtime, long ctime) {
|
||||
Device = device;
|
||||
INode = inode;
|
||||
Mode = (StatMode)mode;
|
||||
NLinks = nlinks;
|
||||
Uid = uid;
|
||||
Gid = gid;
|
||||
DeviceType = rdev;
|
||||
Size = size;
|
||||
BlockSize = blksize;
|
||||
Blocks = blocks;
|
||||
if (atime != 0)
|
||||
ATime = UnixToDateTime(atime);
|
||||
else
|
||||
ATime = new DateTime();
|
||||
if (mtime != 0)
|
||||
MTime = UnixToDateTime(mtime);
|
||||
else
|
||||
MTime = new DateTime();
|
||||
if (ctime != 0)
|
||||
CTime = UnixToDateTime(ctime);
|
||||
else
|
||||
CTime = new DateTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
118
Mono.Posix/Mono.Posix/UnixEndPoint.cs
Normal file
118
Mono.Posix/Mono.Posix/UnixEndPoint.cs
Normal file
@ -0,0 +1,118 @@
|
||||
//
|
||||
// Mono.Posix.UnixEndPoint: EndPoint derived class for AF_UNIX family sockets.
|
||||
//
|
||||
// Authors:
|
||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
||||
//
|
||||
// (C) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Posix
|
||||
{
|
||||
[Serializable]
|
||||
[Obsolete ("Use Mono.Unix.UnixEndPoint")]
|
||||
public class UnixEndPoint : EndPoint
|
||||
{
|
||||
string filename;
|
||||
|
||||
public UnixEndPoint (string filename)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException ("filename");
|
||||
|
||||
if (filename == "")
|
||||
throw new ArgumentException ("Cannot be empty.", "filename");
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public string Filename {
|
||||
get {
|
||||
return(filename);
|
||||
}
|
||||
set {
|
||||
filename=value;
|
||||
}
|
||||
}
|
||||
|
||||
public override AddressFamily AddressFamily {
|
||||
get { return 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 (socketAddress [1] != ((addr & 0xFF00) >> 8))
|
||||
throw new ArgumentException ("socketAddress is not a unix socket address.");
|
||||
*/
|
||||
|
||||
byte [] bytes = new byte [socketAddress.Size - 2];
|
||||
for (int i = 0; i < bytes.Length; i++) {
|
||||
bytes [i] = socketAddress [i + 2];
|
||||
}
|
||||
|
||||
string name = Encoding.Default.GetString (bytes);
|
||||
return new UnixEndPoint (name);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
Mono.Posix/Mono.Remoting.Channels.Unix/.gitattributes
vendored
Normal file
1
Mono.Posix/Mono.Remoting.Channels.Unix/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
/UnixConnectionPool.cs -crlf
|
@ -0,0 +1,167 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixBinaryClientFormatterSink.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Dietmar Maurer (dietmar@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// 2002 (C) Copyright, Ximian, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixBinaryClientFormatterSink : IClientFormatterSink, IMessageSink, IClientChannelSink, IChannelSinkBase
|
||||
{
|
||||
UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
|
||||
IClientChannelSink _nextInChain;
|
||||
|
||||
public UnixBinaryClientFormatterSink (IClientChannelSink nextSink)
|
||||
{
|
||||
_nextInChain = nextSink;
|
||||
}
|
||||
|
||||
internal UnixBinaryCore BinaryCore
|
||||
{
|
||||
get { return _binaryCore; }
|
||||
set { _binaryCore = value; }
|
||||
}
|
||||
|
||||
public IClientChannelSink NextChannelSink
|
||||
{
|
||||
get {
|
||||
return _nextInChain;
|
||||
}
|
||||
}
|
||||
|
||||
public IMessageSink NextSink
|
||||
{
|
||||
get {
|
||||
// This is the last sink in the IMessageSink sink chain
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary Properties
|
||||
{
|
||||
get {
|
||||
return 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)_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixBinaryClientFormatterSinkProvider.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ximian.com)
|
||||
//
|
||||
// 2002 (C) Copyright, Ximian, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixBinaryClientFormatterSinkProvider: IClientFormatterSinkProvider, IClientChannelSinkProvider
|
||||
{
|
||||
IClientChannelSinkProvider next = null;
|
||||
UnixBinaryCore _binaryCore;
|
||||
static string[] allowedProperties = new string [] { "includeVersions", "strictBinding" };
|
||||
|
||||
public UnixBinaryClientFormatterSinkProvider ()
|
||||
{
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
148
Mono.Posix/Mono.Remoting.Channels.Unix/UnixBinaryCore.cs
Normal file
148
Mono.Posix/Mono.Remoting.Channels.Unix/UnixBinaryCore.cs
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.BinaryCore.cs
|
||||
//
|
||||
// Author: Lluis Sanchez Gual (lluis@novell.com)
|
||||
//
|
||||
// 2005 (C) Copyright, Novell, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixBinaryCore
|
||||
{
|
||||
BinaryFormatter _serializationFormatter;
|
||||
BinaryFormatter _deserializationFormatter;
|
||||
bool _includeVersions = true;
|
||||
bool _strictBinding = false;
|
||||
IDictionary _properties;
|
||||
|
||||
public static UnixBinaryCore DefaultInstance = new UnixBinaryCore ();
|
||||
|
||||
public UnixBinaryCore (object owner, IDictionary properties, string[] allowedProperties)
|
||||
{
|
||||
_properties = properties;
|
||||
|
||||
foreach(DictionaryEntry property in properties)
|
||||
{
|
||||
string key = (string) property.Key;
|
||||
if (Array.IndexOf (allowedProperties, key) == -1)
|
||||
throw new RemotingException (owner.GetType().Name + " does not recognize '" + key + "' configuration property");
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case "includeVersions":
|
||||
_includeVersions = Convert.ToBoolean (property.Value);
|
||||
break;
|
||||
|
||||
case "strictBinding":
|
||||
_strictBinding = Convert.ToBoolean (property.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Init ();
|
||||
}
|
||||
|
||||
public UnixBinaryCore ()
|
||||
{
|
||||
_properties = new Hashtable ();
|
||||
Init ();
|
||||
}
|
||||
|
||||
public void Init ()
|
||||
{
|
||||
RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector ();
|
||||
StreamingContext context = new StreamingContext (StreamingContextStates.Remoting, null);
|
||||
|
||||
_serializationFormatter = new BinaryFormatter (surrogateSelector, context);
|
||||
_deserializationFormatter = new BinaryFormatter (null, context);
|
||||
|
||||
if (!_includeVersions)
|
||||
{
|
||||
_serializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
|
||||
_deserializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
|
||||
}
|
||||
|
||||
if (!_strictBinding)
|
||||
{
|
||||
_serializationFormatter.Binder = SimpleBinder.Instance;
|
||||
_deserializationFormatter.Binder = SimpleBinder.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
public BinaryFormatter Serializer
|
||||
{
|
||||
get { return _serializationFormatter; }
|
||||
}
|
||||
|
||||
public BinaryFormatter Deserializer
|
||||
{
|
||||
get { return _deserializationFormatter; }
|
||||
}
|
||||
|
||||
public IDictionary Properties
|
||||
{
|
||||
get { return _properties; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class SimpleBinder: SerializationBinder
|
||||
{
|
||||
public static SimpleBinder Instance = new SimpleBinder ();
|
||||
|
||||
public override Type BindToType (String assemblyName, string typeName)
|
||||
{
|
||||
Assembly asm;
|
||||
|
||||
if (assemblyName.IndexOf (',') != -1)
|
||||
{
|
||||
// Try using the full name
|
||||
try
|
||||
{
|
||||
asm = Assembly.Load (assemblyName);
|
||||
if (asm == null) return null;
|
||||
Type t = asm.GetType (typeName);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,163 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixBinaryServerFormatterSink.cs
|
||||
//
|
||||
// Author: Duncan Mak (duncan@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// 2002 (C) Copyright, Ximian, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix {
|
||||
|
||||
internal class UnixBinaryServerFormatterSink : IServerChannelSink, IChannelSinkBase
|
||||
{
|
||||
UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
|
||||
|
||||
IServerChannelSink next_sink;
|
||||
IChannelReceiver receiver;
|
||||
|
||||
public UnixBinaryServerFormatterSink (IServerChannelSink nextSink, IChannelReceiver receiver)
|
||||
{
|
||||
this.next_sink = nextSink;
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
internal UnixBinaryCore BinaryCore
|
||||
{
|
||||
get { return _binaryCore; }
|
||||
set { _binaryCore = value; }
|
||||
}
|
||||
|
||||
public IServerChannelSink NextChannelSink {
|
||||
get {
|
||||
return next_sink;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary Properties {
|
||||
get {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
|
||||
IMessage message, ITransportHeaders headers, Stream stream)
|
||||
{
|
||||
ITransportHeaders responseHeaders = new TransportHeaders();
|
||||
|
||||
if (sinkStack != null) stream = sinkStack.GetResponseStream (message, responseHeaders);
|
||||
if (stream == null) stream = new MemoryStream();
|
||||
|
||||
_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)
|
||||
{
|
||||
return 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixBinaryServerFormatterSinkProvider.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ximian.com)
|
||||
//
|
||||
// 2002 (C) Copyright, Ximian, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixBinaryServerFormatterSinkProvider: IServerFormatterSinkProvider, IServerChannelSinkProvider
|
||||
{
|
||||
IServerChannelSinkProvider next = null;
|
||||
UnixBinaryCore _binaryCore;
|
||||
|
||||
internal static string[] AllowedProperties = new string [] { "includeVersions", "strictBinding" };
|
||||
|
||||
public UnixBinaryServerFormatterSinkProvider ()
|
||||
{
|
||||
_binaryCore = UnixBinaryCore.DefaultInstance;
|
||||
}
|
||||
|
||||
public UnixBinaryServerFormatterSinkProvider (IDictionary properties, ICollection providerData)
|
||||
{
|
||||
_binaryCore = new UnixBinaryCore (this, properties, AllowedProperties);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
143
Mono.Posix/Mono.Remoting.Channels.Unix/UnixChannel.cs
Normal file
143
Mono.Posix/Mono.Remoting.Channels.Unix/UnixChannel.cs
Normal file
@ -0,0 +1,143 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixChannel.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
public class UnixChannel : IChannelReceiver, IChannel, IChannelSender
|
||||
{
|
||||
private UnixClientChannel _clientChannel;
|
||||
private UnixServerChannel _serverChannel = null;
|
||||
private string _name = "unix";
|
||||
private int _priority = 1;
|
||||
|
||||
public UnixChannel (): this (null)
|
||||
{
|
||||
}
|
||||
|
||||
public UnixChannel (string path)
|
||||
{
|
||||
Hashtable ht = new Hashtable();
|
||||
ht["path"] = path;
|
||||
Init(ht, null, null);
|
||||
}
|
||||
|
||||
void Init (IDictionary properties, IClientChannelSinkProvider clientSink, IServerChannelSinkProvider serverSink)
|
||||
{
|
||||
_clientChannel = new UnixClientChannel (properties,clientSink);
|
||||
|
||||
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)
|
||||
{
|
||||
if (_serverChannel != null) _serverChannel.StopListening(data);
|
||||
}
|
||||
|
||||
public string[] GetUrlsForUri (string uri)
|
||||
{
|
||||
if (_serverChannel != null) return _serverChannel.GetUrlsForUri(uri);
|
||||
else return null;
|
||||
}
|
||||
|
||||
public object ChannelData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_serverChannel != null) return _serverChannel.ChannelData;
|
||||
else return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string Parse (string url, out string objectURI)
|
||||
{
|
||||
return UnixChannel.ParseUnixURL (url, out objectURI);
|
||||
}
|
||||
|
||||
internal static string ParseUnixURL (string url, out string objectURI)
|
||||
{
|
||||
// format: "unix:///path/to/unix/socket?/path/to/object"
|
||||
|
||||
objectURI = null;
|
||||
|
||||
if (!url.StartsWith ("unix://")) return null;
|
||||
|
||||
int i = url.IndexOf ('?');
|
||||
if (i == -1) return url.Substring (7);
|
||||
|
||||
objectURI = url.Substring (i+1);
|
||||
|
||||
if (objectURI.Length == 0)
|
||||
objectURI = null;
|
||||
|
||||
return url.Substring (7, i - 7);
|
||||
}
|
||||
}
|
||||
}
|
134
Mono.Posix/Mono.Remoting.Channels.Unix/UnixClientChannel.cs
Normal file
134
Mono.Posix/Mono.Remoting.Channels.Unix/UnixClientChannel.cs
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixClientChannel.cs
|
||||
//
|
||||
// Author: Dietmar Maurer (dietmar@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@novell.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Threading;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
public class UnixClientChannel : IChannelSender, IChannel
|
||||
{
|
||||
int priority = 1;
|
||||
string name = "unix";
|
||||
IClientChannelSinkProvider _sinkProvider;
|
||||
|
||||
public UnixClientChannel ()
|
||||
{
|
||||
_sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
|
||||
_sinkProvider.Next = new UnixClientTransportSinkProvider ();
|
||||
}
|
||||
|
||||
public UnixClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
|
||||
{
|
||||
object val = properties ["name"];
|
||||
if (val != null) name = val as string;
|
||||
|
||||
val = properties ["priority"];
|
||||
if (val != null) priority = Convert.ToInt32 (val);
|
||||
|
||||
if (sinkProvider != null)
|
||||
{
|
||||
_sinkProvider = sinkProvider;
|
||||
|
||||
// add the unix provider at the end of the chain
|
||||
IClientChannelSinkProvider prov = sinkProvider;
|
||||
while (prov.Next != null) prov = prov.Next;
|
||||
prov.Next = new UnixClientTransportSinkProvider ();
|
||||
|
||||
// Note: a default formatter is added only when
|
||||
// no sink providers are specified in the config file.
|
||||
}
|
||||
else
|
||||
{
|
||||
_sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
|
||||
_sinkProvider.Next = new UnixClientTransportSinkProvider ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public UnixClientChannel (string name, IClientChannelSinkProvider sinkProvider)
|
||||
{
|
||||
this.name = name;
|
||||
_sinkProvider = sinkProvider;
|
||||
|
||||
// add the unix provider at the end of the chain
|
||||
IClientChannelSinkProvider prov = sinkProvider;
|
||||
while (prov.Next != null) prov = prov.Next;
|
||||
prov.Next = new UnixClientTransportSinkProvider ();
|
||||
}
|
||||
|
||||
public string ChannelName
|
||||
{
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (ds != null && ds.ChannelUris.Length > 0)
|
||||
url = ds.ChannelUris [0];
|
||||
else {
|
||||
objectURI = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (Parse (url, out objectURI) == null)
|
||||
return null;
|
||||
|
||||
return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
|
||||
}
|
||||
|
||||
public string Parse (string url, out string objectURI)
|
||||
{
|
||||
return UnixChannel.ParseUnixURL (url, out objectURI);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixClientTransportSink.cs
|
||||
//
|
||||
// Author: Dietmar Maurer (dietmar@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@novell.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Runtime.Remoting;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixClientTransportSink : IClientChannelSink
|
||||
{
|
||||
string _path;
|
||||
|
||||
public UnixClientTransportSink (string url)
|
||||
{
|
||||
string objectUri;
|
||||
_path = UnixChannel.ParseUnixURL (url, out objectUri);
|
||||
}
|
||||
|
||||
public IDictionary Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IClientChannelSink NextChannelSink
|
||||
{
|
||||
get
|
||||
{
|
||||
// we are the last one
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
|
||||
ITransportHeaders headers, Stream requestStream)
|
||||
{
|
||||
UnixConnection connection = null;
|
||||
bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
|
||||
|
||||
try
|
||||
{
|
||||
if (headers == null) headers = new TransportHeaders();
|
||||
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
|
||||
|
||||
connection = UnixConnectionPool.GetConnection (_path);
|
||||
UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
|
||||
connection.Stream.Flush ();
|
||||
|
||||
if (!isOneWay)
|
||||
{
|
||||
sinkStack.Push (this, connection);
|
||||
ThreadPool.QueueUserWorkItem (new WaitCallback(data => {
|
||||
try {
|
||||
ReadAsyncUnixMessage (data);
|
||||
} catch {}
|
||||
}), sinkStack);
|
||||
}
|
||||
else
|
||||
connection.Release();
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (connection != null) connection.Release();
|
||||
if (!isOneWay) throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadAsyncUnixMessage(object data)
|
||||
{
|
||||
// This method is called by a new thread to asynchronously
|
||||
// read the response to a request
|
||||
|
||||
// The stack was provided as state data in QueueUserWorkItem
|
||||
IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
|
||||
|
||||
// The first sink in the stack is this sink. Pop it and
|
||||
// get the status data, which is the UnixConnection used to send
|
||||
// the request
|
||||
UnixConnection connection = (UnixConnection)stack.Pop(this);
|
||||
|
||||
try
|
||||
{
|
||||
ITransportHeaders responseHeaders;
|
||||
|
||||
// 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 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixClientTransportSinkProvider.cs
|
||||
//
|
||||
// Author: Dietmar Maurer (dietmar@ximian.com)
|
||||
// Lluis Sanchez (lluis@novell.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixClientTransportSinkProvider : IClientChannelSinkProvider
|
||||
{
|
||||
public UnixClientTransportSinkProvider ()
|
||||
{
|
||||
// what should we do here ?
|
||||
}
|
||||
|
||||
public IClientChannelSinkProvider Next
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
// ignore, we are always the last in the chain
|
||||
}
|
||||
}
|
||||
|
||||
public IClientChannelSink CreateSink (IChannelSender channel, string url,
|
||||
object remoteChannelData)
|
||||
{
|
||||
return new UnixClientTransportSink (url);
|
||||
}
|
||||
}
|
||||
}
|
311
Mono.Posix/Mono.Remoting.Channels.Unix/UnixConnectionPool.cs
Normal file
311
Mono.Posix/Mono.Remoting.Channels.Unix/UnixConnectionPool.cs
Normal file
@ -0,0 +1,311 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixConnectionPool.cs
|
||||
//
|
||||
// Author: Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Remoting;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
// This is a pool of Unix connections. Connections requested
|
||||
// by the TCP channel are pooled after their use, and can
|
||||
// be reused later. Connections are automaticaly closed
|
||||
// if not used after some time, specified in KeepAliveSeconds.
|
||||
// The number of allowed open connections can also be specified
|
||||
// in MaxOpenConnections. The limit is per host.
|
||||
// If a thread requests a connection and the limit has been
|
||||
// reached, the thread is suspended until one is released.
|
||||
|
||||
internal class UnixConnectionPool
|
||||
{
|
||||
// Table of pools. There is a HostConnectionPool
|
||||
// instance for each host
|
||||
static Hashtable _pools = new Hashtable();
|
||||
|
||||
static int _maxOpenConnections = int.MaxValue;
|
||||
static int _keepAliveSeconds = 15;
|
||||
|
||||
static Thread _poolThread;
|
||||
|
||||
static UnixConnectionPool()
|
||||
{
|
||||
// This thread will close unused connections
|
||||
_poolThread = new Thread (new ThreadStart (ConnectionCollector));
|
||||
_poolThread.Start();
|
||||
_poolThread.IsBackground = true;
|
||||
}
|
||||
|
||||
public static void Shutdown ()
|
||||
{
|
||||
if (_poolThread != null)
|
||||
_poolThread.Abort();
|
||||
}
|
||||
|
||||
public static int MaxOpenConnections
|
||||
{
|
||||
get { return _maxOpenConnections; }
|
||||
set
|
||||
{
|
||||
if (value < 1) throw new RemotingException ("MaxOpenConnections must be greater than zero");
|
||||
_maxOpenConnections = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static int KeepAliveSeconds
|
||||
{
|
||||
get { return _keepAliveSeconds; }
|
||||
set { _keepAliveSeconds = value; }
|
||||
}
|
||||
|
||||
public static UnixConnection GetConnection (string path)
|
||||
{
|
||||
HostConnectionPool hostPool;
|
||||
|
||||
lock (_pools)
|
||||
{
|
||||
hostPool = (HostConnectionPool) _pools[path];
|
||||
if (hostPool == null)
|
||||
{
|
||||
hostPool = new HostConnectionPool(path);
|
||||
_pools[path] = hostPool;
|
||||
}
|
||||
}
|
||||
|
||||
return hostPool.GetConnection();
|
||||
}
|
||||
|
||||
private static void ConnectionCollector ()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(3000);
|
||||
lock (_pools)
|
||||
{
|
||||
ICollection values = _pools.Values;
|
||||
foreach (HostConnectionPool pool in values)
|
||||
pool.PurgeConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReusableUnixClient : UnixClient
|
||||
{
|
||||
public ReusableUnixClient (string path): base (path)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
// 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
|
||||
{
|
||||
DateTime _controlTime;
|
||||
Stream _stream;
|
||||
ReusableUnixClient _client;
|
||||
HostConnectionPool _pool;
|
||||
byte[] _buffer;
|
||||
|
||||
public UnixConnection (HostConnectionPool pool, ReusableUnixClient client)
|
||||
{
|
||||
_pool = pool;
|
||||
_client = client;
|
||||
_stream = new BufferedStream (client.GetStream());
|
||||
_controlTime = DateTime.UtcNow;
|
||||
_buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
|
||||
}
|
||||
|
||||
public Stream Stream
|
||||
{
|
||||
get { return _stream; }
|
||||
}
|
||||
|
||||
public DateTime ControlTime
|
||||
{
|
||||
get { return _controlTime; }
|
||||
set { _controlTime = value; }
|
||||
}
|
||||
|
||||
public bool IsAlive
|
||||
{
|
||||
get { return _client.IsAlive; }
|
||||
}
|
||||
|
||||
// This is a "thread safe" buffer that can be used by
|
||||
// UnixClientTransportSink to read or send data to the stream.
|
||||
// The buffer is "thread safe" since only one thread can
|
||||
// use a connection at a given time.
|
||||
public byte[] Buffer
|
||||
{
|
||||
get { return _buffer; }
|
||||
}
|
||||
|
||||
// Returns the connection to the pool
|
||||
public void Release()
|
||||
{
|
||||
_pool.ReleaseConnection (this);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_client.Close();
|
||||
}
|
||||
}
|
||||
|
||||
internal class HostConnectionPool
|
||||
{
|
||||
ArrayList _pool = new ArrayList();
|
||||
int _activeConnections = 0;
|
||||
|
||||
string _path;
|
||||
|
||||
public HostConnectionPool (string path)
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public UnixConnection GetConnection ()
|
||||
{
|
||||
UnixConnection connection = null;
|
||||
lock (_pool)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (_pool.Count > 0)
|
||||
{
|
||||
// There are available connections
|
||||
|
||||
connection = (UnixConnection)_pool[_pool.Count - 1];
|
||||
_pool.RemoveAt(_pool.Count - 1);
|
||||
if (!connection.IsAlive) {
|
||||
CancelConnection (connection);
|
||||
connection = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (connection == null && _activeConnections < UnixConnectionPool.MaxOpenConnections)
|
||||
{
|
||||
// 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
|
||||
break;
|
||||
}
|
||||
|
||||
// No available connections in the pool
|
||||
// Wait for somewone to release one.
|
||||
|
||||
if (connection == null)
|
||||
{
|
||||
Monitor.Wait(_pool);
|
||||
}
|
||||
}
|
||||
while (connection == null);
|
||||
}
|
||||
|
||||
if (connection == null)
|
||||
return CreateConnection ();
|
||||
else
|
||||
return connection;
|
||||
}
|
||||
|
||||
private UnixConnection CreateConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
ReusableUnixClient client = new ReusableUnixClient (_path);
|
||||
UnixConnection entry = new UnixConnection(this, client);
|
||||
_activeConnections++;
|
||||
return entry;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new RemotingException (ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseConnection (UnixConnection entry)
|
||||
{
|
||||
lock (_pool)
|
||||
{
|
||||
entry.ControlTime = DateTime.UtcNow; // Initialize timeout
|
||||
_pool.Add (entry);
|
||||
Monitor.Pulse (_pool);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelConnection(UnixConnection entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
entry.Stream.Close();
|
||||
_activeConnections--;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void PurgeConnections()
|
||||
{
|
||||
lock (_pool)
|
||||
{
|
||||
for (int n=0; n < _pool.Count; n++)
|
||||
{
|
||||
UnixConnection entry = (UnixConnection)_pool[n];
|
||||
if ( (DateTime.UtcNow - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)
|
||||
{
|
||||
CancelConnection (entry);
|
||||
_pool.RemoveAt(n);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
283
Mono.Posix/Mono.Remoting.Channels.Unix/UnixMessageIO.cs
Normal file
283
Mono.Posix/Mono.Remoting.Channels.Unix/UnixMessageIO.cs
Normal file
@ -0,0 +1,283 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixMessageIO.cs
|
||||
//
|
||||
// Author: Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using System.Runtime.Remoting;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
enum MessageStatus { MethodMessage = 0, CancelSignal = 1, Unknown = 10}
|
||||
|
||||
internal class UnixMessageIO
|
||||
{
|
||||
static byte[][] _msgHeaders =
|
||||
{
|
||||
new byte[] { (byte)'.', (byte)'N', (byte)'E', (byte)'T', 1, 0 },
|
||||
new byte[] { 255, 255, 255, 255, 255, 255 }
|
||||
};
|
||||
|
||||
public static int DefaultStreamBufferSize = 1000;
|
||||
|
||||
// Identifies an incoming message
|
||||
public static MessageStatus ReceiveMessageStatus (Stream networkStream, byte[] buffer)
|
||||
{
|
||||
try {
|
||||
StreamRead (networkStream, buffer, 6);
|
||||
} catch (Exception ex) {
|
||||
throw new RemotingException ("Unix transport error.", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool[] isOnTrack = new bool[_msgHeaders.Length];
|
||||
bool atLeastOneOnTrack = true;
|
||||
int i = 0;
|
||||
|
||||
while (atLeastOneOnTrack)
|
||||
{
|
||||
atLeastOneOnTrack = false;
|
||||
byte c = buffer [i];
|
||||
for (int n = 0; n<_msgHeaders.Length; n++)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
|
||||
|
||||
// Writes the message start header
|
||||
byte[] dotnetHeader = _msgHeaders[(int) MessageStatus.MethodMessage];
|
||||
networkStream.Write(dotnetHeader, 0, dotnetHeader.Length);
|
||||
|
||||
// Writes header tag (0x0000 if request stream, 0x0002 if response stream)
|
||||
if(requestHeaders["__RequestUri"]!=null) buffer [0] = (byte) 0;
|
||||
else buffer[0] = (byte) 2;
|
||||
buffer [1] = (byte) 0 ;
|
||||
|
||||
// Writes ID
|
||||
buffer [2] = (byte) 0;
|
||||
|
||||
// Writes assemblyID????
|
||||
buffer [3] = (byte) 0;
|
||||
|
||||
// Writes the length of the stream being sent (not including the headers)
|
||||
int num = (int)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 the stream
|
||||
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, (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)
|
||||
{
|
||||
// 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 ();
|
||||
|
||||
while (headerType != 0)
|
||||
{
|
||||
string key;
|
||||
StreamRead (networkStream, buffer, 1); // byte 1
|
||||
switch (headerType)
|
||||
{
|
||||
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);
|
||||
headerType = buffer [0];
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
public static Stream ReceiveMessageStream (Stream networkStream, out ITransportHeaders headers, byte[] buffer)
|
||||
{
|
||||
headers = null;
|
||||
|
||||
if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
|
||||
|
||||
// Reads header tag: 0 -> Stream with headers or 2 -> Response Stream
|
||||
// +
|
||||
// Gets the length of the data stream
|
||||
StreamRead (networkStream, buffer, 8);
|
||||
|
||||
int byteCount = (buffer [4] | (buffer [5] << 8) |
|
||||
(buffer [6] << 16) | (buffer [7] << 24));
|
||||
|
||||
// Reads the headers
|
||||
headers = ReceiveHeaders (networkStream, buffer);
|
||||
|
||||
byte[] resultBuffer = new byte[byteCount];
|
||||
StreamRead (networkStream, resultBuffer, byteCount);
|
||||
|
||||
return new MemoryStream (resultBuffer);
|
||||
}
|
||||
|
||||
private static void SendString (Stream networkStream, string str, byte[] buffer)
|
||||
{
|
||||
// Allocates a buffer. Use the internal buffer if it is
|
||||
// big enough. If not, create a new one.
|
||||
|
||||
int maxBytes = Encoding.UTF8.GetMaxByteCount(str.Length)+4; //+4 bytes for storing the string length
|
||||
if (maxBytes > buffer.Length)
|
||||
buffer = new byte[maxBytes];
|
||||
|
||||
int num = Encoding.UTF8.GetBytes (str, 0, str.Length, buffer, 4);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
330
Mono.Posix/Mono.Remoting.Channels.Unix/UnixServerChannel.cs
Normal file
330
Mono.Posix/Mono.Remoting.Channels.Unix/UnixServerChannel.cs
Normal file
@ -0,0 +1,330 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixServerChannel.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Lluis Sanchez Gual (lluis@ideary.com)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
public class UnixServerChannel : IChannelReceiver, IChannel
|
||||
{
|
||||
string path = null;
|
||||
string name = "unix";
|
||||
|
||||
int priority = 1;
|
||||
bool supressChannelData = false;
|
||||
|
||||
Thread server_thread = null;
|
||||
UnixListener listener;
|
||||
UnixServerTransportSink sink;
|
||||
ChannelDataStore channel_data;
|
||||
int _maxConcurrentConnections = 100;
|
||||
ArrayList _activeConnections = new ArrayList();
|
||||
|
||||
|
||||
void Init (IServerChannelSinkProvider serverSinkProvider)
|
||||
{
|
||||
if (serverSinkProvider == null)
|
||||
{
|
||||
serverSinkProvider = new UnixBinaryServerFormatterSinkProvider ();
|
||||
}
|
||||
|
||||
// Gets channel data from the chain of channel providers
|
||||
|
||||
channel_data = new ChannelDataStore (null);
|
||||
IServerChannelSinkProvider provider = serverSinkProvider;
|
||||
while (provider != null)
|
||||
{
|
||||
provider.GetChannelData(channel_data);
|
||||
provider = provider.Next;
|
||||
}
|
||||
|
||||
// Creates the sink chain that will process all incoming messages
|
||||
|
||||
IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
|
||||
sink = new UnixServerTransportSink (next_sink);
|
||||
|
||||
StartListening (null);
|
||||
}
|
||||
|
||||
public UnixServerChannel (string path)
|
||||
{
|
||||
this.path = path;
|
||||
Init (null);
|
||||
}
|
||||
|
||||
public UnixServerChannel (IDictionary properties,
|
||||
IServerChannelSinkProvider serverSinkProvider)
|
||||
{
|
||||
foreach(DictionaryEntry property in properties)
|
||||
{
|
||||
switch((string)property.Key)
|
||||
{
|
||||
case "path":
|
||||
path = property.Value as string;
|
||||
break;
|
||||
case "priority":
|
||||
priority = Convert.ToInt32(property.Value);
|
||||
break;
|
||||
case "supressChannelData":
|
||||
supressChannelData = Convert.ToBoolean (property.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Init (serverSinkProvider);
|
||||
}
|
||||
|
||||
public UnixServerChannel (string name, string path,
|
||||
IServerChannelSinkProvider serverSinkProvider)
|
||||
{
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
Init (serverSinkProvider);
|
||||
}
|
||||
|
||||
public UnixServerChannel (string name, string path)
|
||||
{
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
Init (null);
|
||||
}
|
||||
|
||||
public object ChannelData
|
||||
{
|
||||
get {
|
||||
if (supressChannelData) return null;
|
||||
else return channel_data;
|
||||
}
|
||||
}
|
||||
|
||||
public string ChannelName
|
||||
{
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public int ChannelPriority
|
||||
{
|
||||
get {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetChannelUri ()
|
||||
{
|
||||
return "unix://" + path;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Socket client = listener.AcceptSocket ();
|
||||
CreateListenerConnection (client);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{}
|
||||
}
|
||||
|
||||
internal void CreateListenerConnection (Socket client)
|
||||
{
|
||||
lock (_activeConnections)
|
||||
{
|
||||
if (_activeConnections.Count >= _maxConcurrentConnections)
|
||||
Monitor.Wait (_activeConnections);
|
||||
|
||||
if (server_thread == null) return; // Server was stopped while waiting
|
||||
|
||||
ClientConnection reader = new ClientConnection (this, client, sink);
|
||||
Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
|
||||
thread.Start();
|
||||
thread.IsBackground = true;
|
||||
_activeConnections.Add (thread);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ReleaseConnection (Thread thread)
|
||||
{
|
||||
lock (_activeConnections)
|
||||
{
|
||||
_activeConnections.Remove (thread);
|
||||
Monitor.Pulse (_activeConnections);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartListening (object data)
|
||||
{
|
||||
listener = new UnixListener (path);
|
||||
Mono.Unix.Native.Syscall.chmod (path,
|
||||
Mono.Unix.Native.FilePermissions.S_IRUSR |
|
||||
Mono.Unix.Native.FilePermissions.S_IWUSR |
|
||||
Mono.Unix.Native.FilePermissions.S_IRGRP |
|
||||
Mono.Unix.Native.FilePermissions.S_IWGRP |
|
||||
Mono.Unix.Native.FilePermissions.S_IROTH |
|
||||
Mono.Unix.Native.FilePermissions.S_IWOTH);
|
||||
|
||||
if (server_thread == null)
|
||||
{
|
||||
listener.Start ();
|
||||
|
||||
string[] uris = new String [1];
|
||||
uris = new String [1];
|
||||
uris [0] = GetChannelUri ();
|
||||
channel_data.ChannelUris = uris;
|
||||
|
||||
server_thread = new Thread (new ThreadStart (WaitForConnections));
|
||||
server_thread.IsBackground = true;
|
||||
server_thread.Start ();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopListening (object data)
|
||||
{
|
||||
if (server_thread == null) return;
|
||||
|
||||
lock (_activeConnections)
|
||||
{
|
||||
server_thread.Abort ();
|
||||
server_thread = null;
|
||||
listener.Stop ();
|
||||
|
||||
foreach (Thread thread in _activeConnections)
|
||||
thread.Abort();
|
||||
|
||||
_activeConnections.Clear();
|
||||
Monitor.PulseAll (_activeConnections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ClientConnection
|
||||
{
|
||||
Socket _client;
|
||||
UnixServerTransportSink _sink;
|
||||
Stream _stream;
|
||||
UnixServerChannel _serverChannel;
|
||||
|
||||
byte[] _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
|
||||
|
||||
public ClientConnection (UnixServerChannel serverChannel, Socket client, UnixServerTransportSink sink)
|
||||
{
|
||||
_serverChannel = serverChannel;
|
||||
_client = client;
|
||||
_sink = sink;
|
||||
}
|
||||
|
||||
public Socket Client {
|
||||
get { return _client; }
|
||||
}
|
||||
|
||||
public byte[] Buffer
|
||||
{
|
||||
get { return _buffer; }
|
||||
}
|
||||
|
||||
public void ProcessMessages()
|
||||
{
|
||||
byte[] buffer = new byte[256];
|
||||
_stream = new BufferedStream (new NetworkStream (_client));
|
||||
|
||||
try
|
||||
{
|
||||
bool end = false;
|
||||
while (!end)
|
||||
{
|
||||
MessageStatus type = UnixMessageIO.ReceiveMessageStatus (_stream, buffer);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MessageStatus.MethodMessage:
|
||||
_sink.InternalProcessMessage (this, _stream);
|
||||
break;
|
||||
|
||||
case MessageStatus.Unknown:
|
||||
case MessageStatus.CancelSignal:
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Console.WriteLine (ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try {
|
||||
_serverChannel.ReleaseConnection (Thread.CurrentThread);
|
||||
_stream.Close();
|
||||
_client.Close ();
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsLocal
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Mono.Remoting.Channels.Unix.UnixServerTransportSink.cs
|
||||
//
|
||||
// Author: Rodrigo Moya (rodrigo@ximian.com)
|
||||
// Lluis Sanchez Gual (lsg@ctv.es)
|
||||
//
|
||||
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.IO;
|
||||
using System.Runtime.Remoting.Channels;
|
||||
|
||||
namespace Mono.Remoting.Channels.Unix
|
||||
{
|
||||
internal class UnixServerTransportSink : IServerChannelSink, IChannelSinkBase
|
||||
{
|
||||
IServerChannelSink next_sink;
|
||||
|
||||
public UnixServerTransportSink (IServerChannelSink next)
|
||||
{
|
||||
next_sink = next;
|
||||
}
|
||||
|
||||
public IServerChannelSink NextChannelSink
|
||||
{
|
||||
get
|
||||
{
|
||||
return next_sink;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (next_sink != null) return next_sink.Properties;
|
||||
else return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
|
||||
IMessage msg, ITransportHeaders headers, Stream responseStream)
|
||||
{
|
||||
ClientConnection connection = (ClientConnection)state;
|
||||
NetworkStream stream = new NetworkStream (connection.Client);
|
||||
UnixMessageIO.SendMessageStream (stream, responseStream, headers, connection.Buffer);
|
||||
stream.Flush ();
|
||||
stream.Close ();
|
||||
}
|
||||
|
||||
public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
|
||||
IMessage msg, ITransportHeaders headers)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
|
||||
IMessage requestMsg,
|
||||
ITransportHeaders requestHeaders,
|
||||
Stream requestStream,
|
||||
out IMessage responseMsg,
|
||||
out ITransportHeaders responseHeaders,
|
||||
out Stream responseStream)
|
||||
{
|
||||
// this is the first sink, and UnixServerChannel does not call it.
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
internal void InternalProcessMessage (ClientConnection connection, Stream stream)
|
||||
{
|
||||
// Reads the headers and the request stream
|
||||
|
||||
Stream requestStream;
|
||||
ITransportHeaders requestHeaders;
|
||||
|
||||
requestStream = UnixMessageIO.ReceiveMessageStream (stream, out requestHeaders, connection.Buffer);
|
||||
|
||||
/* try {
|
||||
PeerCred cred = connection.Client.PeerCredential;
|
||||
requestHeaders["__uid"] = cred.UserID;
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine ("Couldn't get the peer cred: " + e);
|
||||
}
|
||||
*/
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
188
Mono.Posix/Mono.Unix.Native/CdeclFunction.cs
Normal file
188
Mono.Posix/Mono.Unix.Native/CdeclFunction.cs
Normal file
@ -0,0 +1,188 @@
|
||||
//
|
||||
// Mono.Unix/CdeclFunction.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Unix.Native {
|
||||
|
||||
// This class represents a single unmanaged function with "cdecl" calling
|
||||
// convention -- that is, it can accept a variable number of arguments which
|
||||
// are passed on the runtime stack.
|
||||
//
|
||||
// To use, create an instance:
|
||||
//
|
||||
// CdeclFunction printf = new CdeclFunction ("the library",
|
||||
// "the function name", /* optional */ typeof (ReturnType));
|
||||
//
|
||||
// Then call the Invoke method with the appropriate number of arguments:
|
||||
//
|
||||
// printf.Invoke (new object[]{"hello, %s\n", "world!"});
|
||||
//
|
||||
// In the background a P/Invoke definition for the method with the
|
||||
// requested argument types will be generated and invoked, invoking the
|
||||
// unmanaged function. The generated methods are cached, so that subsequent
|
||||
// calls with the same argument list do not generate new code, speeding up
|
||||
// the call sequence.
|
||||
//
|
||||
// Invoking Cdecl functions is not guaranteed to be portable across all
|
||||
// platforms. For example, AMD64 requires that the caller set EAX to the
|
||||
// number of floating point arguments passed in the SSE registers. This
|
||||
// is only required for variable argument/cdecl functions; consequently,
|
||||
// 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
|
||||
// invocations, allowing CdeclFunction to work properly, but it will not
|
||||
// necessarily always work. See also:
|
||||
//
|
||||
// http://lwn.net/Articles/5201/?format=printable
|
||||
//
|
||||
// Due to potential portability issues, cdecl functions should be avoided
|
||||
// on most platforms.
|
||||
//
|
||||
// This class is intended to be thread-safe.
|
||||
public sealed class CdeclFunction
|
||||
{
|
||||
// The readonly fields (1) shouldn't be modified, and (2) should only be
|
||||
// used when `overloads' is locked.
|
||||
private readonly string library;
|
||||
private readonly string method;
|
||||
private readonly Type returnType;
|
||||
private readonly AssemblyName assemblyName;
|
||||
private readonly AssemblyBuilder assemblyBuilder;
|
||||
private readonly ModuleBuilder moduleBuilder;
|
||||
|
||||
private Hashtable overloads;
|
||||
|
||||
public CdeclFunction (string library, string method)
|
||||
: this (library, method, typeof(void))
|
||||
{
|
||||
}
|
||||
|
||||
public CdeclFunction (string library, string method, Type returnType)
|
||||
{
|
||||
this.library = library;
|
||||
this.method = method;
|
||||
this.returnType = returnType;
|
||||
this.overloads = new Hashtable ();
|
||||
this.assemblyName = new AssemblyName ();
|
||||
this.assemblyName.Name = "Mono.Posix.Imports." + library;
|
||||
this.assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
|
||||
assemblyName, AssemblyBuilderAccess.Run);
|
||||
this.moduleBuilder = assemblyBuilder.DefineDynamicModule (assemblyName.Name);
|
||||
}
|
||||
|
||||
public object Invoke (object[] parameters)
|
||||
{
|
||||
Type[] parameterTypes = GetParameterTypes (parameters);
|
||||
MethodInfo m = CreateMethod (parameterTypes);
|
||||
return m.Invoke (null, parameters);
|
||||
}
|
||||
|
||||
private MethodInfo CreateMethod (Type[] parameterTypes)
|
||||
{
|
||||
string typeName = GetTypeName (parameterTypes);
|
||||
|
||||
lock (overloads) {
|
||||
MethodInfo mi = (MethodInfo) overloads [typeName];
|
||||
|
||||
if (mi != null) {
|
||||
return mi;
|
||||
}
|
||||
|
||||
TypeBuilder tb = CreateType (typeName);
|
||||
/* MethodBuilder mb = */ tb.DefinePInvokeMethod (
|
||||
method,
|
||||
library,
|
||||
MethodAttributes.PinvokeImpl | MethodAttributes.Static | MethodAttributes.Public,
|
||||
CallingConventions.Standard,
|
||||
returnType,
|
||||
parameterTypes,
|
||||
CallingConvention.Cdecl,
|
||||
CharSet.Ansi);
|
||||
mi = tb.CreateType ().GetMethod (method);
|
||||
overloads.Add (typeName, mi);
|
||||
return mi;
|
||||
}
|
||||
}
|
||||
|
||||
private TypeBuilder CreateType (string typeName)
|
||||
{
|
||||
return 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(int);
|
||||
case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32:
|
||||
return typeof(uint);
|
||||
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)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
|
||||
sb.Append ("[").Append (library).Append ("] ").Append (method);
|
||||
sb.Append ("(");
|
||||
|
||||
if (parameterTypes.Length > 0)
|
||||
sb.Append (parameterTypes [0]);
|
||||
for (int i = 1; i < parameterTypes.Length; ++i)
|
||||
sb.Append (",").Append (parameterTypes [i]);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
79
Mono.Posix/Mono.Unix.Native/FileNameMarshaler.cs
Normal file
79
Mono.Posix/Mono.Unix.Native/FileNameMarshaler.cs
Normal file
@ -0,0 +1,79 @@
|
||||
//
|
||||
// Mono.Unix/FileNameMarshaler.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix.Native {
|
||||
|
||||
class FileNameMarshaler : ICustomMarshaler {
|
||||
|
||||
private static FileNameMarshaler Instance = new FileNameMarshaler ();
|
||||
|
||||
public static ICustomMarshaler GetInstance (string s)
|
||||
{
|
||||
return Instance;
|
||||
}
|
||||
|
||||
public void CleanUpManagedData (object o)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
60
Mono.Posix/Mono.Unix.Native/MapAttribute.cs
Normal file
60
Mono.Posix/Mono.Unix.Native/MapAttribute.cs
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// MapAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Miguel de Icaza (miguel@gnome.org)
|
||||
//
|
||||
// (C) Novell, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
|
||||
[AttributeUsage (
|
||||
AttributeTargets.Class |
|
||||
AttributeTargets.Delegate |
|
||||
AttributeTargets.Enum |
|
||||
AttributeTargets.Field |
|
||||
AttributeTargets.Struct)]
|
||||
internal class MapAttribute : Attribute {
|
||||
private string nativeType;
|
||||
private string suppressFlags;
|
||||
|
||||
public MapAttribute ()
|
||||
{
|
||||
}
|
||||
|
||||
public MapAttribute (string nativeType)
|
||||
{
|
||||
this.nativeType = nativeType;
|
||||
}
|
||||
|
||||
public string NativeType {
|
||||
get {return nativeType;}
|
||||
}
|
||||
|
||||
public string SuppressFlags {
|
||||
get {return suppressFlags;}
|
||||
set {suppressFlags = value;}
|
||||
}
|
||||
}
|
||||
|
488
Mono.Posix/Mono.Unix.Native/NativeConvert.cs
Normal file
488
Mono.Posix/Mono.Unix.Native/NativeConvert.cs
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* This file was automatically generated by make-map from Mono.Posix.dll.
|
||||
*
|
||||
* DO NOT MODIFY.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Mono.Unix.Native;
|
||||
#if MONODROID
|
||||
using Mono.Unix.Android;
|
||||
#endif
|
||||
|
||||
namespace Mono.Unix.Native {
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public sealed /* static */ partial class NativeConvert
|
||||
{
|
||||
//
|
||||
// Non-generated exports
|
||||
//
|
||||
#if MONODROID
|
||||
[DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
|
||||
static extern int HelperFromRealTimeSignum (Int32 offset, out Int32 rval);
|
||||
|
||||
static int FromRealTimeSignum (Int32 offset, out Int32 rval)
|
||||
{
|
||||
if (!AndroidUtils.AreRealTimeSignalsSafe ())
|
||||
throw new PlatformNotSupportedException ("Real-time signals are not supported on this Android architecture");
|
||||
return HelperFromRealTimeSignum (offset, out rval);
|
||||
}
|
||||
#else
|
||||
[DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
|
||||
private static extern int FromRealTimeSignum (Int32 offset, out Int32 rval);
|
||||
#endif
|
||||
// convert a realtime signal to os signal
|
||||
public static int FromRealTimeSignum (RealTimeSignum sig)
|
||||
{
|
||||
int sigNum;
|
||||
if (FromRealTimeSignum (sig.Offset, out sigNum) == -1)
|
||||
ThrowArgumentException (sig.Offset);
|
||||
return sigNum;
|
||||
}
|
||||
|
||||
// convert an offset to an rt signum
|
||||
public static RealTimeSignum ToRealTimeSignum (int offset)
|
||||
{
|
||||
return new RealTimeSignum (offset);
|
||||
}
|
||||
|
||||
// convert from octal representation.
|
||||
public static FilePermissions FromOctalPermissionString (string value)
|
||||
{
|
||||
uint n = Convert.ToUInt32 (value, 8);
|
||||
return ToFilePermissions (n);
|
||||
}
|
||||
|
||||
public static string ToOctalPermissionString (FilePermissions value)
|
||||
{
|
||||
string s = Convert.ToString ((int) (value & ~FilePermissions.S_IFMT), 8);
|
||||
return new string ('0', 4-s.Length) + s;
|
||||
}
|
||||
|
||||
public static FilePermissions FromUnixPermissionString (string value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
if (value.Length != 9 && value.Length != 10)
|
||||
throw new ArgumentException ("value", "must contain 9 or 10 characters");
|
||||
|
||||
int i = 0;
|
||||
FilePermissions perms = new FilePermissions ();
|
||||
|
||||
if (value.Length == 10) {
|
||||
perms |= GetUnixPermissionDevice (value [i]);
|
||||
++i;
|
||||
}
|
||||
|
||||
perms |= GetUnixPermissionGroup (
|
||||
value [i++], FilePermissions.S_IRUSR,
|
||||
value [i++], FilePermissions.S_IWUSR,
|
||||
value [i++], FilePermissions.S_IXUSR,
|
||||
's', 'S', FilePermissions.S_ISUID);
|
||||
|
||||
perms |= GetUnixPermissionGroup (
|
||||
value [i++], FilePermissions.S_IRGRP,
|
||||
value [i++], FilePermissions.S_IWGRP,
|
||||
value [i++], FilePermissions.S_IXGRP,
|
||||
's', 'S', FilePermissions.S_ISGID);
|
||||
|
||||
perms |= GetUnixPermissionGroup (
|
||||
value [i++], FilePermissions.S_IROTH,
|
||||
value [i++], FilePermissions.S_IWOTH,
|
||||
value [i++], FilePermissions.S_IXOTH,
|
||||
't', 'T', FilePermissions.S_ISVTX);
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
private static FilePermissions GetUnixPermissionDevice (char value)
|
||||
{
|
||||
switch (value) {
|
||||
case 'd': return FilePermissions.S_IFDIR;
|
||||
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);
|
||||
}
|
||||
|
||||
private static FilePermissions GetUnixPermissionGroup (
|
||||
char read, FilePermissions readb,
|
||||
char write, FilePermissions writeb,
|
||||
char exec, FilePermissions execb,
|
||||
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;
|
||||
}
|
||||
|
||||
// Create ls(1) drwxrwxrwx permissions display
|
||||
public static string ToUnixPermissionString (FilePermissions value)
|
||||
{
|
||||
char [] access = new char[] {
|
||||
'-', // device
|
||||
'-', '-', '-', // owner
|
||||
'-', '-', '-', // group
|
||||
'-', '-', '-', // other
|
||||
};
|
||||
bool 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 void SetUnixPermissionGroup (FilePermissions value,
|
||||
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`,
|
||||
// section 10.1.2, the `-l' argument information.
|
||||
private static char GetSymbolicMode (FilePermissions value,
|
||||
FilePermissions xbit, char both, char setonly, FilePermissions setxbit)
|
||||
{
|
||||
bool is_x = UnixFileSystemInfo.IsSet (value, xbit);
|
||||
bool is_sx = UnixFileSystemInfo.IsSet (value, setxbit);
|
||||
|
||||
if (is_x && is_sx)
|
||||
return both;
|
||||
if (is_sx)
|
||||
return setonly;
|
||||
if (is_x)
|
||||
return 'x';
|
||||
return '-';
|
||||
}
|
||||
|
||||
public static readonly DateTime UnixEpoch =
|
||||
new DateTime (year:1970, month:1, day:1, hour:0, minute:0, second:0, kind:DateTimeKind.Utc);
|
||||
public static readonly DateTime LocalUnixEpoch =
|
||||
new DateTime (1970, 1, 1);
|
||||
public static readonly TimeSpan LocalUtcOffset =
|
||||
TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.UtcNow);
|
||||
|
||||
public static DateTime ToDateTime (long time)
|
||||
{
|
||||
return FromTimeT (time);
|
||||
}
|
||||
|
||||
public static DateTime ToDateTime (long time, long nanoTime)
|
||||
{
|
||||
return FromTimeT (time).AddMilliseconds (nanoTime / 1000);
|
||||
}
|
||||
|
||||
public static long FromDateTime (DateTime time)
|
||||
{
|
||||
return ToTimeT (time);
|
||||
}
|
||||
|
||||
public static DateTime FromTimeT (long time)
|
||||
{
|
||||
return UnixEpoch.AddSeconds (time).ToLocalTime ();
|
||||
}
|
||||
|
||||
public static long 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 (long) (time - UnixEpoch).TotalSeconds;
|
||||
}
|
||||
|
||||
public static OpenFlags ToOpenFlags (FileMode mode, FileAccess access)
|
||||
{
|
||||
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?
|
||||
int _v;
|
||||
if (TryFromOpenFlags (OpenFlags.O_LARGEFILE, out _v))
|
||||
flags |= OpenFlags.O_LARGEFILE;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static string ToFopenMode (FileAccess access)
|
||||
{
|
||||
switch (access) {
|
||||
case FileAccess.Read: return "rb";
|
||||
case FileAccess.Write: return "wb";
|
||||
case FileAccess.ReadWrite: return "r+b";
|
||||
default: throw new ArgumentOutOfRangeException ("access");
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToFopenMode (FileMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case FileMode.CreateNew: case FileMode.Create: return "w+b";
|
||||
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
|
||||
// Local Variables:
|
||||
// tab-width: 4
|
||||
// c-basic-offset: 4
|
||||
// indent-tabs-mode: t
|
||||
// End:
|
1451
Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs
Normal file
1451
Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs
Normal file
File diff suppressed because it is too large
Load Diff
81
Mono.Posix/Mono.Unix.Native/RealTimeSignum.cs
Normal file
81
Mono.Posix/Mono.Unix.Native/RealTimeSignum.cs
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Authors:
|
||||
// Tim Jenks (tim.jenks@realtimeworlds.com)
|
||||
//
|
||||
// (C) 2008 Realtime Worlds Ltd
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Mono.Unix.Native {
|
||||
|
||||
public struct RealTimeSignum
|
||||
: IEquatable <RealTimeSignum>
|
||||
{
|
||||
private int rt_offset;
|
||||
private static readonly int MaxOffset = UnixSignal.GetSIGRTMAX () - UnixSignal.GetSIGRTMIN () - 1;
|
||||
public static readonly RealTimeSignum MinValue = new RealTimeSignum (0);
|
||||
public static readonly RealTimeSignum MaxValue = new RealTimeSignum (MaxOffset);
|
||||
|
||||
public RealTimeSignum (int offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException ("Offset cannot be negative");
|
||||
if (offset > MaxOffset)
|
||||
throw new ArgumentOutOfRangeException ("Offset greater than maximum supported SIGRT");
|
||||
rt_offset = offset;
|
||||
}
|
||||
|
||||
public int Offset {
|
||||
get { return rt_offset; }
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return rt_offset.GetHashCode ();
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if ((obj == null) || (obj.GetType () != GetType ()))
|
||||
return false;
|
||||
return Equals ((RealTimeSignum)obj);
|
||||
}
|
||||
|
||||
public bool Equals (RealTimeSignum value)
|
||||
{
|
||||
return Offset == value.Offset;
|
||||
}
|
||||
|
||||
public static bool operator== (RealTimeSignum lhs, RealTimeSignum rhs)
|
||||
{
|
||||
return lhs.Equals (rhs);
|
||||
}
|
||||
|
||||
public static bool operator!= (RealTimeSignum lhs, RealTimeSignum rhs)
|
||||
{
|
||||
return !lhs.Equals (rhs);
|
||||
}
|
||||
}
|
||||
}
|
1171
Mono.Posix/Mono.Unix.Native/Stdlib.cs
Normal file
1171
Mono.Posix/Mono.Unix.Native/Stdlib.cs
Normal file
File diff suppressed because it is too large
Load Diff
5881
Mono.Posix/Mono.Unix.Native/Syscall.cs
Normal file
5881
Mono.Posix/Mono.Unix.Native/Syscall.cs
Normal file
File diff suppressed because it is too large
Load Diff
138
Mono.Posix/Mono.Unix.Native/TypeAttributes.cs
Normal file
138
Mono.Posix/Mono.Unix.Native/TypeAttributes.cs
Normal file
@ -0,0 +1,138 @@
|
||||
//
|
||||
// TypeAttributes.cs
|
||||
//
|
||||
// Author:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2006 Jonathan Pryor
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
|
||||
namespace Mono.Unix.Native {
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class blkcnt_tAttribute : MapAttribute {
|
||||
|
||||
public blkcnt_tAttribute () : base ("blkcnt_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
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)]
|
||||
internal class gid_tAttribute : MapAttribute {
|
||||
|
||||
public gid_tAttribute () : base ("gid_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class fsblkcnt_tAttribute : MapAttribute {
|
||||
|
||||
public fsblkcnt_tAttribute () : base ("fsblkcnt_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class fsfilcnt_tAttribute : MapAttribute {
|
||||
|
||||
public fsfilcnt_tAttribute () : base ("fsfilcnt_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class ino_tAttribute : MapAttribute {
|
||||
|
||||
public ino_tAttribute () : base ("ino_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class nlink_tAttribute : MapAttribute {
|
||||
|
||||
public nlink_tAttribute () : base ("nlink_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class off_tAttribute : MapAttribute {
|
||||
|
||||
public off_tAttribute () : base ("off_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class pid_tAttribute : MapAttribute {
|
||||
|
||||
public pid_tAttribute () : base ("pid_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class suseconds_tAttribute : MapAttribute {
|
||||
|
||||
public suseconds_tAttribute () : base ("suseconds_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class uid_tAttribute : MapAttribute {
|
||||
|
||||
public uid_tAttribute () : base ("uid_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Field)]
|
||||
internal class time_tAttribute : MapAttribute {
|
||||
|
||||
public time_tAttribute () : base ("time_t")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
123
Mono.Posix/Mono.Unix/AbstractUnixEndPoint.cs
Normal file
123
Mono.Posix/Mono.Unix/AbstractUnixEndPoint.cs
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// Mono.Unix.AbstractUnixEndPoint: EndPoint derived class for AF_UNIX family sockets.
|
||||
//
|
||||
// Authors:
|
||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
||||
// Alp Toker (alp@atoker.com)
|
||||
//
|
||||
// (C) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
// (C) 2006 Alp Toker
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Unix
|
||||
{
|
||||
[Serializable]
|
||||
public class AbstractUnixEndPoint : EndPoint
|
||||
{
|
||||
string path;
|
||||
|
||||
public AbstractUnixEndPoint (string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
|
||||
if (path == "")
|
||||
throw new ArgumentException ("Cannot be empty.", "path");
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public string Path {
|
||||
get {
|
||||
return(path);
|
||||
}
|
||||
set {
|
||||
path=value;
|
||||
}
|
||||
}
|
||||
|
||||
public override AddressFamily AddressFamily {
|
||||
get { return 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 (socketAddress [1] != ((addr & 0xFF00) >> 8))
|
||||
throw new ArgumentException ("socketAddress is not a unix socket address.");
|
||||
*/
|
||||
|
||||
byte [] bytes = new byte [socketAddress.Size - 2 - 1];
|
||||
for (int i = 0; i < bytes.Length; i++) {
|
||||
bytes [i] = socketAddress [2 + 1 + i];
|
||||
}
|
||||
|
||||
string name = Encoding.Default.GetString (bytes);
|
||||
return new AbstractUnixEndPoint (name);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
136
Mono.Posix/Mono.Unix/Catalog.cs
Normal file
136
Mono.Posix/Mono.Unix/Catalog.cs
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Mono.Unix.Catalog.cs: Wrappers for the libintl library.
|
||||
//
|
||||
// Authors:
|
||||
// Edd Dumbill (edd@usefulinc.com)
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004 Edd Dumbill
|
||||
// (C) 2005-2006 Jonathan Pryor
|
||||
//
|
||||
// This file implements the low-level syscall interface to the POSIX
|
||||
// subsystem.
|
||||
//
|
||||
// This file tries to stay close to the low-level API as much as possible
|
||||
// using enumerations, structures and in a few cases, using existing .NET
|
||||
// data types.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// Since the values for the various constants on the API changes
|
||||
// from system to system (even Linux on different architectures will
|
||||
// have different values), we define our own set of values, and we
|
||||
// use a set of C helper routines to map from the constants we define
|
||||
// to the values of the native OS.
|
||||
//
|
||||
// Bitfields are flagged with the [Map] attribute, and a helper program
|
||||
// generates a set of map_XXXX routines that we can call to convert
|
||||
// from our value definitions to the value definitions expected by the
|
||||
// OS.
|
||||
//
|
||||
// Methods that require tuning are bound as `internal syscal_NAME' methods
|
||||
// and then a `NAME' method is exposed.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public class Catalog {
|
||||
private Catalog () {}
|
||||
|
||||
[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
|
||||
[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
|
||||
IntPtr codeset);
|
||||
[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr textdomain (IntPtr domainname);
|
||||
|
||||
public static void Init (String package, String localedir)
|
||||
{
|
||||
IntPtr ipackage, ilocaledir, iutf8;
|
||||
MarshalStrings (package, out ipackage, localedir, out ilocaledir,
|
||||
"UTF-8", out iutf8);
|
||||
try {
|
||||
if (bindtextdomain (ipackage, ilocaledir) == IntPtr.Zero)
|
||||
throw new UnixIOException (Native.Errno.ENOMEM);
|
||||
if (bind_textdomain_codeset (ipackage, iutf8) == IntPtr.Zero)
|
||||
throw new UnixIOException (Native.Errno.ENOMEM);
|
||||
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,
|
||||
string s2, out IntPtr p2, string s3, out IntPtr p3)
|
||||
{
|
||||
p1 = p2 = p3 = IntPtr.Zero;
|
||||
|
||||
bool cleanup = true;
|
||||
|
||||
try {
|
||||
p1 = UnixMarshal.StringToHeap (s1);
|
||||
p2 = UnixMarshal.StringToHeap (s2);
|
||||
if (s3 != null)
|
||||
p3 = UnixMarshal.StringToHeap (s3);
|
||||
cleanup = false;
|
||||
}
|
||||
finally {
|
||||
if (cleanup) {
|
||||
UnixMarshal.FreeHeap (p1);
|
||||
UnixMarshal.FreeHeap (p2);
|
||||
UnixMarshal.FreeHeap (p3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("intl", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr gettext (IntPtr instring);
|
||||
|
||||
public static String GetString (String s)
|
||||
{
|
||||
IntPtr ints = UnixMarshal.StringToHeap (s);
|
||||
try {
|
||||
// gettext(3) returns the input pointer if no translation is found
|
||||
IntPtr r = gettext (ints);
|
||||
if (r != ints)
|
||||
return UnixMarshal.PtrToStringUnix (r);
|
||||
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)
|
||||
{
|
||||
IntPtr ints, intp, _ignore;
|
||||
MarshalStrings (s, out ints, p, out intp, null, out _ignore);
|
||||
|
||||
try {
|
||||
// ngettext(3) returns an input pointer if no translation is found
|
||||
IntPtr r = ngettext (ints, intp, n);
|
||||
if (r == ints)
|
||||
return s;
|
||||
if (r == intp)
|
||||
return p;
|
||||
return UnixMarshal.PtrToStringUnix (r);
|
||||
}
|
||||
finally {
|
||||
UnixMarshal.FreeHeap (ints);
|
||||
UnixMarshal.FreeHeap (intp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
Mono.Posix/Mono.Unix/FileAccessPattern.cs
Normal file
43
Mono.Posix/Mono.Unix/FileAccessPattern.cs
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// Mono.Unix/FileAccessPattern.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public enum FileAccessPattern {
|
||||
Normal = Native.PosixFadviseAdvice.POSIX_FADV_NORMAL,
|
||||
Sequential = Native.PosixFadviseAdvice.POSIX_FADV_SEQUENTIAL,
|
||||
Random = Native.PosixFadviseAdvice.POSIX_FADV_RANDOM,
|
||||
NoReuse = Native.PosixFadviseAdvice.POSIX_FADV_NOREUSE,
|
||||
PreLoad = Native.PosixFadviseAdvice.POSIX_FADV_WILLNEED,
|
||||
FlushCache = Native.PosixFadviseAdvice.POSIX_FADV_DONTNEED,
|
||||
}
|
||||
}
|
||||
|
53
Mono.Posix/Mono.Unix/FileAccessPermissions.cs
Normal file
53
Mono.Posix/Mono.Unix/FileAccessPermissions.cs
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// Mono.Unix/FileAccessPermissions.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
[Flags]
|
||||
public enum FileAccessPermissions {
|
||||
UserReadWriteExecute = (int) Native.FilePermissions.S_IRWXU,
|
||||
UserRead = (int) Native.FilePermissions.S_IRUSR,
|
||||
UserWrite = (int) Native.FilePermissions.S_IWUSR,
|
||||
UserExecute = (int) Native.FilePermissions.S_IXUSR,
|
||||
GroupReadWriteExecute = (int) Native.FilePermissions.S_IRWXG,
|
||||
GroupRead = (int) Native.FilePermissions.S_IRGRP,
|
||||
GroupWrite = (int) Native.FilePermissions.S_IWGRP,
|
||||
GroupExecute = (int) Native.FilePermissions.S_IXGRP,
|
||||
OtherReadWriteExecute = (int) Native.FilePermissions.S_IRWXO,
|
||||
OtherRead = (int) Native.FilePermissions.S_IROTH,
|
||||
OtherWrite = (int) Native.FilePermissions.S_IWOTH,
|
||||
OtherExecute = (int) Native.FilePermissions.S_IXOTH,
|
||||
|
||||
DefaultPermissions = (int) Native.FilePermissions.DEFFILEMODE,
|
||||
AllPermissions = (int) Native.FilePermissions.ACCESSPERMS,
|
||||
}
|
||||
}
|
||||
|
82
Mono.Posix/Mono.Unix/FileHandleOperations.cs
Normal file
82
Mono.Posix/Mono.Unix/FileHandleOperations.cs
Normal file
@ -0,0 +1,82 @@
|
||||
//
|
||||
// Mono.Unix/FileHandleOperations.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed /* static */ class FileHandleOperations
|
||||
{
|
||||
private FileHandleOperations () {}
|
||||
|
||||
public static void AdviseFileAccessPattern (int fd, FileAccessPattern pattern, long offset, long len)
|
||||
{
|
||||
int r = Native.Syscall.posix_fadvise (fd, offset, len,
|
||||
(Native.PosixFadviseAdvice) pattern);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public static void AdviseFileAccessPattern (int fd, FileAccessPattern pattern)
|
||||
{
|
||||
AdviseFileAccessPattern (fd, pattern, 0, 0);
|
||||
}
|
||||
|
||||
public static void AdviseFileAccessPattern (FileStream file, FileAccessPattern pattern, long offset, long len)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException ("file");
|
||||
int r = Native.Syscall.posix_fadvise (file.Handle.ToInt32(), offset, len,
|
||||
(Native.PosixFadviseAdvice) pattern);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public static void AdviseFileAccessPattern (FileStream file, FileAccessPattern pattern)
|
||||
{
|
||||
AdviseFileAccessPattern (file, pattern, 0, 0);
|
||||
}
|
||||
|
||||
public static void AdviseFileAccessPattern (UnixStream stream, FileAccessPattern pattern, long offset, long len)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException ("stream");
|
||||
int r = Native.Syscall.posix_fadvise (stream.Handle, offset, len,
|
||||
(Native.PosixFadviseAdvice) pattern);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public static void AdviseFileAccessPattern (UnixStream stream, FileAccessPattern pattern)
|
||||
{
|
||||
AdviseFileAccessPattern (stream, pattern, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
41
Mono.Posix/Mono.Unix/FileSpecialAttributes.cs
Normal file
41
Mono.Posix/Mono.Unix/FileSpecialAttributes.cs
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// Mono.Unix/FileSpecialAttributes.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
[Flags]
|
||||
public enum FileSpecialAttributes {
|
||||
SetUserId = (int) Native.FilePermissions.S_ISUID,
|
||||
SetGroupId = (int) Native.FilePermissions.S_ISGID,
|
||||
Sticky = (int) Native.FilePermissions.S_ISVTX,
|
||||
}
|
||||
}
|
||||
|
44
Mono.Posix/Mono.Unix/FileTypes.cs
Normal file
44
Mono.Posix/Mono.Unix/FileTypes.cs
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Mono.Unix/FileTypes.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public enum FileTypes {
|
||||
Directory = (int) Native.FilePermissions.S_IFDIR,
|
||||
CharacterDevice = (int) Native.FilePermissions.S_IFCHR,
|
||||
BlockDevice = (int) Native.FilePermissions.S_IFBLK,
|
||||
RegularFile = (int) Native.FilePermissions.S_IFREG,
|
||||
Fifo = (int) Native.FilePermissions.S_IFIFO,
|
||||
SymbolicLink = (int) Native.FilePermissions.S_IFLNK,
|
||||
Socket = (int) Native.FilePermissions.S_IFSOCK,
|
||||
}
|
||||
}
|
||||
|
81
Mono.Posix/Mono.Unix/PeerCred.cs
Normal file
81
Mono.Posix/Mono.Unix/PeerCred.cs
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Mono.Unix.PeerCred: Peer credentials class for AF_UNIX sockets
|
||||
//
|
||||
// Authors:
|
||||
// Dick Porter (dick@ximian.com)
|
||||
//
|
||||
// (C) 2004 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Mono.Unix
|
||||
{
|
||||
#pragma warning disable 649
|
||||
internal struct PeerCredData {
|
||||
public int pid;
|
||||
public int uid;
|
||||
public int gid;
|
||||
}
|
||||
#pragma warning restore 649
|
||||
|
||||
public class PeerCred
|
||||
{
|
||||
/* Make sure this doesn't clash with anything in
|
||||
* SocketOptionName, and keep it synchronised with the
|
||||
* runtime
|
||||
*/
|
||||
private const int so_peercred=10001;
|
||||
private PeerCredData data;
|
||||
|
||||
public PeerCred (Socket sock) {
|
||||
if (sock.AddressFamily != AddressFamily.Unix) {
|
||||
throw new ArgumentException ("Only Unix sockets are supported", "sock");
|
||||
}
|
||||
|
||||
data = (PeerCredData)
|
||||
sock.GetSocketOption (SocketOptionLevel.Socket, (SocketOptionName)so_peercred);
|
||||
}
|
||||
|
||||
public int ProcessID {
|
||||
get {
|
||||
return(data.pid);
|
||||
}
|
||||
}
|
||||
|
||||
public int UserID {
|
||||
get {
|
||||
return(data.uid);
|
||||
}
|
||||
}
|
||||
|
||||
public int GroupID {
|
||||
get {
|
||||
return(data.gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
406
Mono.Posix/Mono.Unix/StdioFileStream.cs
Normal file
406
Mono.Posix/Mono.Unix/StdioFileStream.cs
Normal file
@ -0,0 +1,406 @@
|
||||
//
|
||||
// Mono.Unix/StdioFileStream.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2005-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public class StdioFileStream : Stream
|
||||
{
|
||||
public static readonly IntPtr InvalidFileStream = IntPtr.Zero;
|
||||
public static readonly IntPtr StandardInput = Native.Stdlib.stdin;
|
||||
public static readonly IntPtr StandardOutput = Native.Stdlib.stdout;
|
||||
public static readonly IntPtr StandardError = Native.Stdlib.stderr;
|
||||
|
||||
public StdioFileStream (IntPtr fileStream)
|
||||
: this (fileStream, true) {}
|
||||
|
||||
public StdioFileStream (IntPtr fileStream, bool ownsHandle)
|
||||
{
|
||||
InitStream (fileStream, ownsHandle);
|
||||
}
|
||||
|
||||
public StdioFileStream (IntPtr fileStream, FileAccess access)
|
||||
: this (fileStream, access, true) {}
|
||||
|
||||
public StdioFileStream (IntPtr fileStream, FileAccess access, bool ownsHandle)
|
||||
{
|
||||
InitStream (fileStream, ownsHandle);
|
||||
InitCanReadWrite (access);
|
||||
}
|
||||
|
||||
public StdioFileStream (string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
InitStream (Fopen (path, "rb"), true);
|
||||
}
|
||||
|
||||
public StdioFileStream (string path, string mode)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
InitStream (Fopen (path, mode), true);
|
||||
}
|
||||
|
||||
public StdioFileStream (string path, FileMode mode)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
InitStream (Fopen (path, ToFopenMode (path, mode)), true);
|
||||
}
|
||||
|
||||
public StdioFileStream (string path, FileAccess access)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
InitStream (Fopen (path, ToFopenMode (path, access)), true);
|
||||
InitCanReadWrite (access);
|
||||
}
|
||||
|
||||
public StdioFileStream (string path, FileMode mode, FileAccess access)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
InitStream (Fopen (path, ToFopenMode (path, mode, access)), true);
|
||||
InitCanReadWrite (access);
|
||||
}
|
||||
|
||||
private static IntPtr Fopen (string path, string mode)
|
||||
{
|
||||
if (path.Length == 0)
|
||||
throw new ArgumentException ("path");
|
||||
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;
|
||||
}
|
||||
|
||||
private void InitStream (IntPtr fileStream, bool ownsHandle)
|
||||
{
|
||||
if (InvalidFileStream == fileStream)
|
||||
throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
|
||||
|
||||
this.file = fileStream;
|
||||
this.owner = ownsHandle;
|
||||
|
||||
try {
|
||||
long offset = Native.Stdlib.fseek (file, 0, Native.SeekFlags.SEEK_CUR);
|
||||
if (offset != -1)
|
||||
canSeek = true;
|
||||
Native.Stdlib.fread (IntPtr.Zero, 0, 0, file);
|
||||
if (Native.Stdlib.ferror (file) == 0)
|
||||
canRead = true;
|
||||
Native.Stdlib.fwrite (IntPtr.Zero, 0, 0, file);
|
||||
if (Native.Stdlib.ferror (file) == 0)
|
||||
canWrite = true;
|
||||
Native.Stdlib.clearerr (file);
|
||||
}
|
||||
catch (Exception) {
|
||||
throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
|
||||
}
|
||||
GC.KeepAlive (this);
|
||||
}
|
||||
|
||||
private void InitCanReadWrite (FileAccess access)
|
||||
{
|
||||
canRead = canRead &&
|
||||
(access == FileAccess.Read || access == FileAccess.ReadWrite);
|
||||
canWrite = canWrite &&
|
||||
(access == FileAccess.Write || access == FileAccess.ReadWrite);
|
||||
}
|
||||
|
||||
private static string ToFopenMode (string file, FileMode mode)
|
||||
{
|
||||
string cmode = Native.NativeConvert.ToFopenMode (mode);
|
||||
AssertFileMode (file, mode);
|
||||
return cmode;
|
||||
}
|
||||
|
||||
private static string ToFopenMode (string file, FileAccess access)
|
||||
{
|
||||
return Native.NativeConvert.ToFopenMode (access);
|
||||
}
|
||||
|
||||
private static string ToFopenMode (string file, FileMode mode, FileAccess access)
|
||||
{
|
||||
string cmode = Native.NativeConvert.ToFopenMode (mode, access);
|
||||
bool exists = AssertFileMode (file, mode);
|
||||
// HACK: for open-or-create & read, mode is "rb", which doesn't create
|
||||
// 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";
|
||||
return cmode;
|
||||
}
|
||||
|
||||
private static bool AssertFileMode (string file, FileMode mode)
|
||||
{
|
||||
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)
|
||||
{
|
||||
bool found = false;
|
||||
IntPtr f = Native.Stdlib.fopen (file, "r");
|
||||
found = f != IntPtr.Zero;
|
||||
if (f != IntPtr.Zero)
|
||||
Native.Stdlib.fclose (f);
|
||||
return found;
|
||||
}
|
||||
|
||||
private void AssertNotDisposed ()
|
||||
{
|
||||
if (file == InvalidFileStream)
|
||||
throw new ObjectDisposedException ("Invalid File Stream");
|
||||
GC.KeepAlive (this);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
AssertNotDisposed ();
|
||||
GC.KeepAlive (this);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanRead {
|
||||
get {return canRead;}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {return canSeek;}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {return canWrite;}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
AssertNotDisposed ();
|
||||
if (!CanSeek)
|
||||
throw new NotSupportedException ("File Stream doesn't support seeking");
|
||||
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);
|
||||
if (endPos == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
r = Native.Stdlib.fseek (file, curPos, Native.SeekFlags.SEEK_SET);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
|
||||
GC.KeepAlive (this);
|
||||
return endPos;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get {
|
||||
AssertNotDisposed ();
|
||||
if (!CanSeek)
|
||||
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
|
230
Mono.Posix/Mono.Unix/UnixClient.cs
Normal file
230
Mono.Posix/Mono.Unix/UnixClient.cs
Normal file
@ -0,0 +1,230 @@
|
||||
//
|
||||
// UnixClient.cs
|
||||
//
|
||||
// Authors:
|
||||
// Joe Shaw (joeshaw@novell.com)
|
||||
//
|
||||
// Copyright (C) 2004-2005 Novell, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public class UnixClient : MarshalByRefObject, IDisposable {
|
||||
NetworkStream stream;
|
||||
Socket client;
|
||||
bool disposed;
|
||||
|
||||
public UnixClient ()
|
||||
{
|
||||
if (client != null) {
|
||||
client.Close ();
|
||||
client = null;
|
||||
}
|
||||
|
||||
client = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
|
||||
}
|
||||
|
||||
public UnixClient (string path) : this ()
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("ep");
|
||||
|
||||
Connect (path);
|
||||
}
|
||||
|
||||
public UnixClient (UnixEndPoint ep) : this ()
|
||||
{
|
||||
if (ep == null)
|
||||
throw new ArgumentNullException ("ep");
|
||||
|
||||
Connect (ep);
|
||||
}
|
||||
|
||||
// UnixListener uses this when accepting a connection.
|
||||
internal UnixClient (Socket sock)
|
||||
{
|
||||
Client = sock;
|
||||
}
|
||||
|
||||
public
|
||||
Socket Client {
|
||||
get { return client; }
|
||||
set {
|
||||
client = value;
|
||||
stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public PeerCred PeerCredential {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return new PeerCred (client);
|
||||
}
|
||||
}
|
||||
|
||||
public LingerOption LingerState {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return (LingerOption) client.GetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.Linger);
|
||||
}
|
||||
|
||||
set {
|
||||
CheckDisposed ();
|
||||
client.SetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.Linger, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int ReceiveBufferSize {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return (int) client.GetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveBuffer);
|
||||
}
|
||||
|
||||
set {
|
||||
CheckDisposed ();
|
||||
client.SetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveBuffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int ReceiveTimeout {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return (int) client.GetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveTimeout);
|
||||
}
|
||||
|
||||
set {
|
||||
CheckDisposed ();
|
||||
client.SetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveTimeout, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SendBufferSize {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return (int) client.GetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendBuffer);
|
||||
}
|
||||
|
||||
set {
|
||||
CheckDisposed ();
|
||||
client.SetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendBuffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SendTimeout {
|
||||
get {
|
||||
CheckDisposed ();
|
||||
return (int) client.GetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendTimeout);
|
||||
}
|
||||
|
||||
set {
|
||||
CheckDisposed ();
|
||||
client.SetSocketOption (SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendTimeout, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
CheckDisposed ();
|
||||
Dispose ();
|
||||
}
|
||||
|
||||
public void Connect (UnixEndPoint remoteEndPoint)
|
||||
{
|
||||
CheckDisposed ();
|
||||
client.Connect (remoteEndPoint);
|
||||
stream = new NetworkStream (client, true);
|
||||
}
|
||||
|
||||
public void Connect (string path)
|
||||
{
|
||||
CheckDisposed ();
|
||||
Connect (new UnixEndPoint (path));
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (disposing) {
|
||||
// release managed resources
|
||||
NetworkStream s = stream;
|
||||
stream = null;
|
||||
if (s != null) {
|
||||
// This closes the socket as well, as the NetworkStream
|
||||
// owns the socket.
|
||||
s.Close();
|
||||
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 ()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException (GetType().FullName);
|
||||
}
|
||||
|
||||
~UnixClient ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
250
Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs
Normal file
250
Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs
Normal file
@ -0,0 +1,250 @@
|
||||
//
|
||||
// Mono.Unix/UnixDirectoryInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixDirectoryInfo : UnixFileSystemInfo
|
||||
{
|
||||
public UnixDirectoryInfo (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
internal UnixDirectoryInfo (string path, Native.Stat stat)
|
||||
: base (path, stat)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
string r = UnixPath.GetFileName (FullPath);
|
||||
if (r == null || r.Length == 0)
|
||||
return FullPath;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
public UnixDirectoryInfo Parent {
|
||||
get {
|
||||
if (FullPath == "/")
|
||||
return this;
|
||||
string dirname = UnixPath.GetDirectoryName (FullPath);
|
||||
if (dirname == "")
|
||||
throw new InvalidOperationException ("Do not know parent directory for path `" + FullPath + "'");
|
||||
return new UnixDirectoryInfo (dirname);
|
||||
}
|
||||
}
|
||||
|
||||
public UnixDirectoryInfo Root {
|
||||
get {
|
||||
string root = UnixPath.GetPathRoot (FullPath);
|
||||
if (root == null)
|
||||
return null;
|
||||
return new UnixDirectoryInfo (root);
|
||||
}
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public void Create (Mono.Unix.Native.FilePermissions mode)
|
||||
{
|
||||
int r = Mono.Unix.Native.Syscall.mkdir (FullPath, mode);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
base.Refresh ();
|
||||
}
|
||||
|
||||
public void Create (FileAccessPermissions mode)
|
||||
{
|
||||
Create ((Native.FilePermissions) mode);
|
||||
}
|
||||
|
||||
public void Create ()
|
||||
{
|
||||
Mono.Unix.Native.FilePermissions mode =
|
||||
Mono.Unix.Native.FilePermissions.ACCESSPERMS;
|
||||
Create (mode);
|
||||
}
|
||||
|
||||
public override void Delete ()
|
||||
{
|
||||
Delete (false);
|
||||
}
|
||||
|
||||
public void Delete (bool recursive)
|
||||
{
|
||||
if (recursive) {
|
||||
foreach (UnixFileSystemInfo e in GetFileSystemEntries ()) {
|
||||
UnixDirectoryInfo d = e as UnixDirectoryInfo;
|
||||
if (d != null)
|
||||
d.Delete (true);
|
||||
else
|
||||
e.Delete ();
|
||||
}
|
||||
}
|
||||
int r = Native.Syscall.rmdir (FullPath);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
base.Refresh ();
|
||||
}
|
||||
|
||||
public Native.Dirent[] GetEntries ()
|
||||
{
|
||||
IntPtr dirp = Native.Syscall.opendir (FullPath);
|
||||
if (dirp == IntPtr.Zero)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
bool complete = false;
|
||||
try {
|
||||
Native.Dirent[] entries = GetEntries (dirp);
|
||||
complete = true;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
// 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 Native.Dirent[] GetEntries (Regex regex)
|
||||
{
|
||||
IntPtr dirp = Native.Syscall.opendir (FullPath);
|
||||
if (dirp == IntPtr.Zero)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
try {
|
||||
return GetEntries (dirp, regex);
|
||||
}
|
||||
finally {
|
||||
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
|
195
Mono.Posix/Mono.Unix/UnixDriveInfo.cs
Normal file
195
Mono.Posix/Mono.Unix/UnixDriveInfo.cs
Normal file
@ -0,0 +1,195 @@
|
||||
//
|
||||
// Mono.Unix/UnixDriveInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public enum UnixDriveType {
|
||||
Unknown,
|
||||
NoRootDirectory,
|
||||
Removable,
|
||||
Fixed,
|
||||
Network,
|
||||
CDRom,
|
||||
Ram
|
||||
}
|
||||
|
||||
// All methods & properties can throw IOException
|
||||
public sealed class UnixDriveInfo
|
||||
{
|
||||
private Native.Statvfs stat;
|
||||
private string fstype, mount_point, block_device;
|
||||
|
||||
public UnixDriveInfo (string mountPoint)
|
||||
{
|
||||
if (mountPoint == null)
|
||||
throw new ArgumentNullException ("mountPoint");
|
||||
Native.Fstab fstab = Native.Syscall.getfsfile (mountPoint);
|
||||
if (fstab != null) {
|
||||
FromFstab (fstab);
|
||||
}
|
||||
else {
|
||||
this.mount_point = mountPoint;
|
||||
this.block_device = "";
|
||||
this.fstype = "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private void FromFstab (Native.Fstab fstab)
|
||||
{
|
||||
this.fstype = fstab.fs_vfstype;
|
||||
this.mount_point = fstab.fs_file;
|
||||
this.block_device = fstab.fs_spec;
|
||||
}
|
||||
|
||||
public static UnixDriveInfo GetForSpecialFile (string specialFile)
|
||||
{
|
||||
if (specialFile == null)
|
||||
throw new ArgumentNullException ("specialFile");
|
||||
Native.Fstab f = Native.Syscall.getfsspec (specialFile);
|
||||
if (f == null)
|
||||
throw new ArgumentException ("specialFile isn't valid: " + specialFile);
|
||||
return new UnixDriveInfo (f);
|
||||
}
|
||||
|
||||
private UnixDriveInfo (Native.Fstab fstab)
|
||||
{
|
||||
FromFstab (fstab);
|
||||
}
|
||||
|
||||
public long AvailableFreeSpace {
|
||||
get {Refresh (); return Convert.ToInt64 (stat.f_bavail * stat.f_frsize);}
|
||||
}
|
||||
|
||||
public string DriveFormat {
|
||||
get {return fstype;}
|
||||
}
|
||||
|
||||
public UnixDriveType DriveType {
|
||||
get {return UnixDriveType.Unknown;}
|
||||
}
|
||||
|
||||
// this throws no exceptions
|
||||
public bool IsReady {
|
||||
get {
|
||||
bool ready = Refresh (false);
|
||||
if (mount_point == "/" || !ready)
|
||||
return ready;
|
||||
Native.Statvfs parent;
|
||||
int r = Native.Syscall.statvfs (RootDirectory.Parent.FullName,
|
||||
out parent);
|
||||
if (r != 0)
|
||||
return false;
|
||||
return parent.f_fsid != stat.f_fsid;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {return mount_point;}
|
||||
}
|
||||
|
||||
public UnixDirectoryInfo RootDirectory {
|
||||
get {return new UnixDirectoryInfo (mount_point);}
|
||||
}
|
||||
|
||||
public long TotalFreeSpace {
|
||||
get {Refresh (); return (long) (stat.f_bfree * stat.f_frsize);}
|
||||
}
|
||||
|
||||
public long TotalSize {
|
||||
get {Refresh (); return (long) (stat.f_frsize * stat.f_blocks);}
|
||||
}
|
||||
|
||||
// also throws SecurityException if caller lacks perms
|
||||
public string VolumeLabel {
|
||||
get {return block_device;}
|
||||
// set {}
|
||||
}
|
||||
|
||||
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
|
856
Mono.Posix/Mono.Unix/UnixEncoding.cs
Normal file
856
Mono.Posix/Mono.Unix/UnixEncoding.cs
Normal file
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Mono.Unix/UnixEncoding.cs
|
||||
*
|
||||
* Authors:
|
||||
* Jonathan Pryor (jonpryor@vt.edu)
|
||||
*
|
||||
* Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd
|
||||
* Copyright (C) 2004 Novell, Inc (http://www.novell.com)
|
||||
* Copyright (C) 2005 Jonathan Pryor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Mono.Unix
|
||||
{
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
[Serializable]
|
||||
public class UnixEncoding : Encoding
|
||||
{
|
||||
public static readonly Encoding Instance = new UnixEncoding ();
|
||||
|
||||
public static readonly char EscapeByte = '\u0000';
|
||||
|
||||
// Constructors.
|
||||
public UnixEncoding ()
|
||||
{
|
||||
}
|
||||
|
||||
// Internal version of "GetByteCount" which can handle a rolling
|
||||
// state between multiple calls to this method.
|
||||
private static int InternalGetByteCount (char[] chars, int index, int count, uint leftOver, bool flush)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (chars == null) {
|
||||
throw new ArgumentNullException ("chars");
|
||||
}
|
||||
if (index < 0 || index > chars.Length) {
|
||||
throw new ArgumentOutOfRangeException ("index", _("ArgRange_Array"));
|
||||
}
|
||||
if (count < 0 || count > (chars.Length - index)) {
|
||||
throw new ArgumentOutOfRangeException ("count", _("ArgRange_Array"));
|
||||
}
|
||||
|
||||
// Determine the lengths of all characters.
|
||||
char ch;
|
||||
int length = 0;
|
||||
uint pair = leftOver;
|
||||
while (count > 0) {
|
||||
ch = chars[index];
|
||||
if (pair == 0) {
|
||||
if (ch == EscapeByte && count > 1) {
|
||||
++length;
|
||||
++index;
|
||||
--count;
|
||||
} else if (ch < '\u0080') {
|
||||
++length;
|
||||
} else if (ch < '\u0800') {
|
||||
length += 2;
|
||||
} else if (ch >= '\uD800' && ch <= '\uDBFF') {
|
||||
// This is the start of a surrogate pair.
|
||||
pair = (uint)ch;
|
||||
} else {
|
||||
length += 3;
|
||||
}
|
||||
} else if (ch >= '\uDC00' && ch <= '\uDFFF') {
|
||||
// We have a surrogate pair.
|
||||
length += 4;
|
||||
pair = 0;
|
||||
} else {
|
||||
// We have a surrogate start followed by a
|
||||
// regular character. Technically, this is
|
||||
// invalid, but we have to do something.
|
||||
// We write out the surrogate start and then
|
||||
// re-visit the current character again.
|
||||
length += 3;
|
||||
pair = 0;
|
||||
continue;
|
||||
}
|
||||
++index;
|
||||
--count;
|
||||
}
|
||||
if (flush && pair != 0) {
|
||||
// Flush the left-over surrogate pair start.
|
||||
length += 3;
|
||||
}
|
||||
|
||||
// Return the final length to the caller.
|
||||
return length;
|
||||
}
|
||||
|
||||
// Get the number of bytes needed to encode a character buffer.
|
||||
public override int GetByteCount (char[] chars, int index, int count)
|
||||
{
|
||||
return InternalGetByteCount (chars, index, count, 0, true);
|
||||
}
|
||||
|
||||
// Convenience wrappers for "GetByteCount".
|
||||
public override int GetByteCount (String s)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (s == null) {
|
||||
throw new ArgumentNullException ("s");
|
||||
}
|
||||
|
||||
// Determine the lengths of all characters.
|
||||
char ch;
|
||||
int index = 0;
|
||||
int count = s.Length;
|
||||
int length = 0;
|
||||
uint pair;
|
||||
while (count > 0) {
|
||||
ch = s[index++];
|
||||
if (ch == EscapeByte && count > 1) {
|
||||
++length;
|
||||
++index;
|
||||
--count;
|
||||
} else if (ch < '\u0080') {
|
||||
++length;
|
||||
} else if (ch < '\u0800') {
|
||||
length += 2;
|
||||
} else if (ch >= '\uD800' && ch <= '\uDBFF' && count > 1) {
|
||||
// This may be the start of a surrogate pair.
|
||||
pair = (uint)(s[index]);
|
||||
if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
|
||||
length += 4;
|
||||
++index;
|
||||
--count;
|
||||
} else {
|
||||
length += 3;
|
||||
}
|
||||
} else {
|
||||
length += 3;
|
||||
}
|
||||
--count;
|
||||
}
|
||||
|
||||
// Return the final length to the caller.
|
||||
return length;
|
||||
}
|
||||
|
||||
// Internal version of "GetBytes" which can handle a rolling
|
||||
// state between multiple calls to this method.
|
||||
private static int InternalGetBytes (char[] chars, int charIndex,
|
||||
int charCount, byte[] bytes,
|
||||
int byteIndex, ref uint leftOver,
|
||||
bool flush)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (chars == null) {
|
||||
throw new ArgumentNullException ("chars");
|
||||
}
|
||||
if (bytes == null) {
|
||||
throw new ArgumentNullException ("bytes");
|
||||
}
|
||||
if (charIndex < 0 || charIndex > chars.Length) {
|
||||
throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
|
||||
}
|
||||
if (charCount < 0 || charCount > (chars.Length - charIndex)) {
|
||||
throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
|
||||
}
|
||||
if (byteIndex < 0 || byteIndex > bytes.Length) {
|
||||
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
|
||||
}
|
||||
|
||||
// Convert the characters into bytes.
|
||||
char ch;
|
||||
int length = bytes.Length;
|
||||
uint pair;
|
||||
uint left = leftOver;
|
||||
int posn = byteIndex;
|
||||
while (charCount > 0) {
|
||||
// Fetch the next UTF-16 character pair value.
|
||||
ch = chars[charIndex++];
|
||||
--charCount;
|
||||
if (left == 0) {
|
||||
if (ch >= '\uD800' && ch <= '\uDBFF') {
|
||||
// This is the start of a surrogate pair.
|
||||
left = (uint)ch;
|
||||
continue;
|
||||
} else if (ch == EscapeByte) {
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
if (--charCount >= 0) {
|
||||
bytes[posn++] = (byte) chars [charIndex++];
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
// This is a regular character.
|
||||
pair = (uint)ch;
|
||||
}
|
||||
} else if (ch >= '\uDC00' && ch <= '\uDFFF') {
|
||||
// We have a surrogate pair.
|
||||
pair = ((left - (uint)0xD800) << 10) +
|
||||
(((uint)ch) - (uint)0xDC00) +
|
||||
(uint)0x10000;
|
||||
left = 0;
|
||||
} else {
|
||||
// We have a surrogate start followed by a
|
||||
// regular character. Technically, this is
|
||||
// invalid, but we have to do something.
|
||||
// We write out the surrogate start and then
|
||||
// re-visit the current character again.
|
||||
pair = (uint)left;
|
||||
left = 0;
|
||||
--charIndex;
|
||||
++charCount;
|
||||
}
|
||||
|
||||
// Encode the character pair value.
|
||||
if (pair < (uint)0x0080) {
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)pair;
|
||||
} else if (pair < (uint)0x0800) {
|
||||
if ((posn + 2) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xC0 | (pair >> 6));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
} else if (pair < (uint)0x10000) {
|
||||
if ((posn + 3) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xE0 | (pair >> 12));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
} else {
|
||||
if ((posn + 4) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xF0 | (pair >> 18));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 12) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
}
|
||||
}
|
||||
if (flush && left != 0) {
|
||||
// Flush the left-over surrogate pair start.
|
||||
if ((posn + 3) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xE0 | (left >> 12));
|
||||
bytes[posn++] = (byte)(0x80 | ((left >> 6) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | (left & 0x3F));
|
||||
left = 0;
|
||||
}
|
||||
leftOver = left;
|
||||
|
||||
// Return the final count to the caller.
|
||||
return posn - byteIndex;
|
||||
}
|
||||
|
||||
// Get the bytes that result from encoding a character buffer.
|
||||
public override int GetBytes (char[] chars, int charIndex, int charCount,
|
||||
byte[] bytes, int byteIndex)
|
||||
{
|
||||
uint leftOver = 0;
|
||||
return InternalGetBytes (chars, charIndex, charCount, bytes, byteIndex, ref leftOver, true);
|
||||
}
|
||||
|
||||
// Convenience wrappers for "GetBytes".
|
||||
public override int GetBytes (String s, int charIndex, int charCount,
|
||||
byte[] bytes, int byteIndex)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (s == null) {
|
||||
throw new ArgumentNullException ("s");
|
||||
}
|
||||
if (bytes == null) {
|
||||
throw new ArgumentNullException ("bytes");
|
||||
}
|
||||
if (charIndex < 0 || charIndex > s.Length) {
|
||||
throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_StringIndex"));
|
||||
}
|
||||
if (charCount < 0 || charCount > (s.Length - charIndex)) {
|
||||
throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_StringRange"));
|
||||
}
|
||||
if (byteIndex < 0 || byteIndex > bytes.Length) {
|
||||
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
fixed (char* p = s) {
|
||||
fixed (byte* b = bytes) {
|
||||
return GetBytes (p + charIndex, charCount, b + byteIndex, bytes.Length - byteIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
|
||||
{
|
||||
if (bytes == null || chars == null)
|
||||
throw new ArgumentNullException (bytes == null ? "bytes" : "chars");
|
||||
|
||||
if (charCount < 0 || byteCount < 0)
|
||||
throw new ArgumentOutOfRangeException (charCount < 0 ? "charCount" : "byteCount");
|
||||
|
||||
// Convert the characters into bytes.
|
||||
char ch;
|
||||
int length = byteCount;
|
||||
uint pair;
|
||||
int posn = 0;
|
||||
int charIndex = 0;
|
||||
while (charCount > 0) {
|
||||
// Fetch the next UTF-16 character pair value.
|
||||
ch = chars [charIndex++];
|
||||
if (ch >= '\uD800' && ch <= '\uDBFF' && charCount > 1) {
|
||||
// This may be the start of a surrogate pair.
|
||||
pair = (uint)(chars[charIndex]);
|
||||
if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
|
||||
pair = (pair - (uint)0xDC00) +
|
||||
((((uint)ch) - (uint)0xD800) << 10) +
|
||||
(uint)0x10000;
|
||||
++charIndex;
|
||||
--charCount;
|
||||
} else {
|
||||
pair = (uint)ch;
|
||||
}
|
||||
} else if (ch == EscapeByte && charCount > 1) {
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
charCount -= 2;
|
||||
if (charCount >= 0) {
|
||||
bytes[posn++] = (byte)chars [charIndex++];
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
pair = (uint)ch;
|
||||
}
|
||||
--charCount;
|
||||
|
||||
// Encode the character pair value.
|
||||
if (pair < (uint)0x0080) {
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)pair;
|
||||
} else if (pair < (uint)0x0800) {
|
||||
if ((posn + 2) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xC0 | (pair >> 6));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
} else if (pair < (uint)0x10000) {
|
||||
if ((posn + 3) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xE0 | (pair >> 12));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
} else {
|
||||
if ((posn + 4) > length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "bytes");
|
||||
}
|
||||
bytes[posn++] = (byte)(0xF0 | (pair >> 18));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 12) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | ((pair >> 6) & 0x3F));
|
||||
bytes[posn++] = (byte)(0x80 | (pair & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
// Return the final count to the caller.
|
||||
return posn;
|
||||
}
|
||||
|
||||
// Internal version of "GetCharCount" which can handle a rolling
|
||||
// state between multiple calls to this method.
|
||||
private static int InternalGetCharCount (byte[] bytes, int index, int count,
|
||||
uint leftOverBits,
|
||||
uint leftOverCount,
|
||||
bool throwOnInvalid, bool flush)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (bytes == null) {
|
||||
throw new ArgumentNullException ("bytes");
|
||||
}
|
||||
if (index < 0 || index > bytes.Length) {
|
||||
throw new ArgumentOutOfRangeException ("index", _("ArgRange_Array"));
|
||||
}
|
||||
if (count < 0 || count > (bytes.Length - index)) {
|
||||
throw new ArgumentOutOfRangeException ("count", _("ArgRange_Array"));
|
||||
}
|
||||
|
||||
// Determine the number of characters that we have.
|
||||
int next_raw = 0;
|
||||
uint ch;
|
||||
int length = 0;
|
||||
uint leftBits = leftOverBits;
|
||||
uint leftSoFar = (leftOverCount & (uint)0x0F);
|
||||
uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
|
||||
while (count > 0) {
|
||||
ch = (uint)(bytes [index++]);
|
||||
++next_raw;
|
||||
--count;
|
||||
if (leftSize == 0) {
|
||||
// Process a UTF-8 start character.
|
||||
if (ch < (uint)0x0080) {
|
||||
// Single-byte UTF-8 character.
|
||||
++length;
|
||||
next_raw = 0;
|
||||
} else if ((ch & (uint)0xE0) == (uint)0xC0) {
|
||||
// Double-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x1F);
|
||||
leftSoFar = 1;
|
||||
leftSize = 2;
|
||||
} else if ((ch & (uint)0xF0) == (uint)0xE0) {
|
||||
// Three-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x0F);
|
||||
leftSoFar = 1;
|
||||
leftSize = 3;
|
||||
} else if ((ch & (uint)0xF8) == (uint)0xF0) {
|
||||
// Four-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x07);
|
||||
leftSoFar = 1;
|
||||
leftSize = 4;
|
||||
} else if ((ch & (uint)0xFC) == (uint)0xF8) {
|
||||
// Five-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x03);
|
||||
leftSoFar = 1;
|
||||
leftSize = 5;
|
||||
} else if ((ch & (uint)0xFE) == (uint)0xFC) {
|
||||
// Six-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x03);
|
||||
leftSoFar = 1;
|
||||
leftSize = 6;
|
||||
} else {
|
||||
// Invalid UTF-8 start character.
|
||||
if (throwOnInvalid) {
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
}
|
||||
length += next_raw*2;
|
||||
next_raw = 0;
|
||||
}
|
||||
} else {
|
||||
// Process an extra byte in a multi-byte sequence.
|
||||
if ((ch & (uint)0xC0) == (uint)0x80) {
|
||||
leftBits = ((leftBits << 6) | (ch & (uint)0x3F));
|
||||
if (++leftSoFar >= leftSize) {
|
||||
// We have a complete character now.
|
||||
if (leftBits < (uint)0x10000) {
|
||||
// is it an overlong ?
|
||||
bool overlong = false;
|
||||
switch (leftSize) {
|
||||
case 2:
|
||||
overlong = (leftBits <= 0x7F);
|
||||
break;
|
||||
case 3:
|
||||
overlong = (leftBits <= 0x07FF);
|
||||
break;
|
||||
case 4:
|
||||
overlong = (leftBits <= 0xFFFF);
|
||||
break;
|
||||
case 5:
|
||||
overlong = (leftBits <= 0x1FFFFF);
|
||||
break;
|
||||
case 6:
|
||||
overlong = (leftBits <= 0x03FFFFFF);
|
||||
break;
|
||||
}
|
||||
if (overlong) {
|
||||
// if (throwOnInvalid)
|
||||
// throw new ArgumentException (_("Overlong"), leftBits.ToString ());
|
||||
length += next_raw*2;
|
||||
}
|
||||
else
|
||||
++length;
|
||||
} else if (leftBits < (uint)0x110000) {
|
||||
length += 2;
|
||||
} else if (throwOnInvalid) {
|
||||
// ???
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
length += next_raw*2;
|
||||
}
|
||||
leftSize = 0;
|
||||
next_raw = 0;
|
||||
}
|
||||
} else {
|
||||
// Invalid UTF-8 sequence: clear and restart.
|
||||
if (throwOnInvalid) {
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
}
|
||||
// don't escape the current byte, process it normally
|
||||
if (ch < (uint)0x0080) {
|
||||
--index;
|
||||
++count;
|
||||
--next_raw;
|
||||
}
|
||||
length += next_raw*2;
|
||||
leftSize = 0;
|
||||
next_raw = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flush && leftSize != 0 && throwOnInvalid) {
|
||||
// We had left-over bytes that didn't make up
|
||||
// a complete UTF-8 character sequence.
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
length += next_raw * 2;
|
||||
}
|
||||
|
||||
// Return the final length to the caller.
|
||||
return length;
|
||||
}
|
||||
|
||||
// Get the number of characters needed to decode a byte buffer.
|
||||
public override int GetCharCount (byte[] bytes, int index, int count)
|
||||
{
|
||||
return InternalGetCharCount (bytes, index, count, 0, 0, true, true);
|
||||
}
|
||||
|
||||
// Get the characters that result from decoding a byte buffer.
|
||||
private static int InternalGetChars (byte[] bytes, int byteIndex,
|
||||
int byteCount, char[] chars,
|
||||
int charIndex, ref uint leftOverBits,
|
||||
ref uint leftOverCount,
|
||||
bool throwOnInvalid, bool flush)
|
||||
{
|
||||
// Validate the parameters.
|
||||
if (bytes == null) {
|
||||
throw new ArgumentNullException ("bytes");
|
||||
}
|
||||
if (chars == null) {
|
||||
throw new ArgumentNullException ("chars");
|
||||
}
|
||||
if (byteIndex < 0 || byteIndex > bytes.Length) {
|
||||
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
|
||||
}
|
||||
if (byteCount < 0 || byteCount > (bytes.Length - byteIndex)) {
|
||||
throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_Array"));
|
||||
}
|
||||
if (charIndex < 0 || charIndex > chars.Length) {
|
||||
throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
|
||||
}
|
||||
|
||||
if (charIndex == chars.Length)
|
||||
return 0;
|
||||
|
||||
// Convert the bytes into the output buffer.
|
||||
byte[] raw = new byte[6];
|
||||
int next_raw = 0;
|
||||
uint ch;
|
||||
int length = chars.Length;
|
||||
int posn = charIndex;
|
||||
uint leftBits = leftOverBits;
|
||||
uint leftSoFar = (leftOverCount & (uint)0x0F);
|
||||
uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
|
||||
while (byteCount > 0) {
|
||||
// Fetch the next character from the byte buffer.
|
||||
ch = (uint)(bytes[byteIndex++]);
|
||||
raw [next_raw++] = (byte) ch;
|
||||
--byteCount;
|
||||
if (leftSize == 0) {
|
||||
// Process a UTF-8 start character.
|
||||
if (ch < (uint)0x0080) {
|
||||
// Single-byte UTF-8 character.
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "chars");
|
||||
}
|
||||
next_raw = 0;
|
||||
chars[posn++] = (char)ch;
|
||||
} else if ((ch & (uint)0xE0) == (uint)0xC0) {
|
||||
// Double-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x1F);
|
||||
leftSoFar = 1;
|
||||
leftSize = 2;
|
||||
} else if ((ch & (uint)0xF0) == (uint)0xE0) {
|
||||
// Three-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x0F);
|
||||
leftSoFar = 1;
|
||||
leftSize = 3;
|
||||
} else if ((ch & (uint)0xF8) == (uint)0xF0) {
|
||||
// Four-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x07);
|
||||
leftSoFar = 1;
|
||||
leftSize = 4;
|
||||
} else if ((ch & (uint)0xFC) == (uint)0xF8) {
|
||||
// Five-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x03);
|
||||
leftSoFar = 1;
|
||||
leftSize = 5;
|
||||
} else if ((ch & (uint)0xFE) == (uint)0xFC) {
|
||||
// Six-byte UTF-8 character.
|
||||
leftBits = (ch & (uint)0x03);
|
||||
leftSoFar = 1;
|
||||
leftSize = 6;
|
||||
} else {
|
||||
// Invalid UTF-8 start character.
|
||||
if (throwOnInvalid) {
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
}
|
||||
next_raw = 0;
|
||||
chars[posn++] = EscapeByte;
|
||||
chars[posn++] = (char) ch;
|
||||
}
|
||||
} else {
|
||||
// Process an extra byte in a multi-byte sequence.
|
||||
if ((ch & (uint)0xC0) == (uint)0x80) {
|
||||
leftBits = ((leftBits << 6) | (ch & (uint)0x3F));
|
||||
if (++leftSoFar >= leftSize) {
|
||||
// We have a complete character now.
|
||||
if (leftBits < (uint)0x10000) {
|
||||
// is it an overlong ?
|
||||
bool overlong = false;
|
||||
switch (leftSize) {
|
||||
case 2:
|
||||
overlong = (leftBits <= 0x7F);
|
||||
break;
|
||||
case 3:
|
||||
overlong = (leftBits <= 0x07FF);
|
||||
break;
|
||||
case 4:
|
||||
overlong = (leftBits <= 0xFFFF);
|
||||
break;
|
||||
case 5:
|
||||
overlong = (leftBits <= 0x1FFFFF);
|
||||
break;
|
||||
case 6:
|
||||
overlong = (leftBits <= 0x03FFFFFF);
|
||||
break;
|
||||
}
|
||||
if (overlong) {
|
||||
// if (throwOnInvalid)
|
||||
// throw new ArgumentException (_("Overlong"), leftBits.ToString ());
|
||||
CopyRaw (raw, ref next_raw, chars, ref posn, length);
|
||||
}
|
||||
else {
|
||||
if (posn >= length) {
|
||||
throw new ArgumentException
|
||||
(_("Arg_InsufficientSpace"), "chars");
|
||||
}
|
||||
chars[posn++] = (char)leftBits;
|
||||
}
|
||||
} else if (leftBits < (uint)0x110000) {
|
||||
if ((posn + 2) > length) {
|
||||
throw new ArgumentException
|
||||
(_("Arg_InsufficientSpace"), "chars");
|
||||
}
|
||||
leftBits -= (uint)0x10000;
|
||||
chars[posn++] = (char)((leftBits >> 10) +
|
||||
(uint)0xD800);
|
||||
chars[posn++] =
|
||||
(char)((leftBits & (uint)0x3FF) + (uint)0xDC00);
|
||||
} else if (throwOnInvalid) {
|
||||
// ???
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
CopyRaw (raw, ref next_raw, chars, ref posn, length);
|
||||
}
|
||||
leftSize = 0;
|
||||
next_raw = 0;
|
||||
}
|
||||
} else {
|
||||
// Invalid UTF-8 sequence: clear and restart.
|
||||
if (throwOnInvalid) {
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
}
|
||||
// don't escape the current byte, process it normally
|
||||
if (ch < (uint)0x0080) {
|
||||
--byteIndex;
|
||||
++byteCount;
|
||||
--next_raw;
|
||||
}
|
||||
CopyRaw (raw, ref next_raw, chars, ref posn, length);
|
||||
leftSize = 0;
|
||||
next_raw = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flush && leftSize != 0 && throwOnInvalid) {
|
||||
// We had left-over bytes that didn't make up
|
||||
// a complete UTF-8 character sequence.
|
||||
// throw new ArgumentException (_("Arg_InvalidUTF8"), "bytes");
|
||||
CopyRaw (raw, ref next_raw, chars, ref posn, length);
|
||||
}
|
||||
leftOverBits = leftBits;
|
||||
leftOverCount = (leftSoFar | (leftSize << 4));
|
||||
|
||||
// Return the final length to the caller.
|
||||
return posn - charIndex;
|
||||
}
|
||||
|
||||
private static void CopyRaw (byte[] raw, ref int next_raw, char[] chars, ref int posn, int length)
|
||||
{
|
||||
if (posn+(next_raw*2) > length)
|
||||
throw new ArgumentException (_("Arg_InsufficientSpace"), "chars");
|
||||
|
||||
for (int i = 0; i < next_raw; ++i) {
|
||||
chars[posn++] = EscapeByte;
|
||||
chars[posn++] = (char) raw [i];
|
||||
}
|
||||
|
||||
next_raw = 0;
|
||||
}
|
||||
|
||||
// Get the characters that result from decoding a byte buffer.
|
||||
public override int GetChars (byte[] bytes, int byteIndex, int byteCount,
|
||||
char[] chars, int charIndex)
|
||||
{
|
||||
uint leftOverBits = 0;
|
||||
uint leftOverCount = 0;
|
||||
return InternalGetChars (bytes, byteIndex, byteCount, chars,
|
||||
charIndex, ref leftOverBits, ref leftOverCount, true, true);
|
||||
}
|
||||
|
||||
// Get the maximum number of bytes needed to encode a
|
||||
// specified number of characters.
|
||||
public override int GetMaxByteCount (int charCount)
|
||||
{
|
||||
if (charCount < 0) {
|
||||
throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_NonNegative"));
|
||||
}
|
||||
return charCount * 4;
|
||||
}
|
||||
|
||||
// Get the maximum number of characters needed to decode a
|
||||
// specified number of bytes.
|
||||
public override int GetMaxCharCount (int byteCount)
|
||||
{
|
||||
if (byteCount < 0) {
|
||||
throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative"));
|
||||
}
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
// Get a Unix-specific decoder that is attached to this instance.
|
||||
public override Decoder GetDecoder ()
|
||||
{
|
||||
return new UnixDecoder ();
|
||||
}
|
||||
|
||||
// Get a Unix-specific encoder that is attached to this instance.
|
||||
public override Encoder GetEncoder ()
|
||||
{
|
||||
return new UnixEncoder ();
|
||||
}
|
||||
|
||||
// Get the Unix preamble.
|
||||
public override byte[] GetPreamble ()
|
||||
{
|
||||
return new byte [0];
|
||||
}
|
||||
|
||||
// Determine if this object is equal to another.
|
||||
public override bool Equals (Object value)
|
||||
{
|
||||
UnixEncoding enc = (value as UnixEncoding);
|
||||
if (enc != null) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the hash code for this object.
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return base.GetHashCode ();
|
||||
}
|
||||
|
||||
public override byte [] GetBytes (String s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException ("s");
|
||||
|
||||
int length = GetByteCount (s);
|
||||
byte [] bytes = new byte [length];
|
||||
GetBytes (s, 0, s.Length, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// Unix decoder implementation.
|
||||
[Serializable]
|
||||
private class UnixDecoder : Decoder
|
||||
{
|
||||
private uint leftOverBits;
|
||||
private uint leftOverCount;
|
||||
|
||||
// Constructor.
|
||||
public UnixDecoder ()
|
||||
{
|
||||
leftOverBits = 0;
|
||||
leftOverCount = 0;
|
||||
}
|
||||
|
||||
// Override inherited methods.
|
||||
public override int GetCharCount (byte[] bytes, int index, int count)
|
||||
{
|
||||
return InternalGetCharCount (bytes, index, count,
|
||||
leftOverBits, leftOverCount, true, false);
|
||||
}
|
||||
public override int GetChars (byte[] bytes, int byteIndex,
|
||||
int byteCount, char[] chars, int charIndex)
|
||||
{
|
||||
return InternalGetChars (bytes, byteIndex, byteCount,
|
||||
chars, charIndex, ref leftOverBits, ref leftOverCount, true, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Unix encoder implementation.
|
||||
[Serializable]
|
||||
private class UnixEncoder : Encoder
|
||||
{
|
||||
private uint leftOver;
|
||||
|
||||
// Constructor.
|
||||
public UnixEncoder ()
|
||||
{
|
||||
leftOver = 0;
|
||||
}
|
||||
|
||||
// Override inherited methods.
|
||||
public override int GetByteCount (char[] chars, int index,
|
||||
int count, bool flush)
|
||||
{
|
||||
return InternalGetByteCount (chars, index, count, leftOver, flush);
|
||||
}
|
||||
public override int GetBytes (char[] chars, int charIndex,
|
||||
int charCount, byte[] bytes, int byteCount, bool flush)
|
||||
{
|
||||
int result;
|
||||
result = InternalGetBytes (chars, charIndex, charCount, bytes, byteCount, ref leftOver, flush);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static string _ (string arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
133
Mono.Posix/Mono.Unix/UnixEndPoint.cs
Normal file
133
Mono.Posix/Mono.Unix/UnixEndPoint.cs
Normal file
@ -0,0 +1,133 @@
|
||||
//
|
||||
// Mono.Unix.UnixEndPoint: EndPoint derived class for AF_UNIX family sockets.
|
||||
//
|
||||
// Authors:
|
||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
||||
//
|
||||
// (C) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Unix
|
||||
{
|
||||
[Serializable]
|
||||
public class UnixEndPoint : EndPoint
|
||||
{
|
||||
string filename;
|
||||
|
||||
public UnixEndPoint (string filename)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException ("filename");
|
||||
|
||||
if (filename == "")
|
||||
throw new ArgumentException ("Cannot be empty.", "filename");
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public string Filename {
|
||||
get {
|
||||
return(filename);
|
||||
}
|
||||
set {
|
||||
filename=value;
|
||||
}
|
||||
}
|
||||
|
||||
public override AddressFamily AddressFamily {
|
||||
get { return 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 (socketAddress [1] != ((addr & 0xFF00) >> 8))
|
||||
throw new ArgumentException ("socketAddress is not a unix socket address.");
|
||||
*/
|
||||
|
||||
if (socketAddress.Size == 2) {
|
||||
// Empty filename.
|
||||
// Probably from RemoteEndPoint which on linux does not return the file name.
|
||||
UnixEndPoint uep = new UnixEndPoint ("a");
|
||||
uep.filename = "";
|
||||
return uep;
|
||||
}
|
||||
int size = socketAddress.Size - 2;
|
||||
byte [] bytes = new byte [size];
|
||||
for (int 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
238
Mono.Posix/Mono.Unix/UnixEnvironment.cs
Normal file
238
Mono.Posix/Mono.Unix/UnixEnvironment.cs
Normal file
@ -0,0 +1,238 @@
|
||||
//
|
||||
// Mono.Unix/UnixEnvironment.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed /* static */ class UnixEnvironment
|
||||
{
|
||||
private UnixEnvironment () {}
|
||||
|
||||
public static string CurrentDirectory {
|
||||
get {
|
||||
return UnixDirectoryInfo.GetCurrentDirectory ();
|
||||
}
|
||||
set {
|
||||
UnixDirectoryInfo.SetCurrentDirectory (value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string MachineName {
|
||||
get {
|
||||
Native.Utsname buf;
|
||||
if (Native.Syscall.uname (out buf) != 0)
|
||||
throw UnixMarshal.CreateExceptionForLastError ();
|
||||
return buf.nodename;
|
||||
}
|
||||
set {
|
||||
int r = Native.Syscall.sethostname (value);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
}
|
||||
|
||||
public static string UserName {
|
||||
get {return UnixUserInfo.GetRealUser ().UserName;}
|
||||
}
|
||||
|
||||
public static UnixGroupInfo RealGroup {
|
||||
get {return new UnixGroupInfo (RealGroupId);}
|
||||
// set can't be done as setgid(2) modifies effective gid as well
|
||||
}
|
||||
|
||||
public static long RealGroupId {
|
||||
get {return Native.Syscall.getgid ();}
|
||||
// set can't be done as setgid(2) modifies effective gid as well
|
||||
}
|
||||
|
||||
public static UnixUserInfo RealUser {
|
||||
get {return new UnixUserInfo (RealUserId);}
|
||||
// set can't be done as setuid(2) modifies effective uid as well
|
||||
}
|
||||
|
||||
public static long RealUserId {
|
||||
get {return Native.Syscall.getuid ();}
|
||||
// set can't be done as setuid(2) modifies effective uid as well
|
||||
}
|
||||
|
||||
public static UnixGroupInfo EffectiveGroup {
|
||||
get {return new UnixGroupInfo (EffectiveGroupId);}
|
||||
set {EffectiveGroupId = value.GroupId;}
|
||||
}
|
||||
|
||||
public static long EffectiveGroupId {
|
||||
get {return Native.Syscall.getegid ();}
|
||||
set {Native.Syscall.setegid (Convert.ToUInt32 (value));}
|
||||
}
|
||||
|
||||
public static UnixUserInfo EffectiveUser {
|
||||
get {return new UnixUserInfo (EffectiveUserId);}
|
||||
set {EffectiveUserId = value.UserId;}
|
||||
}
|
||||
|
||||
public static long EffectiveUserId {
|
||||
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
|
147
Mono.Posix/Mono.Unix/UnixFileInfo.cs
Normal file
147
Mono.Posix/Mono.Unix/UnixFileInfo.cs
Normal file
@ -0,0 +1,147 @@
|
||||
//
|
||||
// Mono.Unix/UnixFileInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixFileInfo : UnixFileSystemInfo
|
||||
{
|
||||
public UnixFileInfo (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
internal UnixFileInfo (string path, Native.Stat stat)
|
||||
: base (path, stat)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {return UnixPath.GetFileName (FullPath);}
|
||||
}
|
||||
|
||||
public string DirectoryName {
|
||||
get {return UnixPath.GetDirectoryName (FullPath);}
|
||||
}
|
||||
|
||||
public UnixDirectoryInfo Directory {
|
||||
get {return new UnixDirectoryInfo (DirectoryName);}
|
||||
}
|
||||
|
||||
public override void Delete ()
|
||||
{
|
||||
int r = Native.Syscall.unlink (FullPath);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
base.Refresh ();
|
||||
}
|
||||
|
||||
public UnixStream Create ()
|
||||
{
|
||||
Native.FilePermissions mode = // 0644
|
||||
Native.FilePermissions.S_IRUSR | Native.FilePermissions.S_IWUSR |
|
||||
Native.FilePermissions.S_IRGRP | Native.FilePermissions.S_IROTH;
|
||||
return Create (mode);
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public UnixStream Create (Native.FilePermissions mode)
|
||||
{
|
||||
int fd = Native.Syscall.creat (FullPath, mode);
|
||||
if (fd < 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
base.Refresh ();
|
||||
return new UnixStream (fd);
|
||||
}
|
||||
|
||||
public UnixStream Create (FileAccessPermissions mode)
|
||||
{
|
||||
return 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");
|
||||
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
|
428
Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs
Normal file
428
Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs
Normal file
@ -0,0 +1,428 @@
|
||||
//
|
||||
// Mono.Unix/UnixFileSystemInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public abstract class UnixFileSystemInfo
|
||||
{
|
||||
private Native.Stat stat;
|
||||
private string fullPath;
|
||||
private string originalPath;
|
||||
private bool valid = false;
|
||||
|
||||
internal const FileSpecialAttributes AllSpecialAttributes =
|
||||
FileSpecialAttributes.SetUserId | FileSpecialAttributes.SetGroupId |
|
||||
FileSpecialAttributes.Sticky;
|
||||
internal const FileTypes AllFileTypes =
|
||||
FileTypes.Directory | FileTypes.CharacterDevice | FileTypes.BlockDevice |
|
||||
FileTypes.RegularFile | FileTypes.Fifo | FileTypes.SymbolicLink |
|
||||
FileTypes.Socket;
|
||||
|
||||
protected UnixFileSystemInfo (string path)
|
||||
{
|
||||
UnixPath.CheckPath (path);
|
||||
this.originalPath = path;
|
||||
this.fullPath = UnixPath.GetFullPath (path);
|
||||
Refresh (true);
|
||||
}
|
||||
|
||||
internal UnixFileSystemInfo (String path, Native.Stat stat)
|
||||
{
|
||||
this.originalPath = path;
|
||||
this.fullPath = UnixPath.GetFullPath (path);
|
||||
this.stat = stat;
|
||||
this.valid = true;
|
||||
}
|
||||
|
||||
protected string FullPath {
|
||||
get {return fullPath;}
|
||||
set {
|
||||
if (fullPath != value) {
|
||||
UnixPath.CheckPath (value);
|
||||
valid = false;
|
||||
fullPath = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string OriginalPath {
|
||||
get {return originalPath;}
|
||||
set {originalPath = value;}
|
||||
}
|
||||
|
||||
private void AssertValid ()
|
||||
{
|
||||
Refresh (false);
|
||||
if (!valid)
|
||||
throw new InvalidOperationException ("Path doesn't exist!");
|
||||
}
|
||||
|
||||
public virtual string FullName {
|
||||
get {return FullPath;}
|
||||
}
|
||||
|
||||
public abstract string Name {get;}
|
||||
|
||||
public bool Exists {
|
||||
get {
|
||||
Refresh (true);
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
|
||||
public long Device {
|
||||
get {AssertValid (); return Convert.ToInt64 (stat.st_dev);}
|
||||
}
|
||||
|
||||
public long Inode {
|
||||
get {AssertValid (); return Convert.ToInt64 (stat.st_ino);}
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public Native.FilePermissions Protection {
|
||||
get {AssertValid (); return (Native.FilePermissions) stat.st_mode;}
|
||||
set {
|
||||
int r = Native.Syscall.chmod (FullPath, value);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
}
|
||||
|
||||
public FileTypes FileType {
|
||||
get {
|
||||
AssertValid ();
|
||||
return (FileTypes) (stat.st_mode & Native.FilePermissions.S_IFMT);
|
||||
}
|
||||
// no set as chmod(2) won't accept changing the file type.
|
||||
}
|
||||
|
||||
public FileAccessPermissions FileAccessPermissions {
|
||||
get {
|
||||
AssertValid ();
|
||||
int perms = (int) stat.st_mode;
|
||||
return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
|
||||
}
|
||||
set {
|
||||
AssertValid ();
|
||||
int perms = (int) stat.st_mode;
|
||||
perms &= (int) ~FileAccessPermissions.AllPermissions;
|
||||
perms |= (int) value;
|
||||
Protection = (Native.FilePermissions) perms;
|
||||
}
|
||||
}
|
||||
|
||||
public FileSpecialAttributes FileSpecialAttributes {
|
||||
get {
|
||||
AssertValid ();
|
||||
int attrs = (int) stat.st_mode;
|
||||
return (FileSpecialAttributes) (attrs & (int) AllSpecialAttributes);
|
||||
}
|
||||
set {
|
||||
AssertValid ();
|
||||
int perms = (int) stat.st_mode;
|
||||
perms &= (int) ~AllSpecialAttributes;
|
||||
perms |= (int) value;
|
||||
Protection = (Native.FilePermissions) perms;
|
||||
}
|
||||
}
|
||||
|
||||
public long LinkCount {
|
||||
get {AssertValid (); return Convert.ToInt64 (stat.st_nlink);}
|
||||
}
|
||||
|
||||
public UnixUserInfo OwnerUser {
|
||||
get {AssertValid (); return new UnixUserInfo (stat.st_uid);}
|
||||
}
|
||||
|
||||
public long OwnerUserId {
|
||||
get {AssertValid (); return stat.st_uid;}
|
||||
}
|
||||
|
||||
public UnixGroupInfo OwnerGroup {
|
||||
get {AssertValid (); return new UnixGroupInfo (stat.st_gid);}
|
||||
}
|
||||
|
||||
public long OwnerGroupId {
|
||||
get {AssertValid (); return stat.st_gid;}
|
||||
}
|
||||
|
||||
public long DeviceType {
|
||||
get {AssertValid (); return Convert.ToInt64 (stat.st_rdev);}
|
||||
}
|
||||
|
||||
public long Length {
|
||||
get {AssertValid (); return (long) stat.st_size;}
|
||||
}
|
||||
|
||||
public long BlockSize {
|
||||
get {AssertValid (); return (long) stat.st_blksize;}
|
||||
}
|
||||
|
||||
public long BlocksAllocated {
|
||||
get {AssertValid (); return (long) stat.st_blocks;}
|
||||
}
|
||||
|
||||
public DateTime LastAccessTime {
|
||||
get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime, stat.st_atime_nsec);}
|
||||
}
|
||||
|
||||
public DateTime LastAccessTimeUtc {
|
||||
get {return LastAccessTime.ToUniversalTime ();}
|
||||
}
|
||||
|
||||
public DateTime LastWriteTime {
|
||||
get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime, stat.st_mtime_nsec);}
|
||||
}
|
||||
|
||||
public DateTime LastWriteTimeUtc {
|
||||
get {return LastWriteTime.ToUniversalTime ();}
|
||||
}
|
||||
|
||||
public DateTime LastStatusChangeTime {
|
||||
get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime, stat.st_ctime_nsec);}
|
||||
}
|
||||
|
||||
public DateTime LastStatusChangeTimeUtc {
|
||||
get {return LastStatusChangeTime.ToUniversalTime ();}
|
||||
}
|
||||
|
||||
public bool IsDirectory {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR);}
|
||||
}
|
||||
|
||||
public bool IsCharacterDevice {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFCHR);}
|
||||
}
|
||||
|
||||
public bool IsBlockDevice {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFBLK);}
|
||||
}
|
||||
|
||||
public bool IsRegularFile {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFREG);}
|
||||
}
|
||||
|
||||
public bool IsFifo {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
|
||||
}
|
||||
|
||||
public bool IsSymbolicLink {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK);}
|
||||
}
|
||||
|
||||
public bool IsSocket {
|
||||
get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFSOCK);}
|
||||
}
|
||||
|
||||
public bool IsSetUser {
|
||||
get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISUID);}
|
||||
}
|
||||
|
||||
public bool IsSetGroup {
|
||||
get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISGID);}
|
||||
}
|
||||
|
||||
public bool IsSticky {
|
||||
get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISVTX);}
|
||||
}
|
||||
|
||||
internal static bool IsFileType (Native.FilePermissions mode, Native.FilePermissions type)
|
||||
{
|
||||
return (mode & Native.FilePermissions.S_IFMT) == type;
|
||||
}
|
||||
|
||||
internal static bool IsSet (Native.FilePermissions mode, Native.FilePermissions type)
|
||||
{
|
||||
return (mode & type) == type;
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public bool CanAccess (Native.AccessModes mode)
|
||||
{
|
||||
int r = Native.Syscall.access (FullPath, mode);
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
public UnixFileSystemInfo CreateLink (string path)
|
||||
{
|
||||
int r = Native.Syscall.link (FullName, path);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return GetFileSystemEntry (path);
|
||||
}
|
||||
|
||||
public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
|
||||
{
|
||||
int r = Native.Syscall.symlink (FullName, path);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return new UnixSymbolicLinkInfo (path);
|
||||
}
|
||||
|
||||
public abstract void Delete ();
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public long GetConfigurationValue (Native.PathconfName name)
|
||||
{
|
||||
long r = Native.Syscall.pathconf (FullPath, name);
|
||||
if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
return r;
|
||||
}
|
||||
|
||||
public void Refresh ()
|
||||
{
|
||||
Refresh (true);
|
||||
}
|
||||
|
||||
internal void Refresh (bool force)
|
||||
{
|
||||
if (valid && !force)
|
||||
return;
|
||||
valid = GetFileStatus (FullPath, out this.stat);
|
||||
}
|
||||
|
||||
protected virtual bool GetFileStatus (string path, out Native.Stat stat)
|
||||
{
|
||||
return Native.Syscall.stat (path, out stat) == 0;
|
||||
}
|
||||
|
||||
public void SetLength (long length)
|
||||
{
|
||||
int r;
|
||||
do {
|
||||
r = Native.Syscall.truncate (FullPath, length);
|
||||
} while (UnixMarshal.ShouldRetrySyscall (r));
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public virtual void SetOwner (long owner, long group)
|
||||
{
|
||||
uint _owner = Convert.ToUInt32 (owner);
|
||||
uint _group = Convert.ToUInt32 (group);
|
||||
int r = Native.Syscall.chown (FullPath, _owner, _group);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public void SetOwner (string owner)
|
||||
{
|
||||
Native.Passwd pw = Native.Syscall.getpwnam (owner);
|
||||
if (pw == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
|
||||
uint uid = pw.pw_uid;
|
||||
uint gid = pw.pw_gid;
|
||||
SetOwner ((long) uid, (long) gid);
|
||||
}
|
||||
|
||||
public void SetOwner (string owner, string group)
|
||||
{
|
||||
long uid = -1;
|
||||
if (owner != null)
|
||||
uid = new UnixUserInfo (owner).UserId;
|
||||
long gid = -1;
|
||||
if (group != null)
|
||||
gid = new UnixGroupInfo (group).GroupId;
|
||||
|
||||
SetOwner (uid, gid);
|
||||
}
|
||||
|
||||
public void SetOwner (UnixUserInfo owner)
|
||||
{
|
||||
long uid, gid;
|
||||
uid = gid = -1;
|
||||
if (owner != null) {
|
||||
uid = owner.UserId;
|
||||
gid = owner.GroupId;
|
||||
}
|
||||
SetOwner (uid, gid);
|
||||
}
|
||||
|
||||
public void SetOwner (UnixUserInfo owner, UnixGroupInfo group)
|
||||
{
|
||||
long uid, gid;
|
||||
uid = gid = -1;
|
||||
if (owner != null)
|
||||
uid = owner.UserId;
|
||||
if (group != null)
|
||||
gid = owner.GroupId;
|
||||
SetOwner (uid, gid);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return FullPath;
|
||||
}
|
||||
|
||||
public Native.Stat ToStat ()
|
||||
{
|
||||
AssertValid ();
|
||||
return stat;
|
||||
}
|
||||
|
||||
public static UnixFileSystemInfo GetFileSystemEntry (string path)
|
||||
{
|
||||
UnixFileSystemInfo info;
|
||||
if (TryGetFileSystemEntry (path, out info))
|
||||
return info;
|
||||
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
|
||||
// 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.
|
||||
throw new DirectoryNotFoundException ("UnixMarshal.ThrowExceptionForLastError didn't throw?!");
|
||||
}
|
||||
|
||||
public static bool TryGetFileSystemEntry (string path, out UnixFileSystemInfo entry)
|
||||
{
|
||||
Native.Stat stat;
|
||||
int r = Native.Syscall.lstat (path, out stat);
|
||||
if (r == -1) {
|
||||
if (Native.Stdlib.GetLastError() == Native.Errno.ENOENT) {
|
||||
entry = new UnixFileInfo (path);
|
||||
return true;
|
||||
}
|
||||
entry = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR))
|
||||
entry = new UnixDirectoryInfo (path, stat);
|
||||
else if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK))
|
||||
entry = new UnixSymbolicLinkInfo (path, stat);
|
||||
else
|
||||
entry = new UnixFileInfo (path, stat);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
149
Mono.Posix/Mono.Unix/UnixGroupInfo.cs
Normal file
149
Mono.Posix/Mono.Unix/UnixGroupInfo.cs
Normal file
@ -0,0 +1,149 @@
|
||||
//
|
||||
// Mono.Unix/UnixGroupInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixGroupInfo
|
||||
{
|
||||
private Native.Group group;
|
||||
|
||||
public UnixGroupInfo (string group)
|
||||
{
|
||||
this.group = new Native.Group ();
|
||||
Native.Group gr;
|
||||
int r = Native.Syscall.getgrnam_r (group, this.group, out gr);
|
||||
if (r != 0 || gr == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid group name"), "group");
|
||||
}
|
||||
|
||||
public UnixGroupInfo (long group)
|
||||
{
|
||||
this.group = new Native.Group ();
|
||||
Native.Group gr;
|
||||
int r = Native.Syscall.getgrgid_r (Convert.ToUInt32 (group), this.group, out gr);
|
||||
if (r != 0 || gr == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid group id"), "group");
|
||||
}
|
||||
|
||||
public UnixGroupInfo (Native.Group group)
|
||||
{
|
||||
this.group = CopyGroup (group);
|
||||
}
|
||||
|
||||
private static Native.Group CopyGroup (Native.Group group)
|
||||
{
|
||||
Native.Group g = new Native.Group ();
|
||||
|
||||
g.gr_gid = group.gr_gid;
|
||||
g.gr_mem = group.gr_mem;
|
||||
g.gr_name = group.gr_name;
|
||||
g.gr_passwd = group.gr_passwd;
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
public string GroupName {
|
||||
get {return group.gr_name;}
|
||||
}
|
||||
|
||||
public string Password {
|
||||
get {return group.gr_passwd;}
|
||||
}
|
||||
|
||||
public long GroupId {
|
||||
get {return group.gr_gid;}
|
||||
}
|
||||
|
||||
public UnixUserInfo[] GetMembers ()
|
||||
{
|
||||
ArrayList members = new ArrayList (group.gr_mem.Length);
|
||||
for (int i = 0; i < group.gr_mem.Length; ++i) {
|
||||
try {
|
||||
members.Add (new UnixUserInfo (group.gr_mem [i]));
|
||||
} catch (ArgumentException) {
|
||||
// ignore invalid users
|
||||
}
|
||||
}
|
||||
return (UnixUserInfo[]) members.ToArray (typeof (UnixUserInfo));
|
||||
}
|
||||
|
||||
public string[] GetMemberNames ()
|
||||
{
|
||||
return (string[]) group.gr_mem.Clone ();
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return group.GetHashCode ();
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj == null || GetType () != obj.GetType())
|
||||
return false;
|
||||
return group.Equals (((UnixGroupInfo) obj).group);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
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
|
104
Mono.Posix/Mono.Unix/UnixIOException.cs
Normal file
104
Mono.Posix/Mono.Unix/UnixIOException.cs
Normal file
@ -0,0 +1,104 @@
|
||||
//
|
||||
// Mono.Unix/UnixIOException.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
[Serializable]
|
||||
public class UnixIOException : IOException
|
||||
{
|
||||
private int errno;
|
||||
|
||||
public UnixIOException ()
|
||||
: this (Marshal.GetLastWin32Error())
|
||||
{}
|
||||
|
||||
public UnixIOException (int errno)
|
||||
: base (GetMessage (Native.NativeConvert.ToErrno (errno)))
|
||||
{
|
||||
this.errno = errno;
|
||||
}
|
||||
|
||||
public UnixIOException (int errno, Exception inner)
|
||||
: base (GetMessage (Native.NativeConvert.ToErrno (errno)), inner)
|
||||
{
|
||||
this.errno = errno;
|
||||
}
|
||||
|
||||
public UnixIOException (Native.Errno errno)
|
||||
: base (GetMessage (errno))
|
||||
{
|
||||
this.errno = Native.NativeConvert.FromErrno (errno);
|
||||
}
|
||||
|
||||
public UnixIOException (Native.Errno errno, Exception inner)
|
||||
: base (GetMessage (errno), inner)
|
||||
{
|
||||
this.errno = Native.NativeConvert.FromErrno (errno);
|
||||
}
|
||||
|
||||
public UnixIOException (string message)
|
||||
: base (message)
|
||||
{
|
||||
this.errno = 0;
|
||||
}
|
||||
|
||||
public UnixIOException (string message, Exception inner)
|
||||
: base (message, inner)
|
||||
{
|
||||
this.errno = 0;
|
||||
}
|
||||
|
||||
protected UnixIOException (SerializationInfo info, StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public int NativeErrorCode {
|
||||
get {return errno;}
|
||||
}
|
||||
|
||||
public Native.Errno ErrorCode {
|
||||
get {return Native.NativeConvert.ToErrno (errno);}
|
||||
}
|
||||
|
||||
private static string GetMessage (Native.Errno errno)
|
||||
{
|
||||
return string.Format ("{0} [{1}].",
|
||||
UnixMarshal.GetErrorDescription (errno),
|
||||
errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
173
Mono.Posix/Mono.Unix/UnixListener.cs
Normal file
173
Mono.Posix/Mono.Unix/UnixListener.cs
Normal file
@ -0,0 +1,173 @@
|
||||
//
|
||||
// UnixListener.cs
|
||||
//
|
||||
// Authors:
|
||||
// Joe Shaw (joeshaw@novell.com)
|
||||
//
|
||||
// Copyright (C) 2004-2005 Novell, Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.IO;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public class UnixListener : MarshalByRefObject, IDisposable {
|
||||
bool disposed;
|
||||
bool listening;
|
||||
Socket server;
|
||||
EndPoint savedEP;
|
||||
|
||||
void Init (UnixEndPoint ep)
|
||||
{
|
||||
listening = false;
|
||||
string filename = ep.Filename;
|
||||
if (File.Exists (filename)) {
|
||||
Socket conn = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
|
||||
try {
|
||||
conn.Connect (ep);
|
||||
conn.Close ();
|
||||
throw new InvalidOperationException ("There's already a server listening on " + filename);
|
||||
} catch (SocketException) {
|
||||
}
|
||||
File.Delete (filename);
|
||||
}
|
||||
|
||||
server = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
|
||||
server.Bind (ep);
|
||||
savedEP = server.LocalEndPoint;
|
||||
}
|
||||
|
||||
public UnixListener (string path)
|
||||
{
|
||||
if (!Directory.Exists (Path.GetDirectoryName (path)))
|
||||
Directory.CreateDirectory (Path.GetDirectoryName (path));
|
||||
|
||||
Init (new UnixEndPoint (path));
|
||||
}
|
||||
|
||||
public UnixListener (UnixEndPoint localEndPoint)
|
||||
{
|
||||
if (localEndPoint == null)
|
||||
throw new ArgumentNullException ("localendPoint");
|
||||
|
||||
Init (localEndPoint);
|
||||
}
|
||||
|
||||
public EndPoint LocalEndpoint {
|
||||
get { return savedEP; }
|
||||
}
|
||||
|
||||
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 ()
|
||||
{
|
||||
CheckDisposed ();
|
||||
if (!listening)
|
||||
throw new InvalidOperationException ("Socket is not listening");
|
||||
|
||||
return server.Poll (1000, SelectMode.SelectRead);
|
||||
}
|
||||
|
||||
public void Start ()
|
||||
{
|
||||
Start (5);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
496
Mono.Posix/Mono.Unix/UnixMarshal.cs
Normal file
496
Mono.Posix/Mono.Unix/UnixMarshal.cs
Normal file
@ -0,0 +1,496 @@
|
||||
//
|
||||
// Mono.Unix/UnixMarshal.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
// Scenario: We want to be able to translate an Error to a string.
|
||||
// Problem: Thread-safety. Strerror(3) isn't thread safe (unless
|
||||
// thread-local-variables are used, which is probably only
|
||||
// true on Windows).
|
||||
// Solution: Use strerror_r().
|
||||
// Problem: strerror_r() isn't portable.
|
||||
// (Apparently Solaris doesn't provide it.)
|
||||
// Solution: Cry. Then introduce an intermediary, ErrorMarshal.
|
||||
// ErrorMarshal exposes a single public delegate, Translator,
|
||||
// which will convert an Error to a string. It's static
|
||||
// constructor first tries using strerror_r(). If it works,
|
||||
// great; use it in the future. If it doesn't work, fallback to
|
||||
// using strerror(3).
|
||||
// This should be thread safe, since the check is done within the
|
||||
// class constructor lock.
|
||||
// Strerror(3) will be thread-safe from managed code, but won't
|
||||
// be thread-safe between managed & unmanaged code.
|
||||
internal class ErrorMarshal
|
||||
{
|
||||
internal delegate string ErrorTranslator (Native.Errno errno);
|
||||
|
||||
internal static readonly ErrorTranslator Translate;
|
||||
|
||||
static ErrorMarshal ()
|
||||
{
|
||||
try {
|
||||
Translate = new ErrorTranslator (strerror_r);
|
||||
Translate (Native.Errno.ERANGE);
|
||||
}
|
||||
catch (EntryPointNotFoundException) {
|
||||
Translate = new ErrorTranslator (strerror);
|
||||
}
|
||||
}
|
||||
|
||||
private static string strerror (Native.Errno errno)
|
||||
{
|
||||
return Native.Stdlib.strerror (errno);
|
||||
}
|
||||
|
||||
private static string strerror_r (Native.Errno errno)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder (16);
|
||||
int r = 0;
|
||||
do {
|
||||
buf.Capacity *= 2;
|
||||
r = Native.Syscall.strerror_r (errno, buf);
|
||||
} while (r == -1 && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
|
||||
|
||||
if (r == -1)
|
||||
return "** Unknown error code: " + ((int) errno) + "**";
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed /* static */ class UnixMarshal
|
||||
{
|
||||
private UnixMarshal () {}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public static string GetErrorDescription (Native.Errno errno)
|
||||
{
|
||||
return ErrorMarshal.Translate (errno);
|
||||
}
|
||||
|
||||
public static IntPtr AllocHeap (long size)
|
||||
{
|
||||
if (size < 0)
|
||||
throw new ArgumentOutOfRangeException ("size", "< 0");
|
||||
return Native.Stdlib.malloc ((ulong) size);
|
||||
}
|
||||
|
||||
public static IntPtr ReAllocHeap (IntPtr ptr, long size)
|
||||
{
|
||||
if (size < 0)
|
||||
throw new ArgumentOutOfRangeException ("size", "< 0");
|
||||
return Native.Stdlib.realloc (ptr, (ulong) size);
|
||||
}
|
||||
|
||||
public static void FreeHeap (IntPtr ptr)
|
||||
{
|
||||
Native.Stdlib.free (ptr);
|
||||
}
|
||||
|
||||
public static unsafe string PtrToStringUnix (IntPtr p)
|
||||
{
|
||||
if (p == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
int len = checked ((int) Native.Stdlib.strlen (p));
|
||||
return new string ((sbyte*) p, 0, len, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static string PtrToString (IntPtr p)
|
||||
{
|
||||
if (p == IntPtr.Zero)
|
||||
return null;
|
||||
return PtrToString (p, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static unsafe string PtrToString (IntPtr p, Encoding encoding)
|
||||
{
|
||||
if (p == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
if (encoding == null)
|
||||
throw new ArgumentNullException ("encoding");
|
||||
|
||||
int len = GetStringByteLength (p, encoding);
|
||||
|
||||
// Due to variable-length encoding schemes, GetStringByteLength() may
|
||||
// have returned multiple "null" characters. (For example, when
|
||||
// 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.
|
||||
string s = new string ((sbyte*) p, 0, len, encoding);
|
||||
len = s.Length;
|
||||
while (len > 0 && s [len-1] == 0)
|
||||
--len;
|
||||
if (len == s.Length)
|
||||
return s;
|
||||
return s.Substring (0, len);
|
||||
}
|
||||
|
||||
private static int GetStringByteLength (IntPtr p, Encoding encoding)
|
||||
{
|
||||
Type encodingType = encoding.GetType ();
|
||||
|
||||
int len = -1;
|
||||
|
||||
// Encodings that will always end with a single null byte
|
||||
if (typeof(UTF8Encoding).IsAssignableFrom (encodingType) ||
|
||||
typeof(UTF7Encoding).IsAssignableFrom (encodingType) ||
|
||||
typeof(UnixEncoding).IsAssignableFrom (encodingType) ||
|
||||
typeof(ASCIIEncoding).IsAssignableFrom (encodingType)) {
|
||||
len = checked ((int) Native.Stdlib.strlen (p));
|
||||
}
|
||||
// Encodings that will always end with a 0x0000 16-bit word
|
||||
else if (typeof(UnicodeEncoding).IsAssignableFrom (encodingType)) {
|
||||
len = GetInt16BufferLength (p);
|
||||
}
|
||||
// Encodings that will always end with a 0x00000000 32-bit word
|
||||
else if (typeof(UTF32Encoding).IsAssignableFrom (encodingType)) {
|
||||
len = GetInt32BufferLength (p);
|
||||
}
|
||||
// Some non-public encoding, such as Latin1 or a DBCS charset.
|
||||
// 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
|
||||
// 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).
|
||||
else {
|
||||
len = GetRandomBufferLength (p, encoding.GetMaxByteCount(1));
|
||||
}
|
||||
|
||||
if (len == -1)
|
||||
throw new NotSupportedException ("Unable to determine native string buffer length");
|
||||
return len;
|
||||
}
|
||||
|
||||
private static int GetInt16BufferLength (IntPtr p)
|
||||
{
|
||||
int len = 0;
|
||||
while (Marshal.ReadInt16 (p, len*2) != 0)
|
||||
checked {++len;}
|
||||
return checked(len*2);
|
||||
}
|
||||
|
||||
private static int GetInt32BufferLength (IntPtr p)
|
||||
{
|
||||
int len = 0;
|
||||
while (Marshal.ReadInt32 (p, len*4) != 0)
|
||||
checked {++len;}
|
||||
return checked(len*4);
|
||||
}
|
||||
|
||||
private static int GetRandomBufferLength (IntPtr p, int nullLength)
|
||||
{
|
||||
switch (nullLength) {
|
||||
case 1: return checked ((int) Native.Stdlib.strlen (p));
|
||||
case 2: return GetInt16BufferLength (p);
|
||||
case 4: return GetInt32BufferLength (p);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
int num_null_seen = 0;
|
||||
|
||||
do {
|
||||
byte b = Marshal.ReadByte (p, len++);
|
||||
if (b == 0)
|
||||
++num_null_seen;
|
||||
else
|
||||
num_null_seen = 0;
|
||||
} while (num_null_seen != nullLength);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Marshal a C `char **'. ANSI C `main' requirements are assumed:
|
||||
*
|
||||
* stringArray is an array of pointers to C strings
|
||||
* stringArray has a terminating NULL string.
|
||||
*
|
||||
* For example:
|
||||
* stringArray[0] = "string 1";
|
||||
* stringArray[1] = "string 2";
|
||||
* stringArray[2] = NULL
|
||||
*
|
||||
* The terminating NULL is required so that we know when to stop looking
|
||||
* for strings.
|
||||
*/
|
||||
public static string[] PtrToStringArray (IntPtr stringArray)
|
||||
{
|
||||
return PtrToStringArray (stringArray, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static string[] PtrToStringArray (IntPtr stringArray, Encoding encoding)
|
||||
{
|
||||
if (stringArray == IntPtr.Zero)
|
||||
return new string[]{};
|
||||
|
||||
int argc = CountStrings (stringArray);
|
||||
return PtrToStringArray (argc, stringArray, encoding);
|
||||
}
|
||||
|
||||
private static int CountStrings (IntPtr stringArray)
|
||||
{
|
||||
int count = 0;
|
||||
while (Marshal.ReadIntPtr (stringArray, count*IntPtr.Size) != IntPtr.Zero)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* terminating NULL element is not required.
|
||||
*
|
||||
* Usage is similar to ANSI C `main': count is argc, stringArray is argv.
|
||||
* stringArray[count] is NOT accessed (though ANSI C requires that
|
||||
* argv[argc] = NULL, which PtrToStringArray(IntPtr) requires).
|
||||
*/
|
||||
public static string[] PtrToStringArray (int count, IntPtr stringArray)
|
||||
{
|
||||
return PtrToStringArray (count, stringArray, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static string[] PtrToStringArray (int count, IntPtr stringArray, Encoding encoding)
|
||||
{
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException ("count", "< 0");
|
||||
if (encoding == null)
|
||||
throw new ArgumentNullException ("encoding");
|
||||
if (stringArray == IntPtr.Zero)
|
||||
return new string[count];
|
||||
|
||||
string[] members = new string[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
IntPtr s = Marshal.ReadIntPtr (stringArray, i * IntPtr.Size);
|
||||
members[i] = PtrToString (s, encoding);
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
public static IntPtr StringToHeap (string s)
|
||||
{
|
||||
return StringToHeap (s, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static IntPtr StringToHeap (string s, Encoding encoding)
|
||||
{
|
||||
if (s == null)
|
||||
return IntPtr.Zero;
|
||||
|
||||
return StringToHeap (s, 0, s.Length, encoding);
|
||||
}
|
||||
|
||||
public static IntPtr StringToHeap (string s, int index, int count)
|
||||
{
|
||||
return StringToHeap (s, index, count, UnixEncoding.Instance);
|
||||
}
|
||||
|
||||
public static IntPtr StringToHeap (string s, int index, int count, Encoding encoding)
|
||||
{
|
||||
if (s == null)
|
||||
return IntPtr.Zero;
|
||||
|
||||
if (encoding == null)
|
||||
throw new ArgumentNullException ("encoding");
|
||||
|
||||
if (index < 0 || count < 0)
|
||||
throw new ArgumentOutOfRangeException ((index < 0 ? "index" : "count"),
|
||||
"Non - negative number required.");
|
||||
|
||||
if (s.Length - index < count)
|
||||
throw new ArgumentOutOfRangeException ("s", "Index and count must refer to a location within the string.");
|
||||
|
||||
int null_terminator_count = encoding.GetMaxByteCount (1);
|
||||
int length_without_null = encoding.GetByteCount (s);
|
||||
int marshalLength = checked (length_without_null + null_terminator_count);
|
||||
|
||||
IntPtr mem = AllocHeap (marshalLength);
|
||||
if (mem == IntPtr.Zero)
|
||||
throw new UnixIOException (Native.Errno.ENOMEM);
|
||||
|
||||
unsafe {
|
||||
fixed (char* p = s) {
|
||||
byte* marshal = (byte*)mem;
|
||||
int bytes_copied;
|
||||
|
||||
try {
|
||||
bytes_copied = encoding.GetBytes (p + index, count, marshal, marshalLength);
|
||||
} catch {
|
||||
FreeHeap (mem);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (bytes_copied != length_without_null) {
|
||||
FreeHeap (mem);
|
||||
throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
|
||||
}
|
||||
|
||||
marshal += length_without_null;
|
||||
for (int i = 0; i < null_terminator_count; ++i)
|
||||
marshal[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
public static bool ShouldRetrySyscall (int r)
|
||||
{
|
||||
if (r == -1 && Native.Stdlib.GetLastError () == Native.Errno.EINTR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public static bool ShouldRetrySyscall (int r, out Native.Errno errno)
|
||||
{
|
||||
errno = (Native.Errno) 0;
|
||||
if (r == -1 && (errno = Native.Stdlib.GetLastError ()) == Native.Errno.EINTR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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)).
|
||||
internal static string EscapeFormatString (string message,
|
||||
char [] permitted)
|
||||
{
|
||||
if (message == null)
|
||||
return "";
|
||||
StringBuilder sb = new StringBuilder (message.Length);
|
||||
for (int i = 0; i < message.Length; ++i) {
|
||||
char c = message [i];
|
||||
sb.Append (c);
|
||||
if (c == '%' && (i+1) < message.Length) {
|
||||
char n = message [i+1];
|
||||
if (n == '%' || IsCharPresent (permitted, n))
|
||||
sb.Append (n);
|
||||
else
|
||||
sb.Append ('%').Append (n);
|
||||
++i;
|
||||
}
|
||||
// invalid format string: % at EOS.
|
||||
else if (c == '%')
|
||||
sb.Append ('%');
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
private static bool IsCharPresent (char[] array, char c)
|
||||
{
|
||||
if (array == null)
|
||||
return false;
|
||||
for (int i = 0; i < array.Length; ++i)
|
||||
if (array [i] == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static Exception CreateExceptionForError (Native.Errno errno)
|
||||
{
|
||||
string message = GetErrorDescription (errno);
|
||||
UnixIOException p = new UnixIOException (errno);
|
||||
|
||||
// Ordering: Order alphabetically by exception first (right column),
|
||||
// then order alphabetically by Errno value (left column) for the given
|
||||
// exception.
|
||||
switch (errno) {
|
||||
case Native.Errno.EBADF:
|
||||
case Native.Errno.EINVAL: return new ArgumentException (message, p);
|
||||
|
||||
case Native.Errno.ERANGE: return new ArgumentOutOfRangeException (message);
|
||||
case Native.Errno.ENOTDIR: return new DirectoryNotFoundException (message, p);
|
||||
case Native.Errno.ENOENT: return new FileNotFoundException (message, p);
|
||||
|
||||
case Native.Errno.EOPNOTSUPP:
|
||||
case Native.Errno.EPERM: return new InvalidOperationException (message, p);
|
||||
|
||||
case Native.Errno.ENOEXEC: return new InvalidProgramException (message, p);
|
||||
|
||||
case Native.Errno.EIO:
|
||||
case Native.Errno.ENOSPC:
|
||||
case Native.Errno.ENOTEMPTY:
|
||||
case Native.Errno.ENXIO:
|
||||
case Native.Errno.EROFS:
|
||||
case Native.Errno.ESPIPE: return new IOException (message, p);
|
||||
|
||||
case Native.Errno.EFAULT: return new NullReferenceException (message, p);
|
||||
case Native.Errno.EOVERFLOW: return new OverflowException (message, p);
|
||||
case Native.Errno.ENAMETOOLONG: return new PathTooLongException (message, p);
|
||||
|
||||
case Native.Errno.EACCES:
|
||||
case Native.Errno.EISDIR: return new UnauthorizedAccessException (message, p);
|
||||
|
||||
default: /* ignore */ break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
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
|
286
Mono.Posix/Mono.Unix/UnixPath.cs
Normal file
286
Mono.Posix/Mono.Unix/UnixPath.cs
Normal file
@ -0,0 +1,286 @@
|
||||
//
|
||||
// Mono.Unix/UnixPath.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixPath
|
||||
{
|
||||
private UnixPath () {}
|
||||
|
||||
public static readonly char DirectorySeparatorChar = '/';
|
||||
public static readonly char AltDirectorySeparatorChar = '/';
|
||||
public static readonly char PathSeparator = ':';
|
||||
public static readonly char VolumeSeparatorChar = '/';
|
||||
|
||||
private static readonly char[] _InvalidPathChars = new char[]{};
|
||||
|
||||
public static char[] GetInvalidPathChars ()
|
||||
{
|
||||
return (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");
|
||||
|
||||
int len = path1.Length;
|
||||
int start = -1;
|
||||
for (int 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;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder (len);
|
||||
if (start == -1) {
|
||||
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)
|
||||
{
|
||||
if (path.Length > 0 && part.Length > 0) {
|
||||
char end = path [path.Length-1];
|
||||
if (end != DirectorySeparatorChar &&
|
||||
end != AltDirectorySeparatorChar &&
|
||||
end != VolumeSeparatorChar)
|
||||
path.Append (DirectorySeparatorChar);
|
||||
}
|
||||
path.Append (part);
|
||||
}
|
||||
|
||||
public static string GetDirectoryName (string path)
|
||||
{
|
||||
CheckPath (path);
|
||||
|
||||
int lastDir = path.LastIndexOf (DirectorySeparatorChar);
|
||||
if (lastDir > 0)
|
||||
return path.Substring (0, lastDir);
|
||||
if (lastDir == 0)
|
||||
return "/";
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string GetFileName (string path)
|
||||
{
|
||||
if (path == null || path.Length == 0)
|
||||
return path;
|
||||
|
||||
int lastDir = path.LastIndexOf (DirectorySeparatorChar);
|
||||
if (lastDir >= 0)
|
||||
return path.Substring (lastDir+1);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string GetFullPath (string path)
|
||||
{
|
||||
path = _GetFullPath (path);
|
||||
return GetCanonicalPath (path);
|
||||
}
|
||||
|
||||
private static string _GetFullPath (string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
if (!IsPathRooted (path))
|
||||
path = UnixDirectoryInfo.GetCurrentDirectory() + DirectorySeparatorChar + path;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string GetCanonicalPath (string path)
|
||||
{
|
||||
string [] dirs;
|
||||
int lastIndex;
|
||||
GetPathComponents (path, out dirs, out lastIndex);
|
||||
string end = string.Join ("/", dirs, 0, lastIndex);
|
||||
return IsPathRooted (path) ? "/" + end : end;
|
||||
}
|
||||
|
||||
private static void GetPathComponents (string path,
|
||||
out string[] components, out int lastIndex)
|
||||
{
|
||||
string [] dirs = path.Split (DirectorySeparatorChar);
|
||||
int target = 0;
|
||||
for (int 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;
|
||||
}
|
||||
|
||||
public static string GetPathRoot (string path)
|
||||
{
|
||||
if (path == null)
|
||||
return null;
|
||||
if (!IsPathRooted (path))
|
||||
return "";
|
||||
return "/";
|
||||
}
|
||||
|
||||
public static string GetCompleteRealPath (string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException ("path");
|
||||
string [] dirs;
|
||||
int lastIndex;
|
||||
GetPathComponents (path, out dirs, out lastIndex);
|
||||
StringBuilder realPath = new StringBuilder ();
|
||||
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)
|
||||
{
|
||||
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,
|
||||
// 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 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
|
88
Mono.Posix/Mono.Unix/UnixPipes.cs
Normal file
88
Mono.Posix/Mono.Unix/UnixPipes.cs
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// Mono.Unix/UnixPipes.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public struct UnixPipes
|
||||
: IEquatable <UnixPipes>
|
||||
{
|
||||
public UnixPipes (UnixStream reading, UnixStream writing)
|
||||
{
|
||||
Reading = reading;
|
||||
Writing = writing;
|
||||
}
|
||||
|
||||
public UnixStream Reading;
|
||||
public UnixStream Writing;
|
||||
|
||||
public static UnixPipes CreatePipes ()
|
||||
{
|
||||
int reading, writing;
|
||||
int r = Native.Syscall.pipe (out reading, out writing);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return new UnixPipes (new UnixStream (reading), new UnixStream (writing));
|
||||
}
|
||||
|
||||
public override bool Equals (object value)
|
||||
{
|
||||
if ((value == null) || (value.GetType () != GetType ()))
|
||||
return false;
|
||||
UnixPipes other = (UnixPipes) value;
|
||||
return Reading.Handle == other.Reading.Handle &&
|
||||
Writing.Handle == other.Writing.Handle;
|
||||
}
|
||||
|
||||
public bool Equals (UnixPipes value)
|
||||
{
|
||||
return Reading.Handle == value.Reading.Handle &&
|
||||
Writing.Handle == value.Writing.Handle;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return Reading.Handle.GetHashCode () ^ Writing.Handle.GetHashCode ();
|
||||
}
|
||||
|
||||
public static bool operator== (UnixPipes lhs, UnixPipes rhs)
|
||||
{
|
||||
return lhs.Equals (rhs);
|
||||
}
|
||||
|
||||
public static bool operator!= (UnixPipes lhs, UnixPipes rhs)
|
||||
{
|
||||
return !lhs.Equals (rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
157
Mono.Posix/Mono.Unix/UnixProcess.cs
Normal file
157
Mono.Posix/Mono.Unix/UnixProcess.cs
Normal file
@ -0,0 +1,157 @@
|
||||
//
|
||||
// Mono.Unix/UnixProcess.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixProcess
|
||||
{
|
||||
private int pid;
|
||||
|
||||
internal UnixProcess (int pid)
|
||||
{
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public int Id {
|
||||
get {return pid;}
|
||||
}
|
||||
|
||||
public bool HasExited {
|
||||
get {
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WIFEXITED (status);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetProcessStatus ()
|
||||
{
|
||||
int status;
|
||||
int r = Native.Syscall.waitpid (pid, out status,
|
||||
Native.WaitOptions.WNOHANG | Native.WaitOptions.WUNTRACED);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
public int ExitCode {
|
||||
get {
|
||||
if (!HasExited)
|
||||
throw new InvalidOperationException (
|
||||
Locale.GetText ("Process hasn't exited"));
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WEXITSTATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSignaled {
|
||||
get {
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WIFSIGNALED (status);
|
||||
}
|
||||
}
|
||||
|
||||
public Native.Signum TerminationSignal {
|
||||
get {
|
||||
if (!HasSignaled)
|
||||
throw new InvalidOperationException (
|
||||
Locale.GetText ("Process wasn't terminated by a signal"));
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WTERMSIG (status);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasStopped {
|
||||
get {
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WIFSTOPPED (status);
|
||||
}
|
||||
}
|
||||
|
||||
public Native.Signum StopSignal {
|
||||
get {
|
||||
if (!HasStopped)
|
||||
throw new InvalidOperationException (
|
||||
Locale.GetText ("Process isn't stopped"));
|
||||
int status = GetProcessStatus ();
|
||||
return Native.Syscall.WSTOPSIG (status);
|
||||
}
|
||||
}
|
||||
|
||||
public int ProcessGroupId {
|
||||
get {return Native.Syscall.getpgid (pid);}
|
||||
set {
|
||||
int r = Native.Syscall.setpgid (pid, value);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
}
|
||||
|
||||
public int SessionId {
|
||||
get {
|
||||
int r = Native.Syscall.getsid (pid);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
public static UnixProcess GetCurrentProcess ()
|
||||
{
|
||||
return new UnixProcess (GetCurrentProcessId ());
|
||||
}
|
||||
|
||||
public static int GetCurrentProcessId ()
|
||||
{
|
||||
return Native.Syscall.getpid ();
|
||||
}
|
||||
|
||||
public void Kill ()
|
||||
{
|
||||
Signal (Native.Signum.SIGKILL);
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public void Signal (Native.Signum signal)
|
||||
{
|
||||
int r = Native.Syscall.kill (pid, signal);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public void WaitForExit ()
|
||||
{
|
||||
int status;
|
||||
int r;
|
||||
do {
|
||||
r = Native.Syscall.waitpid (pid, out status, (Native.WaitOptions) 0);
|
||||
} while (UnixMarshal.ShouldRetrySyscall (r));
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
227
Mono.Posix/Mono.Unix/UnixSignal.cs
Normal file
227
Mono.Posix/Mono.Unix/UnixSignal.cs
Normal file
@ -0,0 +1,227 @@
|
||||
//
|
||||
// Mono.Unix/UnixSignal.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jpryor@novell.com)
|
||||
// Tim Jenks (tim.jenks@realtimeworlds.com)
|
||||
//
|
||||
// (C) 2008 Novell, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using Mono.Unix.Native;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public class UnixSignal : WaitHandle {
|
||||
private int signum;
|
||||
private IntPtr signal_info;
|
||||
|
||||
static UnixSignal ()
|
||||
{
|
||||
Stdlib.VersionCheck ();
|
||||
}
|
||||
|
||||
public UnixSignal (Signum signum)
|
||||
{
|
||||
this.signum = NativeConvert.FromSignum (signum);
|
||||
this.signal_info = install (this.signum);
|
||||
if (this.signal_info == IntPtr.Zero) {
|
||||
throw new ArgumentException ("Unable to handle signal", "signum");
|
||||
}
|
||||
}
|
||||
|
||||
public UnixSignal (Mono.Unix.Native.RealTimeSignum rtsig)
|
||||
{
|
||||
signum = NativeConvert.FromRealTimeSignum (rtsig);
|
||||
this.signal_info = install (this.signum);
|
||||
Native.Errno err = Native.Stdlib.GetLastError ();
|
||||
if (this.signal_info == IntPtr.Zero) {
|
||||
if (err == Native.Errno.EADDRINUSE)
|
||||
throw new ArgumentException ("Signal registered outside of Mono.Posix", "signum");
|
||||
throw new ArgumentException ("Unable to handle signal", "signum");
|
||||
}
|
||||
}
|
||||
|
||||
public Signum Signum {
|
||||
get {
|
||||
if (IsRealTimeSignal)
|
||||
throw new InvalidOperationException ("This signal is a RealTimeSignum");
|
||||
return NativeConvert.ToSignum (signum);
|
||||
}
|
||||
}
|
||||
|
||||
public RealTimeSignum RealTimeSignum {
|
||||
get {
|
||||
if (!IsRealTimeSignal)
|
||||
throw new InvalidOperationException ("This signal is not a RealTimeSignum");
|
||||
return NativeConvert.ToRealTimeSignum (signum-GetSIGRTMIN ());
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRealTimeSignal {
|
||||
get {
|
||||
AssertValid ();
|
||||
int sigrtmin = GetSIGRTMIN ();
|
||||
if (sigrtmin == -1)
|
||||
return false;
|
||||
return signum >= sigrtmin;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
|
||||
EntryPoint="Mono_Unix_UnixSignal_install", SetLastError=true)]
|
||||
private static extern IntPtr install (int signum);
|
||||
|
||||
[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
|
||||
EntryPoint="Mono_Unix_UnixSignal_uninstall")]
|
||||
private static extern int uninstall (IntPtr info);
|
||||
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
delegate int Mono_Posix_RuntimeIsShuttingDown ();
|
||||
static Mono_Posix_RuntimeIsShuttingDown ShuttingDown = RuntimeShuttingDownCallback;
|
||||
|
||||
static int RuntimeShuttingDownCallback ()
|
||||
{
|
||||
return Environment.HasShutdownStarted ? 1 : 0;
|
||||
}
|
||||
|
||||
[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
|
||||
EntryPoint="Mono_Unix_UnixSignal_WaitAny")]
|
||||
private static extern int WaitAny (IntPtr[] infos, int count, int timeout, Mono_Posix_RuntimeIsShuttingDown shutting_down);
|
||||
|
||||
[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
|
||||
EntryPoint="Mono_Posix_SIGRTMIN")]
|
||||
internal static extern int GetSIGRTMIN ();
|
||||
|
||||
[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
|
||||
EntryPoint="Mono_Posix_SIGRTMAX")]
|
||||
internal static extern int GetSIGRTMAX ();
|
||||
|
||||
private void AssertValid ()
|
||||
{
|
||||
if (signal_info == IntPtr.Zero)
|
||||
throw new ObjectDisposedException (GetType().FullName);
|
||||
}
|
||||
|
||||
private unsafe SignalInfo* Info {
|
||||
get {
|
||||
AssertValid ();
|
||||
return (SignalInfo*) signal_info;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSet {
|
||||
get {
|
||||
return Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool Reset ()
|
||||
{
|
||||
int n = Interlocked.Exchange (ref Info->count, 0);
|
||||
return n != 0;
|
||||
}
|
||||
|
||||
public unsafe int Count {
|
||||
get {return Info->count;}
|
||||
set {Interlocked.Exchange (ref Info->count, value);}
|
||||
}
|
||||
|
||||
// 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
|
||||
#pragma warning disable 649
|
||||
[Map]
|
||||
struct SignalInfo {
|
||||
public int signum, count, read_fd, write_fd, pipecnt, pipelock, have_handler;
|
||||
public IntPtr handler; // Backed-up handler to restore when signal unregistered
|
||||
}
|
||||
#pragma warning restore 649
|
||||
|
||||
#region WaitHandle overrides
|
||||
protected unsafe override void Dispose (bool disposing)
|
||||
{
|
||||
base.Dispose (disposing);
|
||||
if (signal_info == IntPtr.Zero)
|
||||
return;
|
||||
uninstall (signal_info);
|
||||
signal_info = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public override bool WaitOne ()
|
||||
{
|
||||
return WaitOne (-1, false);
|
||||
}
|
||||
|
||||
public override bool WaitOne (TimeSpan timeout, bool exitContext)
|
||||
{
|
||||
long ms = (long) timeout.TotalMilliseconds;
|
||||
if (ms < -1 || ms > Int32.MaxValue)
|
||||
throw new ArgumentOutOfRangeException ("timeout");
|
||||
return WaitOne ((int) ms, exitContext);
|
||||
}
|
||||
|
||||
public override bool WaitOne (int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
AssertValid ();
|
||||
if (exitContext)
|
||||
throw new InvalidOperationException ("exitContext is not supported");
|
||||
if (millisecondsTimeout == 0)
|
||||
return IsSet;
|
||||
return WaitAny (new UnixSignal[]{this}, millisecondsTimeout) == 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static int WaitAny (UnixSignal[] signals)
|
||||
{
|
||||
return WaitAny (signals, -1);
|
||||
}
|
||||
|
||||
public static int WaitAny (UnixSignal[] signals, TimeSpan timeout)
|
||||
{
|
||||
long ms = (long) timeout.TotalMilliseconds;
|
||||
if (ms < -1 || ms > Int32.MaxValue)
|
||||
throw new ArgumentOutOfRangeException ("timeout");
|
||||
return WaitAny (signals, (int) ms);
|
||||
}
|
||||
|
||||
|
||||
public static unsafe int WaitAny (UnixSignal[] signals, int millisecondsTimeout)
|
||||
{
|
||||
if (signals == null)
|
||||
throw new ArgumentNullException ("signals");
|
||||
if (millisecondsTimeout < -1)
|
||||
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
|
||||
IntPtr[] infos = new IntPtr [signals.Length];
|
||||
for (int i = 0; i < signals.Length; ++i) {
|
||||
infos [i] = signals [i].signal_info;
|
||||
if (infos [i] == IntPtr.Zero)
|
||||
throw new InvalidOperationException ("Disposed UnixSignal");
|
||||
}
|
||||
return WaitAny (infos, infos.Length, millisecondsTimeout, ShuttingDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
435
Mono.Posix/Mono.Unix/UnixStream.cs
Normal file
435
Mono.Posix/Mono.Unix/UnixStream.cs
Normal file
@ -0,0 +1,435 @@
|
||||
//
|
||||
// Mono.Unix/UnixStream.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
// (C) 2007 Novell, Inc.
|
||||
//
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixStream : Stream, IDisposable
|
||||
{
|
||||
public const int InvalidFileDescriptor = -1;
|
||||
public const int StandardInputFileDescriptor = 0;
|
||||
public const int StandardOutputFileDescriptor = 1;
|
||||
public const int StandardErrorFileDescriptor = 2;
|
||||
|
||||
public UnixStream (int fileDescriptor)
|
||||
: this (fileDescriptor, true) {}
|
||||
|
||||
public UnixStream (int fileDescriptor, bool ownsHandle)
|
||||
{
|
||||
if (InvalidFileDescriptor == fileDescriptor)
|
||||
throw new ArgumentException (Locale.GetText ("Invalid file descriptor"), "fileDescriptor");
|
||||
|
||||
this.fileDescriptor = fileDescriptor;
|
||||
this.owner = ownsHandle;
|
||||
|
||||
long offset = Native.Syscall.lseek (fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
|
||||
if (offset != -1)
|
||||
canSeek = true;
|
||||
long read = Native.Syscall.read (fileDescriptor, IntPtr.Zero, 0);
|
||||
if (read != -1)
|
||||
canRead = true;
|
||||
long write = Native.Syscall.write (fileDescriptor, IntPtr.Zero, 0);
|
||||
if (write != -1)
|
||||
canWrite = true;
|
||||
}
|
||||
|
||||
private void AssertNotDisposed ()
|
||||
{
|
||||
if (fileDescriptor == InvalidFileDescriptor)
|
||||
throw new ObjectDisposedException ("Invalid File Descriptor");
|
||||
}
|
||||
|
||||
public int Handle {
|
||||
get {return fileDescriptor;}
|
||||
}
|
||||
|
||||
public override bool CanRead {
|
||||
get {return canRead;}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {return canSeek;}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {return canWrite;}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
AssertNotDisposed ();
|
||||
if (!CanSeek)
|
||||
throw new NotSupportedException ("File descriptor doesn't support seeking");
|
||||
RefreshStat ();
|
||||
return stat.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get {
|
||||
AssertNotDisposed ();
|
||||
if (!CanSeek)
|
||||
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 ();
|
||||
return (long) pos;
|
||||
}
|
||||
set {
|
||||
Seek (value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public Native.FilePermissions Protection {
|
||||
get {
|
||||
RefreshStat ();
|
||||
return stat.st_mode;
|
||||
}
|
||||
set {
|
||||
// we can't change file type with fchmod, so clear out that portion
|
||||
value &= ~Native.FilePermissions.S_IFMT;
|
||||
int r = Native.Syscall.fchmod (fileDescriptor, value);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
}
|
||||
|
||||
public FileTypes FileType {
|
||||
get {
|
||||
int type = (int) Protection;
|
||||
return (FileTypes) (type & (int) UnixFileSystemInfo.AllFileTypes);
|
||||
}
|
||||
// no set as fchmod(2) won't accept changing the file type.
|
||||
}
|
||||
|
||||
public FileAccessPermissions FileAccessPermissions {
|
||||
get {
|
||||
int perms = (int) Protection;
|
||||
return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
|
||||
}
|
||||
set {
|
||||
int perms = (int) Protection;
|
||||
perms &= (int) ~FileAccessPermissions.AllPermissions;
|
||||
perms |= (int) value;
|
||||
Protection = (Native.FilePermissions) perms;
|
||||
}
|
||||
}
|
||||
|
||||
public FileSpecialAttributes FileSpecialAttributes {
|
||||
get {
|
||||
int attrs = (int) Protection;
|
||||
return (FileSpecialAttributes) (attrs & (int) UnixFileSystemInfo.AllSpecialAttributes);
|
||||
}
|
||||
set {
|
||||
int perms = (int) Protection;
|
||||
perms &= (int) ~UnixFileSystemInfo.AllSpecialAttributes;
|
||||
perms |= (int) value;
|
||||
Protection = (Native.FilePermissions) perms;
|
||||
}
|
||||
}
|
||||
|
||||
public UnixUserInfo OwnerUser {
|
||||
get {RefreshStat (); return new UnixUserInfo (stat.st_uid);}
|
||||
}
|
||||
|
||||
public long OwnerUserId {
|
||||
get {RefreshStat (); return stat.st_uid;}
|
||||
}
|
||||
|
||||
public UnixGroupInfo OwnerGroup {
|
||||
get {RefreshStat (); return new UnixGroupInfo (stat.st_gid);}
|
||||
}
|
||||
|
||||
public long OwnerGroupId {
|
||||
get {RefreshStat (); return stat.st_gid;}
|
||||
}
|
||||
|
||||
private void RefreshStat ()
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
int r = Native.Syscall.fstat (fileDescriptor, out stat);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public void AdviseFileAccessPattern (FileAccessPattern pattern, long offset, long len)
|
||||
{
|
||||
FileHandleOperations.AdviseFileAccessPattern (fileDescriptor, pattern, offset, len);
|
||||
}
|
||||
|
||||
public void AdviseFileAccessPattern (FileAccessPattern pattern)
|
||||
{
|
||||
AdviseFileAccessPattern (pattern, 0, 0);
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (buffer.Length == 0)
|
||||
return 0;
|
||||
|
||||
long r = 0;
|
||||
fixed (byte* buf = &buffer[offset]) {
|
||||
do {
|
||||
r = Native.Syscall.read (fileDescriptor, buf, (ulong) count);
|
||||
} while (UnixMarshal.ShouldRetrySyscall ((int) r));
|
||||
}
|
||||
if (r == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
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 unsafe int ReadAtOffset ([In, Out] byte[] buffer,
|
||||
int offset, int count, long fileOffset)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
AssertValidBuffer (buffer, offset, count);
|
||||
if (!CanRead)
|
||||
throw new NotSupportedException ("Stream does not support reading");
|
||||
|
||||
if (buffer.Length == 0)
|
||||
return 0;
|
||||
|
||||
long r = 0;
|
||||
fixed (byte* buf = &buffer[offset]) {
|
||||
do {
|
||||
r = Native.Syscall.pread (fileDescriptor, buf, (ulong) count, fileOffset);
|
||||
} while (UnixMarshal.ShouldRetrySyscall ((int) r));
|
||||
}
|
||||
if (r == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
return (int) r;
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
if (!CanSeek)
|
||||
throw new NotSupportedException ("The File Descriptor 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;
|
||||
}
|
||||
|
||||
long pos = Native.Syscall.lseek (fileDescriptor, offset, sf);
|
||||
if (pos == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
return (long) pos;
|
||||
}
|
||||
|
||||
public override void SetLength (long value)
|
||||
{
|
||||
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)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
AssertValidBuffer (buffer, offset, count);
|
||||
if (!CanWrite)
|
||||
throw new NotSupportedException ("File Descriptor does not support writing");
|
||||
|
||||
if (buffer.Length == 0)
|
||||
return;
|
||||
|
||||
long r = 0;
|
||||
fixed (byte* buf = &buffer[offset]) {
|
||||
do {
|
||||
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)
|
||||
return;
|
||||
|
||||
long r = 0;
|
||||
fixed (byte* buf = &buffer[offset]) {
|
||||
do {
|
||||
r = Native.Syscall.pwrite (fileDescriptor, buf, (ulong) count, fileOffset);
|
||||
} while (UnixMarshal.ShouldRetrySyscall ((int) r));
|
||||
}
|
||||
if (r == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
}
|
||||
|
||||
public void SendTo (UnixStream output)
|
||||
{
|
||||
SendTo (output, (ulong) output.Length);
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public void SendTo (UnixStream output, ulong count)
|
||||
{
|
||||
SendTo (output.Handle, count);
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public void SendTo (int out_fd, ulong count)
|
||||
{
|
||||
if (!CanWrite)
|
||||
throw new NotSupportedException ("Unable to write to the current file descriptor");
|
||||
long offset = Position;
|
||||
long r = Native.Syscall.sendfile (out_fd, fileDescriptor, ref offset, count);
|
||||
if (r == -1)
|
||||
UnixMarshal.ThrowExceptionForLastError ();
|
||||
}
|
||||
|
||||
public void SetOwner (long user, long group)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
|
||||
int r = Native.Syscall.fchown (fileDescriptor,
|
||||
Convert.ToUInt32 (user), Convert.ToUInt32 (group));
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public void SetOwner (string user, string group)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
|
||||
long uid = new UnixUserInfo (user).UserId;
|
||||
long gid = new UnixGroupInfo (group).GroupId;
|
||||
SetOwner (uid, gid);
|
||||
}
|
||||
|
||||
public void SetOwner (string user)
|
||||
{
|
||||
AssertNotDisposed ();
|
||||
|
||||
Native.Passwd pw = Native.Syscall.getpwnam (user);
|
||||
if (pw == null)
|
||||
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
|
108
Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs
Normal file
108
Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// Mono.Unix/UnixSymbolicLinkInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2006 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixSymbolicLinkInfo : UnixFileSystemInfo
|
||||
{
|
||||
public UnixSymbolicLinkInfo (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
internal UnixSymbolicLinkInfo (string path, Native.Stat stat)
|
||||
: base (path, stat)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {return UnixPath.GetFileName (FullPath);}
|
||||
}
|
||||
|
||||
[Obsolete ("Use GetContents()")]
|
||||
public UnixFileSystemInfo Contents {
|
||||
get {return GetContents ();}
|
||||
}
|
||||
|
||||
public string ContentsPath {
|
||||
get {
|
||||
return UnixPath.ReadLink (FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasContents {
|
||||
get {
|
||||
return UnixPath.TryReadLink (FullPath) != null;
|
||||
}
|
||||
}
|
||||
|
||||
public UnixFileSystemInfo GetContents ()
|
||||
{
|
||||
return UnixFileSystemInfo.GetFileSystemEntry (
|
||||
UnixPath.Combine (UnixPath.GetDirectoryName (FullPath),
|
||||
ContentsPath));
|
||||
}
|
||||
|
||||
public void CreateSymbolicLinkTo (string path)
|
||||
{
|
||||
int r = Native.Syscall.symlink (path, FullName);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public void CreateSymbolicLinkTo (UnixFileSystemInfo path)
|
||||
{
|
||||
int r = Native.Syscall.symlink (path.FullName, FullName);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
public override void Delete ()
|
||||
{
|
||||
int r = Native.Syscall.unlink (FullPath);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
base.Refresh ();
|
||||
}
|
||||
|
||||
public override void SetOwner (long owner, long group)
|
||||
{
|
||||
int r = Native.Syscall.lchown (FullPath, Convert.ToUInt32 (owner), Convert.ToUInt32 (group));
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
}
|
||||
|
||||
protected override bool GetFileStatus (string path, out Native.Stat stat)
|
||||
{
|
||||
return Native.Syscall.lstat (path, out stat) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
193
Mono.Posix/Mono.Unix/UnixUserInfo.cs
Normal file
193
Mono.Posix/Mono.Unix/UnixUserInfo.cs
Normal file
@ -0,0 +1,193 @@
|
||||
//
|
||||
// Mono.Unix/UnixUserInfo.cs
|
||||
//
|
||||
// Authors:
|
||||
// Jonathan Pryor (jonpryor@vt.edu)
|
||||
//
|
||||
// (C) 2004-2005 Jonathan Pryor
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace Mono.Unix {
|
||||
|
||||
public sealed class UnixUserInfo
|
||||
{
|
||||
private Native.Passwd passwd;
|
||||
|
||||
public UnixUserInfo (string user)
|
||||
{
|
||||
passwd = new Native.Passwd ();
|
||||
Native.Passwd pw;
|
||||
int r = Native.Syscall.getpwnam_r (user, passwd, out pw);
|
||||
if (r != 0 || pw == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid username"), "user");
|
||||
}
|
||||
|
||||
[CLSCompliant (false)]
|
||||
public UnixUserInfo (uint user)
|
||||
{
|
||||
passwd = new Native.Passwd ();
|
||||
Native.Passwd pw;
|
||||
int r = Native.Syscall.getpwuid_r (user, passwd, out pw);
|
||||
if (r != 0 || pw == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
|
||||
}
|
||||
|
||||
public UnixUserInfo (long user)
|
||||
{
|
||||
passwd = new Native.Passwd ();
|
||||
Native.Passwd pw;
|
||||
int r = Native.Syscall.getpwuid_r (Convert.ToUInt32 (user), passwd, out pw);
|
||||
if (r != 0 || pw == null)
|
||||
throw new ArgumentException (Locale.GetText ("invalid user id"), "user");
|
||||
}
|
||||
|
||||
public UnixUserInfo (Native.Passwd passwd)
|
||||
{
|
||||
this.passwd = CopyPasswd (passwd);
|
||||
}
|
||||
|
||||
private static Native.Passwd CopyPasswd (Native.Passwd pw)
|
||||
{
|
||||
Native.Passwd p = new Native.Passwd ();
|
||||
|
||||
p.pw_name = pw.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 UserName {
|
||||
get {return passwd.pw_name;}
|
||||
}
|
||||
|
||||
public string Password {
|
||||
get {return passwd.pw_passwd;}
|
||||
}
|
||||
|
||||
public long UserId {
|
||||
get {return passwd.pw_uid;}
|
||||
}
|
||||
|
||||
public UnixGroupInfo Group {
|
||||
get {return new UnixGroupInfo (passwd.pw_gid);}
|
||||
}
|
||||
|
||||
public long GroupId {
|
||||
get {return passwd.pw_gid;}
|
||||
}
|
||||
|
||||
public string GroupName {
|
||||
get {return Group.GroupName;}
|
||||
}
|
||||
|
||||
public string RealName {
|
||||
get {return passwd.pw_gecos;}
|
||||
}
|
||||
|
||||
public string HomeDirectory {
|
||||
get {return passwd.pw_dir;}
|
||||
}
|
||||
|
||||
public string ShellProgram {
|
||||
get {return passwd.pw_shell;}
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return passwd.GetHashCode ();
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj == null || GetType () != obj.GetType())
|
||||
return false;
|
||||
return passwd.Equals (((UnixUserInfo) obj).passwd);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return passwd.ToString ();
|
||||
}
|
||||
|
||||
public static UnixUserInfo GetRealUser ()
|
||||
{
|
||||
return new UnixUserInfo (GetRealUserId ());
|
||||
}
|
||||
|
||||
public static long GetRealUserId ()
|
||||
{
|
||||
return Native.Syscall.getuid ();
|
||||
}
|
||||
|
||||
// I would hope that this is the same as GetCurrentUserName, but it is a
|
||||
// different syscall, so who knows.
|
||||
public static string GetLoginName ()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder (4);
|
||||
int r;
|
||||
do {
|
||||
buf.Capacity *= 2;
|
||||
r = Native.Syscall.getlogin_r (buf, (ulong) buf.Capacity);
|
||||
} while (r == (-1) && Native.Stdlib.GetLastError() == Native.Errno.ERANGE);
|
||||
UnixMarshal.ThrowExceptionForLastErrorIf (r);
|
||||
return buf.ToString ();
|
||||
}
|
||||
|
||||
public Native.Passwd ToPasswd ()
|
||||
{
|
||||
return CopyPasswd (passwd);
|
||||
}
|
||||
|
||||
public static UnixUserInfo[] GetLocalUsers ()
|
||||
{
|
||||
ArrayList entries = new ArrayList ();
|
||||
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
|
36
Mono.Posix/Properties/AssemblyInfo.cs
Normal file
36
Mono.Posix/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die einer Assembly zugeordnet sind.
|
||||
[assembly: AssemblyTitle("Mono.Posix.dll")]
|
||||
[assembly: AssemblyDescription("Unix Integration Classes")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Mono development team")]
|
||||
[assembly: AssemblyProduct("Mono Common Language Infrastructure")]
|
||||
[assembly: AssemblyCopyright("(c) Various Mono authors")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
|
||||
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("e2ca132e-e85c-40ad-be94-b138aa68772b")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
|
||||
// indem Sie "*" wie unten gezeigt eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("4.6.57.0")]
|
||||
[assembly: AssemblyFileVersion("4.6.57.0")]
|
Loading…
Reference in New Issue
Block a user