From 6b5244eafe773aa866f2811cba43b1ab34cb12dd Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Wed, 18 Mar 2015 14:56:26 +0100 Subject: [PATCH] Some ArchiveExtractor bugs fixed and its code formatted --- .../libraries/ui/LibraryInstaller.java | 13 +- .../packages/ContributionInstaller.java | 13 +- .../os/linux/LinuxFileNativeUtils.java | 2 +- .../cc/arduino/utils/ArchiveExtractor.java | 149 ++++++++++-------- 4 files changed, 105 insertions(+), 72 deletions(-) diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryInstaller.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryInstaller.java index b20a56f7f..ede80d64f 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryInstaller.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryInstaller.java @@ -44,6 +44,17 @@ import cc.arduino.utils.Progress; public class LibraryInstaller { + private static final String LIBRARY_INDEX_URL; + + static { + String extenalLibraryIndexUrl = System.getProperty("LIBRARY_INDEX_URL"); + if (extenalLibraryIndexUrl != null && !"".equals(extenalLibraryIndexUrl)) { + LIBRARY_INDEX_URL = extenalLibraryIndexUrl; + } else { + LIBRARY_INDEX_URL = "http://arduino.cc/download.php?f=/libraries/library_index.json"; + } + } + private LibrariesIndexer indexer; private File stagingFolder; private DownloadableContributionsDownloader downloader; @@ -63,7 +74,7 @@ public class LibraryInstaller { final MultiStepProgress progress = new MultiStepProgress(2); // Step 1: Download index - URL url = new URL("http://arduino.cc/download.php?f=/libraries/library_index.json"); + URL url = new URL(LIBRARY_INDEX_URL); File outputFile = indexer.getIndexFile(); File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp"); try { diff --git a/arduino-core/src/cc/arduino/contributions/packages/ContributionInstaller.java b/arduino-core/src/cc/arduino/contributions/packages/ContributionInstaller.java index 166b8e7c5..5876b6dda 100644 --- a/arduino-core/src/cc/arduino/contributions/packages/ContributionInstaller.java +++ b/arduino-core/src/cc/arduino/contributions/packages/ContributionInstaller.java @@ -44,6 +44,17 @@ import static processing.app.I18n.format; public class ContributionInstaller { + private static final String PACKAGE_INDEX_URL; + + static { + String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL"); + if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) { + PACKAGE_INDEX_URL = extenalPackageIndexUrl; + } else { + PACKAGE_INDEX_URL = "http://arduino.cc/download.php?f=/packages/package_index.json"; + } + } + private File stagingFolder; private ContributionsIndexer indexer; private DownloadableContributionsDownloader downloader; @@ -172,7 +183,7 @@ public class ContributionInstaller { final MultiStepProgress progress = new MultiStepProgress(1); final String statusText = _("Downloading platforms index..."); - URL url = new URL("http://arduino.cc/download.php?f=/packages/package_index.json"); + URL url = new URL(PACKAGE_INDEX_URL); File outputFile = indexer.getIndexFile(); File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp"); downloader.download(url, tmpFile, progress, statusText); diff --git a/arduino-core/src/cc/arduino/os/linux/LinuxFileNativeUtils.java b/arduino-core/src/cc/arduino/os/linux/LinuxFileNativeUtils.java index df1a615d1..818da7a48 100644 --- a/arduino-core/src/cc/arduino/os/linux/LinuxFileNativeUtils.java +++ b/arduino-core/src/cc/arduino/os/linux/LinuxFileNativeUtils.java @@ -44,7 +44,7 @@ public class LinuxFileNativeUtils { public static void link(File file, File link) throws IOException { int res = libc.link(file.getAbsolutePath(), link.getAbsolutePath()); if (res == -1) - throw new IOException("Could not create hard link: " + strerror()); + throw new IOException("Could not create hard link to " + file + " from " + link + ": " + strerror()); } public static void symlink(File file, File link) throws IOException { diff --git a/arduino-core/src/cc/arduino/utils/ArchiveExtractor.java b/arduino-core/src/cc/arduino/utils/ArchiveExtractor.java index 95f87c9f1..134d76734 100644 --- a/arduino-core/src/cc/arduino/utils/ArchiveExtractor.java +++ b/arduino-core/src/cc/arduino/utils/ArchiveExtractor.java @@ -28,15 +28,7 @@ */ package cc.arduino.utils; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - +import cc.arduino.os.FileNativeUtils; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; @@ -45,38 +37,35 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -import cc.arduino.os.FileNativeUtils; +import java.io.*; +import java.util.HashMap; +import java.util.Map; public class ArchiveExtractor { /** * Extract source into destFolder. source file archive * format is autodetected from file extension. - * + * * @param archiveFile * @param destFolder * @throws IOException */ - public static void extract(File archiveFile, File destFolder) - throws IOException { + public static void extract(File archiveFile, File destFolder) throws IOException { extract(archiveFile, destFolder, 0); } /** * Extract source into destFolder. source file archive * format is autodetected from file extension. - * - * @param archiveFile - * Archive file to extract - * @param destFolder - * Destination folder - * @param stripPath - * Number of path elements to strip from the paths contained in the - * archived files + * + * @param archiveFile Archive file to extract + * @param destFolder Destination folder + * @param stripPath Number of path elements to strip from the paths contained in the + * archived files * @throws IOException */ - public static void extract(File archiveFile, File destFolder, int stripPath) - throws IOException { + public static void extract(File archiveFile, File destFolder, int stripPath) throws IOException { // Folders timestamps must be set at the end of archive extraction // (because creating a file in a folder alters the folder's timestamp) @@ -106,11 +95,17 @@ public class ArchiveExtractor { String pathPrefix = ""; + Map hardLinks = new HashMap(); + Map hardLinksMode = new HashMap(); + Map symLinks = new HashMap(); + Map symLinksModifiedTimes = new HashMap(); + // Cycle through all the archive entries while (true) { ArchiveEntry entry = in.getNextEntry(); - if (entry == null) + if (entry == null) { break; + } // Extract entry info long size = entry.getSize(); @@ -127,18 +122,21 @@ public class ArchiveExtractor { // http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x int slash = name.lastIndexOf('/'); if (slash == -1) { - if (name.startsWith("._")) + if (name.startsWith("._")) { continue; + } } else { - if (name.substring(slash + 1).startsWith("._")) + if (name.substring(slash + 1).startsWith("._")) { continue; + } } } // Skip git metadata // http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html - if (name.contains("pax_global_header")) + if (name.contains("pax_global_header")) { continue; + } if (entry instanceof TarArchiveEntry) { TarArchiveEntry tarEntry = (TarArchiveEntry) entry; @@ -154,9 +152,9 @@ public class ArchiveExtractor { int slash = 0; while (stripPath > 0) { slash = name.indexOf("/", slash); - if (slash == -1) - throw new IOException( - "Invalid archive: it must contains a single root folder"); + if (slash == -1) { + throw new IOException("Invalid archive: it must contains a single root folder"); + } slash++; stripPath--; } @@ -164,21 +162,19 @@ public class ArchiveExtractor { } // Strip the common path prefix when requested - if (!name.startsWith(pathPrefix)) - throw new IOException( - "Invalid archive: it must contains a single root folder while file " - + name + " is outside " + pathPrefix); + if (!name.startsWith(pathPrefix)) { + throw new IOException("Invalid archive: it must contains a single root folder while file " + name + " is outside " + pathPrefix); + } name = name.substring(pathPrefix.length()); - if (name.isEmpty()) + if (name.isEmpty()) { continue; + } File outputFile = new File(destFolder, name); File outputLinkFile = null; if (isLink) { if (!linkName.startsWith(pathPrefix)) { - throw new IOException( - "Invalid archive: it must contains a single root folder while file " - + linkName + " is outside " + pathPrefix); + throw new IOException("Invalid archive: it must contains a single root folder while file " + linkName + " is outside " + pathPrefix); } linkName = linkName.substring(pathPrefix.length()); outputLinkFile = new File(destFolder, linkName); @@ -186,52 +182,69 @@ public class ArchiveExtractor { if (isSymLink) { // Symbolic links are referenced with relative paths outputLinkFile = new File(linkName); - if (outputLinkFile.isAbsolute()) - throw new IOException( - "Invalid archive: it contains a symbolic link with absolute path '" - + outputLinkFile + "'"); + if (outputLinkFile.isAbsolute()) { + throw new IOException("Invalid archive: it contains a symbolic link with absolute path '" + outputLinkFile + "'"); + } } // Safety check if (isDirectory) { - if (outputFile.isFile()) - throw new IOException("Can't create folder " + outputFile - + ", a file with the same name exists!"); + if (outputFile.isFile()) { + throw new IOException("Can't create folder " + outputFile + ", a file with the same name exists!"); + } } else { // - isLink // - isSymLink // - anything else - if (outputFile.exists()) - throw new IOException("Can't extract file " + outputFile - + ", file already exists!"); + if (outputFile.exists()) { + throw new IOException("Can't extract file " + outputFile + ", file already exists!"); + } } // Extract the entry if (isDirectory) { - if (!outputFile.exists()) - if (!outputFile.mkdirs()) - throw new IOException("Could not create folder: " + outputFile); + if (!outputFile.exists() && !outputFile.mkdirs()) { + throw new IOException("Could not create folder: " + outputFile); + } foldersTimestamps.put(outputFile, modifiedTime); } else if (isLink) { - FileNativeUtils.link(outputLinkFile, outputFile); + hardLinks.put(outputLinkFile, outputFile); + hardLinksMode.put(outputFile, mode); } else if (isSymLink) { - FileNativeUtils.symlink(outputLinkFile, outputFile); - outputFile.setLastModified(modifiedTime); + symLinks.put(outputLinkFile, outputFile); + symLinksModifiedTimes.put(outputFile, modifiedTime); } else { // Create the containing folder if not exists - if (!outputFile.getParentFile().isDirectory()) + if (!outputFile.getParentFile().isDirectory()) { outputFile.getParentFile().mkdirs(); + } copyStreamToFile(in, size, outputFile); outputFile.setLastModified(modifiedTime); } // Set file/folder permission - if (mode != null && !isSymLink) + if (mode != null && !isSymLink && outputFile.exists()) { FileNativeUtils.chmod(outputFile, mode); + } } + + for (Map.Entry entry : hardLinks.entrySet()) { + FileNativeUtils.link(entry.getKey(), entry.getValue()); + Integer mode = hardLinksMode.get(entry.getValue()); + if (mode != null) { + FileNativeUtils.chmod(entry.getValue(), mode); + } + } + + for (Map.Entry entry : symLinks.entrySet()) { + FileNativeUtils.symlink(entry.getKey(), entry.getValue()); + entry.getValue().setLastModified(symLinksModifiedTimes.get(entry.getValue())); + } + } finally { - if (in != null) + if (in != null) { in.close(); + } } // Set folders timestamps @@ -240,17 +253,15 @@ public class ArchiveExtractor { } } - private static void copyStreamToFile(InputStream in, long size, - File outputFile) - throws FileNotFoundException, IOException { + private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException { FileOutputStream fos = new FileOutputStream(outputFile); try { // if size is not available, copy until EOF... if (size == -1) { byte buffer[] = new byte[4096]; - int l; - while ((l = in.read(buffer)) != -1) { - fos.write(buffer, 0, l); + int length; + while ((length = in.read(buffer)) != -1) { + fos.write(buffer, 0, length); } return; } @@ -258,12 +269,12 @@ public class ArchiveExtractor { // ...else copy just the needed amount of bytes byte buffer[] = new byte[4096]; while (size > 0) { - int l = in.read(buffer); - if (l <= 0) - throw new IOException("Error while extracting file " - + outputFile.getAbsolutePath()); - fos.write(buffer, 0, l); - size -= l; + int length = in.read(buffer); + if (length <= 0) { + throw new IOException("Error while extracting file " + outputFile.getAbsolutePath()); + } + fos.write(buffer, 0, length); + size -= length; } } finally { fos.close();