UnixStream.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. using System;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. namespace BepInEx.Unix
  5. {
  6. internal class UnixStream : Stream
  7. {
  8. public override bool CanRead => Access == FileAccess.Read || Access == FileAccess.ReadWrite;
  9. public override bool CanSeek => false;
  10. public override bool CanWrite => Access == FileAccess.Write || Access == FileAccess.ReadWrite;
  11. public override long Length => throw new InvalidOperationException();
  12. public override long Position
  13. {
  14. get => throw new InvalidOperationException();
  15. set => throw new InvalidOperationException();
  16. }
  17. public FileAccess Access { get; }
  18. public IntPtr FileHandle { get; }
  19. public UnixStream(int fileDescriptor, FileAccess access)
  20. {
  21. Access = access;
  22. int newFd = UnixStreamHelper.dup(fileDescriptor);
  23. FileHandle = UnixStreamHelper.fdopen(newFd, access == FileAccess.Write ? "w" : "r");
  24. }
  25. public override void Flush()
  26. {
  27. UnixStreamHelper.fflush(FileHandle);
  28. }
  29. public override long Seek(long offset, SeekOrigin origin)
  30. {
  31. throw new InvalidOperationException();
  32. }
  33. public override void SetLength(long value)
  34. {
  35. throw new InvalidOperationException();
  36. }
  37. public override int Read(byte[] buffer, int offset, int count)
  38. {
  39. GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
  40. var read = UnixStreamHelper.fread(new IntPtr(gcHandle.AddrOfPinnedObject().ToInt64() + offset), (IntPtr)count, (IntPtr)1, FileHandle);
  41. gcHandle.Free();
  42. return read.ToInt32();
  43. }
  44. public override void Write(byte[] buffer, int offset, int count)
  45. {
  46. GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
  47. UnixStreamHelper.fwrite(new IntPtr(gcHandle.AddrOfPinnedObject().ToInt64() + offset), (IntPtr)count, (IntPtr)1, FileHandle);
  48. gcHandle.Free();
  49. }
  50. private void ReleaseUnmanagedResources()
  51. {
  52. UnixStreamHelper.fclose(FileHandle);
  53. }
  54. protected override void Dispose(bool disposing)
  55. {
  56. ReleaseUnmanagedResources();
  57. base.Dispose(disposing);
  58. }
  59. ~UnixStream()
  60. {
  61. Dispose(false);
  62. }
  63. }
  64. }