PathEntry.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Text;
  6. namespace IsoFilePatcher.Iso9660
  7. {
  8. [DebuggerDisplay("\\{ Name={Name} {ChildPathEntries} \\}")]
  9. internal class PathEntry
  10. {
  11. public static PathEntry Parse(Stream stream, VolumeDescriptor volumeDescriptor)
  12. {
  13. var obj = new PathEntry();
  14. obj.VolumeDescriptor = volumeDescriptor;
  15. obj.Read(stream);
  16. return obj;
  17. }
  18. public VolumeDescriptor VolumeDescriptor { get; set; }
  19. private void Read(Stream stream)
  20. {
  21. var begin = stream.Position; // For DEBUGGING watch
  22. var len = stream.ReadByte(); //this byte included in size
  23. if (len == 0)
  24. {
  25. InvalidData = true;
  26. return;
  27. }
  28. int nameByteLen;
  29. using (var br = new BinaryReader(stream, Encoding.ASCII, true))
  30. {
  31. ExtendedAttributeRecordlength = br.ReadByte();
  32. ExtentLba = br.ReadUInt32LsbMsb();
  33. DataLength = br.ReadUInt32LsbMsb();
  34. Date = br.ReadFileRecordDate();
  35. FileFlags = br.ReadByte();
  36. FileUnitSize = br.ReadByte();
  37. InterleaveGapSize = br.ReadByte();
  38. VolumeSequenceNumber = br.ReadUInt16LsbMsb();
  39. nameByteLen = br.ReadByte();
  40. Name = br.ReadString(nameByteLen, VolumeDescriptor.Encoding);
  41. if (Name.EndsWith(";1"))
  42. Name = Name.Substring(0, Name.Length - 2);
  43. if (nameByteLen % 2 == 0)
  44. {
  45. PaddingByte = br.ReadByte();
  46. if (PaddingByte != 0)
  47. {
  48. throw new InvalidDataException("Invalid padding byte, data error?");
  49. }
  50. }
  51. var remain = len - (stream.Position - begin);
  52. if (remain > 0)
  53. RemainBytes = br.ReadBytes((int)remain);
  54. }
  55. }
  56. public byte? PaddingByte { get; set; }
  57. public byte[] RemainBytes { get; set; }
  58. public bool InvalidData { get; set; }
  59. public string Name { get; set; }
  60. public ushort VolumeSequenceNumber { get; set; }
  61. public byte InterleaveGapSize { get; set; }
  62. public byte FileUnitSize { get; set; }
  63. public byte FileFlags { get; set; }
  64. public DateTime Date { get; set; }
  65. public uint DataLength { get; set; }
  66. public uint ExtentLba { get; set; }
  67. public byte ExtendedAttributeRecordlength { get; set; }
  68. public bool IsHidden => (FileFlags & 1) != 0;
  69. public bool IsDirectory => (FileFlags & (1 << 1)) != 0;
  70. public bool IsAssociatedFile => (FileFlags & (1 << 2)) != 0;
  71. public PathEntry[] ChildPathEntries { get; set; }
  72. public void ScanChilds(Stream stream)
  73. {
  74. stream.Seek(ExtentLba * VolumeDescriptor.LogicalBlockSize, SeekOrigin.Begin);
  75. var list = new List<PathEntry>();
  76. var endofData = stream.Position + DataLength;
  77. while (stream.Position < endofData)
  78. {
  79. var item = Parse(stream, VolumeDescriptor);
  80. if (VolumeDescriptor.Type == 1)
  81. if (item.Name == "\0" || item.Name == "\u0001") continue;
  82. if(VolumeDescriptor.Type==2)
  83. if (item.Name == "�" || item.Name == "\u0001") continue;
  84. if (item.InvalidData) break;
  85. list.Add(item);
  86. }
  87. ChildPathEntries = list.ToArray();
  88. list.ForEach(p =>
  89. {
  90. if (p.IsDirectory)
  91. p.ScanChilds(stream);
  92. });
  93. }
  94. }
  95. }