/*-
* Copyright (C) 2006-2009 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.fs.hfscommon;
import org.catacombae.io.ReadableRandomAccessStream;
import org.catacombae.util.Util;
/**
* This contains methods to detect if the file system is of type MFS, HFS, HFS+
* or HFSX.
*
* @author <a href="http://www.catacombae.org/" target="_top">Erik Larsson</a>
*/
public class HFSCommonFileSystemRecognizer {
private static final short SIGNATURE_MFS = (short) 0xD2D7; // Extreme legacy... won't be used
private static final short SIGNATURE_HFS = (short) 0x4244; // ASCII: 'BD' Legacy...
private static final short SIGNATURE_HFS_PLUS = (short) 0x482B; // ASCII: 'H+'
private static final short SIGNATURE_HFSX = (short) 0x4858; // ASCII: 'HX'
public static enum FileSystemType {
MFS, HFS, HFS_PLUS, HFS_WRAPPED_HFS_PLUS, HFSX, UNKNOWN
};
/**
* Detects one of the following file systems:
* <ul>
* <li>HFS+</li>
* <li>HFSX</li>
* <li>HFS</li>
* <li>HFS+ wrapped inside a HFS file system</li>
* <li>MFS</li>
* </ul>
* NOTE: This method should never ever throw an exception, and instead just returns UNKNOWN.
*
* @param bitstream the stream to check for a file system.
* @param offset the offset in the stream to the start of the file system.
* @return the detected file system type (UNKNOWN if none could be detected).
*/
public static FileSystemType detectFileSystem(ReadableRandomAccessStream bitstream, long offset) {
try {
bitstream.seek(offset);
byte[] signatureData = new byte[4096];
int bytesRead = bitstream.read(signatureData);
if(bytesRead < 4096) {
return FileSystemType.UNKNOWN;
}
short signature = Util.readShortBE(signatureData, 1024);
switch(signature) {
case SIGNATURE_MFS:
return FileSystemType.MFS;
case SIGNATURE_HFS:
try {
short embeddedSignature =
Util.readShortBE(signatureData, 1024 + 124);
if(embeddedSignature == SIGNATURE_HFS_PLUS)
return FileSystemType.HFS_WRAPPED_HFS_PLUS;
else
return FileSystemType.HFS;
} catch(Exception e) {
return FileSystemType.HFS;
}
case SIGNATURE_HFS_PLUS:
return FileSystemType.HFS_PLUS;
case SIGNATURE_HFSX:
return FileSystemType.HFSX;
default:
return FileSystemType.UNKNOWN;
}
} catch(Exception e) {
System.err.println("Exception while detecting file system:");
e.printStackTrace();
return FileSystemType.UNKNOWN;
}
}
/**
* Change this array to tell the recognizer which types the
* FileSystemHandler supports.
*/
public static final FileSystemType[] supportedTypes = {
FileSystemType.HFS,
FileSystemType.HFS_PLUS,
FileSystemType.HFS_WRAPPED_HFS_PLUS,
FileSystemType.HFSX,
};
public static boolean isTypeSupported(FileSystemType fst) {
for(FileSystemType cur : supportedTypes)
if(cur == fst)
return true;
return false;
}
}