Package er.woinstaller.archiver

Source Code of er.woinstaller.archiver.CPIO$Link

package er.woinstaller.archiver;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import er.woinstaller.io.BoundedInputStream;
import er.woinstaller.io.FileUtilities;
import er.woinstaller.ui.IWOInstallerProgressMonitor;
import er.woinstaller.ui.NullProgressMonitor;

public class CPIO {

  public static final int S_IFDIR = 16384;
  public static final int S_IFREG = 32768;
  public static final int S_IFLNK = 40960;

  private File _cpioFile;
  InputStream paxStream;
  long fileLength = 0;

  public CPIO(File cpioFile) throws FileNotFoundException {
  this(new BufferedInputStream(new FileInputStream(cpioFile)));
    _cpioFile = cpioFile;
    fileLength = _cpioFile.length();

  }

  public CPIO(InputStream input) {
  paxStream = input;
  }

  public void setLength(long length) {
    this.fileLength = length;
  }

  @SuppressWarnings("unused")
  public void extractTo(File destinationFolder, boolean symbolicLinksSupported, IWOInstallerProgressMonitor progressMonitor) throws IOException, InterruptedException {
    progressMonitor.beginTask("Extracting WebObjects ...", fileLength);
   
    long amount = 0;
    List<Link> links = new LinkedList<Link>();

    try {
      byte[] sixBuffer = new byte[6];
      byte[] elevenBuffer = new byte[11];
      boolean done = false;
      do {
        String magic = readString(paxStream, sixBuffer);
        if (!"070707".equals(magic)) {
          throw new IOException("Expected magic '070707' but got '" + magic + "' (next = " + readString(paxStream, new byte[50]) + ").");
        }
        else {
          String dev = readString(paxStream, sixBuffer);
          String ino = readString(paxStream, sixBuffer);
          String modeStr = readString(paxStream, sixBuffer);
          String uid = readString(paxStream, sixBuffer);
          String gid = readString(paxStream, sixBuffer);
          String nlink = readString(paxStream, sixBuffer);
          String rdev = readString(paxStream, sixBuffer);
          String mtime = readString(paxStream, elevenBuffer);
          String nameSizeStr = readString(paxStream, sixBuffer);
          String fileSizeStr = readString(paxStream, elevenBuffer);

          int nameSize = Integer.parseInt(nameSizeStr, 8);
          String name = readString(paxStream, new byte[nameSize]);

          int fileSize = Integer.parseInt(fileSizeStr, 8);

          if ("TRAILER!!!".equals(name)) {
            done = true;
          }
          else {
            File destinationFile = toFile(destinationFolder, name);
            int mode = Integer.parseInt(modeStr, 8);
            if ((mode & S_IFDIR) == S_IFDIR) {
              if (".".equals(name)) {
                // skip
              }
              else if (destinationFile.exists()) {
                throw new IOException("The directory '" + destinationFile + "' already exists.");
              }
              else if (!destinationFile.mkdirs()) {
                throw new IOException("Failed to create directory '" + destinationFile + "'.");
              }
              skipFully(paxStream, fileSize);
            }
            else if ((mode & S_IFLNK) == S_IFLNK) {
              String realName = readString(paxStream, new byte[fileSize]);
              File realFile = new File(realName);
              if (!symbolicLinksSupported) {
                realFile = toFile(destinationFile.getParentFile(), realName);
              }
              links.add(new Link(realFile, destinationFile));
            }
            else if ((mode & S_IFREG) == S_IFREG) {
              if (destinationFile.exists()) {
                throw new IOException("The file '" + destinationFile + "' already exists.");
              }
              InputStream is = new BoundedInputStream(paxStream, 0, fileSize);
              FileOutputStream fos = new FileOutputStream(destinationFile);
              FileUtilities.writeInputStreamToOutputStream(is, fos, fileSize, new NullProgressMonitor());
            }
            else {
              throw new IOException("Unknown mode " + modeStr + " for " + name + ".");
            }

            int relativeAmount = 70 + nameSize + fileSize;
            amount += relativeAmount;
            progressMonitor.worked(amount);
          }
        }
       
        if (progressMonitor.isCanceled()) {
          throw new IOException("Operation canceled.");
        }
      } while (!done);
    }
    finally {
//      System.out.println(amount + ":" + fileLength);
      paxStream.close();
    }
    progressMonitor.done();
    progressMonitor.beginTask("Linking WebObjects ...", links.size());
    Collections.sort(links, new LinkNameLengthComparator());
    int linkNum = 0;
    for (Link link : links) {
      link.create(symbolicLinksSupported);
      progressMonitor.worked(linkNum++);
    }
  }

  protected File toFile(File workingDir, String path) {
    String localPath = path.replaceFirst("^\\./", "");
    localPath = localPath.replace("/", File.separator);
    File file = new File(localPath);
    if (!file.isAbsolute()) {
      file = new File(workingDir, localPath);
    }
    return file;
  }

  protected String readString(InputStream is, byte[] b) throws IOException {
    readFully(is, b);
    int length;
    for (length = b.length - 1; length >= 0 && b[length] == 0; length--) {
      // skip
    }
    return new String(b, 0, length + 1);
  }

  protected byte[] readFully(InputStream is, byte[] b) throws IOException {
    return readFully(is, b, 0, b.length);
  }

  protected byte[] readFully(InputStream is, byte[] b, int offset, int length) throws IOException {
    int totalAmountRead = 0;
    while (totalAmountRead < length) {
      int amountRead = is.read(b, offset + totalAmountRead, length - totalAmountRead);
      if (amountRead == -1) {
        throw new IOException("Stream ended before " + length + " bytes (read " + totalAmountRead + ")");
      }
      totalAmountRead += amountRead;
    }
    return b;
  }
 
  protected void skipFully(InputStream inputStream, long skip) throws IOException {
    long toSkip = skip;
    while (toSkip > 0) {
      toSkip -= inputStream.skip(toSkip);
    }
  }

  protected static class Link {
    private File _realFile;
    private File _linkFile;

    public Link(File realFile, File linkFile) {
      _realFile = realFile;
      _linkFile = linkFile;
    }

    public Link(String realName, String linkName) {
      _realFile = new File(realName);
      _linkFile = new File(linkName);
    }
   
    public File getRealFile() {
      return _realFile;
    }

    public File getLinkFile() {
      return _linkFile;
    }

    public void create(boolean symbolicLinksSupported) throws IOException, InterruptedException {
      if (symbolicLinksSupported) {
       
        Process p = Runtime.getRuntime().exec(new String[] { "/bin/ln", "-s", _realFile.getPath(), _linkFile.getCanonicalPath() });
        int retval = p.waitFor();
        if (retval != 0) {
          throw new IOException("Failed to create link from " + _realFile + " to " + _linkFile);
        }
      }
      else {
        try {
          copyFileToFile(_realFile, _linkFile);
        } catch (IOException e) {
          System.err.println(e.getMessage());
        }
      }
    }

    protected void copyFileToFile(File source, File destination) throws IOException {
      if (!source.exists()) {
        throw new IOException("The file '" + source + "' does not exist (tried to link to '" + destination + "').");
      }
      if (destination.exists()) {
        throw new IOException("The file '" + destination + "' already exists.");
      }
      if (source.isDirectory()) {
        if (!destination.mkdirs()) {
          throw new IOException("Failed to create the directory '" + destination + "'.");
        }
        for (File child : source.listFiles()) {
          copyFileToFile(child, new File(destination, child.getName()));
        }
      }
      else {
        FileInputStream fis = new FileInputStream(source);
        FileUtilities.writeInputStreamToFile(fis, destination, (int) source.length(), new NullProgressMonitor());
      }
    }
  }

  protected static class LinkNameLengthComparator implements Comparator<Link>, Serializable {

    public int compare(Link s1, Link s2) {
      int length1 = s1.getRealFile().toString().length();
      int length2 = s2.getRealFile().toString().length();
      int comparison;
      if (length1 > length2) {
        comparison = 1;
      }
      else if (length1 < length2) {
        comparison = -1;
      }
      else {
        comparison = 0;
      }
      return comparison;
    }
  }
}
TOP

Related Classes of er.woinstaller.archiver.CPIO$Link

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.