PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Core/System.IO.Pipes/PipeUnix.cs

https://bitbucket.org/steenlund/mono-2.6.7-for-amiga
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
  1. //
  2. // PipeUnix.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <atsushi@ximian.com>
  6. //
  7. // Copyright (C) 2009 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.ComponentModel;
  30. using System.IO;
  31. using System.Linq;
  32. using System.Net;
  33. using System.Runtime.InteropServices;
  34. using System.Security.AccessControl;
  35. using System.Security.Permissions;
  36. using System.Security.Principal;
  37. using System.Text;
  38. using System.Threading;
  39. using Microsoft.Win32;
  40. using Microsoft.Win32.SafeHandles;
  41. using Mono.Unix.Native;
  42. namespace System.IO.Pipes
  43. {
  44. abstract class UnixAnonymousPipe : IPipe
  45. {
  46. protected UnixAnonymousPipe ()
  47. {
  48. }
  49. public abstract SafePipeHandle Handle { get; }
  50. public void WaitForPipeDrain ()
  51. {
  52. throw new NotImplementedException ();
  53. }
  54. }
  55. class UnixAnonymousPipeClient : UnixAnonymousPipe, IAnonymousPipeClient
  56. {
  57. // AnonymousPipeClientStream owner;
  58. public UnixAnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
  59. {
  60. // this.owner = owner;
  61. this.handle = handle;
  62. }
  63. SafePipeHandle handle;
  64. public override SafePipeHandle Handle {
  65. get { return handle; }
  66. }
  67. }
  68. class UnixAnonymousPipeServer : UnixAnonymousPipe, IAnonymousPipeServer
  69. {
  70. // AnonymousPipeServerStream owner;
  71. public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
  72. {
  73. // this.owner = owner;
  74. throw new NotImplementedException ();
  75. }
  76. public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
  77. {
  78. // this.owner = owner;
  79. this.server_handle = serverHandle;
  80. this.client_handle = clientHandle;
  81. throw new NotImplementedException ();
  82. }
  83. SafePipeHandle server_handle, client_handle;
  84. public override SafePipeHandle Handle {
  85. get { return server_handle; }
  86. }
  87. public SafePipeHandle ClientHandle {
  88. get { return client_handle; }
  89. }
  90. public void DisposeLocalCopyOfClientHandle ()
  91. {
  92. throw new NotImplementedException ();
  93. }
  94. }
  95. abstract class UnixNamedPipe : IPipe
  96. {
  97. public abstract SafePipeHandle Handle { get; }
  98. public void WaitForPipeDrain ()
  99. {
  100. throw new NotImplementedException ();
  101. }
  102. public void EnsureTargetFile (string name)
  103. {
  104. if (!File.Exists (name)) {
  105. var error = Syscall.mknod (name, FilePermissions.S_IFIFO | FilePermissions.ALLPERMS, 0);
  106. if (error != 0)
  107. throw new IOException (String.Format ("Error on creating named pipe: error code {0}", error));
  108. }
  109. }
  110. protected void ValidateOptions (PipeOptions options, PipeTransmissionMode mode)
  111. {
  112. if ((options & PipeOptions.WriteThrough) != 0)
  113. throw new NotImplementedException ("WriteThrough is not supported");
  114. if ((mode & PipeTransmissionMode.Message) != 0)
  115. throw new NotImplementedException ("Message transmission mode is not supported");
  116. if ((options & PipeOptions.Asynchronous) != 0) // FIXME: use O_NONBLOCK?
  117. throw new NotImplementedException ("Asynchronous pipe mode is not supported");
  118. }
  119. protected string RightsToAccess (PipeAccessRights rights)
  120. {
  121. string access = null;
  122. if ((rights & PipeAccessRights.ReadData) != 0) {
  123. if ((rights & PipeAccessRights.WriteData) != 0)
  124. access = "r+";
  125. else
  126. access = "r";
  127. }
  128. else if ((rights & PipeAccessRights.WriteData) != 0)
  129. access = "w";
  130. else
  131. throw new InvalidOperationException ("The pipe must be opened to either read or write");
  132. return access;
  133. }
  134. protected FileAccess RightsToFileAccess (PipeAccessRights rights)
  135. {
  136. string access = null;
  137. if ((rights & PipeAccessRights.ReadData) != 0) {
  138. if ((rights & PipeAccessRights.WriteData) != 0)
  139. return FileAccess.ReadWrite;
  140. else
  141. return FileAccess.Read;
  142. }
  143. else if ((rights & PipeAccessRights.WriteData) != 0)
  144. return FileAccess.Write;
  145. else
  146. throw new InvalidOperationException ("The pipe must be opened to either read or write");
  147. }
  148. }
  149. class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
  150. {
  151. // .ctor with existing handle
  152. public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
  153. {
  154. this.owner = owner;
  155. this.handle = safePipeHandle;
  156. // FIXME: dunno how is_async could be filled.
  157. }
  158. // .ctor without handle - create new
  159. public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
  160. PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
  161. {
  162. this.owner = owner;
  163. if (serverName != "." && !Dns.GetHostEntry (serverName).AddressList.Contains (IPAddress.Loopback))
  164. throw new NotImplementedException ("Unix fifo does not support remote server connection");
  165. var name = Path.Combine ("/var/tmp/", pipeName);
  166. EnsureTargetFile (name);
  167. string access = RightsToAccess (desiredAccessRights);
  168. ValidateOptions (options, owner.TransmissionMode);
  169. // FIXME: handle inheritability
  170. opener = delegate {
  171. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (desiredAccessRights), FileShare.ReadWrite);
  172. owner.Stream = fs;
  173. handle = new SafePipeHandle (fs.Handle, false);
  174. };
  175. }
  176. NamedPipeClientStream owner;
  177. bool is_async;
  178. SafePipeHandle handle;
  179. Action opener;
  180. public override SafePipeHandle Handle {
  181. get { return handle; }
  182. }
  183. public void Connect ()
  184. {
  185. if (owner.IsConnected)
  186. throw new InvalidOperationException ("The named pipe is already connected");
  187. opener ();
  188. }
  189. public void Connect (int timeout)
  190. {
  191. AutoResetEvent waitHandle = new AutoResetEvent (false);
  192. opener.BeginInvoke (delegate (IAsyncResult result) {
  193. opener.EndInvoke (result);
  194. waitHandle.Set ();
  195. }, null);
  196. if (!waitHandle.WaitOne (TimeSpan.FromMilliseconds (timeout)))
  197. throw new TimeoutException ();
  198. }
  199. public bool IsAsync {
  200. get { return is_async; }
  201. }
  202. public int NumberOfServerInstances {
  203. get { throw new NotImplementedException (); }
  204. }
  205. }
  206. class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
  207. {
  208. //NamedPipeServerStream owner;
  209. // .ctor with existing handle
  210. public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
  211. {
  212. this.handle = safePipeHandle;
  213. //this.owner = owner;
  214. }
  215. // .ctor without handle - create new
  216. public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
  217. PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options,
  218. int inBufferSize, int outBufferSize, HandleInheritability inheritability)
  219. {
  220. string name = Path.Combine ("/var/tmp/", pipeName);
  221. EnsureTargetFile (name);
  222. string access = RightsToAccess (rights);
  223. ValidateOptions (options, owner.TransmissionMode);
  224. // FIXME: maxNumberOfServerInstances, modes, sizes, handle inheritability
  225. var fs = new FileStream (name, FileMode.Open, RightsToFileAccess (rights), FileShare.ReadWrite);
  226. handle = new SafePipeHandle (fs.Handle, false);
  227. owner.Stream = fs;
  228. should_close_handle = true;
  229. }
  230. SafePipeHandle handle;
  231. bool should_close_handle;
  232. public override SafePipeHandle Handle {
  233. get { return handle; }
  234. }
  235. public void Disconnect ()
  236. {
  237. if (should_close_handle)
  238. Syscall.fclose (handle.DangerousGetHandle ());
  239. }
  240. public void WaitForConnection ()
  241. {
  242. // FIXME: what can I do here?
  243. }
  244. }
  245. }