~ubuntu-branches/ubuntu/saucy/libcommons-compress-java/saucy-proposed

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2011-08-07 01:56:15 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110807015615-cvbmhuv10g12fpz1
Tags: 1.2-1
* New upstream release
* Clean up Depends and Suggests fields.
* Switch to source format 3.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
    private final InputStream input;
37
37
    private long offset = 0;
38
38
    private boolean closed;
39
 
    
 
39
 
40
40
    /*
41
41
     * If getNextEnxtry has been called, the entry metadata is stored in
42
42
     * currentEntry.
43
43
     */
44
44
    private ArArchiveEntry currentEntry = null;
45
 
    
 
45
 
 
46
    // Storage area for extra long names (GNU ar)
 
47
    private byte[] namebuffer = null;
 
48
 
46
49
    /*
47
50
     * The offset where the current entry started. -1 if no entry has been
48
51
     * called
86
89
            final byte[] realized = new byte[expected.length];
87
90
            final int read = read(realized);
88
91
            if (read != expected.length) {
89
 
                throw new IOException("failed to read header. Occured at byte: " + getCount());
 
92
                throw new IOException("failed to read header. Occured at byte: " + getBytesRead());
90
93
            }
91
94
            for (int i = 0; i < expected.length; i++) {
92
95
                if (expected[i] != realized[i]) {
95
98
            }
96
99
        }
97
100
 
98
 
        if (offset % 2 != 0) {
99
 
            if (read() < 0) {
100
 
                // hit eof
101
 
                return null;
102
 
            }
 
101
        if (offset % 2 != 0 && read() < 0) {
 
102
            // hit eof
 
103
            return null;
103
104
        }
104
105
 
105
106
        if (input.available() == 0) {
125
126
            final byte[] realized = new byte[expected.length];
126
127
            final int read = read(realized);
127
128
            if (read != expected.length) {
128
 
                throw new IOException("failed to read entry header. Occured at byte: " + getCount());
 
129
                throw new IOException("failed to read entry trailer. Occured at byte: " + getBytesRead());
129
130
            }
130
131
            for (int i = 0; i < expected.length; i++) {
131
132
                if (expected[i] != realized[i]) {
132
 
                    throw new IOException("invalid entry header. not read the content? Occured at byte: " + getCount());
 
133
                    throw new IOException("invalid entry trailer. not read the content? Occured at byte: " + getBytesRead());
133
134
                }
134
135
            }
135
136
        }
136
137
 
137
138
        entryOffset = offset;
138
139
 
139
 
        // SVR4/GNU adds a trailing "/" to names
 
140
//        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.
 
141
//
 
142
//        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.
 
143
 
140
144
        // entry name is stored as ASCII string
141
145
        String temp = ArchiveUtils.toAsciiString(name).trim();
142
 
        if (temp.endsWith("/")) {
 
146
 
 
147
        if (temp.equals("//")){ // GNU extended filenames entry
 
148
            int bufflen = asInt(length); // Assume length will fit in an int
 
149
            namebuffer = new byte[bufflen];
 
150
            int read = read(namebuffer, 0, bufflen);
 
151
            if (read != bufflen){
 
152
                throw new IOException("Failed to read complete // record: expected="+bufflen+" read="+read);
 
153
            }
 
154
            currentEntry = new ArArchiveEntry(temp, bufflen);
 
155
            return getNextArEntry();
 
156
        } else if (temp.endsWith("/")) { // GNU terminator
143
157
            temp = temp.substring(0, temp.length() - 1);
 
158
        } else if (temp.matches("^/\\d+")) {// GNU long filename ref.
 
159
            int offset = Integer.parseInt(temp.substring(1));// get the offset
 
160
            temp = getExtendedName(offset); // convert to the long name
144
161
        }
145
 
        currentEntry = new ArArchiveEntry(temp, Long.parseLong(new String(length).trim()));
 
162
        currentEntry = new ArArchiveEntry(temp, asLong(length), asInt(userid, true),
 
163
                                          asInt(groupid, true), asInt(filemode, 8),
 
164
                                          asLong(lastmodified));
146
165
        return currentEntry;
147
166
    }
148
167
 
 
168
    /**
 
169
     * Get an extended name from the GNU extended name buffer.
 
170
     * 
 
171
     * @param offset pointer to entry within the buffer
 
172
     * @return the extended file name; without trailing "/" if present.
 
173
     * @throws IOException if name not found or buffer not set up
 
174
     */
 
175
    private String getExtendedName(int offset) throws IOException{
 
176
        if (namebuffer == null) {
 
177
            throw new IOException("Cannot process GNU long filename as no // record was found");
 
178
        }
 
179
        for(int i=offset; i < namebuffer.length; i++){
 
180
            if (namebuffer[i]=='\012'){
 
181
                if (namebuffer[i-1]=='/') {
 
182
                    i--; // drop trailing /
 
183
                }
 
184
                return ArchiveUtils.toAsciiString(namebuffer, offset, i-offset);
 
185
            }
 
186
        }
 
187
        throw new IOException("Failed to read entry: "+offset);
 
188
    }
 
189
    private long asLong(byte[] input) {
 
190
        return Long.parseLong(new String(input).trim());
 
191
    }
 
192
 
 
193
    private int asInt(byte[] input) {
 
194
        return asInt(input, 10, false);
 
195
    }
 
196
 
 
197
    private int asInt(byte[] input, boolean treatBlankAsZero) {
 
198
        return asInt(input, 10, treatBlankAsZero);
 
199
    }
 
200
 
 
201
    private int asInt(byte[] input, int base) {
 
202
        return asInt(input, base, false);
 
203
    }
 
204
 
 
205
    private int asInt(byte[] input, int base, boolean treatBlankAsZero) {
 
206
        String string = new String(input).trim();
 
207
        if (string.length() == 0 && treatBlankAsZero) {
 
208
            return 0;
 
209
        }
 
210
        return Integer.parseInt(string, base);
 
211
    }
 
212
 
149
213
    /*
150
214
     * (non-Javadoc)
151
215
     *