Android Open Source - libaums Cluster Chain






From Project

Back to project page libaums.

License

The source code is released under:

Apache License

If you think the Android project libaums listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * (C) Copyright 2014 mjahnen <jahnen@in.tum.de>
 */*w ww  .  j  a va  2 s.  co m*/
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

package com.github.mjdev.libaums.fs.fat32;

import java.io.IOException;
import java.nio.ByteBuffer;

import android.util.Log;

import com.github.mjdev.libaums.driver.BlockDeviceDriver;

/**
 * This class represents a cluster chain which can be followed in the FAT of a
 * FAT32 file system. You can {@link #read(long, ByteBuffer) read} from or
 * {@link #write(long, ByteBuffer) write} to it easily without having to worry
 * about the specific clusters.
 * 
 * @author mjahnen
 * 
 */
public class ClusterChain {

  private static final String TAG = ClusterChain.class.getSimpleName();

  private BlockDeviceDriver blockDevice;
  private FAT fat;
  private Long[] chain;
  private long clusterSize;
  private long dataAreaOffset;

  /**
   * Constructs a new ClusterChain with the given information.
   * 
   * @param startCluster
   *            The start cluster which shall be followed in the FAT.
   * @param blockDevice
   *            The block device where the fat fs is located.
   * @param fat
   *            The file allocation table.
   * @param bootSector
   *            The boot sector of the FAT32 fs.
   * @throws IOException
   */
  /* package */ClusterChain(long startCluster, BlockDeviceDriver blockDevice, FAT fat,
      Fat32BootSector bootSector) throws IOException {
    this.fat = fat;
    this.blockDevice = blockDevice;
    chain = fat.getChain(startCluster);
    clusterSize = bootSector.getBytesPerCluster();
    dataAreaOffset = bootSector.getDataAreaOffset();
  }

  /**
   * Reads from the cluster chain at the given offset into the given buffer.
   * This method automatically searches for following clusters in the chain
   * and reads from them appropriately.
   * 
   * @param offset
   *            The offset in bytes where reading shall start.
   * @param dest
   *            The destination buffer the contents of the chain shall be
   *            copied to.
   * @throws IOException
   *             If reading fails.
   */
  /* package */void read(long offset, ByteBuffer dest) throws IOException {
    int length = dest.remaining();

    int chainIndex = (int) (offset / clusterSize);
    // if the offset is not a multiple of the cluster size we have to start
    // reading
    // directly in the cluster
    if (offset % clusterSize != 0) {
      // offset in the cluster
      int clusterOffset = (int) (offset % clusterSize);
      int size = Math.min(length, (int) (clusterSize - clusterOffset));
      dest.limit(dest.position() + size);

      blockDevice.read(getFileSystemOffset(chain[chainIndex], clusterOffset), dest);

      // round up to next cluster in the chain
      chainIndex++;
      // make length now a multiple of the cluster size
      length -= size;
    }

    // now we can proceed reading the clusters without an offset in the
    // cluster
    while (length > 0) {
      // we always read one cluster at a time, or if remaining size is
      // less than the cluster size, only "size" bytes
      int size = (int) Math.min(clusterSize, length);
      dest.limit(dest.position() + size);

      blockDevice.read(getFileSystemOffset(chain[chainIndex], 0), dest);

      chainIndex++;
      length -= size;
    }
  }

  /**
   * Writes to the cluster chain at the given offset from the given buffer.
   * This method automatically searches for following clusters in the chain
   * and reads from them appropriately.
   * 
   * @param offset
   *            The offset in bytes where writing shall start.
   * @param source
   *            The buffer which holds the contents which shall be transferred
   *            into the cluster chain.
   * @throws IOException
   *             If writing fails.
   */
  /* package */void write(long offset, ByteBuffer source) throws IOException {
    int length = source.remaining();

    int chainIndex = (int) (offset / clusterSize);
    // if the offset is not a multiple of the cluster size we have to start
    // reading
    // directly in the cluster
    if (offset % clusterSize != 0) {
      int clusterOffset = (int) (offset % clusterSize);
      int size = Math.min(length, (int) (clusterSize - clusterOffset));
      source.limit(source.position() + size);

      blockDevice.write(getFileSystemOffset(chain[chainIndex], clusterOffset), source);

      // round up to next cluster in the chain
      chainIndex++;
      // make length now a multiple of the cluster size
      length -= size;
    }

    // now we can proceed reading the clusters without an offset in the
    // cluster
    while (length > 0) {
      // we always write one cluster at a time, or if remaining size is
      // less than the cluster size, only "size" bytes
      int size = (int) Math.min(clusterSize, length);
      source.limit(source.position() + size);

      blockDevice.write(getFileSystemOffset(chain[chainIndex], 0), source);

      chainIndex++;
      length -= size;
    }
  }

  /**
   * Returns the offset of a cluster from the beginning of the FAT32 file
   * system in bytes.
   * 
   * @param cluster
   *            The desired cluster.
   * @param clusterOffset
   *            The desired offset in bytes in the cluster.
   * @return Offset in bytes from the beginning of the disk (FAT32 file
   *         system).
   */
  private long getFileSystemOffset(long cluster, int clusterOffset) {
    return dataAreaOffset + clusterOffset + (cluster - 2) * clusterSize;
  }

  /**
   * Sets a new cluster size for the cluster chain. This method allocates or
   * frees clusters in the FAT if the number of the new clusters is bigger or
   * lower than the current number of allocated clusters.
   * 
   * @param newNumberOfClusters
   *            The new number of clusters.
   * @throws IOException
   *             If growing or allocating the chain fails.
   * @see #getClusters()
   * @see #setLength(long)
   */
  /* package */void setClusters(int newNumberOfClusters) throws IOException {
    int oldNumberOfClusters = getClusters();
    if (newNumberOfClusters == oldNumberOfClusters)
      return;

    if (newNumberOfClusters > oldNumberOfClusters) {
      Log.d(TAG, "grow chain");
      chain = fat.alloc(chain, newNumberOfClusters - oldNumberOfClusters);
    } else {
      Log.d(TAG, "shrink chain");
      chain = fat.free(chain, oldNumberOfClusters - newNumberOfClusters);
    }
  }

  /**
   * Gets the current allocated clusters for this chain.
   * 
   * @return The number of clusters.
   * @see #setClusters(int)
   * @see #getLength()
   */
  /* package */int getClusters() {
    return chain.length;
  }

  /**
   * Sets the new length in bytes of this chain. This method allocates or
   * frees new space on the disk depending on the new length.
   * 
   * @param newLength
   *            The new length.
   * @throws IOException
   *             If growing or allocating the chain fails.
   * @see #getLength()
   * @see #setClusters(int)
   */
  /* package */void setLength(long newLength) throws IOException {
    final long newNumberOfClusters = ((newLength + clusterSize - 1) / clusterSize);
    setClusters((int) newNumberOfClusters);
  }

  /**
   * Returns the size in bytes the chain currently occupies on the disk.
   * 
   * @return The size / length in bytes of the chain.
   * @see #setLength(long)
   * @see #getClusters()
   */
  /* package */long getLength() {
    return chain.length * clusterSize;
  }
}




Java Source Code List

com.github.mjdev.libaums.UsbCommunication.java
com.github.mjdev.libaums.UsbMassStorageDevice.java
com.github.mjdev.libaums.driver.BlockDeviceDriverFactory.java
com.github.mjdev.libaums.driver.BlockDeviceDriver.java
com.github.mjdev.libaums.driver.scsi.ScsiBlockDevice.java
com.github.mjdev.libaums.driver.scsi.commands.CommandBlockWrapper.java
com.github.mjdev.libaums.driver.scsi.commands.CommandStatusWrapper.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiInquiryResponse.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiInquiry.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiRead10.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiReadCapacityResponse.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiReadCapacity.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiRequestSense.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiTestUnitReady.java
com.github.mjdev.libaums.driver.scsi.commands.ScsiWrite10.java
com.github.mjdev.libaums.fs.FileSystemFactory.java
com.github.mjdev.libaums.fs.FileSystem.java
com.github.mjdev.libaums.fs.UsbFile.java
com.github.mjdev.libaums.fs.fat32.ClusterChain.java
com.github.mjdev.libaums.fs.fat32.FAT.java
com.github.mjdev.libaums.fs.fat32.Fat32BootSector.java
com.github.mjdev.libaums.fs.fat32.Fat32FileSystem.java
com.github.mjdev.libaums.fs.fat32.FatDirectoryEntry.java
com.github.mjdev.libaums.fs.fat32.FatDirectory.java
com.github.mjdev.libaums.fs.fat32.FatFile.java
com.github.mjdev.libaums.fs.fat32.FatLfnDirectoryEntry.java
com.github.mjdev.libaums.fs.fat32.FsInfoStructure.java
com.github.mjdev.libaums.fs.fat32.ShortNameGenerator.java
com.github.mjdev.libaums.fs.fat32.ShortName.java
com.github.mjdev.libaums.partition.PartitionTableEntry.java
com.github.mjdev.libaums.partition.PartitionTableFactory.java
com.github.mjdev.libaums.partition.PartitionTable.java
com.github.mjdev.libaums.partition.Partition.java
com.github.mjdev.libaums.partition.mbr.MasterBootRecord.java
com.github.mjdev.libaums.usbfileman.MainActivity.java
com.github.mjdev.libaums.usbfileman.MoveClipboard.java
com.github.mjdev.libaums.usbfileman.UsbFileListAdapter.java