Beispiel #1
0
        /** {@inheritDoc} */
        public override void putArchiveEntry(ArchiveEntry pEntry)   //throws IOException
        {
            if (finished)
            {
                throw new java.io.IOException("Stream has already been finished");
            }

            ArArchiveEntry pArEntry = (ArArchiveEntry)pEntry;

            if (prevEntry == null)
            {
                archiveOffset += writeArchiveHeader();
            }
            else
            {
                if (prevEntry.getLength() != entryOffset)
                {
                    throw new java.io.IOException("length does not match entry (" + prevEntry.getLength() + " != " + entryOffset);
                }

                if (haveUnclosedEntry)
                {
                    closeArchiveEntry();
                }
            }

            prevEntry = pArEntry;

            archiveOffset += writeEntryHeader(pArEntry);

            entryOffset       = 0;
            haveUnclosedEntry = true;
        }
        /**
         * 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);
        }
Beispiel #3
0
        private long writeEntryHeader(ArArchiveEntry pEntry)   //throws IOException
        {
            long offset = 0;

            String n = pEntry.getName();

            if (n.length() > 16)
            {
                throw new java.io.IOException("filename too long, > 16 chars: " + n);
            }
            offset += write(n);

            offset = fill(offset, 16, ' ');
            String m = "" + (pEntry.getLastModified());

            if (m.length() > 12)
            {
                throw new java.io.IOException("modified too long");
            }
            offset += write(m);

            offset = fill(offset, 28, ' ');
            String u = "" + pEntry.getUserId();

            if (u.length() > 6)
            {
                throw new java.io.IOException("userid too long");
            }
            offset += write(u);

            offset = fill(offset, 34, ' ');
            String g = "" + pEntry.getGroupId();

            if (g.length() > 6)
            {
                throw new java.io.IOException("groupid too long");
            }
            offset += write(g);

            offset = fill(offset, 40, ' ');
            String fm = java.lang.Integer.toString(pEntry.getMode(), 8).ToString();

            if (fm.length() > 8)
            {
                throw new java.io.IOException("filemode too long");
            }
            offset += write(fm);

            offset = fill(offset, 48, ' ');
            String s = "" + pEntry.getLength();

            if (s.length() > 10)
            {
                throw new java.io.IOException("size too long");
            }
            offset += write(s);

            offset = fill(offset, 58, ' ');

            offset += write(ArArchiveEntry.TRAILER);

            return(offset);
        }