/*- * Copyright (C) 2008 Erik Larsson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catacombae.storage.ps.ebr; import java.io.PrintStream; import java.util.LinkedList; import org.catacombae.storage.ps.mbr.types.MBRPartitionTable; import org.catacombae.storage.ps.Partition; import org.catacombae.storage.ps.legacy.PartitionSystem; import org.catacombae.storage.io.win32.ReadableWin32FileStream; import org.catacombae.io.ReadableFileStream; import org.catacombae.io.ReadableRandomAccessStream; import org.catacombae.storage.ps.PartitionType; /** * @author <a href="http://www.catacombae.org/" target="_top">Erik Larsson</a> */ public class EBRPartitionSystem implements PartitionSystem { private final ExtendedBootRecord[] bootRecords; public EBRPartitionSystem(ReadableRandomAccessStream psStream, final long ebrPartitionOffset, int sectorSize) { this(psStream, ebrPartitionOffset, -1, sectorSize); } public EBRPartitionSystem(ReadableRandomAccessStream psStream, final long ebrPartitionOffset, final long ebrPartitionLength, int sectorSize) { byte[] tempBuffer = new byte[512]; long curOffset = ebrPartitionOffset; psStream.seek(curOffset); psStream.readFully(tempBuffer); LinkedList<ExtendedBootRecord> recordList = new LinkedList<ExtendedBootRecord>(); ExtendedBootRecord ebr; while((ebr = new ExtendedBootRecord(tempBuffer, 0, ebrPartitionOffset, curOffset, sectorSize)).isValid()) { //System.err.println("EBR partition " + recordList.size() + ":"); //ebr.print(System.err, " "); if(recordList.size() > 10000) throw new RuntimeException("Number of EBR partitions capped at 10000."); recordList.add(ebr); if(ebr.isTerminator()) break; // We have reached the end of the EBR linked list. else { //EBRPartition firstEntry = ebr.getFirstEntry(); curOffset = ebr.getSecondEntry().getStartOffset(); if(ebrPartitionLength > 0 && curOffset > ebrPartitionOffset+ebrPartitionLength) throw new RuntimeException("Invalid DOS Extended partition system (curOffset=" + curOffset + ")."); //System.err.println("Seeking to offset(" + offset + ") + secondEntryStart(" + ebr.getSecondEntry().getStartOffset() + ") = " + curOffset); psStream.seek(curOffset); psStream.readFully(tempBuffer); } } if(!ebr.isValid()) throw new RuntimeException("Invalid extended partition table at index " + recordList.size() + "."); else this.bootRecords = recordList.toArray(new ExtendedBootRecord[recordList.size()]); } public boolean isValid() { return true; // We check this at creation time. } public int getPartitionCount() { return bootRecords.length; } public Partition getPartitionEntry(int index) { return bootRecords[index].getFirstEntry(); } public Partition[] getPartitionEntries() { Partition[] result = new Partition[bootRecords.length]; for(int i = 0; i < result.length; ++i) { result[i] = bootRecords[i].getFirstEntry(); } return result; } public int getUsedPartitionCount() { return getPartitionCount(); } public Partition[] getUsedPartitionEntries() { return getPartitionEntries(); } public String getLongName() { return "Extended Boot Record"; } public String getShortName() { return "EBR"; } public void printFields(PrintStream ps, String prefix) { ps.println(prefix + " bootRecords:"); for(int i = 0; i < bootRecords.length; ++i) { ExtendedBootRecord ebr = bootRecords[i]; ps.print(prefix + " [" + i + "]:"); ebr.print(ps, prefix + " "); } } public void print(PrintStream ps, String prefix) { ps.println(prefix + this.getClass().getSimpleName() + ":"); printFields(ps, prefix); } public static void main(String[] args) { System.err.println("Test code for Extended Boot Record"); String inputFilename = args[0]; ReadableRandomAccessStream inputStream; if(ReadableWin32FileStream.isSystemSupported()) inputStream = new ReadableWin32FileStream(inputFilename); else inputStream = new ReadableFileStream(inputFilename); MBRPartitionTable mpt = new MBRPartitionTable(inputStream, 0); if(!mpt.isValid()) throw new RuntimeException("Invalid MBR."); int i = 0; for(Partition p : mpt.getUsedPartitionEntries()) { if(p.getType() == PartitionType.DOS_EXTENDED) { System.err.println("Found extended partition system at MBR partition " + i + ":"); EBRPartitionSystem ebt = new EBRPartitionSystem(inputStream, p.getStartOffset(), p.getLength(), 512); ebt.print(System.err, " "); } ++i; } inputStream.close(); } }