}
if (!Arrays.equals(buf, LZO_MAGIC)) {
throw new IOException("Invalid LZO header");
}
Arrays.fill(buf, (byte)0);
Adler32 adler = new Adler32();
CRC32 crc32 = new CRC32();
int hitem = readHeaderItem(in, buf, 2, adler, crc32); // lzop version
if (hitem > LZOP_VERSION) {
LOG.debug("Compressed with later version of lzop: " +
Integer.toHexString(hitem) + " (expected 0x" +
Integer.toHexString(LZOP_VERSION) + ")");
}
hitem = readHeaderItem(in, buf, 2, adler, crc32); // lzo library version
if (hitem > LzoDecompressor.LZO_LIBRARY_VERSION) {
throw new IOException("Compressed with incompatible lzo version: 0x" +
Integer.toHexString(hitem) + " (expected 0x" +
Integer.toHexString(LzoDecompressor.LZO_LIBRARY_VERSION) + ")");
}
hitem = readHeaderItem(in, buf, 2, adler, crc32); // lzop extract version
if (hitem > LZOP_VERSION) {
throw new IOException("Compressed with incompatible lzop version: 0x" +
Integer.toHexString(hitem) + " (expected 0x" +
Integer.toHexString(LZOP_VERSION) + ")");
}
hitem = readHeaderItem(in, buf, 1, adler, crc32); // method
if (hitem < 1 || hitem > 3) {
throw new IOException("Invalid strategy: " +
Integer.toHexString(hitem));
}
readHeaderItem(in, buf, 1, adler, crc32); // ignore level
// flags
hitem = readHeaderItem(in, buf, 4, adler, crc32);
try {
for (DChecksum f : dflags) {
if (0 == (f.getHeaderMask() & hitem)) {
dflags.remove(f);
} else {
dcheck.put(f, (int)f.getChecksumClass().newInstance().getValue());
}
}
for (CChecksum f : cflags) {
if (0 == (f.getHeaderMask() & hitem)) {
cflags.remove(f);
} else {
ccheck.put(f, (int)f.getChecksumClass().newInstance().getValue());
}
}
} catch (InstantiationException e) {
throw new RuntimeException("Internal error", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Internal error", e);
}
((LzopDecompressor)decompressor).initHeaderFlags(dflags, cflags);
boolean useCRC32 = 0 != (hitem & 0x00001000); // F_H_CRC32
boolean extraField = 0 != (hitem & 0x00000040); // F_H_EXTRA_FIELD
if (0 != (hitem & 0x400)) { // F_MULTIPART
throw new IOException("Multipart lzop not supported");
}
if (0 != (hitem & 0x800)) { // F_H_FILTER
throw new IOException("lzop filter not supported");
}
if (0 != (hitem & 0x000FC000)) { // F_RESERVED
throw new IOException("Unknown flags in header");
}
// known !F_H_FILTER, so no optional block
readHeaderItem(in, buf, 4, adler, crc32); // ignore mode
readHeaderItem(in, buf, 4, adler, crc32); // ignore mtime
readHeaderItem(in, buf, 4, adler, crc32); // ignore gmtdiff
hitem = readHeaderItem(in, buf, 1, adler, crc32); // fn len
if (hitem > 0) {
// skip filename
readHeaderItem(in, new byte[hitem], hitem, adler, crc32);
}
int checksum = (int)(useCRC32 ? crc32.getValue() : adler.getValue());
hitem = readHeaderItem(in, buf, 4, adler, crc32); // read checksum
if (hitem != checksum) {
throw new IOException("Invalid header checksum: " +
Long.toHexString(checksum) + " (expected 0x" +
Integer.toHexString(hitem) + ")");
}
if (extraField) { // lzop 1.08 ultimately ignores this
LOG.debug("Extra header field not processed");
adler.reset();
crc32.reset();
hitem = readHeaderItem(in, buf, 4, adler, crc32);
readHeaderItem(in, new byte[hitem], hitem, adler, crc32);
checksum = (int)(useCRC32 ? crc32.getValue() : adler.getValue());
if (checksum != readHeaderItem(in, buf, 4, adler, crc32)) {
throw new IOException("Invalid checksum for extra header field");
}
}
}