fat.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 403 行
JAVA
403 行
/**
* $Id: Fat.java,v 1.2 2003/11/29 03:33:28 gbin Exp $
*/
package org.jnode.fs.fat;
import java.io.IOException;
import java.io.PrintWriter;
import org.jnode.driver.block.BlockDeviceAPI;
/**
* <description>
*
* @author epr
*/
public class Fat {
public static final int FAT12 = 12;
public static final int FAT16 = 16;
public static final int FAT32 = 32;
private long[] entries;
/** The type of FAT, legal values are: 12, 16, 32 */
private int bitSize;
/** The number of sectors this fat takes */
private int nrSectors;
/** The number of bytes/sector */
private int sectorSize;
private final long eofMarker;
private boolean dirty;
/**
* Create a new instance
*
* @param bitSize
* @param nrSectors
* @param sectorSize
*/
public Fat(int bitSize, int mediumDescriptor, int nrSectors, int sectorSize) {
this.bitSize = bitSize;
this.nrSectors = nrSectors;
this.sectorSize = sectorSize;
this.dirty = false;
switch (bitSize) {
case FAT12 :
{
entries = new long[(int) ((nrSectors * sectorSize) / 1.5)];
eofMarker = 0xFFF;
}
break;
case FAT16 :
{
entries = new long[(nrSectors * sectorSize) / 2];
eofMarker = 0xFFFF;
}
break;
case FAT32 :
{
entries = new long[(nrSectors * sectorSize) / 4];
eofMarker = 0xFFFFFFFF;
}
break;
default :
throw new IllegalArgumentException("Invalid bitSize " + bitSize);
}
entries[0] = (mediumDescriptor & 0xFF) | 0xFFFFFF00;
}
/**
* Read the contents of this FAT from the given device at the given offset.
*
* @param device
*/
public synchronized void read(BlockDeviceAPI device, long offset) throws IOException {
byte[] data = new byte[nrSectors * sectorSize];
device.read(offset, data, 0, data.length);
for (int i = 0; i < entries.length; i++) {
switch (bitSize) {
case 12 :
{
int idx = (int) (i * 1.5);
int b1 = data[idx] & 0xFF;
int b2 = data[idx + 1] & 0xFF;
int v = (b2 << 8) | b1;
if ((i % 2) == 0) {
entries[i] = v & 0xFFF;
} else {
entries[i] = v >> 4;
}
//System.out.println("i=" + i + ", idx=" + idx + ", b1=0x" +
// Integer.toHexString(b1) + ", b2=0x" +
// Integer.toHexString(b2) + ", v=0x" +
// Integer.toHexString(v) + " -> 0x" +
// Long.toHexString(entries[i]));
}
break;
case 16 :
{
int idx = i * 2;
int b1 = data[idx] & 0xFF;
int b2 = data[idx + 1] & 0xFF;
entries[i] = (b2 << 8) | b1;
}
break;
case 32 :
{
int idx = i * 4;
long b1 = data[idx] & 0xFF;
long b2 = data[idx + 1] & 0xFF;
long b3 = data[idx + 2] & 0xFF;
long b4 = data[idx + 3] & 0xFF;
entries[i] = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
break;
}
}
this.dirty = false;
}
/**
* Write the contents of this FAT to the given device at the given offset.
*
* @param device
*/
public synchronized void write(BlockDeviceAPI device, long offset) throws IOException {
byte[] data = new byte[nrSectors * sectorSize];
for (int i = 0; i < entries.length; i++) {
long v = entries[i];
switch (bitSize) {
case 12 :
{
int idx = (int) (i * 1.5);
if ((i % 2) == 0) {
data[idx] = (byte) (v & 0xFF);
data[idx + 1] = (byte) ((v >> 8) & 0x0F);
} else {
data[idx] |= (byte) ((v & 0x0F) << 4);
data[idx + 1] = (byte) ((v >> 4) & 0xFF);
}
}
break;
case 16 :
{
int idx = i * 2;
data[idx] = (byte) (v & 0xFF);
data[idx + 1] = (byte) ((v >> 8) & 0xFF);
}
break;
case 32 :
{
int idx = i * 4;
data[idx] = (byte) (v & 0xFF);
data[idx + 1] = (byte) ((v >> 8) & 0xFF);
data[idx + 2] = (byte) ((v >> 16) & 0xFF);
data[idx + 3] = (byte) ((v >> 24) & 0xFF);
}
break;
}
}
device.write(offset, data, 0, data.length);
this.dirty = false;
}
/**
* Gets the medium descriptor byte
*
* @return int
*/
public int getMediumDescriptor() {
return (int) (entries[0] & 0xFF);
}
/**
* Sets the medium descriptor byte
*/
public void setMediumDescriptor(int descr) {
entries[0] = 0xFFFFFF00 | (descr & 0xFF);
}
/**
* Gets the number of entries of this fat
*
* @return int
*/
public int getNrEntries() {
return entries.length;
}
/**
* Gets the entry at a given offset
*
* @param index
* @return long
*/
public long getEntry(int index) {
return entries[index];
}
public synchronized long[] getChain(long startCluster) {
testCluster(startCluster);
// Count the chain first
int count = 1;
long cluster = startCluster;
while (!isEofCluster(entries[(int)cluster])) {
count++;
cluster = entries[(int)cluster];
}
// Now create the chain
long[] chain = new long[count];
chain[0] = startCluster;
cluster = startCluster;
int i = 0;
while (!isEofCluster(entries[(int)cluster])) {
cluster = entries[(int)cluster];
chain[++i] = cluster;
}
return chain;
}
/**
* Gets the cluster after the given cluster
*
* @param cluster
* @return long The next cluster number or -1 which means eof.
*/
public synchronized long getNextCluster(long cluster) {
testCluster(cluster);
long entry = entries[(int)cluster];
if (isEofCluster(entry)) {
return -1;
} else {
return entry;
}
}
/**
* Allocate a cluster for a new file
*
* @return long
*/
public synchronized long allocNew() throws IOException {
int i;
for (i = 2; i < entries.length; i++) {
if (isFreeCluster(entries[i])) {
entries[i] = eofMarker;
this.dirty = true;
return i;
} else {
//System.out.print("[" + entries[i] + "] ");
}
}
throw new IOException("FAT Full (" + entries.length + ", " + i + ")");
}
/**
* Allocate a series of clusters for a new file
*
* @return long
*/
public synchronized long[] allocNew(int nrClusters) throws IOException {
long rc[] = new long[nrClusters];
rc[0] = allocNew();
for (int i = 1; i < nrClusters; i++) {
rc[i] = allocAppend(rc[i - 1]);
}
return rc;
}
/**
* Allocate a cluster to append to a new file
*
* @return long
*/
public synchronized long allocAppend(long cluster) throws IOException {
testCluster(cluster);
while (!isEofCluster(entries[(int)cluster])) {
cluster = entries[(int)cluster];
}
long newCluster = allocNew();
entries[(int)cluster] = newCluster;
return newCluster;
}
public synchronized void setEof(long cluster) {
testCluster(cluster);
entries[(int)cluster] = eofMarker;
}
public synchronized void setFree(long cluster) {
testCluster(cluster);
entries[(int)cluster] = 0;
}
/**
* Print the contents of this FAT to the given writer. Used for debugging
* purposes.
*
* @param out
*/
public void printTo(PrintWriter out) {
int freeCount = 0;
out.println("medium descriptor 0x" + Integer.toHexString(getMediumDescriptor()));
for (int i = 2; i < entries.length; i++) {
long v = entries[i];
if (isFreeCluster(v)) {
freeCount++;
} else {
out.print("0x" + Integer.toHexString(i) + " -> ");
if (isEofCluster(v)) {
out.println("eof");
} else if (isReservedCluster(v)) {
out.println("reserved");
} else {
out.println("0x" + Long.toHexString(v));
}
}
}
out.println("Nr free entries " + freeCount);
}
public boolean equals(Object other) {
if (other instanceof Fat) {
Fat of = (Fat)other;
if (entries.length != of.entries.length) {
return false;
}
for (int i = 0; i < entries.length; i++) {
if (of.entries[i] != entries[i]) {
return false;
}
}
return true;
} else {
return false;
}
}
/**
* Is the given entry a free cluster?
*
* @param entry
* @return boolean
*/
protected boolean isFreeCluster(long entry) {
return (entry == 0);
}
/**
* Is the given entry a reserved cluster?
*
* @param entry
* @return boolean
*/
protected boolean isReservedCluster(long entry) {
switch (bitSize) {
case 12 :
return ((entry >= 0xFF0) && (entry <= 0xFF6));
case 16 :
return ((entry >= 0xFFF0) && (entry <= 0xFFF6));
case 32 :
return ((entry >= 0xFFFFFFF0) && (entry <= 0xFFFFFFF6));
default :
throw new IllegalArgumentException("Invalid bitSize " + bitSize);
}
}
/**
* Is the given entry an EOF marker
*
* @param entry
* @return boolean
*/
protected boolean isEofCluster(long entry) {
return (entry >= eofMarker);
}
protected void testCluster(long cluster) throws IllegalArgumentException {
if ((cluster < 2) || (cluster >= entries.length)) {
throw new IllegalArgumentException("Invalid cluster value");
}
}
/**
* Returns the dirty.
*
* @return boolean
*/
public boolean isDirty() {
return dirty;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?