Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
| 19 | package org.apache.commons.compress.archivers.tar; |
| 20 | |
| 21 | import java.io.FilterOutputStream; |
| 22 | import java.io.IOException; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 23 | import java.io.OutputStream; |
| 24 | |
| 25 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 26 | * The TarOutputStream writes a UNIX tar archive as an OutputStream. |
| 27 | * Methods are provided to put entries, and then write their contents |
| 28 | * by writing to this stream using write(). |
| 29 | * |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 30 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 31 | public class TarOutputStream extends FilterOutputStream { |
| 32 | /** Fail if a long file name is required in the archive. */ |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 33 | public static final int LONGFILE_ERROR = 0; |
| 34 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 35 | /** Long paths will be truncated in the archive. */ |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 36 | public static final int LONGFILE_TRUNCATE = 1; |
| 37 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 38 | /** GNU tar extensions are used to store long file names in the archive. */ |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 39 | public static final int LONGFILE_GNU = 2; |
| 40 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 41 | // CheckStyle:VisibilityModifier OFF - bc |
| 42 | protected boolean debug; |
| 43 | protected long currSize; |
| 44 | protected String currName; |
| 45 | protected long currBytes; |
| 46 | protected byte[] oneBuf; |
| 47 | protected byte[] recordBuf; |
| 48 | protected int assemLen; |
| 49 | protected byte[] assemBuf; |
| 50 | protected TarBuffer buffer; |
| 51 | protected int longFileMode = LONGFILE_ERROR; |
| 52 | // CheckStyle:VisibilityModifier ON |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 53 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 54 | private boolean closed = false; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 55 | |
| 56 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 57 | * Constructor for TarInputStream. |
| 58 | * @param os the output stream to use |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 59 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 60 | public TarOutputStream(OutputStream os) { |
| 61 | this(os, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 65 | * Constructor for TarInputStream. |
| 66 | * @param os the output stream to use |
| 67 | * @param blockSize the block size to use |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 68 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 69 | public TarOutputStream(OutputStream os, int blockSize) { |
| 70 | this(os, blockSize, TarBuffer.DEFAULT_RCDSIZE); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 74 | * Constructor for TarInputStream. |
| 75 | * @param os the output stream to use |
| 76 | * @param blockSize the block size to use |
| 77 | * @param recordSize the record size to use |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 78 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 79 | public TarOutputStream(OutputStream os, int blockSize, int recordSize) { |
| 80 | super(os); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 81 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 82 | this.buffer = new TarBuffer(os, blockSize, recordSize); |
| 83 | this.debug = false; |
| 84 | this.assemLen = 0; |
| 85 | this.assemBuf = new byte[recordSize]; |
| 86 | this.recordBuf = new byte[recordSize]; |
| 87 | this.oneBuf = new byte[1]; |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Set the long file mode. |
| 92 | * This can be LONGFILE_ERROR(0), LONGFILE_TRUNCATE(1) or LONGFILE_GNU(2). |
| 93 | * This specifies the treatment of long file names (names >= TarConstants.NAMELEN). |
| 94 | * Default is LONGFILE_ERROR. |
| 95 | * @param longFileMode the mode to use |
| 96 | */ |
| 97 | public void setLongFileMode(int longFileMode) { |
| 98 | this.longFileMode = longFileMode; |
| 99 | } |
| 100 | |
| 101 | |
| 102 | /** |
| 103 | * Sets the debugging flag. |
| 104 | * |
| 105 | * @param debugF True to turn on debugging. |
| 106 | */ |
| 107 | public void setDebug(boolean debugF) { |
| 108 | this.debug = debugF; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | /** |
| 112 | * Sets the debugging flag in this stream's TarBuffer. |
| 113 | * |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 114 | * @param debug True to turn on debugging. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 115 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 116 | public void setBufferDebug(boolean debug) { |
| 117 | buffer.setDebug(debug); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 121 | * Ends the TAR archive without closing the underlying OutputStream. |
| 122 | * The result is that the two EOF records of nulls are written. |
| 123 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 124 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 125 | public void finish() throws IOException { |
| 126 | // See Bugzilla 28776 for a discussion on this |
| 127 | // http://issues.apache.org/bugzilla/show_bug.cgi?id=28776 |
| 128 | writeEOFRecord(); |
| 129 | writeEOFRecord(); |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Ends the TAR archive and closes the underlying OutputStream. |
| 134 | * This means that finish() is called followed by calling the |
| 135 | * TarBuffer's close(). |
| 136 | * @throws IOException on error |
| 137 | */ |
| 138 | public void close() throws IOException { |
| 139 | if (!closed) { |
| 140 | finish(); |
| 141 | buffer.close(); |
| 142 | out.close(); |
| 143 | closed = true; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 144 | } |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Get the record size being used by this stream's TarBuffer. |
| 149 | * |
| 150 | * @return The TarBuffer record size. |
| 151 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 152 | public int getRecordSize() { |
| 153 | return buffer.getRecordSize(); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 157 | * Put an entry on the output stream. This writes the entry's |
| 158 | * header record and positions the output stream for writing |
| 159 | * the contents of the entry. Once this method is called, the |
| 160 | * stream is ready for calls to write() to write the entry's |
| 161 | * contents. Once the contents are written, closeEntry() |
| 162 | * <B>MUST</B> be called to ensure that all buffered data |
| 163 | * is completely written to the output stream. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 164 | * |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 165 | * @param entry The TarEntry to be written to the archive. |
| 166 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 167 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 168 | public void putNextEntry(TarArchiveEntry entry) throws IOException { |
| 169 | if (entry.getName().length() >= TarConstants.NAMELEN) { |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 170 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 171 | if (longFileMode == LONGFILE_GNU) { |
| 172 | // create a TarEntry for the LongLink, the contents |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 173 | // of which are the entry's name |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 174 | TarArchiveEntry longLinkEntry = new TarArchiveEntry(TarConstants.GNU_LONGLINK, |
| 175 | TarConstants.LF_GNUTYPE_LONGNAME); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 176 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 177 | longLinkEntry.setSize(entry.getName().length() + 1); |
| 178 | putNextEntry(longLinkEntry); |
| 179 | write(entry.getName().getBytes()); |
| 180 | write(0); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 181 | closeEntry(); |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 182 | } else if (longFileMode != LONGFILE_TRUNCATE) { |
| 183 | throw new RuntimeException("file name '" + entry.getName() |
| 184 | + "' is too long ( > " |
| 185 | + TarConstants.NAMELEN + " bytes)"); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 186 | } |
| 187 | } |
| 188 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 189 | entry.writeEntryHeader(recordBuf); |
| 190 | buffer.writeRecord(recordBuf); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 191 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 192 | currBytes = 0; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 193 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 194 | if (entry.isDirectory()) { |
| 195 | currSize = 0; |
| 196 | } else { |
| 197 | currSize = entry.getSize(); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 198 | } |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 199 | currName = entry.getName(); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 200 | } |
| 201 | |
| 202 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 203 | * Close an entry. This method MUST be called for all file |
| 204 | * entries that contain data. The reason is that we must |
| 205 | * buffer data written to the stream in order to satisfy |
| 206 | * the buffer's record based writes. Thus, there may be |
| 207 | * data fragments still being assembled that must be written |
| 208 | * to the output stream before this entry is closed and the |
| 209 | * next entry written. |
| 210 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 211 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 212 | public void closeEntry() throws IOException { |
| 213 | if (assemLen > 0) { |
| 214 | for (int i = assemLen; i < assemBuf.length; ++i) { |
| 215 | assemBuf[i] = 0; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 216 | } |
| 217 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 218 | buffer.writeRecord(assemBuf); |
| 219 | |
| 220 | currBytes += assemLen; |
| 221 | assemLen = 0; |
| 222 | } |
| 223 | |
| 224 | if (currBytes < currSize) { |
| 225 | throw new IOException("entry '" + currName + "' closed at '" |
| 226 | + currBytes |
| 227 | + "' before the '" + currSize |
| 228 | + "' bytes specified in the header were written"); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 229 | } |
| 230 | } |
| 231 | |
| 232 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 233 | * Writes a byte to the current tar archive entry. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 234 | * |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 235 | * This method simply calls read( byte[], int, int ). |
| 236 | * |
| 237 | * @param b The byte written. |
| 238 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 239 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 240 | public void write(int b) throws IOException { |
| 241 | oneBuf[0] = (byte) b; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 242 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 243 | write(oneBuf, 0, 1); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 247 | * Writes bytes to the current tar archive entry. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 248 | * |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 249 | * This method simply calls write( byte[], int, int ). |
| 250 | * |
| 251 | * @param wBuf The buffer to write to the archive. |
| 252 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 253 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 254 | public void write(byte[] wBuf) throws IOException { |
| 255 | write(wBuf, 0, wBuf.length); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 256 | } |
| 257 | |
| 258 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 259 | * Writes bytes to the current tar archive entry. This method |
| 260 | * is aware of the current entry and will throw an exception if |
| 261 | * you attempt to write bytes past the length specified for the |
| 262 | * current entry. The method is also (painfully) aware of the |
| 263 | * record buffering required by TarBuffer, and manages buffers |
| 264 | * that are not a multiple of recordsize in length, including |
| 265 | * assembling records from small buffers. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 266 | * |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 267 | * @param wBuf The buffer to write to the archive. |
| 268 | * @param wOffset The offset in the buffer from which to get bytes. |
| 269 | * @param numToWrite The number of bytes to write. |
| 270 | * @throws IOException on error |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 271 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 272 | public void write(byte[] wBuf, int wOffset, int numToWrite) throws IOException { |
| 273 | if ((currBytes + numToWrite) > currSize) { |
| 274 | throw new IOException("request to write '" + numToWrite |
| 275 | + "' bytes exceeds size in header of '" |
| 276 | + currSize + "' bytes for entry '" |
| 277 | + currName + "'"); |
| 278 | |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 279 | // |
| 280 | // We have to deal with assembly!!! |
| 281 | // The programmer can be writing little 32 byte chunks for all |
| 282 | // we know, and we must assemble complete records for writing. |
| 283 | // REVIEW Maybe this should be in TarBuffer? Could that help to |
| 284 | // eliminate some of the buffer copying. |
| 285 | // |
| 286 | } |
| 287 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 288 | if (assemLen > 0) { |
| 289 | if ((assemLen + numToWrite) >= recordBuf.length) { |
| 290 | int aLen = recordBuf.length - assemLen; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 291 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 292 | System.arraycopy(assemBuf, 0, recordBuf, 0, |
| 293 | assemLen); |
| 294 | System.arraycopy(wBuf, wOffset, recordBuf, |
| 295 | assemLen, aLen); |
| 296 | buffer.writeRecord(recordBuf); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 297 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 298 | currBytes += recordBuf.length; |
| 299 | wOffset += aLen; |
| 300 | numToWrite -= aLen; |
| 301 | assemLen = 0; |
| 302 | } else { |
| 303 | System.arraycopy(wBuf, wOffset, assemBuf, assemLen, |
| 304 | numToWrite); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 305 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 306 | wOffset += numToWrite; |
| 307 | assemLen += numToWrite; |
Stefan Bodewig | 5e5804c | 2009-02-05 12:45:23 +0000 | [diff] [blame^] | 308 | numToWrite = 0; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 309 | } |
| 310 | } |
| 311 | |
| 312 | // |
| 313 | // When we get here we have EITHER: |
| 314 | // o An empty "assemble" buffer. |
| 315 | // o No bytes to write (numToWrite == 0) |
| 316 | // |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 317 | while (numToWrite > 0) { |
| 318 | if (numToWrite < recordBuf.length) { |
| 319 | System.arraycopy(wBuf, wOffset, assemBuf, assemLen, |
| 320 | numToWrite); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 321 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 322 | assemLen += numToWrite; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 323 | |
| 324 | break; |
| 325 | } |
| 326 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 327 | buffer.writeRecord(wBuf, wOffset); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 328 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 329 | int num = recordBuf.length; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 330 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 331 | currBytes += num; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 332 | numToWrite -= num; |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 333 | wOffset += num; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 334 | } |
| 335 | } |
| 336 | |
| 337 | /** |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 338 | * Write an EOF (end of archive) record to the tar archive. |
| 339 | * An EOF record consists of a record of all zeros. |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 340 | */ |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 341 | private void writeEOFRecord() throws IOException { |
| 342 | for (int i = 0; i < recordBuf.length; ++i) { |
| 343 | recordBuf[i] = 0; |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 344 | } |
| 345 | |
Torsten Curdt | 46ad24d | 2009-01-08 11:09:25 +0000 | [diff] [blame] | 346 | buffer.writeRecord(recordBuf); |
Torsten Curdt | ca16539 | 2008-07-10 10:17:44 +0000 | [diff] [blame] | 347 | } |
| 348 | } |