private void init() //throws IOException { if (null == inJ) { throw new java.io.IOException("No InputStream"); } if (inJ.available() == 0) { throw new java.io.IOException("Empty InputStream"); } checkMagicChar('B', "first"); checkMagicChar('Z', "second"); checkMagicChar('h', "third"); int blockSize = this.inJ.read(); if ((blockSize < '1') || (blockSize > '9')) { throw new java.io.IOException("Stream is not BZip2 formatted: illegal " + "blocksize " + (char)blockSize); } this.blockSize100k = blockSize - '0'; initBlock(); setupBlock(); }
/** * Returns the next AR entry in this stream. * * @return the next AR entry. * @throws IOException * if the entry could not be read */ public ArArchiveEntry getNextArEntry() // throws IOException { if (currentEntry != null) { long entryEnd = entryOffset + currentEntry.getLength(); while (offset < entryEnd) { int x = read(); if (x == -1) { // hit EOF before previous entry was complete // TODO: throw an exception instead? return(null); } } currentEntry = null; } if (offset == 0) { byte[] expected = ArchiveUtils.toAsciiBytes(ArArchiveEntry.HEADER); byte[] realized = new byte[expected.Length]; int readJ = read(realized); if (readJ != expected.Length) { throw new java.io.IOException("failed to read header. Occured at byte: " + getBytesRead()); } for (int i = 0; i < expected.Length; i++) { if (expected[i] != realized[i]) { throw new java.io.IOException("invalid header " + ArchiveUtils.toAsciiString(realized)); } } } if (offset % 2 != 0) { if (read() < 0) { // hit eof return(null); } } if (input.available() == 0) { return(null); } byte[] name = new byte[16]; byte[] lastmodified = new byte[12]; byte[] userid = new byte[6]; byte[] groupid = new byte[6]; byte[] filemode = new byte[8]; byte[] length = new byte[10]; read(name); read(lastmodified); read(userid); read(groupid); read(filemode); read(length); { byte[] expected = ArchiveUtils.toAsciiBytes(ArArchiveEntry.TRAILER); byte[] realized = new byte[expected.Length]; int readJ = read(realized); if (readJ != expected.Length) { throw new java.io.IOException("failed to read entry trailer. Occured at byte: " + getBytesRead()); } for (int i = 0; i < expected.Length; i++) { if (expected[i] != realized[i]) { throw new java.io.IOException("invalid entry trailer. not read the content? Occured at byte: " + getBytesRead()); } } } entryOffset = offset; // GNU ar stores multiple extended filenames in the data section of a file with the name "//", this record is referred to by future headers. A header references an extended filename by storing a "/" followed by a decimal offset to the start of the filename in the extended filename data section. The format of this "//" file itself is simply a list of the long filenames, each separated by one or more LF characters. Note that the decimal offsets are number of characters, not line or string number within the "//" file. // // GNU ar uses a '/' to mark the end of the filename; this allows for the use of spaces without the use of an extended filename. // entry name is stored as ASCII string String temp = ArchiveUtils.toAsciiString(name).trim(); if (temp.equals("//")) // GNU extended filenames entry { int bufflen = asInt(length); // Assume length will fit in an int namebuffer = new byte[bufflen]; int readJ = read(namebuffer, 0, bufflen); if (readJ != bufflen) { throw new java.io.IOException("Failed to read complete // record: expected=" + bufflen + " read=" + readJ); } currentEntry = new ArArchiveEntry(temp, bufflen); return(getNextArEntry()); } else if (temp.EndsWith("/")) // GNU terminator { temp = temp.substring(0, temp.length() - 1); } else if (temp.matches("^/\\d+")) // GNU long filename ref. { int offsetJ = java.lang.Integer.parseInt(temp.substring(1)); // get the offset temp = getExtendedName(offsetJ); // convert to the long name } currentEntry = new ArArchiveEntry(temp, asLong(length), asInt(userid), asInt(groupid), asInt(filemode, 8), asLong(lastmodified)); return(currentEntry); }