IndexRootRecord.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace DiskAccessLibrary.FileSystems.NTFS
  12. {
  13. [Flags]
  14. public enum IndexRootFlags : byte
  15. {
  16. LargeIndex = 0x01, // denotes the presence of IndexAllocation record
  17. }
  18. // IndexRoot attribute is always resident
  19. public class IndexRootRecord : ResidentAttributeRecord
  20. {
  21. public const string FileNameIndexName = "$I30";
  22. /* Index root start */
  23. public AttributeType IndexedAttributeType; // FileName for directories
  24. public CollationRule CollationRule;
  25. public uint IndexAllocationEntryLength; // in bytes
  26. public byte ClustersPerIndexRecord;
  27. // 3 zero bytes
  28. /* Index root end */
  29. /* Index Header start */
  30. public uint EntriesOffset; // relative to Index Header start offset
  31. public uint IndexLength; // including the Index Header
  32. public uint AllocatedLength;
  33. public IndexRootFlags IndexFlags;
  34. // 3 zero bytes
  35. /* Index Header end */
  36. public List<IndexNodeEntry> IndexEntries = new List<IndexNodeEntry>();
  37. public List<FileNameIndexEntry> FileNameEntries = new List<FileNameIndexEntry>();
  38. public IndexRootRecord(byte[] buffer, int offset) : base(buffer, offset)
  39. {
  40. IndexedAttributeType = (AttributeType)LittleEndianConverter.ToUInt32(this.Data, 0x00);
  41. CollationRule = (CollationRule)LittleEndianConverter.ToUInt32(this.Data, 0x04);
  42. IndexAllocationEntryLength = LittleEndianConverter.ToUInt32(this.Data, 0x08);
  43. ClustersPerIndexRecord = ByteReader.ReadByte(this.Data, 0x0C);
  44. // 3 zero bytes (padding to 8-byte boundary)
  45. EntriesOffset = LittleEndianConverter.ToUInt32(this.Data, 0x10);
  46. IndexLength = LittleEndianConverter.ToUInt32(this.Data, 0x14);
  47. AllocatedLength = LittleEndianConverter.ToUInt32(this.Data, 0x18);
  48. IndexFlags = (IndexRootFlags)ByteReader.ReadByte(this.Data, 0x1C);
  49. // 3 zero bytes (padding to 8-byte boundary)
  50. if (Name == FileNameIndexName)
  51. {
  52. int position = 0x10 + (int)EntriesOffset;
  53. if (IsLargeIndex)
  54. {
  55. IndexNode node = new IndexNode(this.Data, position);
  56. IndexEntries = node.Entries;
  57. }
  58. else
  59. {
  60. FileNameIndexLeafNode leaf = new FileNameIndexLeafNode(this.Data, position);
  61. FileNameEntries = leaf.Entries;
  62. }
  63. }
  64. }
  65. public KeyValuePairList<MftSegmentReference, FileNameRecord> GetSmallIndexEntries()
  66. {
  67. if (IsLargeIndex)
  68. {
  69. throw new ArgumentException("Not a small index");
  70. }
  71. KeyValuePairList<MftSegmentReference, FileNameRecord> result = new KeyValuePairList<MftSegmentReference, FileNameRecord>();
  72. foreach (FileNameIndexEntry entry in FileNameEntries)
  73. {
  74. result.Add(entry.FileReference, entry.Record);
  75. }
  76. return result;
  77. }
  78. public bool IsLargeIndex
  79. {
  80. get
  81. {
  82. return (IndexFlags & IndexRootFlags.LargeIndex) > 0;
  83. }
  84. }
  85. }
  86. }