Esempio n. 1
0
 /**
  * Whether this class is able to read the given entry.
  *
  * <p>May return false if the current entry is a sparse file.
  */
 public boolean canReadEntryData(ArchiveEntry ae) {
   if (ae instanceof TarArchiveEntry) {
     TarArchiveEntry te = (TarArchiveEntry) ae;
     return !te.isGNUSparse();
   }
   return false;
 }
Esempio n. 2
0
 /**
  * Adds the sparse chunks from the current entry to the sparse chunks, including any additional
  * sparse entries following the current entry.
  *
  * @throws IOException on error
  * @todo Sparse files get not yet really processed.
  */
 private void readGNUSparse() throws IOException {
   /* we do not really process sparse files yet
   sparses = new ArrayList();
   sparses.addAll(currEntry.getSparses());
   */
   if (currEntry.isExtended()) {
     TarArchiveSparseEntry entry;
     do {
       byte[] headerBuf = getRecord();
       if (hasHitEOF) {
         currEntry = null;
         break;
       }
       entry = new TarArchiveSparseEntry(headerBuf);
       /* we do not really process sparse files yet
       sparses.addAll(entry.getSparses());
       */
     } while (entry.isExtended());
   }
 }
Esempio n. 3
0
  /**
   * Get the next entry in this tar archive. This will skip over any remaining data in the current
   * entry, if there is one, and place the input stream at the header of the next entry, and read
   * the header and instantiate a new TarEntry from the header bytes and return that entry. If there
   * are no more entries in the archive, null will be returned to indicate that the end of the
   * archive has been reached.
   *
   * @return The next TarEntry in the archive, or null.
   * @throws IOException on error
   */
  public TarArchiveEntry getNextTarEntry() throws IOException {
    if (hasHitEOF) {
      return null;
    }

    if (currEntry != null) {
      long numToSkip = entrySize - entryOffset;

      while (numToSkip > 0) {
        long skipped = skip(numToSkip);
        if (skipped <= 0) {
          throw new RuntimeException("failed to skip current tar entry");
        }
        numToSkip -= skipped;
      }

      readBuf = null;
    }

    byte[] headerBuf = getRecord();

    if (hasHitEOF) {
      currEntry = null;
      return null;
    }

    currEntry = new TarArchiveEntry(headerBuf);
    entryOffset = 0;
    entrySize = currEntry.getSize();

    if (currEntry.isGNULongNameEntry()) {
      // read in the name
      StringBuffer longName = new StringBuffer();
      byte[] buf = new byte[SMALL_BUFFER_SIZE];
      int length = 0;
      while ((length = read(buf)) >= 0) {
        longName.append(new String(buf, 0, length));
      }
      getNextEntry();
      if (currEntry == null) {
        // Bugzilla: 40334
        // Malformed tar file - long entry name not followed by entry
        return null;
      }
      // remove trailing null terminator
      if (longName.length() > 0 && longName.charAt(longName.length() - 1) == 0) {
        longName.deleteCharAt(longName.length() - 1);
      }
      currEntry.setName(longName.toString());
    }

    if (currEntry.isPaxHeader()) { // Process Pax headers
      paxHeaders();
    }

    if (currEntry.isGNUSparse()) { // Process sparse files
      readGNUSparse();
    }

    return currEntry;
  }
Esempio n. 4
0
 private void paxHeaders() throws IOException {
   BufferedInputStream br = new BufferedInputStream(this);
   Map headers = new HashMap();
   // Format is "length keyword=value\n";
   while (true) { // get length
     int ch;
     int len = 0;
     int read = 0;
     while ((ch = br.read()) != -1) {
       read++;
       if (ch == ' ') { // End of length string
         // Get keyword
         StringBuffer sb = new StringBuffer();
         while ((ch = br.read()) != -1) {
           read++;
           if (ch == '=') { // end of keyword
             String keyword = sb.toString();
             // Get rest of entry
             byte[] cbuf = new byte[len - read];
             int got = br.read(cbuf);
             if (got != len - read) {
               throw new IOException(
                   "Failed to read Paxheader. Expected " + (len - read) + " chars, read " + got);
             }
             String value = new String(cbuf, 0, len - read - 1); // Drop trailing NL
             headers.put(keyword, value);
             break;
           }
           sb.append((char) ch);
         }
         break; // Processed single header
       }
       len *= 10;
       len += ch - '0';
     }
     if (ch == -1) { // EOF
       break;
     }
   }
   getNextEntry(); // Get the actual file entry
   /*
    * The following headers are defined for Pax.
    * atime, ctime, mtime, charset: cannot use these without changing TarArchiveEntry fields
    * comment
    * gid, gname
    * linkpath
    * size
    * uid,uname
    */
   Iterator hdrs = headers.entrySet().iterator();
   while (hdrs.hasNext()) {
     Entry ent = (Entry) hdrs.next();
     String key = (String) ent.getKey();
     String val = (String) ent.getValue();
     if ("path".equals(key)) {
       currEntry.setName(val);
     } else if ("linkpath".equals(key)) {
       currEntry.setLinkName(val);
     } else if ("gid".equals(key)) {
       currEntry.setGroupId(Integer.parseInt(val));
     } else if ("gname".equals(key)) {
       currEntry.setGroupName(val);
     } else if ("uid".equals(key)) {
       currEntry.setUserId(Integer.parseInt(val));
     } else if ("uname".equals(key)) {
       currEntry.setUserName(val);
     } else if ("size".equals(key)) {
       currEntry.setSize(Long.parseLong(val));
     }
   }
 }
  private void paxHeaders() throws IOException {
    Reader br =
        new InputStreamReader(this, "UTF-8") {
          @Override
          public void close() {
            // make sure GC doesn't close "this" before we are done
          }
        };
    Map<String, String> headers = new HashMap<String, String>();
    // Format is "length keyword=value\n";
    try {
      while (true) { // get length
        int ch;
        int len = 0;
        int read = 0;
        while ((ch = br.read()) != -1) {
          read++;
          if (ch == ' ') { // End of length string
            // Get keyword
            StringBuffer sb = new StringBuffer();
            while ((ch = br.read()) != -1) {
              read++;
              if (ch == '=') { // end of keyword
                String keyword = sb.toString();
                // Get rest of entry
                char[] cbuf = new char[len - read];
                int got = br.read(cbuf);
                if (got != len - read) {
                  throw new IOException(
                      "Failed to read "
                          + "Paxheader. Expected "
                          + (len - read)
                          + " chars, read "
                          + got);
                }
                // Drop trailing NL
                String value = new String(cbuf, 0, len - read - 1);
                headers.put(keyword, value);
                break;
              }
              sb.append((char) ch);
            }
            break; // Processed single header
          }
          len *= 10;
          len += ch - '0';
        }
        if (ch == -1) { // EOF
          break;
        }
      }
    } finally {
      // NO-OP but makes FindBugs happy
      br.close();
    }

    getNextEntry(); // Get the actual file entry
    /*
     * The following headers are defined for Pax.
     * atime, ctime, mtime, charset: cannot use these without changing TarArchiveEntry fields
     * comment
     * gid, gname
     * linkpath
     * size
     * uid,uname
     */
    for (Entry<String, String> ent : headers.entrySet()) {
      String key = ent.getKey();
      String val = ent.getValue();
      if ("path".equals(key)) {
        currEntry.setName(val);
      } else if ("linkpath".equals(key)) {
        currEntry.setLinkName(val);
      } else if ("gid".equals(key)) {
        currEntry.setGroupId(Integer.parseInt(val));
      } else if ("gname".equals(key)) {
        currEntry.setGroupName(val);
      } else if ("uid".equals(key)) {
        currEntry.setUserId(Integer.parseInt(val));
      } else if ("uname".equals(key)) {
        currEntry.setUserName(val);
      } else if ("size".equals(key)) {
        currEntry.setSize(Long.parseLong(val));
      }
    }
  }