fdiskcommand.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 840 行 · 第 1/2 页

JAVA
840
字号
/*
 * $Id: FdiskCommand.java,v 1.3 2004/01/24 23:43:38 gbin Exp $
 */
package org.jnode.fs.partitions.command;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.naming.NameNotFoundException;

import org.jnode.driver.ApiNotFoundException;
import org.jnode.driver.Device;
import org.jnode.driver.DeviceManager;
import org.jnode.driver.DeviceNotFoundException;
import org.jnode.driver.block.BlockDeviceAPI;
import org.jnode.driver.ide.IDEConstants;
import org.jnode.driver.ide.IDEDevice;
import org.jnode.driver.ide.IDEDriveDescriptor;
import org.jnode.fs.fat.BootSector;
import org.jnode.fs.fat.GrubBootSector;
import org.jnode.fs.partitions.ibm.IBMPartitionTable;
import org.jnode.fs.partitions.ibm.IBMPartitionTableEntry;
import org.jnode.fs.partitions.ibm.IBMPartitionTypes;
import org.jnode.naming.InitialNaming;
import org.jnode.shell.help.DeviceArgument;
import org.jnode.shell.help.Help;
import org.jnode.shell.help.OptionArgument;
import org.jnode.shell.help.Parameter;
import org.jnode.shell.help.ParsedArguments;
import org.jnode.shell.help.StringArgument;
import org.jnode.shell.help.Syntax;
/**
 * @author gbin
 */
public class FdiskCommand {

	static final OptionArgument INITMBR =
		new OptionArgument(
			"init. MBR",
			"Type parameter",
			new OptionArgument.Option[] {
				 new OptionArgument.Option("--initmbr", "initialize the Master Boot Record of the device")});

	static final OptionArgument ACTION =
		new OptionArgument(
			"action",
			"Action on a specified partition",
			new OptionArgument.Option[] {
				new OptionArgument.Option("-d", "Delete a partition"),
				new OptionArgument.Option("-b", "Switch the bootable flag of a partition"),
				new OptionArgument.Option("-m", "Modify/create a partition")});

	static final StringArgument PARTITION = new StringArgument("partition number or description", "Targeted partition");

	static final DeviceArgument ARG_DEVICE =
		new DeviceArgument("device-id", "the device on which you want to change the partition");

	static final Parameter PARAM_INITMBR = new Parameter(INITMBR, Parameter.MANDATORY);
	static final Parameter PARAM_ACTION = new Parameter(ACTION, Parameter.MANDATORY);
	static final Parameter PARAM_DEVICE = new Parameter(ARG_DEVICE, Parameter.MANDATORY);
	static final Parameter PARAM_PARTITION = new Parameter(PARTITION, Parameter.MANDATORY);

	public static Help.Info HELP_INFO =
		new Help.Info(
			"fdisk",
			new Syntax[] {
				new Syntax("Lists the available devices"),
				new Syntax("Print the partition table of a device", new Parameter[] { PARAM_DEVICE }),
				new Syntax("Initialize the MBR of a device", new Parameter[] { PARAM_INITMBR, PARAM_DEVICE }),
				new Syntax(
					"Create / Delete / change bootable flag of a partition",
					new Parameter[] { PARAM_ACTION, PARAM_PARTITION, PARAM_DEVICE })
	});

	/*
	 * public static Help.Info HELP_INFO = new Help.Info( "fdisk", "With no
	 * argument, it lists the available devices\n" + "With only the device, it
	 * lists the current partitions on the device\n" + "--initmbr initialize the
	 * Master Boot Record of the device\n" + "-m add or modify the id partition
	 * with first sector at start, size of size sectors and fs id fs\n" + "-d
	 * delete the partition with id id" + "-b switch boot flag on parition id",
	 */

	public static void main(String[] args) {
		ParsedArguments cmdLine = HELP_INFO.parse(args);

		DeviceManager dm;
		try {
			dm = (DeviceManager)InitialNaming.lookup(DeviceManager.NAME);

			boolean isAction = PARAM_ACTION.isSet(cmdLine);
			boolean isInitMBR = PARAM_INITMBR.isSet(cmdLine);
			boolean isDevice = PARAM_DEVICE.isSet(cmdLine);

			// no parameters
			if (!isDevice) {
				listAvailableDevice(dm);
				return;
			}

			// only device is set
			if (!isAction && !isInitMBR && isDevice) {
				printTable(ARG_DEVICE.getValue(cmdLine), dm);
				return;
			}

			// initMBR
			if (isInitMBR) {
				initMbr(ARG_DEVICE.getValue(cmdLine), dm);
				return;
			}

			// now it is a change on a specific partition so read the table

			IDEDevice current = (IDEDevice)dm.getDevice(ARG_DEVICE.getValue(cmdLine));
			BlockDeviceAPI api = (BlockDeviceAPI)current.getAPI(BlockDeviceAPI.class);
			byte[] mbr = new byte[IDEConstants.SECTOR_SIZE];
			api.read(0, mbr, 0, IDEConstants.SECTOR_SIZE);
			if (!IBMPartitionTable.containsPartitionTable(mbr))
				throw new IOException("This device doesn't contain a valid MBR, use --initmbr.");

			BootSector bs = new BootSector(mbr);

			if (ACTION.getValue(cmdLine).intern() == "-m") {
				modifyPartition(PARTITION.getValue(cmdLine), api, bs);
				bs.write(api);
				return;
			}

			// it is not a modify so the PARTITION parameter is only a partition
			// number

			int partNumber;
			try {
				partNumber = Integer.parseInt(PARTITION.getValue(cmdLine));
			} catch (NumberFormatException f) {
				throw new IllegalArgumentException("Partition number is invalid");
			}

			if (partNumber > 3 || partNumber < 0)
				throw new IllegalArgumentException("Partition number is invalid");

			if (ACTION.getValue(cmdLine).intern() == "-d") {
				deletePartition(bs, partNumber);
				bs.write(api);
				return;
			}

			if (ACTION.getValue(cmdLine).intern() == "-b") {
				toggleBootable(bs, partNumber);
				bs.write(api);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		} catch (ApiNotFoundException e) {
			e.printStackTrace();
		} catch (DeviceNotFoundException e) {
			e.printStackTrace();
		} 

	}

	private static void toggleBootable(BootSector bs, int partNumber) {
		// save the current state for the targeted partition
		boolean currentStatus = bs.getPartition(partNumber).getBootIndicator();

		// erase all the states
		for (int i = 0; i < 4; i++) {
			bs.getPartition(i).setBootIndicator(false);
		}

		// put back the reversed state for the targeted partition
		bs.getPartition(partNumber).setBootIndicator(!currentStatus);
	}

	private static void deletePartition(BootSector bs, int partNumber) {
		bs.getPartition(partNumber).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY);
	}

	private static void modifyPartition(String description, BlockDeviceAPI api, BootSector bs) throws IOException {
		// arg 1 should be in the form id:start:size:fs
		StringTokenizer st = new StringTokenizer(description, ":");
		int id = Integer.parseInt(st.nextToken());
		//BUG in long
		//long start = Long.parseLong(st.nextToken());
		//long size = Long.parseLong(st.nextToken());
		int start = Integer.parseInt(st.nextToken());
		int size = Integer.parseInt(st.nextToken());
		int fs = Integer.parseInt(st.nextToken(), 16);
		System.out.println(
			"Init " + id + " with start = " + start + ", size = " + size + ", fs = " + Integer.toHexString(fs & 0xff));
		IBMPartitionTableEntry entry = bs.getPartition(id);
		entry.setBootIndicator(false);
		entry.setSystemIndicator(fs);
		entry.setStartLba(start);
		entry.setNrSectors(size);
		bs.write(api);
		return;
	}

	private static void initMbr(String device, DeviceManager dm)
		throws DeviceNotFoundException, ApiNotFoundException, IOException {
		IDEDevice current = (IDEDevice)dm.getDevice(device);
		BlockDeviceAPI api = (BlockDeviceAPI)current.getAPI(BlockDeviceAPI.class);
		byte[] MBR = new byte[IDEConstants.SECTOR_SIZE];
		api.read(0, MBR, 0, IDEConstants.SECTOR_SIZE);

		System.out.println("Initialize MBR ...");

		GrubBootSector newMBR = new GrubBootSector(PLAIN_MASTER_BOOT_SECTOR);

		if (IBMPartitionTable.containsPartitionTable(MBR)) {
			BootSector oldMBR = new BootSector(MBR);
			System.out.println("This device already contains a partition table. Copy the already existing partitions.");
			for (int i = 0; i < 4; i++) {
				IBMPartitionTableEntry entry = newMBR.getPartition(i);
				entry.setBootIndicator(oldMBR.getPartition(i).getBootIndicator());
				entry.setStartLba(oldMBR.getPartition(i).getStartLba());
				entry.setNrSectors(oldMBR.getPartition(i).getNrSectors());
				entry.setSystemIndicator(oldMBR.getPartition(i).getSystemIndicator());

			}
		} else {
			newMBR.getPartition(0).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY);
			newMBR.getPartition(1).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY);
			newMBR.getPartition(2).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY);
			newMBR.getPartition(3).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY);
		}
		newMBR.write(api);
	}

	private static void printTable(String deviceName, DeviceManager dm)
		throws DeviceNotFoundException, ApiNotFoundException, IOException {
		{
			IDEDevice current = (IDEDevice)dm.getDevice(deviceName);
			BlockDeviceAPI api = (BlockDeviceAPI)current.getAPI(BlockDeviceAPI.class);
			IDEDriveDescriptor descriptor = current.getDescriptor();
			byte[] MBR = new byte[IDEConstants.SECTOR_SIZE];
			api.read(0, MBR, 0, IDEConstants.SECTOR_SIZE);
			if (IBMPartitionTable.containsPartitionTable(MBR)) {
				IBMPartitionTable partitionTable = new IBMPartitionTable(MBR, current);
				int nbPartitions = partitionTable.getLength();

				System.out.println(
					"Disk : " + current.getId() + ": " + descriptor.getSectorsIn28bitAddressing() * 512 + " bytes");
				System.out.println("Device Boot    Start       End    Blocks   System");

				for (int i = 0; i < nbPartitions; i++) {
					IBMPartitionTableEntry entry = (IBMPartitionTableEntry)partitionTable.getEntry(i);
					int si = entry.getSystemIndicator();
					if (si != 0)
						System.out.println(
							"ID "
								+ i
								+ " "
								+ (entry.getBootIndicator() ? "Boot" : "No")
								+ "    "
								+ entry.getStartLba()
								+ "    "
								+ (entry.getStartLba() + entry.getNrSectors())
								+ "    "
								+ entry.getNrSectors()
								+ "    "
								+ Integer.toHexString(si));
					if(entry.isExtended()) {
						final Vector exPartitions = partitionTable.getExtendedPartitions();
						Iterator itter = exPartitions.iterator();
						int j = 0;
						while(itter.hasNext()) {
							IBMPartitionTableEntry exEntry = (IBMPartitionTableEntry)itter.next();
							si = exEntry.getSystemIndicator();
							System.out.println(
									"ID "
									+ i
									+ " "
									+ (exEntry.getBootIndicator() ? "Boot" : "No")
									+ "    "
									+ exEntry.getStartLba()
									+ "    "
									+ "-----"//(exEntry.getStartLba() + entry.getNrSectors())
									+ "    "
									+ "-----"//exEntry.getNrSectors()
									+ "    "
									+ Integer.toHexString(si));
							j++;
						}
					}
						
				}

			} else {
				System.out.println(" No valid MBR found on this device. Use --initmbr to initialize it.");
			}
		}
	}

	private static void listAvailableDevice(DeviceManager dm) {
		Iterator allDevices = dm.getDevicesByAPI(BlockDeviceAPI.class).iterator();
		while (allDevices.hasNext()) {
			Device current = (Device)allDevices.next();
			System.out.println("Found device : " + current.getId() + "[" + current.getClass() + "]");

			if (current instanceof IDEDevice) {
				IDEDevice ideDevice = (IDEDevice)current;
				IDEDriveDescriptor currentDescriptor = ideDevice.getDescriptor();
				if (currentDescriptor.isDisk()) {
					System.out.println(
						"    IDE Disk : "
							+ ideDevice.getId()
							+ "("
							+ currentDescriptor.getModel()
							+ " "
							+ currentDescriptor.getSectorsIn28bitAddressing() * IDEConstants.SECTOR_SIZE
							+ ")");
				}
			}
		}
	}

	private static final byte PLAIN_MASTER_BOOT_SECTOR[] =
		{
			(byte)0xEB,
			(byte)0x48,
			(byte)0x90,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x03,
			(byte)0x02,
			(byte)0xFF,
			(byte)0x00,
			(byte)0x00,
			(byte)0x80,
			(byte)0x01,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x00,
			(byte)0x08,
			(byte)0xFA,
			(byte)0xEA,
			(byte)0x50,
			(byte)0x7C,
			(byte)0x00,
			(byte)0x00,
			(byte)0x31,
			(byte)0xC0,
			(byte)0x8E,
			(byte)0xD8,
			(byte)0x8E,
			(byte)0xD0,
			(byte)0xBC,
			(byte)0x00,
			(byte)0x20,
			(byte)0xFB,
			(byte)0xA0,
			(byte)0x40,
			(byte)0x7C,
			(byte)0x3C,
			(byte)0xFF,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?