/mcs/class/System.Core/System.IO.Pipes/PipeUnix.cs
C# | 296 lines | 203 code | 51 blank | 42 comment | 29 complexity | e2986b82889d0e8b9ee05b136b332c1b MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, LGPL-2.1
- //
- // PipeUnix.cs
- //
- // Author:
- // Atsushi Enomoto <atsushi@ximian.com>
- //
- // Copyright (C) 2009 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.ComponentModel;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Runtime.InteropServices;
- using System.Security.AccessControl;
- using System.Security.Permissions;
- using System.Security.Principal;
- using System.Text;
- using System.Threading;
- using Microsoft.Win32;
- using Microsoft.Win32.SafeHandles;
- using Mono.Unix.Native;
- namespace System.IO.Pipes
- {
- abstract class UnixAnonymousPipe : IPipe
- {
- protected UnixAnonymousPipe ()
- {
- }
- public abstract SafePipeHandle Handle { get; }
- public void WaitForPipeDrain ()
- {
- throw new NotImplementedException ();
- }
- }
- class UnixAnonymousPipeClient : UnixAnonymousPipe, IAnonymousPipeClient
- {
- // AnonymousPipeClientStream owner;
- public UnixAnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
- {
- // this.owner = owner;
- this.handle = handle;
- }
- SafePipeHandle handle;
- public override SafePipeHandle Handle {
- get { return handle; }
- }
- }
- class UnixAnonymousPipeServer : UnixAnonymousPipe, IAnonymousPipeServer
- {
- // AnonymousPipeServerStream owner;
- public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
- {
- // this.owner = owner;
- throw new NotImplementedException ();
- }
- public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
- {
- // this.owner = owner;
- this.server_handle = serverHandle;
- this.client_handle = clientHandle;
- throw new NotImplementedException ();
- }
- SafePipeHandle server_handle, client_handle;
- public override SafePipeHandle Handle {
- get { return server_handle; }
- }
- public SafePipeHandle ClientHandle {
- get { return client_handle; }
- }
- public void DisposeLocalCopyOfClientHandle ()
- {
- throw new NotImplementedException ();
- }
- }
- abstract class UnixNamedPipe : IPipe
- {
- public abstract SafePipeHandle Handle { get; }
- public void WaitForPipeDrain ()
- {
- throw new NotImplementedException ();
- }
-
- public void EnsureTargetFile (string name)
- {
- if (!File.Exists (name)) {
- var error = Syscall.mknod (name, FilePermissions.S_IFIFO | FilePermissions.ALLPERMS, 0);
- if (error != 0)
- throw new IOException (String.Format ("Error on creating named pipe: error code {0}", error));
- }
- }
- protected void ValidateOptions (PipeOptions options, PipeTransmissionMode mode)
- {
- if ((options & PipeOptions.WriteThrough) != 0)
- throw new NotImplementedException ("WriteThrough is not supported");
- if ((mode & PipeTransmissionMode.Message) != 0)
- throw new NotImplementedException ("Message transmission mode is not supported");
- if ((options & PipeOptions.Asynchronous) != 0) // FIXME: use O_NONBLOCK?
- throw new NotImplementedException ("Asynchronous pipe mode is not supported");
- }
-
- protected string RightsToAccess (PipeAccessRights rights)
- {
- string access = null;
- if ((rights & PipeAccessRights.ReadData) != 0) {
- if ((rights & PipeAccessRights.WriteData) != 0)
- access = "r+";
- else
- access = "r";
- }
- else if ((rights & PipeAccessRights.WriteData) != 0)
- access = "w";
- else
- throw new InvalidOperationException ("The pipe must be opened to either read or write");
- return access;
- }
-
- protected FileAccess RightsToFileAccess (PipeAccessRights rights)
- {
- string access = null;
- if ((rights & PipeAccessRights.ReadData) != 0) {
- if ((rights & PipeAccessRights.WriteData) != 0)
- return FileAccess.ReadWrite;
- else
- return FileAccess.Read;
- }
- else if ((rights & PipeAccessRights.WriteData) != 0)
- return FileAccess.Write;
- else
- throw new InvalidOperationException ("The pipe must be opened to either read or write");
- }
- }
- class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
- {
- // .ctor with existing handle
- public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
- {
- this.owner = owner;
- this.handle = safePipeHandle;
- // FIXME: dunno how is_async could be filled.
- }
- // .ctor without handle - create new
- public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
- PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
- {
- this.owner = owner;
- if (serverName != "." && !Dns.GetHostEntry (serverName).AddressList.Contains (IPAddress.Loopback))
- throw new NotImplementedException ("Unix fifo does not support remote server connection");
- var name = Path.Combine ("/var/tmp/", pipeName);
- EnsureTargetFile (name);
-
- string access = RightsToAccess (desiredAccessRights);
-
- ValidateOptions (options, owner.TransmissionMode);
-
- // FIXME: handle inheritability
- opener = delegate {
- var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (desiredAccessRights), FileShare.ReadWrite);
- owner.Stream = fs;
- handle = new SafePipeHandle (fs.Handle, false);
- };
- }
- NamedPipeClientStream owner;
- bool is_async;
- SafePipeHandle handle;
- Action opener;
- public override SafePipeHandle Handle {
- get { return handle; }
- }
- public void Connect ()
- {
- if (owner.IsConnected)
- throw new InvalidOperationException ("The named pipe is already connected");
- opener ();
- }
- public void Connect (int timeout)
- {
- AutoResetEvent waitHandle = new AutoResetEvent (false);
- opener.BeginInvoke (delegate (IAsyncResult result) {
- opener.EndInvoke (result);
- waitHandle.Set ();
- }, null);
- if (!waitHandle.WaitOne (TimeSpan.FromMilliseconds (timeout)))
- throw new TimeoutException ();
- }
- public bool IsAsync {
- get { return is_async; }
- }
- public int NumberOfServerInstances {
- get { throw new NotImplementedException (); }
- }
- }
- class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
- {
- //NamedPipeServerStream owner;
- // .ctor with existing handle
- public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
- {
- this.handle = safePipeHandle;
- //this.owner = owner;
- }
- // .ctor without handle - create new
- public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
- PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options,
- int inBufferSize, int outBufferSize, HandleInheritability inheritability)
- {
- string name = Path.Combine ("/var/tmp/", pipeName);
- EnsureTargetFile (name);
- string access = RightsToAccess (rights);
- ValidateOptions (options, owner.TransmissionMode);
- // FIXME: maxNumberOfServerInstances, modes, sizes, handle inheritability
-
- var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (rights), FileShare.ReadWrite);
- handle = new SafePipeHandle (fs.Handle, false);
- owner.Stream = fs;
- should_close_handle = true;
- }
- SafePipeHandle handle;
- bool should_close_handle;
- public override SafePipeHandle Handle {
- get { return handle; }
- }
- public void Disconnect ()
- {
- if (should_close_handle)
- Syscall.fclose (handle.DangerousGetHandle ());
- }
- public void WaitForConnection ()
- {
- // FIXME: what can I do here?
- }
- }
- }