more idiomatic comparisons with constants
[ruby-mogilefs-client.git] / lib / mogilefs / bigfile / filter.rb
blobd8313124567591f952145c6bf7f50115a12e5666
1 # -*- encoding: binary -*-
2 require 'zlib'
3 require 'digest/md5'
5 # Filter class to wrap IO objects and uncompress DEFLATE'd files
7 # This is used for reading "bigfile" objects generated by the
8 # (deprecated) mogtool(1)
9 class MogileFS::Bigfile::Filter
10   GZIP_HEADER = "\x1f\x8b"
11   INFLATABLE_TYPES = { "file" => true }
12   attr_reader :flushed_bytes
14   def initialize(io, info, opts)
15     @io = io
16     @info = info
17     @md5 = opts[:verify] ? Digest::MD5.new : nil
18     @zi = nil
19     @flushed_bytes = 0
20   end
22   def md5_check!(expect)
23     return unless @md5
24     current = @md5.hexdigest
25     current == expect or
26       raise MogileFS::ChecksumMismatchError, "#{current} != #{expect}"
27     @md5.reset
28   end
30   def flush
31     @flushed_bytes = @io.write(@zi.finish) if @zi
32     @io.flush
33   end
35   def write(buf)
36     unless @zi
37       if @info[:compressed] &&
38          INFLATABLE_TYPES.include?(@info[:type]) &&
39          buf.bytesize >= 2 &&
40          buf[0,2] != GZIP_HEADER
42         @zi = Zlib::Inflate.new
44         # mogtool(1) seems to have a bug that causes it to generate bogus
45         # MD5s if zlib deflate is used.  Don't trust those MD5s for now...
46         @md5 = nil
47       else
48         @zi = false
49       end
50     end
51     if @zi
52       buf = @zi.inflate(buf)
53     else
54       @md5 << buf
55     end
56     @io.write(buf)
57   end
58 end