package org.jnode.fs.ext4;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.jnode.util.LittleEndian;
/**
* A class for checking the ext4 multiple-mount protection (MMP) status.
*/
public class MultipleMountProtection {
/**
* Logger
*/
private static final Logger log = Logger.getLogger(MultipleMountProtection.class);
/**
* The length of the MMP structure.
*/
public static final int MMP_LENGTH = 1024;
/**
* The MMP magic number ("MMP").
*/
public static final int MMP_MAGIC = 0x004D4D50;
/**
* The sequence number value for a clean unmount.
*/
public static final int MMP_SEQ_CLEAN = 0xFF4D4D50;
/**
* The sequence number value when the file system is being fscked.
*/
public static final int MMP_SEQ_FSCK = 0xE24D4D50;
/**
* The maximum valid sequence number value.
*/
public static final int MMP_SEQ_MAX = 0xE24D4D4F;
/**
* The sequence number.
*/
private int sequenceNumber;
/**
* The time the MMP block was last updated.
*/
private long time;
/**
* The host name of the node which opened the file system.
*/
private String nodeName;
/**
* The block device name of the file system.
*/
private String blockDeviceName;
/**
* The recheck interval, in seconds.
*/
private int checkInterval;
/**
* The checksum of the MMP block.
*/
private int checksum;
public MultipleMountProtection(byte[] data) throws IOException {
int magic = LittleEndian.getInt32(data, 0);
if (magic != MMP_MAGIC) {
throw new IOException("Invalid MMP magic: " + magic);
}
sequenceNumber = LittleEndian.getInt32(data, 0x4);
time = LittleEndian.getInt64(data, 0x8);
nodeName = new String(data, 0x10, 64, "UTF-8").replace("\u0000", "");
blockDeviceName = new String(data, 0x50, 64, "UTF-8").replace("\u0000", "");
checkInterval = LittleEndian.getInt16(data, 0x70);
checksum = LittleEndian.getInt32(data, 0x3fc);
}
/**
* Checks if the file system appears to be in use.
*
* @return {@code true} if in use.
*/
public boolean isInUse() {
if (sequenceNumber != MMP_SEQ_CLEAN) {
log.warn(String.format("File system appears to be in use from: %s:%s, seq:%x", nodeName, blockDeviceName,
sequenceNumber));
return true;
} else {
return false;
}
}
}