Class: RawBlockIO

Inherits:
Object
  • Object
show all
Defined in:
lib/disk/modules/RawBlockIO.rb

Constant Summary collapse

MIN_SECTORS_TO_CACHE =
64

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, mode = "r") ⇒ RawBlockIO

Returns a new instance of RawBlockIO.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/disk/modules/RawBlockIO.rb', line 7

def initialize(filename, mode = "r")
  # We must start with a block special file
  raise "RawBlockIO: #{filename} is not a blockSpecial file" unless File.stat(filename).ftype == 'blockSpecial'

  @rawDisk_file = File.open(filename, mode)

  # Enable directio (raw) if supported
  if defined? File::DIRECT
    require 'fcntl'
    @rawDisk_file.fcntl(Fcntl::F_SETFL, File::DIRECT)
  end

  @blockSize      = 512
  @filename       = filename
  @mode           = mode
  @size           = LinuxBlockDevice.size(@rawDisk_file.fileno)
  @sizeInBlocks   = @size / @blockSize
  @startByteAddr  = 0
  @endByteAddr    = @size - 1
  @lbaEnd         = @sizeInBlocks - 1
  @seekPos        = 0

  $log.debug "RawBlockIO: opened #{@filename}, size = #{@size} (#{@sizeInBlocks} blocks)"
end

Instance Attribute Details

#sizeObject (readonly)

Returns the value of attribute size.



75
76
77
# File 'lib/disk/modules/RawBlockIO.rb', line 75

def size
  @size
end

Instance Method Details

#bread(startSector, numSectors) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/disk/modules/RawBlockIO.rb', line 81

def bread(startSector, numSectors)
  # $log.debug "RawBlockIO.bread: startSector = #{startSector}, numSectors = #{numSectors}, @lbaEnd = #{@lbaEnd}"
  return nil if startSector > @lbaEnd
  numSectors = @sizeInBlocks - startSector if (startSector + numSectors) > @sizeInBlocks

  @rawDisk_file.sysseek(startSector * @blockSize, IO::SEEK_SET)
  @rawDisk_file.sysread(numSectors * @blockSize, @cache)
end

#breadCached(startSector, numSectors) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/disk/modules/RawBlockIO.rb', line 98

def breadCached(startSector, numSectors)
  # $log.debug "RawBlockIO.breadCached: startSector = #{startSector}, numSectors = #{numSectors}"
  if @cacheRange.nil? || !@cacheRange.include?(startSector) || !@cacheRange.include?(startSector + numSectors - 1)
    sectorsToRead = [MIN_SECTORS_TO_CACHE, numSectors].max
    @cache        = MemoryBuffer.create_aligned(@blockSize, @blockSize * sectorsToRead)
    bread(startSector, sectorsToRead)
    sectorsRead   = @cache.length / @blockSize
    endSector     = startSector + sectorsRead - 1
    @cacheRange   = Range.new(startSector, endSector)
  end

  sectorOffset = startSector - @cacheRange.first
  bufferOffset = sectorOffset * @blockSize
  length       = numSectors * @blockSize
  # $log.debug "RawBlockIO.breadCached: bufferOffset = #{bufferOffset}, length = #{length}"

  @cache[bufferOffset, length]
end

#bwrite(startSector, numSectors, buf) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/disk/modules/RawBlockIO.rb', line 90

def bwrite(startSector, numSectors, buf)
  return nil if startSector > @lbaEnd
  numSectors = @sizeInBlocks - startSector if (startSector + numSectors) > @sizeInBlocks

  @rawDisk_file.sysseek(startSector * @blockSize, IO::SEEK_SET)
  @rawDisk_file.syswrite(buf, numSectors * @blockSize)
end

#closeObject



77
78
79
# File 'lib/disk/modules/RawBlockIO.rb', line 77

def close
  @rawDisk_file.close
end

#read(len) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/disk/modules/RawBlockIO.rb', line 32

def read(len)
  return nil if @seekPos >= @endByteAddr
  len = @endByteAddr - @seekPos if (@seekPos + len) > @endByteAddr

  startSector, startOffset = @seekPos.divmod(@blockSize)
  endSector = (@seekPos + len - 1) / @blockSize
  numSector = endSector - startSector + 1

  rBuf = breadCached(startSector, numSector)
  @seekPos += len

  rBuf[startOffset, len]
end

#seek(amt, whence = IO::SEEK_SET) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/disk/modules/RawBlockIO.rb', line 63

def seek(amt, whence = IO::SEEK_SET)
  case whence
  when IO::SEEK_CUR
    @seekPos += amt
  when IO::SEEK_END
    @seekPos = @endByteAddr + amt
  when IO::SEEK_SET
    @seekPos = amt + @startByteAddr
  end
  @seekPos
end

#write(buf, len) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/disk/modules/RawBlockIO.rb', line 46

def write(buf, len)
  return nil if @seekPos >= @endByteAddr
  len = @endByteAddr - @seekPos if (@seekPos + len) > @endByteAddr

  startSector, startOffset = @seekPos.divmod(@blockSize)
  endSector = (@seekPos + len - 1) / @blockSize
  numSector = endSector - startSector + 1

  rBuf = bread(startSector, numSector)
  rBuf[startOffset, len] = buf[0, len]

  bwrite(startSector, numSector, rBuf)
  @seekPos += len

  len
end