1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-20 14:54:31 +01:00

Some ArchiveExtractor bugs fixed and its code formatted

This commit is contained in:
Federico Fissore 2015-03-18 14:56:26 +01:00
parent 323458c8d8
commit 6b5244eafe
4 changed files with 105 additions and 72 deletions

View File

@ -44,6 +44,17 @@ import cc.arduino.utils.Progress;
public class LibraryInstaller { 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 LibrariesIndexer indexer;
private File stagingFolder; private File stagingFolder;
private DownloadableContributionsDownloader downloader; private DownloadableContributionsDownloader downloader;
@ -63,7 +74,7 @@ public class LibraryInstaller {
final MultiStepProgress progress = new MultiStepProgress(2); final MultiStepProgress progress = new MultiStepProgress(2);
// Step 1: Download index // 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 outputFile = indexer.getIndexFile();
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp"); File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
try { try {

View File

@ -44,6 +44,17 @@ import static processing.app.I18n.format;
public class ContributionInstaller { 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 File stagingFolder;
private ContributionsIndexer indexer; private ContributionsIndexer indexer;
private DownloadableContributionsDownloader downloader; private DownloadableContributionsDownloader downloader;
@ -172,7 +183,7 @@ public class ContributionInstaller {
final MultiStepProgress progress = new MultiStepProgress(1); final MultiStepProgress progress = new MultiStepProgress(1);
final String statusText = _("Downloading platforms index..."); 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 outputFile = indexer.getIndexFile();
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp"); File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
downloader.download(url, tmpFile, progress, statusText); downloader.download(url, tmpFile, progress, statusText);

View File

@ -44,7 +44,7 @@ public class LinuxFileNativeUtils {
public static void link(File file, File link) throws IOException { public static void link(File file, File link) throws IOException {
int res = libc.link(file.getAbsolutePath(), link.getAbsolutePath()); int res = libc.link(file.getAbsolutePath(), link.getAbsolutePath());
if (res == -1) 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 { public static void symlink(File file, File link) throws IOException {

View File

@ -28,15 +28,7 @@
*/ */
package cc.arduino.utils; package cc.arduino.utils;
import java.io.File; import cc.arduino.os.FileNativeUtils;
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 org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
@ -45,7 +37,9 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 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 { public class ArchiveExtractor {
@ -57,8 +51,7 @@ public class ArchiveExtractor {
* @param destFolder * @param destFolder
* @throws IOException * @throws IOException
*/ */
public static void extract(File archiveFile, File destFolder) public static void extract(File archiveFile, File destFolder) throws IOException {
throws IOException {
extract(archiveFile, destFolder, 0); extract(archiveFile, destFolder, 0);
} }
@ -66,17 +59,13 @@ public class ArchiveExtractor {
* Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive * Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive
* format is autodetected from file extension. * format is autodetected from file extension.
* *
* @param archiveFile * @param archiveFile Archive file to extract
* Archive file to extract * @param destFolder Destination folder
* @param destFolder * @param stripPath Number of path elements to strip from the paths contained in the
* Destination folder * archived files
* @param stripPath
* Number of path elements to strip from the paths contained in the
* archived files
* @throws IOException * @throws IOException
*/ */
public static void extract(File archiveFile, File destFolder, int stripPath) public static void extract(File archiveFile, File destFolder, int stripPath) throws IOException {
throws IOException {
// Folders timestamps must be set at the end of archive extraction // Folders timestamps must be set at the end of archive extraction
// (because creating a file in a folder alters the folder's timestamp) // (because creating a file in a folder alters the folder's timestamp)
@ -106,11 +95,17 @@ public class ArchiveExtractor {
String pathPrefix = ""; String pathPrefix = "";
Map<File, File> hardLinks = new HashMap<File, File>();
Map<File, Integer> hardLinksMode = new HashMap<File, Integer>();
Map<File, File> symLinks = new HashMap<File, File>();
Map<File, Long> symLinksModifiedTimes = new HashMap<File, Long>();
// Cycle through all the archive entries // Cycle through all the archive entries
while (true) { while (true) {
ArchiveEntry entry = in.getNextEntry(); ArchiveEntry entry = in.getNextEntry();
if (entry == null) if (entry == null) {
break; break;
}
// Extract entry info // Extract entry info
long size = entry.getSize(); 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 // http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x
int slash = name.lastIndexOf('/'); int slash = name.lastIndexOf('/');
if (slash == -1) { if (slash == -1) {
if (name.startsWith("._")) if (name.startsWith("._")) {
continue; continue;
}
} else { } else {
if (name.substring(slash + 1).startsWith("._")) if (name.substring(slash + 1).startsWith("._")) {
continue; continue;
}
} }
} }
// Skip git metadata // Skip git metadata
// http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html // 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; continue;
}
if (entry instanceof TarArchiveEntry) { if (entry instanceof TarArchiveEntry) {
TarArchiveEntry tarEntry = (TarArchiveEntry) entry; TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
@ -154,9 +152,9 @@ public class ArchiveExtractor {
int slash = 0; int slash = 0;
while (stripPath > 0) { while (stripPath > 0) {
slash = name.indexOf("/", slash); slash = name.indexOf("/", slash);
if (slash == -1) if (slash == -1) {
throw new IOException( throw new IOException("Invalid archive: it must contains a single root folder");
"Invalid archive: it must contains a single root folder"); }
slash++; slash++;
stripPath--; stripPath--;
} }
@ -164,21 +162,19 @@ public class ArchiveExtractor {
} }
// Strip the common path prefix when requested // Strip the common path prefix when requested
if (!name.startsWith(pathPrefix)) if (!name.startsWith(pathPrefix)) {
throw new IOException( throw new IOException("Invalid archive: it must contains a single root folder while file " + name + " is outside " + pathPrefix);
"Invalid archive: it must contains a single root folder while file " }
+ name + " is outside " + pathPrefix);
name = name.substring(pathPrefix.length()); name = name.substring(pathPrefix.length());
if (name.isEmpty()) if (name.isEmpty()) {
continue; continue;
}
File outputFile = new File(destFolder, name); File outputFile = new File(destFolder, name);
File outputLinkFile = null; File outputLinkFile = null;
if (isLink) { if (isLink) {
if (!linkName.startsWith(pathPrefix)) { if (!linkName.startsWith(pathPrefix)) {
throw new IOException( throw new IOException("Invalid archive: it must contains a single root folder while file " + linkName + " is outside " + pathPrefix);
"Invalid archive: it must contains a single root folder while file "
+ linkName + " is outside " + pathPrefix);
} }
linkName = linkName.substring(pathPrefix.length()); linkName = linkName.substring(pathPrefix.length());
outputLinkFile = new File(destFolder, linkName); outputLinkFile = new File(destFolder, linkName);
@ -186,52 +182,69 @@ public class ArchiveExtractor {
if (isSymLink) { if (isSymLink) {
// Symbolic links are referenced with relative paths // Symbolic links are referenced with relative paths
outputLinkFile = new File(linkName); outputLinkFile = new File(linkName);
if (outputLinkFile.isAbsolute()) if (outputLinkFile.isAbsolute()) {
throw new IOException( throw new IOException("Invalid archive: it contains a symbolic link with absolute path '" + outputLinkFile + "'");
"Invalid archive: it contains a symbolic link with absolute path '" }
+ outputLinkFile + "'");
} }
// Safety check // Safety check
if (isDirectory) { if (isDirectory) {
if (outputFile.isFile()) if (outputFile.isFile()) {
throw new IOException("Can't create folder " + outputFile throw new IOException("Can't create folder " + outputFile + ", a file with the same name exists!");
+ ", a file with the same name exists!"); }
} else { } else {
// - isLink // - isLink
// - isSymLink // - isSymLink
// - anything else // - anything else
if (outputFile.exists()) if (outputFile.exists()) {
throw new IOException("Can't extract file " + outputFile throw new IOException("Can't extract file " + outputFile + ", file already exists!");
+ ", file already exists!"); }
} }
// Extract the entry // Extract the entry
if (isDirectory) { if (isDirectory) {
if (!outputFile.exists()) if (!outputFile.exists() && !outputFile.mkdirs()) {
if (!outputFile.mkdirs()) throw new IOException("Could not create folder: " + outputFile);
throw new IOException("Could not create folder: " + outputFile); }
foldersTimestamps.put(outputFile, modifiedTime); foldersTimestamps.put(outputFile, modifiedTime);
} else if (isLink) { } else if (isLink) {
FileNativeUtils.link(outputLinkFile, outputFile); hardLinks.put(outputLinkFile, outputFile);
hardLinksMode.put(outputFile, mode);
} else if (isSymLink) { } else if (isSymLink) {
FileNativeUtils.symlink(outputLinkFile, outputFile); symLinks.put(outputLinkFile, outputFile);
outputFile.setLastModified(modifiedTime); symLinksModifiedTimes.put(outputFile, modifiedTime);
} else { } else {
// Create the containing folder if not exists // Create the containing folder if not exists
if (!outputFile.getParentFile().isDirectory()) if (!outputFile.getParentFile().isDirectory()) {
outputFile.getParentFile().mkdirs(); outputFile.getParentFile().mkdirs();
}
copyStreamToFile(in, size, outputFile); copyStreamToFile(in, size, outputFile);
outputFile.setLastModified(modifiedTime); outputFile.setLastModified(modifiedTime);
} }
// Set file/folder permission // Set file/folder permission
if (mode != null && !isSymLink) if (mode != null && !isSymLink && outputFile.exists()) {
FileNativeUtils.chmod(outputFile, mode); FileNativeUtils.chmod(outputFile, mode);
}
} }
for (Map.Entry<File, File> 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<File, File> entry : symLinks.entrySet()) {
FileNativeUtils.symlink(entry.getKey(), entry.getValue());
entry.getValue().setLastModified(symLinksModifiedTimes.get(entry.getValue()));
}
} finally { } finally {
if (in != null) if (in != null) {
in.close(); in.close();
}
} }
// Set folders timestamps // Set folders timestamps
@ -240,17 +253,15 @@ public class ArchiveExtractor {
} }
} }
private static void copyStreamToFile(InputStream in, long size, private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException {
File outputFile)
throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream(outputFile); FileOutputStream fos = new FileOutputStream(outputFile);
try { try {
// if size is not available, copy until EOF... // if size is not available, copy until EOF...
if (size == -1) { if (size == -1) {
byte buffer[] = new byte[4096]; byte buffer[] = new byte[4096];
int l; int length;
while ((l = in.read(buffer)) != -1) { while ((length = in.read(buffer)) != -1) {
fos.write(buffer, 0, l); fos.write(buffer, 0, length);
} }
return; return;
} }
@ -258,12 +269,12 @@ public class ArchiveExtractor {
// ...else copy just the needed amount of bytes // ...else copy just the needed amount of bytes
byte buffer[] = new byte[4096]; byte buffer[] = new byte[4096];
while (size > 0) { while (size > 0) {
int l = in.read(buffer); int length = in.read(buffer);
if (l <= 0) if (length <= 0) {
throw new IOException("Error while extracting file " throw new IOException("Error while extracting file " + outputFile.getAbsolutePath());
+ outputFile.getAbsolutePath()); }
fos.write(buffer, 0, l); fos.write(buffer, 0, length);
size -= l; size -= length;
} }
} finally { } finally {
fos.close(); fos.close();