protected void execute() throws ArchiverException, IOException { if (!checkForced()) { return; } ResourceIterator iter = getResources(); if (!iter.hasNext()) { throw new ArchiverException("You must set at least one file."); } File tarFile = getDestFile(); if (tarFile == null) { throw new ArchiverException("You must set the destination tar file."); } if (tarFile.exists() && !tarFile.isFile()) { throw new ArchiverException(tarFile + " isn't a file."); } if (tarFile.exists() && !tarFile.canWrite()) { throw new ArchiverException(tarFile + " is read-only."); } getLogger().info("Building tar: " + tarFile.getAbsolutePath()); final OutputStream bufferedOutputStream = bufferedOutputStream(new FileOutputStream(tarFile)); tOut = new TarArchiveOutputStream(compress(compression, bufferedOutputStream), "UTF8"); if (longFileMode.isTruncateMode()) { tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_TRUNCATE); } else if (longFileMode.isPosixMode() || longFileMode.isPosixWarnMode()) { tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); // Todo: Patch 2.5.1 for this fix. Also make closeable fix on 2.5.1 tOut.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX); } else if (longFileMode.isFailMode() || longFileMode.isOmitMode()) { tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_ERROR); } else { // warn or GNU tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); } longWarningGiven = false; try { while (iter.hasNext()) { ArchiveEntry entry = iter.next(); // Check if we don't add tar file in itself if (ResourceUtils.isSame(entry.getResource(), tarFile)) { throw new ArchiverException("A tar file cannot include itself."); } String fileName = entry.getName(); String name = StringUtils.replace(fileName, File.separatorChar, '/'); tarFile(entry, tOut, name); } } finally { IOUtil.close(tOut); } }
/** * tar a file * * @param entry the file to tar * @param tOut the output stream * @param vPath the path name of the file to tar * @throws IOException on error */ protected void tarFile(ArchiveEntry entry, TarOutputStream tOut, String vPath) throws ArchiverException, IOException { InputStream fIn = null; // don't add "" to the archive if (vPath.length() <= 0) { return; } if (entry.getResource().isDirectory() && !vPath.endsWith("/")) { vPath += "/"; } if (vPath.startsWith("/") && !options.getPreserveLeadingSlashes()) { int l = vPath.length(); if (l <= 1) { // we would end up adding "" to the archive return; } vPath = vPath.substring(1, l); } int pathLength = vPath.length(); try { final TarEntry te; if (!longFileMode.isGnuMode() && pathLength >= TarConstants.NAMELEN) { int maxPosixPathLen = TarConstants.NAMELEN + TarConstants.POSIX_PREFIXLEN; if (longFileMode.isPosixMode()) { if (pathLength > maxPosixPathLen) { te = new TarEntry(vPath); } else { te = new PosixTarEntry(vPath); } } else if (longFileMode.isPosixWarnMode()) { if (pathLength > maxPosixPathLen) { getLogger() .warn("Entry: " + vPath + " longer than " + maxPosixPathLen + " characters."); if (!longWarningGiven) { getLogger() .warn( "Resulting tar file can only be processed " + "successfully by GNU compatible tar commands"); longWarningGiven = true; } te = new TarEntry(vPath); } else { te = new PosixTarEntry(vPath); } } else if (longFileMode.isOmitMode()) { getLogger().info("Omitting: " + vPath); return; } else if (longFileMode.isWarnMode()) { getLogger() .warn("Entry: " + vPath + " longer than " + TarConstants.NAMELEN + " characters."); if (!longWarningGiven) { getLogger() .warn( "Resulting tar file can only be processed " + "successfully by GNU compatible tar commands"); longWarningGiven = true; } te = new TarEntry(vPath); } else if (longFileMode.isFailMode()) { throw new ArchiverException( "Entry: " + vPath + " longer than " + TarConstants.NAMELEN + " characters."); } else { throw new IllegalStateException("Non gnu mode should never get here?"); } } else { /* Did not touch it, because this would change the following default tar format, however * GNU tar can untar POSIX tar, so I think we should us PosixTarEntry here instead. */ te = new TarEntry(vPath); } long teLastModified = entry.getResource().getLastModified(); te.setModTime( teLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE ? System.currentTimeMillis() : teLastModified); if (!entry.getResource().isDirectory()) { final long size = entry.getResource().getSize(); te.setSize(size == PlexusIoResource.UNKNOWN_RESOURCE_SIZE ? 0 : size); te.setMode(entry.getMode()); } else { te.setMode(entry.getMode()); } PlexusIoResourceAttributes attributes = entry.getResourceAttributes(); te.setUserName( (attributes != null && attributes.getUserName() != null) ? attributes.getUserName() : options.getUserName()); te.setGroupName( (attributes != null && attributes.getGroupName() != null) ? attributes.getGroupName() : options.getGroup()); final int userId = (attributes != null && attributes.getUserId() != null) ? attributes.getUserId() : options.getUid(); if (userId > 0) { te.setUserId(userId); } final int groupId = (attributes != null && attributes.getGroupId() != null) ? attributes.getGroupId() : options.getGid(); if (groupId > 0) { te.setGroupId(groupId); } tOut.putNextEntry(te); if (!entry.getResource().isDirectory()) { fIn = entry.getInputStream(); byte[] buffer = new byte[8 * 1024]; int count = 0; do { tOut.write(buffer, 0, count); count = fIn.read(buffer, 0, buffer.length); } while (count != -1); } tOut.closeEntry(); } finally { IOUtil.close(fIn); } }
/** * tar a file * * @param entry the file to tar * @param tOut the output stream * @param vPath the path name of the file to tar * @throws IOException on error */ protected void tarFile(ArchiveEntry entry, TarArchiveOutputStream tOut, String vPath) throws ArchiverException, IOException { // don't add "" to the archive if (vPath.length() <= 0) { return; } if (entry.getResource().isDirectory() && !vPath.endsWith("/")) { vPath += "/"; } if (vPath.startsWith("/") && !options.getPreserveLeadingSlashes()) { int l = vPath.length(); if (l <= 1) { // we would end up adding "" to the archive return; } vPath = vPath.substring(1, l); } int pathLength = vPath.length(); InputStream fIn = null; try { TarArchiveEntry te; if (!longFileMode.isGnuMode() && pathLength >= org.apache.commons.compress.archivers.tar.TarConstants.NAMELEN) { int maxPosixPathLen = org.apache.commons.compress.archivers.tar.TarConstants.NAMELEN + org.apache.commons.compress.archivers.tar.TarConstants.PREFIXLEN; if (longFileMode.isPosixMode()) { } else if (longFileMode.isPosixWarnMode()) { if (pathLength > maxPosixPathLen) { getLogger() .warn("Entry: " + vPath + " longer than " + maxPosixPathLen + " characters."); if (!longWarningGiven) { getLogger() .warn( "Resulting tar file can only be processed " + "successfully by GNU compatible tar commands"); longWarningGiven = true; } } } else if (longFileMode.isOmitMode()) { getLogger().info("Omitting: " + vPath); return; } else if (longFileMode.isWarnMode()) { getLogger() .warn( "Entry: " + vPath + " longer than " + org.apache.commons.compress.archivers.tar.TarConstants.NAMELEN + " characters."); if (!longWarningGiven) { getLogger() .warn( "Resulting tar file can only be processed " + "successfully by GNU compatible tar commands"); longWarningGiven = true; } } else if (longFileMode.isFailMode()) { throw new ArchiverException( "Entry: " + vPath + " longer than " + org.apache.commons.compress.archivers.tar.TarConstants.NAMELEN + " characters."); } else { throw new IllegalStateException("Non gnu mode should never get here?"); } } if (entry.getType() == ArchiveEntry.SYMLINK) { final SymlinkDestinationSupplier plexusIoSymlinkResource = (SymlinkDestinationSupplier) entry.getResource(); te = new TarArchiveEntry(vPath, TarArchiveEntry.LF_SYMLINK); te.setLinkName(plexusIoSymlinkResource.getSymlinkDestination()); } else { te = new TarArchiveEntry(vPath); } long teLastModified = entry.getResource().getLastModified(); te.setModTime( teLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE ? System.currentTimeMillis() : teLastModified); if (entry.getType() == ArchiveEntry.SYMLINK) { te.setSize(0); } else if (!entry.getResource().isDirectory()) { final long size = entry.getResource().getSize(); te.setSize(size == PlexusIoResource.UNKNOWN_RESOURCE_SIZE ? 0 : size); } te.setMode(entry.getMode()); PlexusIoResourceAttributes attributes = entry.getResourceAttributes(); te.setUserName( (attributes != null && attributes.getUserName() != null) ? attributes.getUserName() : options.getUserName()); te.setGroupName( (attributes != null && attributes.getGroupName() != null) ? attributes.getGroupName() : options.getGroup()); final int userId = (attributes != null && attributes.getUserId() != null) ? attributes.getUserId() : options.getUid(); if (userId >= 0) { te.setUserId(userId); } final int groupId = (attributes != null && attributes.getGroupId() != null) ? attributes.getGroupId() : options.getGid(); if (groupId >= 0) { te.setGroupId(groupId); } tOut.putArchiveEntry(te); try { if (entry.getResource().isFile() && !(entry.getType() == ArchiveEntry.SYMLINK)) { fIn = entry.getInputStream(); Streams.copyFullyDontCloseOutput(fIn, tOut, "xAR"); } } catch (Throwable e) { getLogger().warn("When creating tar entry", e); } finally { tOut.closeArchiveEntry(); } } finally { IOUtil.close(fIn); } }