public bool Open()
{
lock (this) {
OpenStore(IsReadOnly);
// If it's small, initialize to empty
if (DataAreaEndOffset < DataAreaOffset)
Init();
byte[] readBuf = new byte[(int) BinAreaOffset];
Read(0, readBuf, 0, readBuf.Length);
using (var stream = new MemoryStream(readBuf)) {
using (var reader = new BinaryReader(stream)) {
int magic = reader.ReadInt32();
if (magic != Magic)
throw new IOException("Format invalid: Magic value is not as expected.");
int version = reader.ReadInt32();
if (version != 1)
throw new IOException("Format invalid: unrecognized version.");
reader.ReadInt64(); // ignore
byte status = reader.ReadByte();
ClosedClean = true;
if (status == 1) {
// This means the store wasn't closed cleanly.
ClosedClean = false;
}
}
}
// Read the bins
ReadBins();
// Mark the file as open
if (!IsReadOnly)
Write(16, 1);
long fileLength = DataAreaEndOffset;
if (fileLength <= 8) {
throw new IOException("Format invalid: File size is too small.");
}
// Set the wilderness offset.
if (fileLength == DataAreaOffset) {
WildernessOffset = -1;
} else {
Read(fileLength - 8, readBuf, 0, 8);
long lastBoundary = BytesUtil.ReadInt8(readBuf, 0);
long lastAreaPointer = fileLength - lastBoundary;
if (lastAreaPointer < DataAreaOffset)
throw new IOException("File corrupt: last area offset is before data part of file.");
if (lastAreaPointer > fileLength - 8)
throw new IOException("File corrupt: last_area_pointer at the end of the file.");
Read(lastAreaPointer, readBuf, 0, 8);
long lastAreaHeader = BytesUtil.ReadInt8(readBuf, 0);
// If this is a freed block, then set this are the wilderness offset.
if ((lastAreaHeader & DeletedFlag) != 0) {
WildernessOffset = lastAreaPointer;
} else {
WildernessOffset = -1;
}
}
IsClosed = false;
return ClosedClean;
}
}