Class: NTFS::AttribHeader
- Inherits:
-
Object
- Object
- NTFS::AttribHeader
- Defined in:
- lib/fs/ntfs/attrib_header.rb
Overview
One Attribute Header.
Constant Summary collapse
- AF_COMPRESSED =
0x0001
- AF_ENCRPYTED =
0x4000
- AF_SPARSE =
0x8000
- RESIDENT_ATTR_IS_INDEXED =
Attribute is referenced in an index
0x01
Instance Attribute Summary collapse
-
#flags ⇒ Object
readonly
Returns the value of attribute flags.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#length ⇒ Object
readonly
Returns the value of attribute length.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#namelen ⇒ Object
readonly
Returns the value of attribute namelen.
-
#specific ⇒ Object
readonly
Returns the value of attribute specific.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
-
#typeName ⇒ Object
readonly
Returns the value of attribute typeName.
Instance Method Summary collapse
-
#containsFileNameIndexes? ⇒ Boolean
The $I30 is the a “file” name given to NTFS MFT attributes containing file name indexes for directories.
- #dump ⇒ Object
- #get_value(buf, boot_sector) ⇒ Object
-
#initialize(buf) ⇒ AttribHeader
constructor
NOTE: All the subordinate objects (attrib header & attributes) take a buffer (a packed string) starting at the start of the sub object.
- #isCompressed? ⇒ Boolean
- #isEncrypted? ⇒ Boolean
- #isResident? ⇒ Boolean
- #isSparse? ⇒ Boolean
-
#to_s ⇒ Object
Name will always be something, either name or N/A.
Constructor Details
#initialize(buf) ⇒ AttribHeader
NOTE: All the subordinate objects (attrib header & attributes) take
a buffer (a packed string) starting at the start of the sub object.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/fs/ntfs/attrib_header.rb', line 83 def initialize(buf) raise "MIQ(NTFS::AttribHeader.initialize) Nil buffer" if buf.nil? # Decode standard attribute header. @header = STANDARD_ATTRIBUTE_HEADER.decode(buf) offset = SIZEOF_STANDARD_ATTRIBUTE_HEADER # If type is AT_END we're done. return nil if @header['attrib_type'] == AT_END # Get accessor values. @length = @header['length'] @id = @header['attrib_id'] @flags = @header['flags'] @type = @header['attrib_type'] @namelen = @header['name_length'] # Get the rest of the data (a resident or non-resident struct). which = isResident? ? SAH_RESIDENT : SAH_NONRESIDENT len = isResident? ? SIZEOF_SAH_RESIDENT : SIZEOF_SAH_NONRESIDENT @specific = which.decode(buf[offset..-1]) offset += len # If there's a name get it. @name = buf[offset, (@namelen * 2)].UnicodeToUtf8 if @namelen != 0 end |
Instance Attribute Details
#flags ⇒ Object (readonly)
Returns the value of attribute flags.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def flags @flags end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def id @id end |
#length ⇒ Object (readonly)
Returns the value of attribute length.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def length @length end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def name @name end |
#namelen ⇒ Object (readonly)
Returns the value of attribute namelen.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def namelen @namelen end |
#specific ⇒ Object (readonly)
Returns the value of attribute specific.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def specific @specific end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def type @type end |
#typeName ⇒ Object (readonly)
Returns the value of attribute typeName.
72 73 74 |
# File 'lib/fs/ntfs/attrib_header.rb', line 72 def typeName @typeName end |
Instance Method Details
#containsFileNameIndexes? ⇒ Boolean
The $I30 is the a “file” name given to NTFS MFT attributes containing file name indexes for directories. NTFS stores the file name contents of the directory in several places, depending on the number of files in the directory:
-
For directories with just a few files, all are stored resident in the MFT entry $INDEX_ROOT
-
For directories with many files, the indexes are stored non-resident in the MFT entry $INDEX_ALLOCATION
-
The allocation status of these entries are managed by the $BITMAP MFT entry
NTFS uses B-tree structures to store and quickly access the data. So, the $INDEX_ROOT attribute (with a name of $I30) was not large enough to store the B-tree index of file names. Instead, it points to index records stored in the non-resident $INDEX_ALLOCATION. Viewing the contents of that file, the B-tree index of file names in the directory.
164 165 166 |
# File 'lib/fs/ntfs/attrib_header.rb', line 164 def containsFileNameIndexes? name == "$I30" end |
#dump ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/fs/ntfs/attrib_header.rb', line 168 def dump out = "\#<#{self.class}:0x#{'%08x' % object_id}>\n" out << " Type : 0x#{'%08x' % @header['attrib_type']} (#{typeName})\n" out << " Length : 0x#{'%08x' % @header['length']}\n" out << " Non resident : 0x#{'%02x' % @header['non_resident']}\n" out << " Name length : 0x#{'%02x' % @header['name_length']}\n" out << " Offset to name : 0x#{'%04x' % @header['name_offset']}\n" out << " Flags : 0x#{'%04x' % @header['flags']}\n" out << " Attrib id : 0x#{'%04x' % @header['attrib_id']}\n" # Further depends on type. if self.isResident? out << " Value length : 0x#{'%08x' % @specific['value_length']}\n" out << " Value offset : 0x#{'%04x' % @specific['value_offset']}\n" out << " Resident Flags : 0x#{'%02x' % @specific['resident_flags']}\n" else out << " First VCN : 0x#{'%016x' % @specific['first_vcn']}\n" out << " Last VCN : 0x#{'%016x' % @specific['last_vcn']}\n" out << " Mapping Pairs Offset: 0x#{'%04x' % @specific['mapping_pairs_offset']}\n" out << " Compression : 0x#{'%04x' % @specific['compression_unit']}\n" out << " Allocated size : 0x#{'%016x' % @specific['allocated_size']}\n" out << " Data size : 0x#{'%016x' % @specific['data_size']}\n" out << " Initialized size : 0x#{'%016x' % @specific['initialized_size']}\n" end out << " Name : #{@name}\n" if @header['name_length'] > 0 out << "---\n" end |
#get_value(buf, boot_sector) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/fs/ntfs/attrib_header.rb', line 110 def get_value(buf, boot_sector) # Prep a buffer to pass to subobjects. if isResident? # Resident attributes are after header res struct & name. abuf = buf[@specific['value_offset'], @specific['value_length']] else # Nonresident attributes are defined by data runs. alen = @specific['data_size'] alen = buf.size if alen == 0 abuf = DataRun.new(boot_sector, buf[@specific['mapping_pairs_offset'], alen], self) end abuf end |
#isCompressed? ⇒ Boolean
138 139 140 |
# File 'lib/fs/ntfs/attrib_header.rb', line 138 def isCompressed? NTFS::Utils.gotBit?(@flags, AF_COMPRESSED) end |
#isEncrypted? ⇒ Boolean
142 143 144 |
# File 'lib/fs/ntfs/attrib_header.rb', line 142 def isEncrypted? NTFS::Utils.gotBit?(@flags, AF_ENCRYPTED) end |
#isResident? ⇒ Boolean
130 131 132 |
# File 'lib/fs/ntfs/attrib_header.rb', line 130 def isResident? @header['non_resident'] == 0 end |
#isSparse? ⇒ Boolean
146 147 148 |
# File 'lib/fs/ntfs/attrib_header.rb', line 146 def isSparse? NTFS::Utils.gotBit?(@flags, AF_SPARSE) end |
#to_s ⇒ Object
Name will always be something, either name or N/A
126 127 128 |
# File 'lib/fs/ntfs/attrib_header.rb', line 126 def to_s @name.nil? ? 'N/A' : @name end |