/** {@inheritDoc} */ public bool equals(Object obj) { if (this == obj) { return(true); } if (obj == null || this.GetType() != obj.GetType()) { return(false); } ArArchiveEntry other = (ArArchiveEntry)obj; if (name == null) { if (other.name != null) { return(false); } } else if (!name.equals(other.name)) { return(false); } return(true); }
/** {@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; }
/* * (non-Javadoc) * * @see java.io.InputStream#close() */ public override void close() { if (!closed) { closed = true; input.close(); } currentEntry = null; }
/** * Calls finish if necessary, and then closes the OutputStream */ public override void close() //throws IOException { if (!finished) { finish(); } outJ.close(); prevEntry = null; }
/** * 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); }
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); }