jext2.BlockGroupDescriptor.java Source code

Java tutorial

Introduction

Here is the source code for jext2.BlockGroupDescriptor.java

Source

/*
 * Copyright (c) 2011 Marcel Lauhoff.
 * 
 * This file is part of jext2.
 * 
 * jext2 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.
 * 
 * jext2 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 jext2.  If not, see <http://www.gnu.org/licenses/>.
 */

package jext2;

import java.nio.ByteBuffer;

import jext2.exceptions.IoError;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class BlockGroupDescriptor extends PartialBlock {
    private static Superblock superblock = Superblock.getInstance();

    private long blockBitmap;
    private long inodeBitmap;
    private long inodeTable;

    private int freeBlocksCount;
    private int freeInodesCount;
    private int usedDirsCount;

    private int blockGroup = -1;

    public final long getBlockBitmapPointer() {
        return this.blockBitmap;
    }

    public final long getInodeBitmapPointer() {
        return this.inodeBitmap;
    }

    public final long getInodeTablePointer() {
        return this.inodeTable;
    }

    public final int getFreeBlocksCount() {
        return this.freeBlocksCount;
    }

    public final int getFreeInodesCount() {
        return this.freeInodesCount;
    }

    public final int getUsedDirsCount() {
        return this.usedDirsCount;
    }

    public final int getBlockGroup() {
        return this.blockGroup;
    }

    void setBlockGroup(int blockGroup) {
        this.blockGroup = blockGroup;
    }

    public void setFreeBlocksCount(int freeBlocksCount) {
        this.freeBlocksCount = freeBlocksCount;
    }

    public void setFreeInodesCount(int freeInodesCount) {
        this.freeInodesCount = freeInodesCount;
    }

    public void setUsedDirsCount(int usedDirsCount) {
        this.usedDirsCount = usedDirsCount;
    }

    public final void setBlockBitmap(long blockBitmap) {
        this.blockBitmap = blockBitmap;
    }

    public final void setInodeBitmap(long inodeBitmap) {
        this.inodeBitmap = inodeBitmap;
    }

    public final void setInodeTable(long inodeTable) {
        this.inodeTable = inodeTable;
    }

    @Override
    protected void read(ByteBuffer buf) throws IoError {
        this.blockBitmap = Ext2fsDataTypes.getLE32U(buf, 0 + offset);
        this.inodeBitmap = Ext2fsDataTypes.getLE32U(buf, 4 + offset);
        this.inodeTable = Ext2fsDataTypes.getLE32U(buf, 8 + offset);
        this.freeBlocksCount = Ext2fsDataTypes.getLE16U(buf, 12 + offset);
        this.freeInodesCount = Ext2fsDataTypes.getLE16U(buf, 14 + offset);
        this.usedDirsCount = Ext2fsDataTypes.getLE16U(buf, 16 + offset);
    }

    @Override
    protected void write(ByteBuffer buf) throws IoError {
        Ext2fsDataTypes.putLE32U(buf, this.blockBitmap, 0);
        Ext2fsDataTypes.putLE32U(buf, this.inodeBitmap, 4);
        Ext2fsDataTypes.putLE32U(buf, this.inodeTable, 8);
        Ext2fsDataTypes.putLE16U(buf, this.freeBlocksCount, 12);
        Ext2fsDataTypes.putLE16U(buf, this.freeInodesCount, 14);
        Ext2fsDataTypes.putLE16U(buf, this.usedDirsCount, 16);
        super.write(buf);
    }

    @Override
    public void write() throws IoError {
        ByteBuffer buf = allocateByteBuffer();
        write(buf);
    }

    protected ByteBuffer allocateByteBuffer() {
        ByteBuffer buf = ByteBuffer.allocate(32);
        buf.rewind();
        return buf;
    }

    protected BlockGroupDescriptor(long blockNr, int offset) {
        super(blockNr, offset);
    }

    public static BlockGroupDescriptor fromByteBuffer(ByteBuffer buf, long blockNr, int offset) {
        BlockGroupDescriptor b = new BlockGroupDescriptor(blockNr, offset);
        try {
            b.read(buf);
            return b;
        } catch (IoError e) {
            throw new RuntimeException("IOException in BlockGroupDescriptor->fromByteBuffer");
        }
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    /**
     * Check if block number is a valid data block in this block group
     */
    public boolean isValidDataBlockNr(long nr) {
        return (nr > 0 && getBlockBitmapPointer() != nr && getInodeBitmapPointer() != nr && nr >= firstBlock()
                && (!(getInodeTablePointer() <= nr
                        && nr < getInodeTablePointer() + superblock.getInodeTableBlocksPerGroup())));
    }

    /**
     * Return the number of blocks used for file system structures
     */
    public int getOverhead() {
        return (((hasSuperblock()) ? 1 : 0) + getDescriptorTableBlocks() + superblock.getInodeTableBlocksPerGroup()
                + 2 /* inode, block bitmap */ );
    }

    /**
     * do not use this method. it is just for later improvement here. It does
     * not take into account that sparse block groups have not descriptor table
     */
    public static long descriptorLocation(int group) {
        int hasSuper = hasSuperblock(group) ? 1 : 0;

        return firstBlock(group) + hasSuper;
    }

    /**
     * Return first block number in group
     */
    public static long firstBlock(int group) {
        return superblock.getFirstDataBlock() + (group * superblock.getBlocksPerGroup());
    }

    /**
     * Return first block number in this group
     */
    public long firstBlock() {
        return firstBlock(this.blockGroup);
    }

    /**
     * Return true if group contains a descriptor table (eg. is not sparse)
     */
    public static boolean hasDescriptorTable(int group) {
        return hasSuperblock(group);
    }

    public boolean hasDescrptiorTable() {
        return hasDescriptorTable(this.blockGroup);
    }

    /**
     * Return the number of blocks used for the descriptor table.
     * Depends on the sparse_super feature
     */
    public int getDescriptorTableBlocks() {
        if (hasDescrptiorTable()) {
            return superblock.getGroupDescrBlocks();
        } else {
            return 0;
        }
    }

    /**
     * Check if group contains a superblock. Depends on the sparse super
     * feature.
     */
    public static boolean hasSuperblock(int group) {
        if (Feature.sparseSuper()) {
            return isSparse(group);
        } else {
            return true;
        }
    }

    public boolean hasSuperblock() {
        return hasSuperblock(this.blockGroup);
    }

    private static boolean isSparse(int group) {
        return ((group <= 1) || test_root(group, 3) || test_root(group, 5) || test_root(group, 7));
    }

    private static boolean test_root(int a, int b) {
        long num = b;

        while (a > num)
            num *= b;
        return num == a;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().appendSuper(super.hashCode()).append(blockBitmap).append(inodeBitmap)
                .append(inodeTable).append(freeBlocksCount).append(freeInodesCount).append(usedDirsCount)
                .append(blockGroup).toHashCode();
    }
}