Create Mono.Posix library

This commit is contained in:
BlubbFish 2019-02-17 15:51:09 +01:00
commit 749da0d8db
61 changed files with 18959 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/.vs
/Mono.Posix/obj
/Mono.Posix/bin

25
Mono.Posix.sln Normal file
View 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
View 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
View 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);
}
}

View 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>

View 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;
}
}
}

View 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);
}
}
}
}

View 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();
}
}
}

View 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);
}
}
}

View File

@ -0,0 +1 @@
/UnixConnectionPool.cs -crlf

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}
}

View 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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}
}

View 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--;
}
}
}
}
}
}

View 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);
}
}
}

View 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;
}
}
}
}

View File

@ -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;
}
}
}
}

View 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;
}
}
}

View 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

View 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;}
}
}

View 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:

File diff suppressed because it is too large Load Diff

View 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);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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")
{
}
}
}

View 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);
}
}
}

View 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);
}
}
}
}

View 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,
}
}

View 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,
}
}

View 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

View 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,
}
}

View 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,
}
}

View 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);
}
}
}
}

View 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

View 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);
}
}
}

View 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

View 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

View 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;
}
}
}

View 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);
}
}
}

View 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

View 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

View 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

View 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

View 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

View 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);
}
}
}

View 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

View 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

View 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

View 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

View 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);
}
}
}

View 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

View 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

View 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

View 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")]