public ArArchiveEntry getNextArEntry()

in src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java [251:339]


    public ArArchiveEntry getNextArEntry() throws IOException {
        if (currentEntry != null) {
            final long entryEnd = entryOffset + currentEntry.getLength();
            final long skipped = org.apache.commons.io.IOUtils.skip(in, entryEnd - offset);
            trackReadBytes(skipped);
            currentEntry = null;
        }
        if (offset == 0) {
            final byte[] expected = ArchiveUtils.toAsciiBytes(ArArchiveEntry.HEADER);
            final byte[] realized = IOUtils.readRange(in, expected.length);
            final int read = realized.length;
            trackReadBytes(read);
            if (read != expected.length) {
                throw new IOException("Failed to read header. Occurred at byte: " + getBytesRead());
            }
            if (!Arrays.equals(expected, realized)) {
                throw new IOException("Invalid header " + ArchiveUtils.toAsciiString(realized));
            }
        }
        if (offset % 2 != 0) {
            if (in.read() < 0) {
                // hit eof
                return null;
            }
            trackReadBytes(1);
        }
        {
            final int read = IOUtils.readFully(in, metaData);
            trackReadBytes(read);
            if (read == 0) {
                return null;
            }
            if (read < metaData.length) {
                throw new IOException("Truncated ar archive");
            }
        }
        {
            final byte[] expected = ArchiveUtils.toAsciiBytes(ArArchiveEntry.TRAILER);
            final byte[] realized = IOUtils.readRange(in, expected.length);
            final int read = realized.length;
            trackReadBytes(read);
            if (read != expected.length) {
                throw new IOException("Failed to read entry trailer. Occurred at byte: " + getBytesRead());
            }
            if (!Arrays.equals(expected, realized)) {
                throw new IOException("Invalid entry trailer. not read the content? Occurred at byte: " + getBytesRead());
            }
        }

        entryOffset = offset;
        // GNU ar uses a '/' to mark the end of the file name; this allows for the use of spaces without the use of an extended file name.
        // entry name is stored as ASCII string
        String temp = ArchiveUtils.toAsciiString(metaData, NAME_OFFSET, NAME_LEN).trim();
        if (isGNUStringTable(temp)) { // GNU extended file names entry
            currentEntry = readGNUStringTable(metaData, LENGTH_OFFSET, LENGTH_LEN);
            return getNextArEntry();
        }
        long len;
        try {
            len = asLong(metaData, LENGTH_OFFSET, LENGTH_LEN);
        } catch (final NumberFormatException ex) {
            throw new IOException("Broken archive, unable to parse ar_size field as a number", ex);
        }
        if (temp.endsWith("/")) { // GNU terminator
            temp = temp.substring(0, temp.length() - 1);
        } else if (isGNULongName(temp)) {
            final int off = ParsingUtils.parseIntValue(temp.substring(1)); // get the offset
            temp = getExtendedName(off); // convert to the long name
        } else if (isBSDLongName(temp)) {
            temp = getBSDLongName(temp);
            // entry length contained the length of the file name in
            // addition to the real length of the entry.
            // assume file name was ASCII, there is no "standard" otherwise
            final int nameLen = temp.length();
            len -= nameLen;
            entryOffset += nameLen;
        }
        if (len < 0) {
            throw new IOException("broken archive, entry with negative size");
        }
        try {
            currentEntry = new ArArchiveEntry(temp, len, asInt(metaData, USER_ID_OFFSET, USER_ID_LEN, true),
                    asInt(metaData, GROUP_ID_OFFSET, GROUP_ID_LEN, true), asInt(metaData, FILE_MODE_OFFSET, FILE_MODE_LEN, 8),
                    asLong(metaData, LAST_MODIFIED_OFFSET, LAST_MODIFIED_LEN));
            return currentEntry;
        } catch (final NumberFormatException ex) {
            throw new IOException("Broken archive, unable to parse entry metadata fields as numbers", ex);
        }
    }