public ArArchiveEntry getNextArEntry()

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


    public ArArchiveEntry getNextArEntry() throws IOException {
        if (currentEntry != null) {
            final long entryEnd = entryOffset + currentEntry.getLength();
            final long skipped = IOUtils.skip(input, entryEnd - offset);
            trackReadBytes(skipped);
            currentEntry = null;
        }

        if (offset == 0) {
            final byte[] expected = ArchiveUtils.toAsciiBytes(ArArchiveEntry.HEADER);
            final byte[] realized = IOUtils.readRange(input, 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 (input.read() < 0) {
                // hit eof
                return null;
            }
            trackReadBytes(1);
        }

        {
            final int read = IOUtils.readFully(input, 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(input, 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 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(metaData, NAME_OFFSET, NAME_LEN).trim();
        if (isGNUStringTable(temp)) { // GNU extended filenames entry
            currentEntry = readGNUStringTable(metaData, LENGTH_OFFSET, LENGTH_LEN);
            return getNextArEntry();
        }

        long len = asLong(metaData, LENGTH_OFFSET, LENGTH_LEN);
        if (temp.endsWith("/")) { // GNU terminator
            temp = temp.substring(0, temp.length() - 1);
        } else if (isGNULongName(temp)) {
            final int off = Integer.parseInt(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");
        }

        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;
    }