/* * $Id$ * * Copyright (C) 2003-2013 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.fs.jfat.command; import java.io.File; import java.io.PrintWriter; import java.util.Map; 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.DeviceUtils; import org.jnode.driver.DriverException; import org.jnode.driver.block.BlockDeviceAPI; import org.jnode.fs.FileSystem; import org.jnode.fs.service.FileSystemService; import org.jnode.naming.InitialNaming; /** * The Grub Installer for JNode. * * TODO: Adding more options for supporting JGRUB with user specified File * System wise. Adding more command support for grub installation. * * @author Tango Devian */ public class JGrub { private final PrintWriter out; private final MBRFormatter stage1; private final Stage1_5 stage1_5; private final Stage2 stage2; private final Device device; private String mountPoint; public JGrub(PrintWriter out, Device device) { this(out, device, new MBRFormatter(), new Stage1_5(), new Stage2()); } protected JGrub(PrintWriter out, Device device, MBRFormatter stage1, Stage1_5 stage1_5, Stage2 stage2) { this.out = out; this.stage1 = stage1; this.stage1_5 = stage1_5; this.stage2 = stage2; this.device = device; } public String getMountPoint() throws GrubException { if (mountPoint == null) { mountPoint = getMountPoint(device); } return mountPoint; } public void install() throws GrubException { final String deviceName = device.getId(); out.println("Installing GRUB to " + deviceName); DeviceManager dm; try { dm = DeviceUtils.getDeviceManager(); } catch (NameNotFoundException e1) { throw new GrubException("can't find device manager", e1); } // workaround. TODO add a new interface to FileSystemService to find // parent device ? int i = deviceName.length() - 1; while ((i >= 0) && Character.isDigit(deviceName.charAt(i))) { i--; } final String parentDeviceName = deviceName.substring(0, i + 1); final int partitionNumber = Integer.parseInt(deviceName.substring(i + 1)); // final Device parentDevice = getDevice(dm, parentDeviceName); final BlockDeviceAPI parentDeviceApi = getBlockDeviceAPI(parentDevice); stage1.format(parentDeviceApi); stage1_5.format(parentDeviceApi, partitionNumber); stage2.format(getMountPoint()); restart(dm, parentDevice); out.println("GRUB has been successfully installed to " + deviceName + "."); } private String getMountPoint(Device device) throws GrubException { FileSystemService fss = null; try { fss = InitialNaming.lookup(FileSystemService.NAME); } catch (NameNotFoundException e) { throw new GrubException("filesystem not found", e); } FileSystem<?> filesystem = fss.getFileSystem(device); if (filesystem == null) { throw new GrubException("can't find filesystem for device " + device.getId()); } Map<String, FileSystem<?>> mountPoints = fss.getMountPoints(); String mountPoint = null; for (String fullPath : mountPoints.keySet()) { FileSystem<?> fs = mountPoints.get(fullPath); if (fs == filesystem) { mountPoint = fullPath; break; } } if (mountPoint == null) { throw new GrubException("can't find mount point for filesystem " + filesystem); } if (!mountPoint.endsWith(File.separator)) { mountPoint += File.separatorChar; } return mountPoint; } private void restart(DeviceManager dm, Device device) throws GrubException { out.println("Restarting device " + device.getId()); try { dm.stop(device); dm.start(device); } catch (DeviceNotFoundException e) { throw new GrubException("device not found : " + device.getId(), e); } catch (DriverException e) { throw new GrubException("device must be a partition device", e); } } private Device getDevice(DeviceManager dm, String deviceName) throws GrubException { Device parentDevice = null; try { parentDevice = dm.getDevice(deviceName); } catch (DeviceNotFoundException e1) { throw new GrubException("can't find device with name " + deviceName, e1); } return parentDevice; } private BlockDeviceAPI getBlockDeviceAPI(Device device) throws GrubException { BlockDeviceAPI deviceApi = null; try { deviceApi = device.getAPI(BlockDeviceAPI.class); } catch (ApiNotFoundException e) { throw new GrubException("device must be a partition device", e); } return deviceApi; } }