1 11 package org.eclipse.ui.internal.wizards.datatransfer; 12 13 import java.io.FilterInputStream ; 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 17 24 public class TarInputStream extends FilterInputStream 25 { 26 private int nextEntry = 0; 27 private int nextEOF = 0; 28 private int filepos = 0; 29 private int bytesread = 0; 30 private TarEntry firstEntry = null; 31 private String longLinkName = null; 32 33 40 public TarInputStream(InputStream in) throws TarException, IOException { 41 super(in); 42 43 firstEntry = getNextEntry(); 46 } 47 48 57 TarInputStream(InputStream in, TarEntry entry) throws TarException, IOException { 58 super(in); 59 skipToEntry(entry); 60 } 61 62 69 private long headerChecksum(byte[] header) { 70 long sum = 0; 71 for(int i = 0; i < 512; i++) { 72 sum += header[i] & 0xff; 73 } 74 return sum; 75 } 76 77 85 boolean skipToEntry(TarEntry entry) throws TarException, IOException { 86 int bytestoskip = entry.filepos - bytesread; 87 if(bytestoskip < 0) { 88 return false; 89 } 90 while(bytestoskip > 0) { 91 long ret = in.skip(bytestoskip); 92 if(ret < 0) { 93 throw new IOException ("early end of stream"); } 95 bytestoskip -= ret; 96 bytesread += ret; 97 } 98 filepos = entry.filepos; 99 nextEntry = 0; 100 nextEOF = 0; 101 getNextEntry(); 103 return true; 104 } 105 106 112 private boolean isValidTarHeader(byte[] header) { 113 long fileChecksum, calculatedChecksum; 114 int pos, i; 115 116 pos = 148; 117 StringBuffer checksumString = new StringBuffer (); 118 for(i = 0; i < 8; i++) { 119 if(header[pos + i] == ' ') { 120 continue; 121 } 122 if(header[pos + i] == 0 || !Character.isDigit((char) header[pos + i])) { 123 break; 124 } 125 checksumString.append((char) header[pos + i]); 126 } 127 if(checksumString.length() == 0) { 128 return false; 129 } 130 if(checksumString.charAt(0) != '0') { 131 checksumString.insert(0, '0'); 132 } 133 try { 134 fileChecksum = Long.decode(checksumString.toString()).longValue(); 135 } catch(NumberFormatException exception) { 136 return false; 138 } 139 140 for(i = 0; i < 8; i++) { 142 header[pos + i] = ' '; 143 } 144 calculatedChecksum = headerChecksum(header); 145 146 return (fileChecksum == calculatedChecksum); 147 } 148 149 157 TarEntry getNextEntryInternal() throws TarException, IOException { 158 byte[] header = new byte[512]; 159 int pos = 0; 160 int i; 161 162 if(firstEntry != null) { 163 TarEntry entryReturn = firstEntry; 164 firstEntry = null; 165 return entryReturn; 166 } 167 168 while(nextEntry > 0) { 169 long ret = in.skip(nextEntry); 170 if(ret < 0) { 171 throw new IOException ("early end of stream"); } 173 nextEntry -= ret; 174 bytesread += ret; 175 } 176 177 int bytestoread = 512; 178 while(bytestoread > 0) { 179 int ret = super.read(header, 512 - bytestoread, bytestoread); 180 if( ret < 0 ) { 181 throw new IOException ("early end of stream"); } 183 bytestoread -= ret; 184 bytesread += ret; 185 } 186 187 if(headerChecksum(header) == 0) { 189 if(filepos > 0) { 191 return null; 192 } 193 194 throw new TarException("not in tar format"); } 197 198 if(!isValidTarHeader(header)) { 200 throw new TarException("not in tar format"); } 202 203 while (pos < 100 && header[pos] != 0) { 204 pos++; 205 } 206 String name = new String (header, 0, pos, "UTF8"); pos = 345; 209 if(header[pos] != 0) { 210 while (pos < 500 && header[pos] != 0) { 211 pos++; 212 } 213 String prefix = new String (header, 345, pos - 345, "UTF8"); name = prefix + "/" + name; } 216 217 TarEntry entry; 218 if(longLinkName != null) { 219 entry = new TarEntry(longLinkName, filepos); 220 longLinkName = null; 221 } else { 222 entry = new TarEntry(name, filepos); 223 } 224 if(header[156] != 0) { 225 entry.setFileType(header[156]); 226 } 227 228 pos = 100; 229 StringBuffer mode = new StringBuffer (); 230 for(i = 0; i < 8; i++) { 231 if(header[pos + i] == 0) { 232 break; 233 } 234 if(header[pos + i] == ' ') { 235 continue; 236 } 237 mode.append((char) header[pos + i]); 238 } 239 if(mode.length() > 0 && mode.charAt(0) != '0') { 240 mode.insert(0, '0'); 241 } 242 try { 243 long fileMode = Long.decode(mode.toString()).longValue(); 244 entry.setMode(fileMode); 245 } catch(NumberFormatException nfe) { 246 throw new TarException(DataTransferMessages.TarImport_invalid_tar_format, nfe); 247 } 248 249 pos = 100 + 24; 250 StringBuffer size = new StringBuffer (); 251 for(i = 0; i < 12; i++) { 252 if(header[pos + i] == 0) { 253 break; 254 } 255 if(header[pos + i] == ' ') { 256 continue; 257 } 258 size.append((char) header[pos + i]); 259 } 260 if(size.charAt(0) != '0') { 261 size.insert(0, '0'); 262 } 263 int fileSize; 264 try { 265 fileSize = Integer.decode(size.toString()).intValue(); 266 } catch(NumberFormatException nfe) { 267 throw new TarException(DataTransferMessages.TarImport_invalid_tar_format, nfe); 268 } 269 270 entry.setSize(fileSize); 271 nextEOF = fileSize; 272 if(fileSize % 512 > 0) { 273 nextEntry = fileSize + (512 - (fileSize % 512)); 274 } else { 275 nextEntry = fileSize; 276 } 277 filepos += (nextEntry + 512); 278 return entry; 279 } 280 281 289 public TarEntry getNextEntry() throws TarException, IOException { 290 TarEntry entry = getNextEntryInternal(); 291 292 if(entry != null && entry.getName().equals("././@LongLink")) { byte[] longNameData = new byte[(int) entry.getSize()]; 297 int bytesread = 0; 298 while (bytesread < longNameData.length) { 299 int cur = read(longNameData, bytesread, longNameData.length - bytesread); 300 if (cur < 0) { 301 throw new IOException ("early end of stream"); } 303 bytesread += cur; 304 } 305 306 int pos = 0; 307 while (pos < longNameData.length && longNameData[pos] != 0) { 308 pos++; 309 } 310 longLinkName = new String (longNameData, 0, pos, "UTF8"); return getNextEntryInternal(); 312 } 313 return entry; 314 } 315 316 319 public int read(byte[] b, int off, int len) throws IOException { 320 if(nextEOF == 0) { 321 return -1; 322 } 323 if(len > nextEOF) { 324 len = nextEOF; 325 } 326 int size = super.read(b, off, len); 327 nextEntry -= size; 328 nextEOF -= size; 329 bytesread += size; 330 return size; 331 } 332 333 336 public int read() throws IOException { 337 byte[] data = new byte[1]; 338 int size = read(data, 0, 1); 339 if (size < 0) { 340 return size; 341 } 342 return data[0]; 343 } 344 } 345 | Popular Tags |