IDirectory.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Core.OsHle.Ipc;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Text;
  7. namespace Ryujinx.Core.OsHle.Objects.FspSrv
  8. {
  9. class IDirectory : IIpcInterface, IDisposable
  10. {
  11. private const int DirectoryEntrySize = 0x310;
  12. private Dictionary<int, ServiceProcessRequest> m_Commands;
  13. public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  14. private List<string> DirectoryEntries;
  15. private int CurrentItemIndex;
  16. public event EventHandler<EventArgs> Disposed;
  17. public string HostPath { get; private set; }
  18. public IDirectory(string HostPath, int Flags)
  19. {
  20. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  21. {
  22. { 0, Read },
  23. { 1, GetEntryCount }
  24. };
  25. this.HostPath = HostPath;
  26. DirectoryEntries = new List<string>();
  27. if ((Flags & 1) != 0)
  28. {
  29. DirectoryEntries.AddRange(Directory.GetDirectories(HostPath));
  30. }
  31. if ((Flags & 2) != 0)
  32. {
  33. DirectoryEntries.AddRange(Directory.GetFiles(HostPath));
  34. }
  35. CurrentItemIndex = 0;
  36. }
  37. public long Read(ServiceCtx Context)
  38. {
  39. long BufferPosition = Context.Request.ReceiveBuff[0].Position;
  40. long BufferLen = Context.Request.ReceiveBuff[0].Size;
  41. int MaxReadCount = (int)(BufferLen / DirectoryEntrySize);
  42. int Count = Math.Min(DirectoryEntries.Count - CurrentItemIndex, MaxReadCount);
  43. for (int Index = 0; Index < Count; Index++)
  44. {
  45. long Position = BufferPosition + Index * DirectoryEntrySize;
  46. WriteDirectoryEntry(Context, Position, DirectoryEntries[CurrentItemIndex++]);
  47. }
  48. Context.ResponseData.Write((long)Count);
  49. return 0;
  50. }
  51. private void WriteDirectoryEntry(ServiceCtx Context, long Position, string FullPath)
  52. {
  53. for (int Offset = 0; Offset < 0x300; Offset += 8)
  54. {
  55. Context.Memory.WriteInt64(Position + Offset, 0);
  56. }
  57. byte[] NameBuffer = Encoding.UTF8.GetBytes(Path.GetFileName(FullPath));
  58. AMemoryHelper.WriteBytes(Context.Memory, Position, NameBuffer);
  59. int Type = 0;
  60. long Size = 0;
  61. if (File.Exists(FullPath))
  62. {
  63. Type = 1;
  64. Size = new FileInfo(FullPath).Length;
  65. }
  66. Context.Memory.WriteInt32(Position + 0x300, 0); //Padding?
  67. Context.Memory.WriteInt32(Position + 0x304, Type);
  68. Context.Memory.WriteInt64(Position + 0x308, Size);
  69. }
  70. public long GetEntryCount(ServiceCtx Context)
  71. {
  72. Context.ResponseData.Write((long)DirectoryEntries.Count);
  73. return 0;
  74. }
  75. public void Dispose()
  76. {
  77. Dispose(true);
  78. }
  79. protected virtual void Dispose(bool disposing)
  80. {
  81. if (disposing)
  82. {
  83. Disposed?.Invoke(this, EventArgs.Empty);
  84. }
  85. }
  86. }
  87. }