private void ReadFrom(Stream inStream)
{
var @in = new StreamReader(inStream);
MessageDigest md = Constants.newMessageDigest();
// Read the index header and verify we understand it.
//
var hdr = new byte[20];
IO.ReadFully(inStream, hdr, 0, 12);
md.Update(hdr, 0, 12);
if (!IsDIRC(hdr))
{
throw new CorruptObjectException("Not a DIRC file.");
}
int ver = NB.DecodeInt32(hdr, 4);
if (ver != 2)
{
throw new CorruptObjectException("Unknown DIRC version " + ver);
}
_entryCnt = NB.DecodeInt32(hdr, 8);
if (_entryCnt < 0)
{
throw new CorruptObjectException("DIRC has too many entries.");
}
// Load the individual file entries.
//
var infos = new byte[InfoLen * _entryCnt];
_sortedEntries = new DirCacheEntry[_entryCnt];
for (int i = 0; i < _entryCnt; i++)
{
_sortedEntries[i] = new DirCacheEntry(infos, i * InfoLen, inStream, md);
}
_lastModified = _liveFile.LastWriteTime;
// After the file entries are index extensions, and then a footer.
//
while (true)
{
var pos = inStream.Position;
IO.ReadFully(inStream, hdr, 0, 20);
int nextByte = @in.Read();
if (nextByte < 0 || inStream.Position == inStream.Length)
{
// No extensions present; the file ended where we expected.
//
break;
}
inStream.Seek(pos, SeekOrigin.Begin);
switch (NB.DecodeInt32(hdr, 0))
{
case ExtTree:
var raw = new byte[NB.DecodeInt32(hdr, 4)];
md.Update(hdr, 0, 8);
IO.skipFully(inStream, 8);
IO.ReadFully(inStream, raw, 0, raw.Length);
md.Update(raw, 0, raw.Length);
_cacheTree = new DirCacheTree(raw, new MutableInteger(), null);
break;
default:
if (hdr[0] >= (byte)'A' && hdr[0] <= (byte)'Z')
{
// The extension is optional and is here only as
// a performance optimization. Since we do not
// understand it, we can safely skip past it.
//
IO.skipFully(inStream, NB.decodeUInt32(hdr, 4));
}
else
{
// The extension is not an optimization and is
// _required_ to understand this index format.
// Since we did not trap it above we must abort.
//
throw new CorruptObjectException("DIRC extension '"
+ Constants.CHARSET.GetString(hdr.Take(4).ToArray())
+ "' not supported by this version.");
}
break;
}
}
byte[] exp = md.Digest();
if (!exp.SequenceEqual(hdr))
{
throw new CorruptObjectException("DIRC checksum mismatch");
}
}