package com.sun.launcher.tasks;

import java.io.*;
import java.util.*;
import com.sun.wizards.core.*;
import com.sun.install.tasks.*;
import com.sun.install.products.*;
import com.sun.launcher.core.*;
import java.text.SimpleDateFormat;



/** MountCDTask: A task to mount a CD 
*
* @version @(#)MountCDTask.java	1.3 99/11/24 15:44:38  */

public class MountCDTask extends Task implements Serializable
{
  private static boolean usingVold = false;

  /*
   * This happens at build time. 
   */
  public MountCDTask()
  {
  }

  /** 
   *  Read the file
   */
  public void perform()
  {
    WizardState state = getSequence().getState();

    /*
     * Initialize mount status to false
     */
    state.setData(LaunchConstants.CDmountOK, Boolean.FALSE);

    String CDmnt = null;
    Boolean vold = (Boolean) state.getData(LaunchConstants.usingVold);

    if (vold.booleanValue()) usingVold = true;

    int result = 0;
    String output = null;
    String cmd = null;
    String CDdev = null;
    String CDdeviceRaw = null;

    if (usingVold) {
      /*
       * vold mounts on /cdrom 
       */
      CDmnt = "/cdrom"; 

      /*
       * Wait a few seconds to allow vold to see CD 
       */
      try {
        Thread.sleep(5000);
      } catch (InterruptedException ex) {
        System.out.println("MountCDTask: mount: sleep: "+ex);
      }

      /*
       * Do ls to see if cdrom is mounted 
       */
      cmd = "/usr/bin/ls /cdrom";
      if (Def.DEBUG) System.out.println ("==>MountCDTask cmd: " + cmd ); 
      int maxAttempts = 4;
      int i = 0;

      for (i=0; i < maxAttempts; i++) {
        RunCmd r = new RunCmd(cmd, true);
        result = r.getResult();
        output =  r.getAllOutput();
        if (Def.DEBUG) System.out.println("MountCDTask: output =" + output);
        if ( r.getOutput().compareTo("") != 0 ) break;
        /*
         * Sleep for a while
         */
        try {
          if (Def.DEBUG)System.out.println("MountCDTask: mount sleep 2 secs");
          Thread.sleep(2000);
        } catch (InterruptedException ex) {
          System.out.println("MountCDTask: mount: sleep: "+ex);
        }
      }
      if ( i < maxAttempts ) {
        result = 0;
      } else {
        result = 99;
      }
    } else {
      /*
       * not using vold, prepare to mount cdrom
       */
      CDmnt = (String) state.getData(LaunchConstants.CDmount);
      File CDmntFile = new File (CDmnt);
      if (CDmntFile.exists()) {
        if ( CDmntFile.isFile()) {
          System.out.println("MountCDTask: " + CDmnt +
                         " is a file. Unable to mount CD.");
          return;
        }
        String umntCmd = "/sbin/umount " + CDmnt;
        result=0;
        RunCmd r = new RunCmd(umntCmd, true);
        result = r.getResult();
        if (Def.DEBUG) {
          System.out.println("==>MountCDTask:" + umntCmd + " return=" + result);
        }
      } else {
        CDmntFile.mkdir();
      }

      /*
       * Run script to manually mount
       */
      CDdev = (String) state.getData("CDdevice");
      CDdeviceRaw= (String) state.getData("CDdeviceRaw");
      cmd = "/sbin/mount -r -F hsfs " + CDdev + " " + CDmnt;

      if (Def.DEBUG) System.out.println ("==>MountCDTask cmd: " + cmd );
      output = null;
      result = 0;
      int maxAttempts = 1;
      int i = 0;

      for (i=0; i < maxAttempts; i++) {
        RunCmd r = new RunCmd(cmd, true);
        result = r.getResult();
        output =  r.getAllOutput();
        if (Def.DEBUG) System.out.println("MountCDTask: output =" + output);
        if (result == 0) break;

          /*
           * Sleep for a while
           */
        try {
          Thread.sleep(5000);
        } catch (InterruptedException ex) {
          System.out.println("MountCDTask: mount: sleep: "+ex);
        }
      }

    }

   /*
    * Check if we have mounted the CD. If so, try to validate
    * that it is the correct cd. If we are automounting, we
    * have a secure way to do this with volID. Otherwise, it's
    * kind of a hack and has problems.
    */ 
    boolean status = false;
    if (result == 0) {
      /*
       * We have mounted the CD. Now we want to verify that we have
       * mounted the correct CD
       *
       * First, check the Volume ID, if it exists. 
       * If there is no VolID, use cd_keyfile
       */
      String volID = ((String) state.getData(LaunchConstants.VolID)).trim();
      if (volID.equals(""))  {
        String keyfile = (String) state.getData(LaunchConstants.Keyfile);
        //if (keyfile != null) 
        if (!keyfile.equals("")) {
          File keyFile = new File(CDmnt + "/" + keyfile); 
          if ( ! keyFile.exists()) {
            if (Def.DEBUG) System.out.println("CD Mounted, but wrong keyfile!");
            state.setData(LaunchConstants.CDmountFailCode, 
                               LaunchConstants.WrongCD);
            status = false;
          } else {
            if (Def.DEBUG) System.out.println("CD Mounted, found keyfile");
            status = true;
          }
        }  else {
          if (Def.DEBUG) System.out.println("CD Mounted, nothing to validate");
          status=true;
        }
      } else {
        /*
         * We have a VOLID
         */
        if (usingVold) { 
          /* 
           * Since we have a volumeID, see if the path /mountpoint/volID
           * actually exists. This correctly and accurately verifies the
           * cd (assuming unique VolumeIDs.
           */
          File CDrom = new File (CDmnt);
          String fileList[]= CDrom.list();
          if (Def.DEBUG) {
              for (int i = 0; i < fileList.length; i++) 
                System.out.println("/cdrom: "+fileList[i]);
          }
          String volPath = CDmnt + "/" + volID;
          String volPath1 = CDmnt + "/" + volID + "#1";
          String volPath2 = CDmnt + "/" + volID + "#2";
          File CDmntFile = new File (volPath);
          File CDmntFile1 = new File (volPath1);
          File CDmntFile2 = new File (volPath2);
          if (CDmntFile.exists()) {
            status = true;
            CDmnt = volPath;
            if (Def.DEBUG)System.out.println("\nMountCDTsk volpath: "+volPath);
          } else if (CDmntFile1.exists()) {
            status = true;
            CDmnt = volPath1;
            if (Def.DEBUG)System.out.println("\nMountCDTsk volpath: "+volPath1);
          } else if (CDmntFile2.exists()) {
            status = true;
            CDmnt = volPath2;
            if (Def.DEBUG)System.out.println("\nMountCDTsk volpath: "+volPath2);
          } else {
            if (Def.DEBUG) System.out.println("CD Mounted, but wrong CD !");
            if (Def.DEBUG)System.out.println("\nMountCDTask path does not exit: "+volPath);
            status = false;
            state.setData(LaunchConstants.CDmountFailCode, 
                                            LaunchConstants.WrongCD);
          }
        } else {
          /*
           * Do a dd of the CD and check the VolumeID.
           */
          SimpleDateFormat sdf = new SimpleDateFormat("MMddhhmm");
          Date date = new Date();
          String ddfile = "/tmp/.ddfile" + sdf.format(date);
          cmd = "/usr/bin/dd if=" + CDdev + " of=" + ddfile
               +  " bs=2048 count=20";
          if (Def.DEBUG)System.out.println ("\nMountCDTask cmd: " + cmd );
          result=0;
          RunCmd r = new RunCmd(cmd, true);
          result = r.getResult();
          output =  r.getAllOutput();
          if (Def.DEBUG)System.out.println("MountCDTask: output =" + output);
          if (Def.DEBUG)System.out.println("MountCDTask: Return code="+result);

          VolumeID volumeID = new VolumeID(ddfile);
          String actualVolID= volumeID.hsfsFindName().trim();
          if ((actualVolID != null) && actualVolID.equalsIgnoreCase(volID)) {
            status = true;
          } else {
            status = false;
            if (Def.DEBUG) System.out.println("Expected volumeID=" + volID +
                          ", actual volID=" + actualVolID + ".");
            if (Def.DEBUG) System.out.println("CD Mounted, but wrong CD !");
            state.setData(LaunchConstants.CDmountFailCode,
                                            LaunchConstants.WrongCD);
          }

          /*
           * Delete the dd file 
           */
          File ddFile = new File(ddfile);
          ddFile.delete();
        }
      }
    } else {
      status = false;
      if (Def.DEBUG) System.out.println("CD Mount failed!");
      state.setData(LaunchConstants.CDmountFailCode, 
                                       LaunchConstants.MountFailed);
    }

    /* 
     * and the answer is...
     */
    if (status) {
      /*
       * set launchLocation for LaunchInstallTask
       */
      state.setData(LaunchConstants.launchLocation, CDmnt);
      state.setData(LaunchConstants.CDmountOK, Boolean.TRUE);
      if (Def.DEBUG) System.out.println("CD Mounted successfully!");
    } else {
      /*
       * Umount the CD and eject it
       */
      if (usingVold) {
        AutoEjectCD();
      } else {
        UmountEject(CDmnt, CDdeviceRaw);
      }
    }
	
  }


  public static void UmountEject(String CDmntpt, String CDraw)
  {
    if (usingVold) {
      AutoEjectCD();
    } else {
      UnmountCD(CDmntpt);
      EjectCD(CDraw);
    }
  }


  /*
   * unmounts cdrom, assumes no vold 
   */
  public static void UnmountCD(String CDmntpt)
  {
    /*
     * Unmount the CD
     */
    String cmd = "/usr/sbin/umount " + CDmntpt;
    if (Def.DEBUG) System.out.println ("\nMountCDTask UnmountCD cmd: " + cmd );
    int result=0;
    RunCmd r = new RunCmd(cmd, true);
    result = r.getResult();
    String output =  r.getAllOutput();
    if (Def.DEBUG) {
      System.out.println("MountCDTask: Unmount output =" + output);
      System.out.println("MountCDTask: Unmount Return code =" + result);
    }
  }


  /*
   * ejects cdrom, assumes vold is running
   */
  public static void AutoEjectCD()
  {
    /*
     * Eject the CD
     */
    String cmd = "/usr/bin/eject cdrom" ;
    if (Def.DEBUG) System.out.println ("\n==>MountCDTask EjectCD cmd: " + cmd );
    int result=0;
    RunCmd r = new RunCmd(cmd, true);
    result = r.getResult();
    String output =  r.getAllOutput();
    if (Def.DEBUG) {
      System.out.println("MountCDTask: Eject output =" + output);
      System.out.println("MountCDTask: Eject Return code =" + result);
    }

  }


  /*
   * ejects cdrom, assumes no vold 
   */
  public static void EjectCD(String CDraw)
  {
    if (usingVold) {
      AutoEjectCD();
    } else {

      /*
       * Eject the CD
       */
      String cmd = "/usr/bin/eject " + CDraw;
      if (Def.DEBUG) System.out.println("\n==>MountCDTask EjectCD cmd: " + cmd);
      int result=0;
      RunCmd r = new RunCmd(cmd, true);
      result = r.getResult();
      String output =  r.getAllOutput();
      if (Def.DEBUG) {
        System.out.println("MountCDTask: Eject output =" + output);
        System.out.println("MountCDTask: Eject Return code =" + result);
      }
    }
  }


  public static void setVold(boolean usingvold)
  {
    if (usingvold) usingVold = true;     
  }


  /**
   * Add the runtime class requirements to the specified vector.
   */
  public void addRuntimeResources(Vector resourceVector)
  {
    resourceVector.addElement(new String[] {null, "com.sun.launcher.tasks.MountCDTask"});
    resourceVector.addElement(new String[] {null, "com.sun.launcher.core.VolumeID"});
  }



}
