Example #1
0
  /**
   * This method, like getNameBytes(), is intended to place a name into a TarHeader's buffer.
   * However, this method is sophisticated enough to recognize long names (name.length() > NAMELEN).
   * In these cases, the method will break the name into a prefix and suffix and place the name in
   * the header in 'ustar' format. It is up to the TarEntry to manage the "entry header format".
   * This method assumes the name is valid for the type of archive being generated.
   *
   * @param outbuf The buffer containing the entry header to modify.
   * @param newName The new name to place into the header buffer.
   * @return The current offset in the tar header (always TarHeader.NAMELEN).
   * @throws InvalidHeaderException If the name will not fit in the header.
   */
  public static int getFileNameBytes(String newName, byte[] outbuf) throws InvalidHeaderException {
    if (newName.length() > 100) {
      // Locate a pathname "break" prior to the maximum name length...
      int index = newName.indexOf("/", newName.length() - 100);
      if (index == -1)
        throw new InvalidHeaderException("file name is greater than 100 characters, " + newName);

      // Get the "suffix subpath" of the name.
      String name = newName.substring(index + 1);

      // Get the "prefix subpath", or "prefix", of the name.
      String prefix = newName.substring(0, index);
      if (prefix.length() > TarHeader.PREFIXLEN)
        throw new InvalidHeaderException("file prefix is greater than 155 characters");

      TarHeader.getNameBytes(
          new StringBuffer(name), outbuf, TarHeader.NAMEOFFSET, TarHeader.NAMELEN);

      TarHeader.getNameBytes(
          new StringBuffer(prefix), outbuf, TarHeader.PREFIXOFFSET, TarHeader.PREFIXLEN);
    } else {
      TarHeader.getNameBytes(
          new StringBuffer(newName), outbuf, TarHeader.NAMEOFFSET, TarHeader.NAMELEN);
    }

    // The offset, regardless of the format, is now the end of the
    // original name field.
    //
    return TarHeader.NAMELEN;
  }
Example #2
0
 /**
  * Parse the checksum octal integer from a header buffer.
  *
  * @param header The header buffer from which to parse.
  * @param offset The offset into the buffer from which to parse.
  * @param length The number of header bytes to parse.
  * @return The integer value of the entry's checksum.
  */
 public static int getCheckSumOctalBytes(long value, byte[] buf, int offset, int length) {
   TarHeader.getOctalBytes(value, buf, offset, length);
   buf[offset + length - 1] = (byte) ' ';
   buf[offset + length - 2] = 0;
   return offset + length;
 }
Example #3
0
 /**
  * Parse an octal long integer from a header buffer.
  *
  * @param header The header buffer from which to parse.
  * @param offset The offset into the buffer from which to parse.
  * @param length The number of header bytes to parse.
  * @return The long value of the octal bytes.
  */
 public static int getLongOctalBytes(long value, byte[] buf, int offset, int length) {
   byte[] temp = new byte[length + 1];
   TarHeader.getOctalBytes(value, temp, 0, length + 1);
   System.arraycopy(temp, 0, buf, offset, length);
   return offset + length;
 }
Example #4
0
  /** TarHeaders can be cloned. */
  public Object clone() {
    TarHeader hdr = null;

    try {
      hdr = (TarHeader) super.clone();

      hdr.name = (this.name == null) ? null : new StringBuffer(this.name.toString());
      hdr.mode = this.mode;
      hdr.userId = this.userId;
      hdr.groupId = this.groupId;
      hdr.size = this.size;
      hdr.modTime = this.modTime;
      hdr.checkSum = this.checkSum;
      hdr.linkFlag = this.linkFlag;
      hdr.linkName = (this.linkName == null) ? null : new StringBuffer(this.linkName.toString());
      hdr.magic = (this.magic == null) ? null : new StringBuffer(this.magic.toString());
      hdr.userName = (this.userName == null) ? null : new StringBuffer(this.userName.toString());
      hdr.groupName = (this.groupName == null) ? null : new StringBuffer(this.groupName.toString());
      hdr.devMajor = this.devMajor;
      hdr.devMinor = this.devMinor;
    } catch (CloneNotSupportedException ex) {
      ex.printStackTrace(System.err);
    }

    return hdr;
  }
Example #5
0
  /**
   * Fill in a TarHeader given only the entry's name.
   *
   * @param hdr The TarHeader to fill in.
   * @param name The tar entry name.
   */
  public void nameTarHeader(TarHeader hdr, String name) {
    boolean isDir = name.endsWith("/");

    this.gnuFormat = false;
    this.ustarFormat = true;
    this.unixFormat = false;

    hdr.checkSum = 0;
    hdr.devMajor = 0;
    hdr.devMinor = 0;

    hdr.name = new StringBuffer(name);
    hdr.mode = isDir ? 040755 : 0100644;
    hdr.userId = 0;
    hdr.groupId = 0;
    hdr.size = 0;
    hdr.checkSum = 0;

    hdr.modTime = (new java.util.Date()).getTime() / 1000;

    hdr.linkFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;

    hdr.linkName = new StringBuffer("");
    hdr.userName = new StringBuffer("");
    hdr.groupName = new StringBuffer("");

    hdr.devMajor = 0;
    hdr.devMinor = 0;
  }
Example #6
0
  /**
   * Parse an entry's TarHeader information from a header buffer.
   *
   * <p>Old unix-style code contributed by David Mehringer <*****@*****.**>.
   *
   * @param hdr The TarHeader to fill in from the buffer information.
   * @param header The tar entry header buffer to get information from.
   */
  public void parseTarHeader(TarHeader hdr, byte[] headerBuf) throws InvalidHeaderException {
    int offset = 0;

    //
    // NOTE Recognize archive header format.
    //
    if (headerBuf[257] == 0
        && headerBuf[258] == 0
        && headerBuf[259] == 0
        && headerBuf[260] == 0
        && headerBuf[261] == 0) {
      this.unixFormat = true;
      this.ustarFormat = false;
      this.gnuFormat = false;
    } else if (headerBuf[257] == 'u'
        && headerBuf[258] == 's'
        && headerBuf[259] == 't'
        && headerBuf[260] == 'a'
        && headerBuf[261] == 'r'
        && headerBuf[262] == 0) {
      this.ustarFormat = true;
      this.gnuFormat = false;
      this.unixFormat = false;
    } else if (headerBuf[257] == 'u'
        && headerBuf[258] == 's'
        && headerBuf[259] == 't'
        && headerBuf[260] == 'a'
        && headerBuf[261] == 'r'
        && headerBuf[262] != 0
        && headerBuf[263] != 0) {
      // REVIEW
      this.gnuFormat = true;
      this.unixFormat = false;
      this.ustarFormat = false;
    } else {
      StringBuffer buf = new StringBuffer(128);

      buf.append("header magic is not 'ustar' or unix-style zeros, it is '");
      buf.append(headerBuf[257]);
      buf.append(headerBuf[258]);
      buf.append(headerBuf[259]);
      buf.append(headerBuf[260]);
      buf.append(headerBuf[261]);
      buf.append(headerBuf[262]);
      buf.append(headerBuf[263]);
      buf.append("', or (dec) ");
      buf.append((int) headerBuf[257]);
      buf.append(", ");
      buf.append((int) headerBuf[258]);
      buf.append(", ");
      buf.append((int) headerBuf[259]);
      buf.append(", ");
      buf.append((int) headerBuf[260]);
      buf.append(", ");
      buf.append((int) headerBuf[261]);
      buf.append(", ");
      buf.append((int) headerBuf[262]);
      buf.append(", ");
      buf.append((int) headerBuf[263]);

      throw new InvalidHeaderException(buf.toString());
    }

    hdr.name = TarHeader.parseFileName(headerBuf);

    offset = TarHeader.NAMELEN;

    hdr.mode = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.MODELEN);

    offset += TarHeader.MODELEN;

    hdr.userId = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.UIDLEN);

    offset += TarHeader.UIDLEN;

    hdr.groupId = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.GIDLEN);

    offset += TarHeader.GIDLEN;

    hdr.size = TarHeader.parseOctal(headerBuf, offset, TarHeader.SIZELEN);

    offset += TarHeader.SIZELEN;

    hdr.modTime = TarHeader.parseOctal(headerBuf, offset, TarHeader.MODTIMELEN);

    offset += TarHeader.MODTIMELEN;

    hdr.checkSum = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.CHKSUMLEN);

    offset += TarHeader.CHKSUMLEN;

    hdr.linkFlag = headerBuf[offset++];

    hdr.linkName = TarHeader.parseName(headerBuf, offset, TarHeader.NAMELEN);

    offset += TarHeader.NAMELEN;

    if (this.ustarFormat) {
      hdr.magic = TarHeader.parseName(headerBuf, offset, TarHeader.MAGICLEN);

      offset += TarHeader.MAGICLEN;

      hdr.userName = TarHeader.parseName(headerBuf, offset, TarHeader.UNAMELEN);

      offset += TarHeader.UNAMELEN;

      hdr.groupName = TarHeader.parseName(headerBuf, offset, TarHeader.GNAMELEN);

      offset += TarHeader.GNAMELEN;

      hdr.devMajor = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.DEVLEN);

      offset += TarHeader.DEVLEN;

      hdr.devMinor = (int) TarHeader.parseOctal(headerBuf, offset, TarHeader.DEVLEN);
    } else {
      hdr.devMajor = 0;
      hdr.devMinor = 0;
      hdr.magic = new StringBuffer("");
      hdr.userName = new StringBuffer("");
      hdr.groupName = new StringBuffer("");
    }
  }
Example #7
0
  /**
   * Write an entry's header information to a header buffer. This method can throw an
   * InvalidHeaderException
   *
   * @param outbuf The tar entry header buffer to fill in.
   * @throws InvalidHeaderException If the name will not fit in the header.
   */
  public void writeEntryHeader(byte[] outbuf) throws InvalidHeaderException {
    int offset = 0;

    if (this.isUnixTarFormat()) {
      if (this.header.name.length() > 100) {
        throw new InvalidHeaderException(
            "file path is greater than 100 characters, " + this.header.name);
      }
    }

    offset = TarHeader.getFileNameBytes(this.header.name.toString(), outbuf);

    offset = TarHeader.getOctalBytes(this.header.mode, outbuf, offset, TarHeader.MODELEN);

    offset = TarHeader.getOctalBytes(this.header.userId, outbuf, offset, TarHeader.UIDLEN);

    offset = TarHeader.getOctalBytes(this.header.groupId, outbuf, offset, TarHeader.GIDLEN);

    long size = this.header.size;

    offset = TarHeader.getLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);

    offset = TarHeader.getLongOctalBytes(this.header.modTime, outbuf, offset, TarHeader.MODTIMELEN);

    int csOffset = offset;
    for (int c = 0; c < TarHeader.CHKSUMLEN; ++c) {
      outbuf[offset++] = (byte) ' ';
    }

    outbuf[offset++] = this.header.linkFlag;

    offset = TarHeader.getNameBytes(this.header.linkName, outbuf, offset, TarHeader.NAMELEN);

    if (this.unixFormat) {
      for (int i = 0; i < TarHeader.MAGICLEN; ++i) {
        outbuf[offset++] = 0;
      }
    } else {
      offset = TarHeader.getNameBytes(this.header.magic, outbuf, offset, TarHeader.MAGICLEN);
    }

    offset = TarHeader.getNameBytes(this.header.userName, outbuf, offset, TarHeader.UNAMELEN);

    offset = TarHeader.getNameBytes(this.header.groupName, outbuf, offset, TarHeader.GNAMELEN);

    offset = TarHeader.getOctalBytes(this.header.devMajor, outbuf, offset, TarHeader.DEVLEN);

    offset = TarHeader.getOctalBytes(this.header.devMinor, outbuf, offset, TarHeader.DEVLEN);

    for (; offset < outbuf.length; ) {
      outbuf[offset++] = 0;
    }

    long checkSum = this.computeCheckSum(outbuf);

    TarHeader.getCheckSumOctalBytes(checkSum, outbuf, csOffset, TarHeader.CHKSUMLEN);
  }
Example #8
0
  /**
   * Fill in a TarHeader with information from a File.
   *
   * @param hdr The TarHeader to fill in.
   * @param file The file from which to get the header information.
   */
  public void getFileTarHeader(TarHeader hdr, File file) throws InvalidHeaderException {
    this.file = file;

    String name = file.getPath();
    String osname = System.getProperty("os.name");
    if (osname != null) {
      // Strip off drive letters!
      // REVIEW Would a better check be "(File.separator == '\')"?

      // String Win32Prefix = "Windows";
      // String prefix = osname.substring( 0, Win32Prefix.length() );
      // if ( prefix.equalsIgnoreCase( Win32Prefix ) )

      // if ( File.separatorChar == '\\' )

      // Windows OS check was contributed by
      // Patrick Beard <*****@*****.**>
      String Win32Prefix = "windows";
      if (osname.toLowerCase().startsWith(Win32Prefix)) {
        if (name.length() > 2) {
          char ch1 = name.charAt(0);
          char ch2 = name.charAt(1);
          if (ch2 == ':' && ((ch1 >= 'a' && ch1 <= 'z') || (ch1 >= 'A' && ch1 <= 'Z'))) {
            name = name.substring(2);
          }
        }
      }
    }

    name = name.replace(File.separatorChar, '/');

    // No absolute pathnames
    // Windows (and Posix?) paths can start with "\\NetworkDrive\",
    // so we loop on starting /'s.

    for (; name.startsWith("/"); ) {
      name = name.substring(1);
    }

    hdr.linkName = new StringBuffer("");

    hdr.name = new StringBuffer(name);

    if (file.isDirectory()) {
      hdr.size = 0;
      hdr.mode = 040755;
      hdr.linkFlag = TarHeader.LF_DIR;
      if (hdr.name.charAt(hdr.name.length() - 1) != '/') {
        hdr.name.append("/");
      }
    } else {
      hdr.size = file.length();
      hdr.mode = 0100644;
      hdr.linkFlag = TarHeader.LF_NORMAL;
    }

    // UNDONE When File lets us get the userName, use it!

    hdr.modTime = file.lastModified() / 1000;
    hdr.checkSum = 0;
    hdr.devMajor = 0;
    hdr.devMinor = 0;
  }