throws FileSystemException, IOException {
final long blockCount = getSizeInBlocks();
final int indirectCount = getIndirectCount();
long allocatedBlocks = i;
if (i != blockCount) {
throw new FileSystemException("Trying to register block " + i +
" (counts from 0), when INode contains only " + blockCount + " blocks");
}
log.debug("registering block #" + blockNr);
setDirty(true);
//the direct blocks (0; 11)
if (i < 12) {
Ext2Utils.set32(data, 40 + (int) i * 4, blockNr);
return;
}
//see the indirect blocks (12; indirectCount-1)
i -= 12;
if (i < indirectCount) {
long indirectBlockNr;
//the 12th index points to the indirect block
if (i == 0) {
//need to reserve the indirect block itself, as this is the
//first time it is used
indirectBlockNr = findFreeBlock(allocatedBlocks++);
Ext2Utils.set32(data, 40 + 12 * 4, indirectBlockNr);
//log.debug("reserved indirect block: "+indirectBlockNr);
//need to blank the block so that e2fsck does not complain
byte[] zeroes = new byte[fs.getBlockSize()]; //blank the block
Arrays.fill(zeroes, 0, fs.getBlockSize(), (byte) 0);
fs.writeBlock(indirectBlockNr, zeroes, false);
} else {
//the indirect block has already been used
indirectBlockNr = Ext2Utils.get32(data, 40 + 12 * 4);
}
indirectWrite(indirectBlockNr, i, allocatedBlocks, blockNr, 1);
return;
}
//see the double indirect blocks (indirectCount; doubleIndirectCount-1)
i -= indirectCount;
final int doubleIndirectCount = indirectCount * indirectCount;
if (i < doubleIndirectCount) {
long doubleIndirectBlockNr;
//the 13th index points to the double indirect block
if (i == 0) {
//need to reserve the double indirect block itself
doubleIndirectBlockNr = findFreeBlock(allocatedBlocks++);
Ext2Utils.set32(data, 40 + 13 * 4, doubleIndirectBlockNr);
//log.debug("reserved double indirect block:
// "+doubleIndirectBlockNr);
//need to blank the block so that e2fsck does not complain
byte[] zeroes = new byte[fs.getBlockSize()]; //blank the block
Arrays.fill(zeroes, 0, fs.getBlockSize(), (byte) 0);
fs.writeBlock(doubleIndirectBlockNr, zeroes, false);
} else {
doubleIndirectBlockNr = Ext2Utils.get32(data, 40 + 13 * 4);
}
indirectWrite(doubleIndirectBlockNr, i, allocatedBlocks, blockNr, 2);
return;
}
//see the triple indirect blocks (doubleIndirectCount;
// tripleIndirectCount-1)
final int tripleIndirectCount = indirectCount * indirectCount * indirectCount;
i -= doubleIndirectCount;
if (i < tripleIndirectCount) {
long tripleIndirectBlockNr;
//the 14th index points to the triple indirect block
if (i == 0) {
//need to reserve the triple indirect block itself
tripleIndirectBlockNr = findFreeBlock(allocatedBlocks++);
Ext2Utils.set32(data, 40 + 13 * 4, tripleIndirectBlockNr);
//log.debug("reserved triple indirect block:
// "+tripleIndirectBlockNr);
//need to blank the block so that e2fsck does not complain
byte[] zeroes = new byte[fs.getBlockSize()]; //blank the block
Arrays.fill(zeroes, 0, fs.getBlockSize(), (byte) 0);
fs.writeBlock(tripleIndirectBlockNr, zeroes, false);
} else {
tripleIndirectBlockNr = Ext2Utils.get32(data, 40 + 14 * 4);
}
indirectWrite(tripleIndirectBlockNr, i, allocatedBlocks, blockNr, 3);
return;
}
//shouldn't get here
throw new FileSystemException("Internal FS exception: getDataBlockIndex(i=" + i + ")");
}