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