Class: Iso9660::BootSector

Inherits:
Object
  • Object
show all
Defined in:
lib/fs/iso9660/boot_sector.rb

Constant Summary collapse

DESCRIPTOR_ID =

Universal Volume Descriptor ID.

"CD001"
TYPE_BOOT =

Volume descriptor types.

0
TYPE_PRIM_DESC =

The descriptor is a boot record.

1
TYPE_SUPP_DESC =

The descriptor is a primary volume descriptor.

2
TYPE_PART_DESC =

The descriptor is a supplementary volume descriptor.

3
TYPE_TERMINATOR =

The descriptor is a volume partition descriptor.

255
VOLUME_DESCRIPTOR =

This serves as both the primary and supplementary descriptor structure.

BinaryStruct.new([
  'C',    'desc_type',                # TYPE_ enum.
  'a5',   'id',                       # Always "CD001".
  'C',    'version',                  # Must be 1.
  'C',    'vol_flags',                # Unused on primary.
  'a32',  'system_id',                # An 'extra' label.
  'a32',  'volume_id',                # Usually known as label.
  'a8',   'unused2',
  'L',    'vol_space_sizeLE',         # Size in sectors.
  'L',    'vol_space_sizeBE',
  'a32',  'esc_sequences',            # Unused on primary, Joliet CDs do not always record escape sequences (assume UCS-2L3).
  'S',    'vol_set_sizeLE',
  'S',    'vol_set_sizeBE',
  'S',    'vol_seq_numberLE',
  'S',    'vol_seq_numberBE',
  'S',    'log_block_sizeLE',         # Sector size in bytes (so far, alwyas 2048).
  'S',    'log_block_sizeBE',
  'L',    'path_table_sizeLE',        # This implementation ignores the path tables.
  'L',    'path_table_sizeBE',
  'S',    'type_1_path_tableLE',
  'S',    'type_1_path_tableBE',
  'S',    'opt_type_1_path_tableLE',
  'S',    'opt_type_1_path_tableBE',
  'S',    'type_m_path_tableLE',
  'S',    'type_m_path_tableBE',
  'S',    'opt_type_m_path_tableLE',
  'S',    'opt_type_m_path_tableBE',
  'a34',  'root_dir_record',          # DirectoryEntry representing root dir.
  'a128', 'vol_set_id',
  'a128', 'publisher_id',
  'a128', 'preparer_id',
  'a128', 'application_id',
  'a37',  'copyright_file_id',
  'a37',  'abstract_file_id',
  'a37',  'biblographic_file_id',
  'a17',  'creation_date',            # Dates are in ISO long date format.
  'a17',  'modification_date',
  'a17',  'experation_date',
  'a17',  'effective_date',
  'C',    'file_structure_version',   # Must be 1.
  'C',    'unused4',
  'a512', 'application_data',
  'a653', 'unused5'
])
SIZEOF_VOLUME_DESCRIPTOR =
VOLUME_DESCRIPTOR.size

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, joliet = false) ⇒ BootSector

Returns a new instance of BootSector.



72
73
74
75
76
77
78
79
80
81
82
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
109
110
111
112
113
114
# File 'lib/fs/iso9660/boot_sector.rb', line 72

def initialize(stream, joliet = false)
  raise "Nil stream" if stream.nil?
  @stream = stream
  @isJoliet = joliet
  @jolietVerified = false

  # Get the suffix to use for all members.
  @suff = getSuffix

  # Read & check descriptor.
  @bs = VOLUME_DESCRIPTOR.decode(@stream.read(SIZEOF_VOLUME_DESCRIPTOR))
  @descType = @bs['desc_type']
  raise "Descriptor type mismatch (type is #{@descType})" if @descType != (@isJoliet ? TYPE_SUPP_DESC : TYPE_PRIM_DESC)
  @recId = @bs['id']
  raise "Descriptor ID mismatch" if @recId != "CD001"
  raise "Descriptor version mismatch" if @bs['version'] != 1
  raise "File structure version mismatch" if @bs['file_structure_version'] != 1

  # If this is supposed to be Joliet then try to verify.
  if @isJoliet
    esc = @bs['esc_sequences'].strip
    if esc[0, 2] == '%/'
      level = esc[2, 1]
      @jolietVerified = true if level == '@' || level == 'C' || level == 'E'
    end
  end
  # From now on, assume Joliet if @isJoliet is true.
  # If verification fails it's up to Directory & DirectoryEntry to be careful.

  # Read fs params.
  @sectorSize = @bs["log_block_size#{@suff}"]
  @volName = @bs['volume_id']
  @volName.Ucs2ToAscii! if @isJoliet
  # fsId can come from Rock Ridge ext if present.
  # Don't forget there's a serial number too if RR isn't there.
  @cTime = Util.IsoToRubyDate(@bs['creation_date'])
  @mTime = Util.IsoToRubyDate(@bs['modification_date'])
  @expirationDate = Util.IsoToRubyDate(@bs['expiration_date'])
  @effectiveDate = Util.IsoToRubyDate(@bs['effective_date'])

  # Filesystem root.
  @rootEntry = @bs['root_dir_record']
end

Instance Attribute Details

#cTimeObject (readonly)

Returns the value of attribute cTime.



69
70
71
# File 'lib/fs/iso9660/boot_sector.rb', line 69

def cTime
  @cTime
end

#descTypeObject (readonly)

Returns the value of attribute descType.



68
69
70
# File 'lib/fs/iso9660/boot_sector.rb', line 68

def descType
  @descType
end

#effectiveDateObject (readonly)

Returns the value of attribute effectiveDate.



69
70
71
# File 'lib/fs/iso9660/boot_sector.rb', line 69

def effectiveDate
  @effectiveDate
end

#expirationDateObject (readonly)

Returns the value of attribute expirationDate.



69
70
71
# File 'lib/fs/iso9660/boot_sector.rb', line 69

def expirationDate
  @expirationDate
end

#fsIdObject (readonly)

Returns the value of attribute fsId.



68
69
70
# File 'lib/fs/iso9660/boot_sector.rb', line 68

def fsId
  @fsId
end

#mTimeObject (readonly)

Returns the value of attribute mTime.



69
70
71
# File 'lib/fs/iso9660/boot_sector.rb', line 69

def mTime
  @mTime
end

#recIdObject (readonly)

Returns the value of attribute recId.



70
71
72
# File 'lib/fs/iso9660/boot_sector.rb', line 70

def recId
  @recId
end

#rootEntryObject (readonly)

Returns the value of attribute rootEntry.



70
71
72
# File 'lib/fs/iso9660/boot_sector.rb', line 70

def rootEntry
  @rootEntry
end

#sectorSizeObject (readonly)

Returns the value of attribute sectorSize.



68
69
70
# File 'lib/fs/iso9660/boot_sector.rb', line 68

def sectorSize
  @sectorSize
end

#suffObject (readonly)

Returns the value of attribute suff.



70
71
72
# File 'lib/fs/iso9660/boot_sector.rb', line 70

def suff
  @suff
end

#volNameObject (readonly)

Returns the value of attribute volName.



68
69
70
# File 'lib/fs/iso9660/boot_sector.rb', line 68

def volName
  @volName
end

Instance Method Details

#diskSizeObject



116
117
118
# File 'lib/fs/iso9660/boot_sector.rb', line 116

def diskSize
  @bs["vol_space_size#{@suff}"] * @sectorSize
end

#dumpObject

This is a raw dump with no character set conversion.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/fs/iso9660/boot_sector.rb', line 141

def dump
  out = "\n"
  out += "Type            : #{@bs['desc_type']}\n"
  out += "Record ID       : #{@bs['id']}\n"
  out += "Version         : #{@bs['version']}\n"
  out += "System ID       : #{@bs['system_id'].strip}\n"
  out += "Volume ID       : #{@volName}\n"
  out += "Vol space size  : #{@bs["vol_space_size#{@suff}"]} (sectors)\n"
  out += "Vol set size    : #{@bs["vol_set_size#{@suff}"]}\n"
  out += "Vol sequence num: #{@bs["vol_seq_number#{@suff}"]}\n"
  out += "Logical blk size: #{@bs["log_block_size#{@suff}"]} (sector size)\n"
  out += "Path table size : #{@bs["path_table_size#{@suff}"]}\n"
  out += "Type 1 path tbl : #{@bs["type_1_path_table#{@suff}"]}\n"
  out += "Opt type 1 pth  : #{@bs["opt_type_1_path_table#{@suff}"]}\n"
  out += "Type M path tbl : #{@bs["type_m_path_table#{@suff}"]}\n"
  out += "Opt type M pth  : #{@bs["opt_type_m_path_table#{@suff}"]}\n"
  out += "Vol set ID      : #{@bs['vol_set_id'].strip}\n"
  out += "Publisher ID    : #{@bs['publisher_id'].strip}\n"
  out += "Preparer ID     : #{@bs['preparer_id'].strip}\n"
  out += "Application ID  : #{@bs['application_id'].strip}\n"
  out += "Copyright       : #{@bs['copyright_file_id'].strip}\n"
  out += "Abstract        : #{@bs['abstract_file_id'].strip}\n"
  out += "Biblographic    : #{@bs['biblographic_file_id'].strip}\n"
  out += "Creation date   : #{@bs['creation_date'].strip} (#{@cTime}, tz = #{Util.GetTimezone(@bs['creation_date'])})\n"
  out += "Mod date        : #{@bs['modification_date'].strip} (#{@mTime}, tz = #{Util.GetTimezone(@bs['modification_date'])})\n"
  out += "Expiration date : #{@bs['experation_date'].strip} (#{@expirationDate}, tz = #{Util.GetTimezone(@bs['experation_date'])})\n"
  out += "Effective date  : #{@bs['effective_date'].strip} (#{@effectiveDate}, tz = #{Util.GetTimezone(@bs['effective_date'])})\n"
  out += "File strct ver  : #{@bs['file_structure_version']}\n"
  out += "Application data: #{@bs['application_data'].strip}\n"
end

#getSectors(sector, num = 1) ⇒ Object



120
121
122
123
# File 'lib/fs/iso9660/boot_sector.rb', line 120

def getSectors(sector, num = 1)
  @stream.seek(sector * @sectorSize)
  @stream.read(@sectorSize * num)
end

#getSuffixObject



129
130
131
132
133
134
135
136
137
138
# File 'lib/fs/iso9660/boot_sector.rb', line 129

def getSuffix
  if Sys::Platform::ARCH == :x86
    @@suff = 'LE'
  else
    # Other architectures are bi-endian and must be determined at run time.
    p = [0xaa, 0x55].pack('N')
    u = p.unpack('L')
    @@suff = u == 0xaa55 ? 'BE' : 'LE'
  end
end

#isJoliet?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/fs/iso9660/boot_sector.rb', line 125

def isJoliet?
  @isJoliet
end